diff -Nru nghttp2-1.13.0/aclocal.m4 nghttp2-0.6.7/aclocal.m4 --- nghttp2-1.13.0/aclocal.m4 2016-07-21 13:48:00.000000000 +0000 +++ nghttp2-0.6.7/aclocal.m4 2014-11-30 14:15:32.000000000 +0000 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15 -*- Autoconf -*- +# generated automatically by aclocal 1.14.1 -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,63 +20,221 @@ If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -dnl serial 11 (pkg-config-0.29) -dnl -dnl Copyright © 2004 Scott James Remnant . -dnl Copyright © 2012-2015 Dan Nicholson -dnl -dnl This program is free software; you can redistribute it and/or modify -dnl it under the terms of the GNU General Public License as published by -dnl the Free Software Foundation; either version 2 of the License, or -dnl (at your option) any later version. -dnl -dnl This program is distributed in the hope that it will be useful, but -dnl WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl General Public License for more details. -dnl -dnl You should have received a copy of the GNU General Public License -dnl along with this program; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -dnl 02111-1307, USA. -dnl -dnl As a special exception to the GNU General Public License, if you -dnl distribute this file as part of a program that contains a -dnl configuration script generated by Autoconf, you may include it under -dnl the same distribution terms that you use for the rest of that -dnl program. - -dnl PKG_PREREQ(MIN-VERSION) -dnl ----------------------- -dnl Since: 0.29 -dnl -dnl Verify that the version of the pkg-config macros are at least -dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's -dnl installed version of pkg-config, this checks the developer's version -dnl of pkg.m4 when generating configure. +# Configure paths for LIBXML2 +# Mike Hommey 2004-06-19 +# use CPPFLAGS instead of CFLAGS +# Toshio Kuratomi 2001-04-21 +# Adapted from: +# Configure paths for GLIB +# Owen Taylor 97-11-3 + +dnl AM_PATH_XML2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for XML, and define XML_CPPFLAGS and XML_LIBS dnl -dnl To ensure that this macro is defined, also add: -dnl m4_ifndef([PKG_PREREQ], -dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +AC_DEFUN([AM_PATH_XML2],[ +AC_ARG_WITH(xml-prefix, + [ --with-xml-prefix=PFX Prefix where libxml is installed (optional)], + xml_config_prefix="$withval", xml_config_prefix="") +AC_ARG_WITH(xml-exec-prefix, + [ --with-xml-exec-prefix=PFX Exec prefix where libxml is installed (optional)], + xml_config_exec_prefix="$withval", xml_config_exec_prefix="") +AC_ARG_ENABLE(xmltest, + [ --disable-xmltest Do not try to compile and run a test LIBXML program],, + enable_xmltest=yes) + + if test x$xml_config_exec_prefix != x ; then + xml_config_args="$xml_config_args" + if test x${XML2_CONFIG+set} != xset ; then + XML2_CONFIG=$xml_config_exec_prefix/bin/xml2-config + fi + fi + if test x$xml_config_prefix != x ; then + xml_config_args="$xml_config_args --prefix=$xml_config_prefix" + if test x${XML2_CONFIG+set} != xset ; then + XML2_CONFIG=$xml_config_prefix/bin/xml2-config + fi + fi + + AC_PATH_PROG(XML2_CONFIG, xml2-config, no) + min_xml_version=ifelse([$1], ,2.0.0,[$1]) + AC_MSG_CHECKING(for libxml - version >= $min_xml_version) + no_xml="" + if test "$XML2_CONFIG" = "no" ; then + no_xml=yes + else + XML_CPPFLAGS=`$XML2_CONFIG $xml_config_args --cflags` + XML_LIBS=`$XML2_CONFIG $xml_config_args --libs` + xml_config_major_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + xml_config_minor_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + xml_config_micro_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_xmltest" = "xyes" ; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" + LIBS="$XML_LIBS $LIBS" dnl -dnl See the "Since" comment for each macro you use to see what version -dnl of the macros you require. -m4_defun([PKG_PREREQ], -[m4_define([PKG_MACROS_VERSION], [0.29]) -m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, - [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) -])dnl PKG_PREREQ - -dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) -dnl ---------------------------------- -dnl Since: 0.16 +dnl Now check if the installed libxml is sufficiently new. +dnl (Also sanity checks the results of xml2-config to some extent) dnl -dnl Search for the pkg-config tool and set the PKG_CONFIG variable to -dnl first found in the path. Checks that the version of pkg-config found -dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is -dnl used since that's the first version where most current features of -dnl pkg-config existed. + rm -f conf.xmltest + AC_TRY_RUN([ +#include +#include +#include +#include + +int +main() +{ + int xml_major_version, xml_minor_version, xml_micro_version; + int major, minor, micro; + char *tmp_version; + + system("touch conf.xmltest"); + + /* Capture xml2-config output via autoconf/configure variables */ + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = (char *)strdup("$min_xml_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string from xml2-config\n", "$min_xml_version"); + exit(1); + } + free(tmp_version); + + /* Capture the version information from the header files */ + tmp_version = (char *)strdup(LIBXML_DOTTED_VERSION); + if (sscanf(tmp_version, "%d.%d.%d", &xml_major_version, &xml_minor_version, &xml_micro_version) != 3) { + printf("%s, bad version string from libxml includes\n", "LIBXML_DOTTED_VERSION"); + exit(1); + } + free(tmp_version); + + /* Compare xml2-config output to the libxml headers */ + if ((xml_major_version != $xml_config_major_version) || + (xml_minor_version != $xml_config_minor_version) || + (xml_micro_version != $xml_config_micro_version)) + { + printf("*** libxml header files (version %d.%d.%d) do not match\n", + xml_major_version, xml_minor_version, xml_micro_version); + printf("*** xml2-config (version %d.%d.%d)\n", + $xml_config_major_version, $xml_config_minor_version, $xml_config_micro_version); + return 1; + } +/* Compare the headers to the library to make sure we match */ + /* Less than ideal -- doesn't provide us with return value feedback, + * only exits if there's a serious mismatch between header and library. + */ + LIBXML_TEST_VERSION; + + /* Test that the library is greater than our minimum version */ + if ((xml_major_version > major) || + ((xml_major_version == major) && (xml_minor_version > minor)) || + ((xml_major_version == major) && (xml_minor_version == minor) && + (xml_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of libxml (%d.%d.%d) was found.\n", + xml_major_version, xml_minor_version, xml_micro_version); + printf("*** You need a version of libxml newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** libxml is always available from ftp://ftp.xmlsoft.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the xml2-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of LIBXML, but you can also set the XML2_CONFIG environment to point to the\n"); + printf("*** correct copy of xml2-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + return 1; +} +],, no_xml=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + + if test "x$no_xml" = x ; then + AC_MSG_RESULT(yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$XML2_CONFIG" = "no" ; then + echo "*** The xml2-config script installed by LIBXML could not be found" + echo "*** If libxml was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the XML2_CONFIG environment variable to the" + echo "*** full path to xml2-config." + else + if test -f conf.xmltest ; then + : + else + echo "*** Could not run libxml test program, checking why..." + CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" + LIBS="$LIBS $XML_LIBS" + AC_TRY_LINK([ +#include +#include +], [ LIBXML_TEST_VERSION; return 0;], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding LIBXML or finding the wrong" + echo "*** version of LIBXML. If it is not finding LIBXML, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means LIBXML was incorrectly installed" + echo "*** or that you have moved LIBXML since it was installed. In the latter case, you" + echo "*** may want to edit the xml2-config script: $XML2_CONFIG" ]) + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + + XML_CPPFLAGS="" + XML_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(XML_CPPFLAGS) + AC_SUBST(XML_LIBS) + rm -f conf.xmltest +]) + +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 1 (pkg-config-0.24) +# +# Copyright © 2004 Scott James Remnant . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) @@ -98,19 +256,18 @@ PKG_CONFIG="" fi fi[]dnl -])dnl PKG_PROG_PKG_CONFIG +])# PKG_PROG_PKG_CONFIG -dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -dnl ------------------------------------------------------------------- -dnl Since: 0.18 -dnl -dnl Check to see whether a particular set of modules exists. Similar to -dnl PKG_CHECK_MODULES(), but does not set variables or print errors. -dnl -dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -dnl only at the first occurence in configure.ac, so if the first place -dnl it's called might be skipped (such as if it is within an "if", you -dnl have to call PKG_CHECK_EXISTS manually +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +# only at the first occurence in configure.ac, so if the first place +# it's called might be skipped (such as if it is within an "if", you +# have to call PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ @@ -120,10 +277,8 @@ $3])dnl fi]) -dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -dnl --------------------------------------------- -dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting -dnl pkg_failed based on the result. +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" @@ -135,11 +290,10 @@ else pkg_failed=untried fi[]dnl -])dnl _PKG_CONFIG +])# _PKG_CONFIG -dnl _PKG_SHORT_ERRORS_SUPPORTED -dnl --------------------------- -dnl Internal check to see if pkg-config supports short errors. +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -147,17 +301,19 @@ else _pkg_short_errors_supported=no fi[]dnl -])dnl _PKG_SHORT_ERRORS_SUPPORTED +])# _PKG_SHORT_ERRORS_SUPPORTED -dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -dnl [ACTION-IF-NOT-FOUND]) -dnl -------------------------------------------------------------- -dnl Since: 0.4.0 -dnl -dnl Note that if there is a possibility the first call to -dnl PKG_CHECK_MODULES might not happen, you should be sure to include an -dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl @@ -211,40 +367,16 @@ AC_MSG_RESULT([yes]) $3 fi[]dnl -])dnl PKG_CHECK_MODULES - +])# PKG_CHECK_MODULES -dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -dnl [ACTION-IF-NOT-FOUND]) -dnl --------------------------------------------------------------------- -dnl Since: 0.29 -dnl -dnl Checks for existence of MODULES and gathers its build flags with -dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags -dnl and VARIABLE-PREFIX_LIBS from --libs. -dnl -dnl Note that if there is a possibility the first call to -dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to -dnl include an explicit call to PKG_PROG_PKG_CONFIG in your -dnl configure.ac. -AC_DEFUN([PKG_CHECK_MODULES_STATIC], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -_save_PKG_CONFIG=$PKG_CONFIG -PKG_CONFIG="$PKG_CONFIG --static" -PKG_CHECK_MODULES($@) -PKG_CONFIG=$_save_PKG_CONFIG[]dnl -])dnl PKG_CHECK_MODULES_STATIC - -dnl PKG_INSTALLDIR([DIRECTORY]) -dnl ------------------------- -dnl Since: 0.27 -dnl -dnl Substitutes the variable pkgconfigdir as the location where a module -dnl should install pkg-config .pc files. By default the directory is -dnl $libdir/pkgconfig, but the default can be changed by passing -dnl DIRECTORY. The user can override through the --with-pkgconfigdir -dnl parameter. +# PKG_INSTALLDIR(DIRECTORY) +# ------------------------- +# Substitutes the variable pkgconfigdir as the location where a module +# should install pkg-config .pc files. By default the directory is +# $libdir/pkgconfig, but the default can be changed by passing +# DIRECTORY. The user can override through the --with-pkgconfigdir +# parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], @@ -255,18 +387,16 @@ AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) -])dnl PKG_INSTALLDIR +]) dnl PKG_INSTALLDIR -dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) -dnl -------------------------------- -dnl Since: 0.27 -dnl -dnl Substitutes the variable noarch_pkgconfigdir as the location where a -dnl module should install arch-independent pkg-config .pc files. By -dnl default the directory is $datadir/pkgconfig, but the default can be -dnl changed by passing DIRECTORY. The user can override through the -dnl --with-noarch-pkgconfigdir parameter. +# PKG_NOARCH_INSTALLDIR(DIRECTORY) +# ------------------------- +# Substitutes the variable noarch_pkgconfigdir as the location where a +# module should install arch-independent pkg-config .pc files. By +# default the directory is $datadir/pkgconfig, but the default can be +# changed by passing DIRECTORY. The user can override through the +# --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], @@ -277,15 +407,13 @@ AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) -])dnl PKG_NOARCH_INSTALLDIR +]) dnl PKG_NOARCH_INSTALLDIR -dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, -dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -dnl ------------------------------------------- -dnl Since: 0.28 -dnl -dnl Retrieves the value of the pkg-config variable for the given module. +# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# ------------------------------------------- +# Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl @@ -294,9 +422,9 @@ AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl -])dnl PKG_CHECK_VAR +])# PKG_CHECK_VAR -# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -308,10 +436,10 @@ # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.15' +[am__api_version='1.14' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.15], [], +m4_if([$1], [1.14.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -327,14 +455,14 @@ # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.15])dnl +[AM_AUTOMAKE_VERSION([1.14.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -386,7 +514,7 @@ # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -417,7 +545,7 @@ Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -608,7 +736,7 @@ # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -684,7 +812,7 @@ # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -774,8 +902,8 @@ # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) -# We need awk for the "check" target (and possibly the TAP driver). The -# system "awk" is bad on some platforms. +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl @@ -849,9 +977,6 @@ AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi -dnl The trailing newline in this macro's definition is deliberate, for -dnl backward compatibility and to allow trailing 'dnl'-style comments -dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not @@ -881,7 +1006,7 @@ done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -892,7 +1017,7 @@ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh+set}" != xset; then +if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -902,7 +1027,7 @@ fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -923,7 +1048,7 @@ # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -973,7 +1098,7 @@ # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1012,7 +1137,7 @@ # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1041,7 +1166,7 @@ AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1088,7 +1213,7 @@ # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1323,7 +1448,7 @@ sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1342,7 +1467,7 @@ # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1423,7 +1548,7 @@ rm -f conftest.file ]) -# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# Copyright (C) 2009-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1483,7 +1608,7 @@ _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1511,7 +1636,7 @@ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# Copyright (C) 2006-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1530,7 +1655,7 @@ # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# Copyright (C) 2004-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1670,7 +1795,6 @@ m4_include([m4/ax_have_epoll.m4]) m4_include([m4/ax_python_devel.m4]) m4_include([m4/libtool.m4]) -m4_include([m4/libxml2.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) diff -Nru nghttp2-1.13.0/android-config nghttp2-0.6.7/android-config --- nghttp2-1.13.0/android-config 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/android-config 2014-11-30 14:15:07.000000000 +0000 @@ -27,9 +27,9 @@ echo 'No $ANDROID_HOME specified.' exit 1 fi -PREFIX="$ANDROID_HOME"/usr/local -TOOLCHAIN="$ANDROID_HOME"/toolchain -PATH="$TOOLCHAIN"/bin:"$PATH" +PREFIX=$ANDROID_HOME/usr/local +TOOLCHAIN=$ANDROID_HOME/toolchain +PATH=$TOOLCHAIN/bin:$PATH ./configure \ --disable-shared \ @@ -39,8 +39,7 @@ --without-libxml2 \ --disable-python-bindings \ --disable-examples \ - CC="$TOOLCHAIN"/bin/arm-linux-androideabi-gcc \ - CXX="$TOOLCHAIN"/bin/arm-linux-androideabi-g++ \ - CPPFLAGS="-fPIE -I$PREFIX/include" \ + --disable-threads \ + CPPFLAGS="-I$PREFIX/include" \ PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \ - LDFLAGS="-fPIE -pie -L$PREFIX/lib" + LDFLAGS="-L$PREFIX/lib" diff -Nru nghttp2-1.13.0/AUTHORS nghttp2-0.6.7/AUTHORS --- nghttp2-1.13.0/AUTHORS 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/AUTHORS 2014-11-30 14:15:07.000000000 +0000 @@ -1,85 +1 @@ -nghttp2 project was started as a fork of spdylay project [1]. Both -projects were started by Tatsuhiro Tsujikawa, who is still the main -author of these projects. Meanwhile, we have many contributions, and -we are not here without them. We sincerely thank you to all who made -a contribution. Here is the all individuals/organizations who -contributed to nghttp2 and spdylay project at which we forked. These -names are retrieved from git commit log. If you have made a -contribution, but you are missing in the list, please let us know via -github issues [2]. - -[1] https://github.com/tatsuhiro-t/spdylay -[2] https://github.com/nghttp2/nghttp2/issues - --------- - -187j3x1 -Alek Storm -Alex Nalivko -Alexis La Goutte -Anders Bakken -Andreas Pohl -Andy Davies -Ant Bryan -Bernard Spil -Brian Card -Brian Suh -Daniel Stenberg -Dave Reisner -David Beitey -David Weekly -Etienne Cimon -Fabian Möller -Fabian Wiesel -Gabi Davar -Jacob Champion -Jan-E -Janusz Dziemidowicz -Jay Satiro -Jianqing Wang -Jim Morrison -José F. Calcerrada -Kamil Dudka -Kazuho Oku -Kenny (kang-yen) Peng -Kenny Peng -Kit Chan -Kyle Schomp -Lucas Pardue -MATSUMOTO Ryosuke -Mike Conlen -Mike Frysinger -Nicholas Hurley -Nora Shoemaker -Peeyush Aggarwal -Peter Wu -Piotr Sikora -Raul Gutierrez Segales -Remo E -Reza Tavakoli -Ross Smith II -Scott Mitchell -Stefan Eissing -Stephen Ludin -Sunpoet Po-Chuan Hsieh -Svante Signell -Syohei YOSHIDA -Tatsuhiko Kubo -Tatsuhiro Tsujikawa -Tom Harwood -Tomasz Buchert -Vernon Tang -Viacheslav Biriukov -Viktor Szépe -Xiaoguang Sun -Zhuoyun Wei -acesso -ayanamist -bxshi -es -fangdingjun -kumagi -mod-h2-dev -moparisthebest -snnn -yuuki-kodama +Tatsuhiro Tsujikawa diff -Nru nghttp2-1.13.0/ChangeLog nghttp2-0.6.7/ChangeLog --- nghttp2-1.13.0/ChangeLog 2016-07-21 13:47:44.000000000 +0000 +++ nghttp2-0.6.7/ChangeLog 2014-11-30 14:15:51.000000000 +0000 @@ -1,205 +1,827 @@ -commit aa0023b3c1d7761fd6b2052793f75ad28961d0f5 (HEAD, tag: v1.13.0, origin/master, origin/HEAD, master) +commit ed1ea91a6f80382c963e4202d6aa3a55a1cb39c5 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-21 +AuthorDate: 2014-11-30 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-21 +CommitDate: 2014-11-30 Update man pages -commit 3bdc143474037c26c85e66abce1b66b3f6ca4a06 +commit 209d1b09466759b124e44bbed2e7aacb567f8e50 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-21 +AuthorDate: 2014-11-30 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-21 +CommitDate: 2014-11-30 - Bump up version number to 1.13.0, LT revision to 23:0:9 + Bump up version number to 0.6.7, LT revision to 7:2:2 -commit 8b50cc0ecebd4cafa39f6cbbd7fa6ff5bd6844fa +commit 761cb97090dd8d1da852ddee4670a500951ce1b6 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-21 +AuthorDate: 2014-11-30 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-21 +CommitDate: 2014-11-30 - Update doc + Update README.rst -commit a24c94e92ab303a382f65b976b27a072ca85eea6 +commit dcc7b239807e8797568da8b534109379c0ab0b9f Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-18 +AuthorDate: 2014-11-30 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-18 +CommitDate: 2014-11-30 - Update doc + nghttpx: Remove cipher suite requirement + + This makes the library h2-16 compatible now. + +commit b9667fd209f9fa75aad7fced02a5f5630830f169 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-30 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-30 + + asio: Listen to all resolved addresses + +commit d23105ccb76a32b20a4a08b5c9b6347a0714c27b +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-30 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-30 + + Add note about pseudo header ordering validation in on_header_callback + +commit 30499005f8a1a44006ca5812a6ad09f86bf7ca68 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-30 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-30 + + Reformat source code in libnghttp2_asio.rst + +commit f2cd057e899a0aefa5177e976937564d850c44ee +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-30 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-30 + + Update tutorial + +commit 2b465ee65fb99f8ba5028cdbd552a734dfe7c22a +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-30 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-30 + + libevent-client: Disable SSLv3 + +commit 7e092a76580d819d357486823ae54a66d99a5a2f +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-30 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-30 + + Make sure that head_stream is not NULL + +commit d39b56adaa6d8adf8131b697050728910c6c802b +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-30 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-30 + + Remove unused nghttp2_stream.blocked_sent + +commit 152a20a4161d6ab3517b4b2a93582e160b1712f8 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-29 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-29 + + Influence last_stream_id to nghttp2_session_want_{read,write} + +commit 7ff0797535c813d5ca6d197ab638c1caa42499d8 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-29 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-29 + + Rewrite session_is_new_peer_stream_id() + +commit ca57c2f6b633ed5ad1568a86e173fc45d51d8c73 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-29 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-29 + + Rename NGHTTP2_GOAWAY_FAIL_ON_SEND with NGHTTP2_GOAWAY_TERM_ON_FAIL + +commit d75ba74bbd450e30f953c3e56efdfe0bad198d38 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-29 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-29 + + Return error if invalid stream_id is given to nghttp2_submit_push_promise -commit a00442bee64a720665b6271b174908fe0386c9ca +commit 9ff192553853d8085726c38e5e968e5446bdb00a Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-17 +AuthorDate: 2014-11-28 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-17 +CommitDate: 2014-11-29 - Work with Android NDK r12b + Robust GOAWAY handling + + This change will utilize last_stream_id in GOAWAY extensively. When + GOAWAY is received with a last_stream_id, library closes all outgoing + streams whose stream_id > received last_stream_id. + nghttp2_on_stream_callback is called for each stream to be closed. - clang + libc++ does not work, it still requires libc++_shared.so - runtime even if -lstdc++ is used, which supposed to link with static - version of libc++. + When GOAWAY is sent with a last_stream_id, library closes all incoming + streams whose stream_id > sent last_stream_id. + nghttp2_on_stream_callback is called for each stream to be closed. -commit f857b6398630f2588e68b0b7b520feaf8b784a31 +commit 1915408096ca3182c1d877e26b39164918543aee Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-16 +AuthorDate: 2014-11-28 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-16 +CommitDate: 2014-11-28 - Fix warning with Sphinx 1.4 + doc: Add language attribute in asio_http2.h.rst.in -commit cbd72da9a1ad030c5926a2dbb2eb55e198c507eb +commit 45801883ba9e75b373e9f215b1e39c1a6b267e77 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-16 +AuthorDate: 2014-11-28 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-16 +CommitDate: 2014-11-28 - Update man pages + Cleanup previous commit -commit 7506a9317924c3bf3d30d7e2317cd75c1c151c71 +commit 382a328eada677ab7ee9623c9641eedcb8f980e1 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-16 +AuthorDate: 2014-11-28 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-16 +CommitDate: 2014-11-28 - doc: Fix Sphinx build warnings + Issue connection error if client receives HEADERS with idle stream ID + + If stream ID is not idle, it might be valid HEADERS. If stream ID is + idle, it is invalid regardless stream ID is even or odd, since client + is not expected to recieve request from server. nghttp2 library + historically allows this, but now we forbids this. -commit 53e1623ab3121ed4723024297bc669594fe87a75 +commit babfa414244217e7a124c529ba658e8fb4a02163 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-16 +AuthorDate: 2014-11-28 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-16 +CommitDate: 2014-11-28 - Update doc + Just ignore HEADERS with non-idle stream ID and not found in stream map + +commit 204ff787fa7a45abb604b6c9c0d91ed85385284f +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-28 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-28 + + nghttpx: Submit RST_STREAM if HEADERS appears in the middle of a stream + +commit 2a68cc7076926a56cb0cec63422d1845e67e3a6d +Merge: c67ccad b1f807a +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-27 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + Merge branch 'clang-format' + +commit b1f807abd1b632826d003dc0730cf8bda0f338cf +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-27 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + Reformat lines with clang-format-3.5 + +commit 2c830a4698fce7e40d6ad9018cc838427061ec9c +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-27 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + Add make clang-format + +commit 87ce5068bbe17ebc9af774a5a621a47472b3cde4 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-26 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + Add pre-commit script + +commit 7c794b8d934f92fac4407e21ccbb60efa006e7c7 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-26 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + Add .clang-format config file and git-clang-format from clang project + +commit 0a406eab94186ef6bd96c3f7e74fe7d86771fb30 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-26 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + Add contribution guidelines + +commit c67ccad74dd4d3b4d8bfd1f1e65e00fa8e508252 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-27 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + nghttpx: Use cached get_config()->pid in save_pid() + +commit 5d59adc52b5777172d344d8e9ed73e651e9384ca +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-27 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + libevent-server: Disable SSLv3 + +commit 770cfcaae9540b5685e3d10aa18b823d4ed9f19e +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-27 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + libevent-server: Enable ECDHE ciphers + +commit 04dae325092896597293dedb04a89e7d0c4175b4 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-27 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + nghttpx: Store PID to Config again after daemon() + +commit 3e0813d40742d46ea481976642b41d33f89c0c1a +Merge: dfbc6e6 c8b83d7 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-27 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + Merge branch 'alagoutte-scan-build' + +commit c8b83d70240b0f88dd8e0ccf8cd79981675a7835 +Merge: dfbc6e6 d128525 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-27 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-27 + + Merge branch 'scan-build' of https://github.com/alagoutte/nghttp2 into alagoutte-scan-build + +commit d1285255ebe97ef89e7e0242f4431ea8dbfc4ddb +Author: Alexis La Goutte +AuthorDate: 2014-11-26 +Commit: Alexis La Goutte +CommitDate: 2014-11-26 + + Fix last warning found by Clang Analyzer - It was markdown, we should use reST. + nghttp2_session.c:636:3: warning: Branch condition evaluates to a garbage value -commit 0cb0bdabecf0c5aa82f5264327618bab716de4fd +commit dfbc6e6a57d6da724dda4e0918dac76481330190 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-13 +AuthorDate: 2014-11-27 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-13 +CommitDate: 2014-11-27 - Update doc + examples: Guard include config.h with HAVE_CONFIG_H -commit ed8d5f04bb0fface95cf527ef2da3dbf8a69d967 +commit 2eab5d03fd09a036cf33f475c908c5834fc159a9 +Merge: 2d10e31 fe634e5 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-10 +AuthorDate: 2014-11-26 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-10 +CommitDate: 2014-11-26 - Update doc + Merge branch 'alagoutte-Wunused-parameter' + +commit fe634e5326cdb8b72af5958b4ca311baefcec025 +Merge: 2d10e31 bac44d7 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-26 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-26 + + Merge branch 'Wunused-parameter' of https://github.com/alagoutte/nghttp2 into alagoutte-Wunused-parameter + +commit bac44d7ffbd4b3a936146ffdb0431adaa087a9ea +Author: Alexis La Goutte +AuthorDate: 2014-10-19 +Commit: Alexis La Goutte +CommitDate: 2014-11-25 + + Fix -Werror=unused-parameter using _U_ macro -commit 33153010c5080ef731a7b1f4c069c351e43308cb +commit 51b59bc8f00e72150b8c17b8d1fa41fcdd7c1c02 +Author: Alexis La Goutte +AuthorDate: 2014-10-19 +Commit: Alexis La Goutte +CommitDate: 2014-11-25 + + Remove -Wno-unused-parameter (and add _U_ macro) + +commit 2d10e31931673eb364b0b2b6ddbf1c28ff9ff8a9 +Merge: e11834d 4cf7b3c Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-08 +AuthorDate: 2014-11-26 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-08 +CommitDate: 2014-11-26 + + Merge branch 'andydavies-master' + +commit 4cf7b3cebdc27af05b3730965b448ab6dc6dfc2a +Author: Andy Davies +AuthorDate: 2014-11-25 +Commit: Andy Davies +CommitDate: 2014-11-25 - nghttpx: Retry memcached connection + Fixed minor typo - Previously, we didn't retry request on connection failure. Sometimes - we hit the edge case where connection is about to lost just when we - write request. To avoid this situation, we now retry request to - failed attempt. We also add ConnectBlocker to MemcachedConnection not - to attempt to connect to memcached if connection could not be made - previously. + turotial -> tutorial + +commit e11834d1c9e8e48a82ba8c9cba6cf64ad3679bd1 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-24 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 + + src: Add code in case struct tm.tm_gmtoff is not available + +commit 8f22ff3032465a725cd3662194e44fae8b78ca87 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-24 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 + + Update man pages -commit 2c500b62fd8634613b14f85357a173c89fd90bad +commit 8e9455188162f378bd4b8fa4dbbf999acc911566 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-07 +AuthorDate: 2014-11-13 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-07 +CommitDate: 2014-11-24 + + Handle idle stream in priority field + +commit 6e1470c9d30c6e129c0ab34e865dbaafb93fd9de +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-12 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 + + Remove duplicated code + +commit 9416bf90794149e977af1051facfee397e3fb30a +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-12 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 Update doc -commit 30f26a2b9d69c0629b339cc215891268b801f089 +commit 24f83eef7c9aeab977898c5686b6df21c0a4aa9a +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-12 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 + + Reduce nghttp2_session_get_stream() call before sending frame + +commit b7c0576eb5fa6c290323d621068eb3d00d8d08cf +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-12 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 + + Make certain type of HEADERS subject to priority + + We make following HEADERS under priority control: + * push response HEADERS + * HEADERS submitted by nghttp2_submit_response + + Currently, HEADERS submitted by nghttp2_submit_headers is not attached + to stream. This is because it may be used as non-final response + header and application may submit final response using + nghttp2_submit_response without checking non-final response header + transmission. + +commit 5a48750e16219fe232c9e36ccc7ba9322eeb540d Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-06 +AuthorDate: 2014-11-09 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-06 +CommitDate: 2014-11-24 - nghttpx: Explicitly cast to uint32_t for hash calculation + Assign default weight if NGHTTP2_MAX_DEP_TREE_LENGTH is exceeded -commit ca39c71ac363addbfe349ddf5f95cdee30c54909 +commit ae93f6345c15b52275a510ccc0cb7155fffaed78 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-06 +AuthorDate: 2014-11-08 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-06 +CommitDate: 2014-11-24 - examples: Fix compile error with OpenSSL v1.1.0-beta2 + Allow PRIORITY frame at anytime. + + Allowing PRIORITY frame at anytime so that PRIORITY frame to idle + stream can create anchor node in dependency tree. In this change, we + open stream with new NGHTTP2_STREAM_IDLE state, which is linked in + session->closed_stream_head and is treated as if it is closed stream. + One difference is that if the stream is opened, we remove it from + linked list and change the state to the appropriate one. To O(1) + removal from linked list, we change session->closed_stream_head to + doubly linked list. + +commit 9bba61642644e60d99b8ebe4caafec4d2cd72997 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-24 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 + + nghttpx: Add $alpn variable to accesslog formatting + + $alpn is a variable which represents ALPN identifier of the protocol + which generates the response. + +commit 1fe50f272b9f4d5e2aa49d78042e0eb86b677d6e +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-24 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 -commit 2bbe4422d2c694b6cd50976352b5f1347bebe3d1 + nghttpx: Add $pid to --accesslog-format variable + + $pid refers to the PID of the running process. + +commit 93023acc6c2bae8e7eeaf83989f7efd07508cc8c Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-06 +AuthorDate: 2014-11-24 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-06 +CommitDate: 2014-11-24 - nghttpx: Use consistent hashing for client IP based session affinity + nghttpx: Make --accesslog-format usage doc help2man friendly - We use technique described in https://github.com/RJ/ketama + This is unfortunate but help2man behaves badly when there is indented + lines in help messages in commnad-line args. We removed indentations + to make help2man happy. + +commit daf659c64e787ca9a260843b3f378e5d64e56a93 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-24 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 + + nghttpx: Note the conversion made in + +commit de2a855572870552a73025be431a27f400e8ae66 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-23 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 + + Implement faster formatting for format_iso8601 and format_common_log + +commit df401f57a29f2aac0726ac09217180098c1abc9e +Merge: ebdbe88 6e17865 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-24 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-24 + + Merge branch 'LPardue-accesslog_port' + +commit 6e178653a5ce3c71bba4133dd1902cba77807f18 +Merge: 9cf1a0c ebdbe88 +Author: Lucas Pardue +AuthorDate: 2014-11-23 +Commit: Lucas Pardue +CommitDate: 2014-11-23 + + fixed conflict + +commit 9cf1a0c77c992ae0548a7f12045a2c969d5d6fda +Author: Lucas Pardue +AuthorDate: 2014-11-19 +Commit: Lucas Pardue +CommitDate: 2014-11-23 + + Add features to logging, client and server port, + time_iso8601 and request_time. + +commit ebdbe88bc09d0e0713ae1142ba295821c92cdc78 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-23 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-23 + + Add contrib/.gitignore + +commit 74ec1d33771128396e5f27062d2c3c94fe9cf311 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-23 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-23 + + nghttpx: Write accesslog when upstream connection is lost for HTTP/2 and SPDY + +commit 1e4f288a7cf08e9d5e6eed294a2e6e2663525e29 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-23 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-23 + + nghttpx: Remove misleading logging + +commit 6a21a6f14883ded4a5ce3d599a8d3f32003a2dcd +Merge: ecd143f 661b99e +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-22 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-22 + + Merge branch 'alagoutte-http_parser' + +commit 661b99ec17f0b7b6edf47b0367686fcd69cc0005 +Merge: ecd143f aa3a6d5 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-22 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-22 + + Merge branch 'http_parser' of https://github.com/alagoutte/nghttp2 into alagoutte-http_parser + +commit ecd143fcc2f029e30e5bdb65ac3848647ea93e93 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-22 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-22 + + nghttpx: Send RST_STREAM with NO_ERROR when closing upgraded connection + +commit bd9389b956f1904c2d8b5de15f98d940b31993f4 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-22 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-22 -commit 5d3535126ed9ed21c935f8006cd49c6052a6110e -Author: Tomasz Buchert -AuthorDate: 2016-07-03 + nghttpx: Refactor http2_data_read_callback + +commit 1a09cef0efc3c9ff7e0d9bee57ad120c2710ee45 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-22 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-22 + + nghttpx: Avoid 0-length DATA in HTTP/2 upstream + +commit aa3a6d5916f5cab35482849cd0d26170ba76d3ef +Author: Alexis La Goutte +AuthorDate: 2014-08-08 +Commit: Alexis La Goutte +CommitDate: 2014-11-21 + + Update Third Party lib (http-parser) + +commit bded1d1115a9a9f29605b1bd9272d6d4775407df +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-22 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-22 + + h2load: Support ALPN + +commit fa4f03525e78a64308c3963586b6d3b56148ca2a +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-22 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-05 +CommitDate: 2014-11-22 - Fix FTBFS on armel by explicitly including the header. + nghttp: Fix compile error and warning with libc++ -commit d2addbc1ed5433408d720c7c769b961b7c2041be +commit 4ee89e62fc78a6aff64130a19dca841adeded738 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-02 +AuthorDate: 2014-11-21 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-02 +CommitDate: 2014-11-21 - Add test for canceling PUSH_PROMISE + nghttp2_hd: Refactor a bit -commit 110ca3131a8cab979bfff0a4febee8a3bb370939 +commit ee65dea8af3da0e263ab75e7b7574eb6008501da Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-07-02 +AuthorDate: 2014-11-19 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-07-02 +CommitDate: 2014-11-19 - Cancel frame transmission from before_frame_send_callback + nghttp: Fix compile error without libjansson + +commit 27609327eecffa1541183221cde8c398e2ce316c +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-19 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-19 + + nghttpx: Fix heap-after-free crash in https upstream - We define the behaviour when NGHTTP2_ERR_CANCEL is returned from - before_frame_send_callback. That is to cancel the frame passed to the - callback. + Add Upstream::on_handler_delete() hook to safely write log for + HttpsUpstream. -commit fd7d3c57d7ecd75567c3c71d7deabc2c2e3b9b7f +commit 958cd0de64e9144878d6b76e0630b9e532749916 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-06-27 +AuthorDate: 2014-11-19 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-06-27 +CommitDate: 2014-11-19 - nghttpx: Use faster version of power + nghttpx: Add configurable access logging format - In our use case, x and y is quite small, and there is no chance for - overflow, and y is always integer. + This commit adds functionality to customize access logging format in + nghttpx. The format variables are inspired by nginx. The default + format is combined format. + +commit 1d7601edfb41f04f211399d510497435362de860 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-18 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-18 + + nghttpx: Better handling EOF from downstream connection to tunnel stream + +commit 8a0fdcfea9ce10be4f4a861ec60caf7d8ceeb766 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-17 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-17 + + nghttpd: Fix crash + +commit 75a1ad8bdb46e3e889da2116ccba5f9af70b44e7 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-16 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-16 + + src: format_iso8601: Fix invalid millisecond formatting + +commit 5bac7f0ca6017837d119e0fcec9ffbaa6484ef9d +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-16 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-16 + + python: Fix request is not sent without TLS + +commit 08fea5705a1f2b4d1f945858a640ceea61765161 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-16 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-16 + + python: Fix bug that settings timer is started when SETTINGS with ACK is sent + +commit 8e5b5d00e1e587dc4e7abbc1c4510ecf307601d8 +Merge: 54232c6 97e8482 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-16 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-16 + + Merge branch 'scoky-master' + +commit 97e8482348f2d4675b97c40876bf7f27fa7719a8 +Merge: 54232c6 0cc73e2 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-16 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-16 + + Merge branch 'master' of https://github.com/scoky/nghttp2 into scoky-master + +commit 0cc73e279e6fe0842411d176ef7112c775d1c782 +Author: Kyle Schomp +AuthorDate: 2014-11-12 +Commit: Kyle Schomp +CommitDate: 2014-11-15 + + Pull of the client Python bindings + +commit 54232c654292ae0ee7f1759527b4249ac3fa4749 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-15 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-15 + + nghttp: Add --no-dep option to disable sending priority hints to server + +commit ee2856f9bc9b512c7ebee871ddedf946742b3c1f +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-15 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-15 + + nghttp: Update doc + +commit 737cea0b386b47df6aeee9296ce58618e4ac9300 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-15 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-15 + + nghttp: Add -r, --har option to output HTTP transactions in HAR format + +commit a8eeea0b182824802a05113c7a8506db5e80ba44 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-15 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-15 + + Initialize frame header for upgrade SETTINGS frame + +commit a2bc88f6dba506f1d3ae5eff5326c0f23176a8c5 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-14 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-14 + + nghttpx: Check max length of ALPN field + +commit 5ce8ae79f0ea615da220e04f90b9c0f1d3d1a71d +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-14 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-14 + + nghttpx: Disable spdy/3 and spdy/2 by default + +commit d98e9a63d02db2592991a942656b232235488b6a +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-14 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-14 + + src: Refactor code around ALPN setup + +commit 8e30adbca07588d2a1c96d857ab383640fe6b62f +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-10 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-10 + + asio: Add http2::backlog API function + +commit 9adfd08848df396e3349d0322498e06944229824 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-10 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-10 + + asio_http2_handler: Use util::utos instead of std::to_string + +commit 2e3419ccbbbb22927b8a622a8156651aae4e6d70 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-10 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-10 + + nghttpd: Cache formatted date string + +commit 5b6b6dc1b7fafd4843b1d1a4d4349443b04a26f0 +Author: Tatsuhiro Tsujikawa +AuthorDate: 2014-11-10 +Commit: Tatsuhiro Tsujikawa +CommitDate: 2014-11-10 + + src: Rewrite http_date -commit 179561e4be3850abf870047c51e4d6eadb0a12ab +commit d0271a90b54a8580e288de02d5fd4934e31ae2a7 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-06-27 +AuthorDate: 2014-11-10 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-06-27 +CommitDate: 2014-11-10 - nghttpx: Cast to double to fix build with gcc 4.8 on Solaris 11 + nghttpd: Use util::utos instead of slow util::to_str -commit 903e0077aa453f2d14ef8bcba4851901cb15feb9 +commit 20ffe2b2a085d5b36bd61c4836b939ba911b7ed9 Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-06-27 +AuthorDate: 2014-11-10 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-06-27 +CommitDate: 2014-11-10 - nghttpx: Fix build error with libressl + tiny-nghttpd: Fix memory leak -commit 3fadad1bf336fc3b6dc2f240fb24dfe282d9986b +commit 94c80e2507eaa813dd08a2cf0bb33e1a37b0b28f Author: Tatsuhiro Tsujikawa -AuthorDate: 2016-06-26 +AuthorDate: 2014-11-08 Commit: Tatsuhiro Tsujikawa -CommitDate: 2016-06-26 +CommitDate: 2014-11-08 - Bump up version number to 1.13.0-DEV + Bump up version number to 0.6.7-DEV diff -Nru nghttp2-1.13.0/cmake/ExtractValidFlags.cmake nghttp2-0.6.7/cmake/ExtractValidFlags.cmake --- nghttp2-1.13.0/cmake/ExtractValidFlags.cmake 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/cmake/ExtractValidFlags.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -# Convenience function that checks the availability of certain -# C or C++ compiler flags and returns valid ones as a string. - -include(CheckCCompilerFlag) -include(CheckCXXCompilerFlag) - -function(extract_valid_c_flags varname) - set(valid_flags) - foreach(flag IN LISTS ARGN) - string(REGEX REPLACE "[^a-zA-Z0-9_]+" "_" flag_var ${flag}) - set(flag_var "C_FLAG_${flag_var}") - check_c_compiler_flag("${flag}" "${flag_var}") - if(${flag_var}) - set(valid_flags "${valid_flags} ${flag}") - endif() - endforeach() - set(${varname} "${valid_flags}" PARENT_SCOPE) -endfunction() - -function(extract_valid_cxx_flags varname) - set(valid_flags) - foreach(flag IN LISTS ARGN) - string(REGEX REPLACE "[^a-zA-Z0-9_]+" "_" flag_var ${flag}) - set(flag_var "CXX_FLAG_${flag_var}") - check_cxx_compiler_flag("${flag}" "${flag_var}") - if(${flag_var}) - set(valid_flags "${valid_flags} ${flag}") - endif() - endforeach() - set(${varname} "${valid_flags}" PARENT_SCOPE) -endfunction() diff -Nru nghttp2-1.13.0/cmake/FindCUnit.cmake nghttp2-0.6.7/cmake/FindCUnit.cmake --- nghttp2-1.13.0/cmake/FindCUnit.cmake 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/cmake/FindCUnit.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -# - Try to find cunit -# Once done this will define -# CUNIT_FOUND - System has cunit -# CUNIT_INCLUDE_DIRS - The cunit include directories -# CUNIT_LIBRARIES - The libraries needed to use cunit - -find_package(PkgConfig QUIET) -pkg_check_modules(PC_CUNIT QUIET cunit) - -find_path(CUNIT_INCLUDE_DIR - NAMES CUnit/CUnit.h - HINTS ${PC_CUNIT_INCLUDE_DIRS} -) -find_library(CUNIT_LIBRARY - NAMES cunit - HINTS ${PC_CUNIT_LIBRARY_DIRS} -) - -if(CUNIT_INCLUDE_DIR) - set(_version_regex "^#define[ \t]+CU_VERSION[ \t]+\"([^\"]+)\".*") - file(STRINGS "${CUNIT_INCLUDE_DIR}/CUnit/CUnit.h" - CUNIT_VERSION REGEX "${_version_regex}") - string(REGEX REPLACE "${_version_regex}" "\\1" - CUNIT_VERSION "${CUNIT_VERSION}") - unset(_version_regex) -endif() - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set CUNIT_FOUND to TRUE -# if all listed variables are TRUE and the requested version matches. -find_package_handle_standard_args(CUnit REQUIRED_VARS - CUNIT_LIBRARY CUNIT_INCLUDE_DIR - VERSION_VAR CUNIT_VERSION) - -if(CUNIT_FOUND) - set(CUNIT_LIBRARIES ${CUNIT_LIBRARY}) - set(CUNIT_INCLUDE_DIRS ${CUNIT_INCLUDE_DIR}) -endif() - -mark_as_advanced(CUNIT_INCLUDE_DIR CUNIT_LIBRARY) diff -Nru nghttp2-1.13.0/cmake/FindCython.cmake nghttp2-0.6.7/cmake/FindCython.cmake --- nghttp2-1.13.0/cmake/FindCython.cmake 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/cmake/FindCython.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -# Find the Cython compiler. -# -# This code sets the following variables: -# -# CYTHON_EXECUTABLE -# -# See also UseCython.cmake - -#============================================================================= -# Copyright 2011 Kitware, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#============================================================================= - -# Use the Cython executable that lives next to the Python executable -# if it is a local installation. -find_package( PythonInterp ) -if( PYTHONINTERP_FOUND ) - get_filename_component( _python_path ${PYTHON_EXECUTABLE} PATH ) - find_program( CYTHON_EXECUTABLE - NAMES cython cython.bat cython3 - HINTS ${_python_path} - ) -else() - find_program( CYTHON_EXECUTABLE - NAMES cython cython.bat cython3 - ) -endif() - - -include( FindPackageHandleStandardArgs ) -FIND_PACKAGE_HANDLE_STANDARD_ARGS( Cython REQUIRED_VARS CYTHON_EXECUTABLE ) - -mark_as_advanced( CYTHON_EXECUTABLE ) diff -Nru nghttp2-1.13.0/cmake/FindJansson.cmake nghttp2-0.6.7/cmake/FindJansson.cmake --- nghttp2-1.13.0/cmake/FindJansson.cmake 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/cmake/FindJansson.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -# - Try to find jansson -# Once done this will define -# JANSSON_FOUND - System has jansson -# JANSSON_INCLUDE_DIRS - The jansson include directories -# JANSSON_LIBRARIES - The libraries needed to use jansson - -find_package(PkgConfig QUIET) -pkg_check_modules(PC_JANSSON QUIET jansson) - -find_path(JANSSON_INCLUDE_DIR - NAMES jansson.h - HINTS ${PC_JANSSON_INCLUDE_DIRS} -) -find_library(JANSSON_LIBRARY - NAMES jansson - HINTS ${PC_JANSSON_LIBRARY_DIRS} -) - -if(JANSSON_INCLUDE_DIR) - set(_version_regex "^#define[ \t]+JANSSON_VERSION[ \t]+\"([^\"]+)\".*") - file(STRINGS "${JANSSON_INCLUDE_DIR}/jansson.h" - JANSSON_VERSION REGEX "${_version_regex}") - string(REGEX REPLACE "${_version_regex}" "\\1" - JANSSON_VERSION "${JANSSON_VERSION}") - unset(_version_regex) -endif() - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set JANSSON_FOUND to TRUE -# if all listed variables are TRUE and the requested version matches. -find_package_handle_standard_args(Jansson REQUIRED_VARS - JANSSON_LIBRARY JANSSON_INCLUDE_DIR - VERSION_VAR JANSSON_VERSION) - -if(JANSSON_FOUND) - set(JANSSON_LIBRARIES ${JANSSON_LIBRARY}) - set(JANSSON_INCLUDE_DIRS ${JANSSON_INCLUDE_DIR}) -endif() - -mark_as_advanced(JANSSON_INCLUDE_DIR JANSSON_LIBRARY) diff -Nru nghttp2-1.13.0/cmake/FindJemalloc.cmake nghttp2-0.6.7/cmake/FindJemalloc.cmake --- nghttp2-1.13.0/cmake/FindJemalloc.cmake 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/cmake/FindJemalloc.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -# - Try to find jemalloc -# Once done this will define -# JEMALLOC_FOUND - System has jemalloc -# JEMALLOC_INCLUDE_DIRS - The jemalloc include directories -# JEMALLOC_LIBRARIES - The libraries needed to use jemalloc - -find_package(PkgConfig QUIET) -pkg_check_modules(PC_JEMALLOC QUIET jemalloc) - -find_path(JEMALLOC_INCLUDE_DIR - NAMES jemalloc/jemalloc.h - HINTS ${PC_JEMALLOC_INCLUDE_DIRS} -) -find_library(JEMALLOC_LIBRARY - NAMES jemalloc - HINTS ${PC_JEMALLOC_LIBRARY_DIRS} -) - -if(JEMALLOC_INCLUDE_DIR) - set(_version_regex "^#define[ \t]+JEMALLOC_VERSION[ \t]+\"([^\"]+)\".*") - file(STRINGS "${JEMALLOC_INCLUDE_DIR}/jemalloc/jemalloc.h" - JEMALLOC_VERSION REGEX "${_version_regex}") - string(REGEX REPLACE "${_version_regex}" "\\1" - JEMALLOC_VERSION "${JEMALLOC_VERSION}") - unset(_version_regex) -endif() - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set JEMALLOC_FOUND to TRUE -# if all listed variables are TRUE and the requested version matches. -find_package_handle_standard_args(Jemalloc REQUIRED_VARS - JEMALLOC_LIBRARY JEMALLOC_INCLUDE_DIR - VERSION_VAR JEMALLOC_VERSION) - -if(JEMALLOC_FOUND) - set(JEMALLOC_LIBRARIES ${JEMALLOC_LIBRARY}) - set(JEMALLOC_INCLUDE_DIRS ${JEMALLOC_INCLUDE_DIR}) -endif() - -mark_as_advanced(JEMALLOC_INCLUDE_DIR JEMALLOC_LIBRARY) diff -Nru nghttp2-1.13.0/cmake/FindLibev.cmake nghttp2-0.6.7/cmake/FindLibev.cmake --- nghttp2-1.13.0/cmake/FindLibev.cmake 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/cmake/FindLibev.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -# - Try to find libev -# Once done this will define -# LIBEV_FOUND - System has libev -# LIBEV_INCLUDE_DIRS - The libev include directories -# LIBEV_LIBRARIES - The libraries needed to use libev - -find_path(LIBEV_INCLUDE_DIR - NAMES ev.h -) -find_library(LIBEV_LIBRARY - NAMES ev -) - -if(LIBEV_INCLUDE_DIR) - file(STRINGS "${LIBEV_INCLUDE_DIR}/ev.h" - LIBEV_VERSION_MAJOR REGEX "^#define[ \t]+EV_VERSION_MAJOR[ \t]+[0-9]+") - file(STRINGS "${LIBEV_INCLUDE_DIR}/ev.h" - LIBEV_VERSION_MINOR REGEX "^#define[ \t]+EV_VERSION_MINOR[ \t]+[0-9]+") - string(REGEX REPLACE "[^0-9]+" "" LIBEV_VERSION_MAJOR "${LIBEV_VERSION_MAJOR}") - string(REGEX REPLACE "[^0-9]+" "" LIBEV_VERSION_MINOR "${LIBEV_VERSION_MINOR}") - set(LIBEV_VERSION "${LIBEV_VERSION_MAJOR}.${LIBEV_VERSION_MINOR}") - unset(LIBEV_VERSION_MINOR) - unset(LIBEV_VERSION_MAJOR) -endif() - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set LIBEV_FOUND to TRUE -# if all listed variables are TRUE and the requested version matches. -find_package_handle_standard_args(Libev REQUIRED_VARS - LIBEV_LIBRARY LIBEV_INCLUDE_DIR - VERSION_VAR LIBEV_VERSION) - -if(LIBEV_FOUND) - set(LIBEV_LIBRARIES ${LIBEV_LIBRARY}) - set(LIBEV_INCLUDE_DIRS ${LIBEV_INCLUDE_DIR}) -endif() - -mark_as_advanced(LIBEV_INCLUDE_DIR LIBEV_LIBRARY) diff -Nru nghttp2-1.13.0/cmake/FindLibevent.cmake nghttp2-0.6.7/cmake/FindLibevent.cmake --- nghttp2-1.13.0/cmake/FindLibevent.cmake 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/cmake/FindLibevent.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -# - Try to find libevent -#.rst -# FindLibevent -# ------------ -# -# Find Libevent include directories and libraries. Invoke as:: -# -# find_package(Libevent -# [version] [EXACT] # Minimum or exact version -# [REQUIRED] # Fail if Libevent is not found -# [COMPONENT ...]) # Libraries to look for -# -# Valid components are one or more of:: libevent core extra pthreads openssl. -# Note that 'libevent' contains both core and extra. You must specify one of -# them for the other components. -# -# This module will define the following variables:: -# -# LIBEVENT_FOUND - True if headers and requested libraries were found -# LIBEVENT_INCLUDE_DIRS - Libevent include directories -# LIBEVENT_LIBRARIES - Libevent libraries to be linked -# LIBEVENT__FOUND - Component was found ( is uppercase) -# LIBEVENT__LIBRARY - Library to be linked for Libevent component . - -find_package(PkgConfig QUIET) -pkg_check_modules(PC_LIBEVENT QUIET libevent) - -# Look for the Libevent 2.0 or 1.4 headers -find_path(LIBEVENT_INCLUDE_DIR - NAMES - event2/event-config.h - event-config.h - HINTS - ${PC_LIBEVENT_INCLUDE_DIRS} -) - -if(LIBEVENT_INCLUDE_DIR) - set(_version_regex "^#define[ \t]+_EVENT_VERSION[ \t]+\"([^\"]+)\".*") - if(EXISTS "${LIBEVENT_INCLUDE_DIR}/event2/event-config.h") - # Libevent 2.0 - file(STRINGS "${LIBEVENT_INCLUDE_DIR}/event2/event-config.h" - LIBEVENT_VERSION REGEX "${_version_regex}") - else() - # Libevent 1.4 - file(STRINGS "${LIBEVENT_INCLUDE_DIR}/event-config.h" - LIBEVENT_VERSION REGEX "${_version_regex}") - endif() - string(REGEX REPLACE "${_version_regex}" "\\1" - LIBEVENT_VERSION "${LIBEVENT_VERSION}") - unset(_version_regex) -endif() - -set(_LIBEVENT_REQUIRED_VARS) -foreach(COMPONENT ${Libevent_FIND_COMPONENTS}) - set(_LIBEVENT_LIBNAME libevent) - # Note: compare two variables to avoid a CMP0054 policy warning - if(COMPONENT STREQUAL _LIBEVENT_LIBNAME) - set(_LIBEVENT_LIBNAME event) - else() - set(_LIBEVENT_LIBNAME "event_${COMPONENT}") - endif() - string(TOUPPER "${COMPONENT}" COMPONENT_UPPER) - find_library(LIBEVENT_${COMPONENT_UPPER}_LIBRARY - NAMES ${_LIBEVENT_LIBNAME} - HINTS ${PC_LIBEVENT_LIBRARY_DIRS} - ) - if(LIBEVENT_${COMPONENT_UPPER}_LIBRARY) - set(Libevent_${COMPONENT}_FOUND 1) - endif() - list(APPEND _LIBEVENT_REQUIRED_VARS LIBEVENT_${COMPONENT_UPPER}_LIBRARY) -endforeach() -unset(_LIBEVENT_LIBNAME) - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set LIBEVENT_FOUND to TRUE -# if all listed variables are TRUE and the requested version matches. -find_package_handle_standard_args(Libevent REQUIRED_VARS - ${_LIBEVENT_REQUIRED_VARS} - LIBEVENT_INCLUDE_DIR - VERSION_VAR LIBEVENT_VERSION - HANDLE_COMPONENTS) - -if(LIBEVENT_FOUND) - set(LIBEVENT_INCLUDE_DIRS ${LIBEVENT_INCLUDE_DIR}) - set(LIBEVENT_LIBRARIES) - foreach(COMPONENT ${Libevent_FIND_COMPONENTS}) - string(TOUPPER "${COMPONENT}" COMPONENT_UPPER) - list(APPEND LIBEVENT_LIBRARIES ${LIBEVENT_${COMPONENT_UPPER}_LIBRARY}) - set(LIBEVENT_${COMPONENT_UPPER}_FOUND ${Libevent_${COMPONENT}_FOUND}) - endforeach() -endif() - -mark_as_advanced(LIBEVENT_INCLUDE_DIR ${_LIBEVENT_REQUIRED_VARS}) -unset(_LIBEVENT_REQUIRED_VARS) diff -Nru nghttp2-1.13.0/cmake/FindSpdylay.cmake nghttp2-0.6.7/cmake/FindSpdylay.cmake --- nghttp2-1.13.0/cmake/FindSpdylay.cmake 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/cmake/FindSpdylay.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -# - Try to find spdylay -# Once done this will define -# SPDYLAY_FOUND - System has spdylay -# SPDYLAY_INCLUDE_DIRS - The spdylay include directories -# SPDYLAY_LIBRARIES - The libraries needed to use spdylay - -find_package(PkgConfig QUIET) -pkg_check_modules(PC_SPDYLAY QUIET libspdylay) - -find_path(SPDYLAY_INCLUDE_DIR - NAMES spdylay/spdylay.h - HINTS ${PC_SPDYLAY_INCLUDE_DIRS} -) -find_library(SPDYLAY_LIBRARY - NAMES spdylay - HINTS ${PC_SPDYLAY_LIBRARY_DIRS} -) - -if(SPDYLAY_INCLUDE_DIR) - set(_version_regex "^#define[ \t]+SPDYLAY_VERSION[ \t]+\"([^\"]+)\".*") - file(STRINGS "${SPDYLAY_INCLUDE_DIR}/spdylay/spdylayver.h" - SPDYLAY_VERSION REGEX "${_version_regex}") - string(REGEX REPLACE "${_version_regex}" "\\1" - SPDYLAY_VERSION "${SPDYLAY_VERSION}") - unset(_version_regex) -endif() - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set SPDYLAY_FOUND to TRUE -# if all listed variables are TRUE and the requested version matches. -find_package_handle_standard_args(Spdylay REQUIRED_VARS - SPDYLAY_LIBRARY SPDYLAY_INCLUDE_DIR - VERSION_VAR SPDYLAY_VERSION) - -if(SPDYLAY_FOUND) - set(SPDYLAY_LIBRARIES ${SPDYLAY_LIBRARY}) - set(SPDYLAY_INCLUDE_DIRS ${SPDYLAY_INCLUDE_DIR}) -endif() - -mark_as_advanced(SPDYLAY_INCLUDE_DIR SPDYLAY_LIBRARY) diff -Nru nghttp2-1.13.0/cmake/Version.cmake nghttp2-0.6.7/cmake/Version.cmake --- nghttp2-1.13.0/cmake/Version.cmake 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/cmake/Version.cmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -# Converts a version such as 1.2.255 to 0x0102ff -function(HexVersion version_hex_var major minor patch) - math(EXPR version_dec "${major} * 256 * 256 + ${minor} * 256 + ${patch}") - set(version_hex "0x") - foreach(i RANGE 5 0 -1) - math(EXPR num "(${version_dec} >> (4 * ${i})) & 15") - string(SUBSTRING "0123456789abcdef" ${num} 1 num_hex) - set(version_hex "${version_hex}${num_hex}") - endforeach() - set(${version_hex_var} "${version_hex}" PARENT_SCOPE) -endfunction() diff -Nru nghttp2-1.13.0/cmakeconfig.h.in nghttp2-0.6.7/cmakeconfig.h.in --- nghttp2-1.13.0/cmakeconfig.h.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/cmakeconfig.h.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ - -/* Hint to the compiler that a function parameter is not used */ -#define _U_ @HINT_UNUSED_PARAM@ - -/* Hint to the compiler that a function never returns */ -#define NGHTTP2_NORETURN @HINT_NORETURN@ - -/* Define to `int' if does not define. */ -#cmakedefine ssize_t @ssize_t@ - -/* Define to 1 if you have the `std::map::emplace`. */ -#cmakedefine HAVE_STD_MAP_EMPLACE 1 - -/* Define to 1 if you have `libjansson` library. */ -#cmakedefine HAVE_JANSSON 1 - -/* Define to 1 if you have `libxml2` library. */ -#cmakedefine HAVE_LIBXML2 1 - -/* Define to 1 if you have `spdylay` library. */ -#cmakedefine HAVE_SPDYLAY 1 - -/* Define to 1 if you have `mruby` library. */ -#cmakedefine HAVE_MRUBY 1 - -/* Define to 1 if you have `neverbleed` library. */ -#cmakedefine HAVE_NEVERBLEED 1 - -/* sizeof(int *) */ -#cmakedefine SIZEOF_INT_P @SIZEOF_INT_P@ - -/* sizeof(time_t) */ -#cmakedefine SIZEOF_TIME_T @SIZEOF_TIME_T@ - -/* Define to 1 if you have the `_Exit` function. */ -#cmakedefine HAVE__EXIT 1 - -/* Define to 1 if you have the `accept4` function. */ -#cmakedefine HAVE_ACCEPT4 1 - -/* Define to 1 if you have the `initgroups` function. */ -#cmakedefine01 HAVE_DECL_INITGROUPS - -/* Define to 1 to enable debug output. */ -#cmakedefine DEBUGBUILD 1 - -/* Define to 1 if you want to disable threads. */ -#cmakedefine NOTHREADS 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ARPA_INET_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_FCNTL_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_NETDB_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_NETINET_IN_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_PWD_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_SOCKET_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYSLOG_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_UNISTD_H 1 diff -Nru nghttp2-1.13.0/CMakeLists.txt nghttp2-0.6.7/CMakeLists.txt --- nghttp2-1.13.0/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,524 +0,0 @@ -# nghttp2 - HTTP/2 C Library -# -# Copyright (c) 2012, 2013, 2014, 2015 Tatsuhiro Tsujikawa -# Copyright (c) 2016 Peter Wu -# -# 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. - -cmake_minimum_required(VERSION 3.0) -# XXX using 1.8.90 instead of 1.9.0-DEV -project(nghttp2 VERSION 1.13.0) - -# See versioning rule: -# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -set(LT_CURRENT 23) -set(LT_REVISION 0) -set(LT_AGE 9) - -set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") -include(Version) - -math(EXPR LT_SOVERSION "${LT_CURRENT} - ${LT_AGE}") -set(LT_VERSION "${LT_SOVERSION}.${LT_AGE}.${LT_REVISION}") -set(PACKAGE_VERSION "${PROJECT_VERSION}") -HexVersion(PACKAGE_VERSION_NUM ${PROJECT_VERSION_MAJOR} ${PROJECT_VERSION_MINOR} ${PROJECT_VERSION_PATCH}) - -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the build type" FORCE) - - # Include "None" as option to disable any additional (optimization) flags, - # relying on just CMAKE_C_FLAGS and CMAKE_CXX_FLAGS (which are empty by - # default). These strings are presented in cmake-gui. - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "None" "Debug" "Release" "MinSizeRel" "RelWithDebInfo") -endif() - -include(GNUInstallDirs) - -# For Python bindings and documentation -# (Must be called before PythonLibs for matching versions.) -find_package(PythonInterp) - -# Auto-detection of features that can be toggled -find_package(OpenSSL 1.0.1) -find_package(Libev 4.11) -find_package(ZLIB 1.2.3) -if(OPENSSL_FOUND AND LIBEV_FOUND AND ZLIB_FOUND) - set(ENABLE_APP_DEFAULT ON) -else() - set(ENABLE_APP_DEFAULT OFF) -endif() -find_package(Jansson 2.5) -set(ENABLE_HPACK_TOOLS_DEFAULT ${JANSSON_FOUND}) -# 2.0.8 is required because we use evconnlistener_set_error_cb() -find_package(Libevent 2.0.8 COMPONENTS libevent openssl) -set(ENABLE_EXAMPLES_DEFAULT ${LIBEVENT_OPENSSL_FOUND}) -find_package(Cython) -find_package(PythonLibs) -if(CYTHON_FOUND AND PYTHONLIBS_FOUND) - set(ENABLE_PYTHON_BINDINGS_DEFAULT ON) -else() - set(ENABLE_PYTHON_BINDINGS_DEFAULT OFF) -endif() - -find_package(LibXml2 2.7.7) -set(WITH_LIBXML2_DEFAULT ${LIBXML2_FOUND}) -find_package(Jemalloc) -set(WITH_JEMALLOC_DEFAULT ${JEMALLOC_FOUND}) -find_package(Spdylay 1.3.2) -set(WITH_SPDYLAY_DEFAULT ${SPDYLAY_FOUND}) - -include(CMakeOptions.txt) - -if(ENABLE_LIB_ONLY AND (ENABLE_APP OR ENABLE_HPACK_TOOLS OR ENABLE_EXAMPLES OR - ENABLE_PYTHON_BINDINGS)) - # Remember when disabled options are disabled for later diagnostics. - set(ENABLE_LIB_ONLY_DISABLED_OTHERS 1) -else() - set(ENABLE_LIB_ONLY_DISABLED_OTHERS 0) -endif() -if(ENABLE_LIB_ONLY) - set(ENABLE_APP OFF) - set(ENABLE_HPACK_TOOLS OFF) - set(ENABLE_EXAMPLES OFF) - set(ENABLE_PYTHON_BINDINGS OFF) -endif() - -# Do not disable assertions based on CMAKE_BUILD_TYPE. -foreach(_build_type "Release" "MinSizeRel" "RelWithDebInfo") - foreach(_lang C CXX) - string(TOUPPER "CMAKE_${_lang}_FLAGS_${_build_type}" _var) - string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" "" ${_var} "${${_var}}") - endforeach() -endforeach() - -# -# If we're running GCC or clang define _U_ to be "__attribute__((unused))" -# so we can use _U_ to flag unused function parameters and not get warnings -# about them. Otherwise, define _U_ to be an empty string so that _U_ used -# to flag an unused function parameters will compile with other compilers. -# -# XXX - similar hints for other compilers? -# -if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") - set(HINT_UNUSED_PARAM "__attribute__((unused))") - set(HINT_NORETURN "__attribute__((noreturn))") -else() - set(HINT_UNUSED_PARAM) - set(HINT_NORETURN) -endif() - -include(ExtractValidFlags) -foreach(_cxx1x_flag -std=c++11 -std=c++0x) - extract_valid_cxx_flags(_cxx1x_flag_supported ${_cxx1x_flag}) - if(_cxx1x_flag_supported) - set(CXX1XCXXFLAGS ${_cxx1x_flag}) - break() - endif() -endforeach() - -include(CMakePushCheckState) -include(CheckCXXSourceCompiles) -cmake_push_check_state() -set(CMAKE_REQUIRED_DEFINITIONS "${CXX1XCXXFLAGS}") -# Check that std::future is available. -check_cxx_source_compiles(" -#include -#include -int main() { std::vector> v; }" HAVE_STD_FUTURE) -# Check that std::map::emplace is available for g++-4.7. -check_cxx_source_compiles(" -#include -int main() { std::map().emplace(1, 2); }" HAVE_STD_MAP_EMPLACE) -cmake_pop_check_state() - - -# Checks for libraries. -# Additional libraries required for programs under src directory. -set(APP_LIBRARIES) - -if(ENABLE_PYTHON_BINDINGS) - if(NOT (CYTHON_FOUND AND PYTHONLIBS_FOUND)) - message(FATAL_ERROR "python bindings were requested " - "(ENABLE_PYTHON_BINDINGS=1) but dependencies are not met.") - endif() - if(NOT PYTHON_VERSION_STRING STREQUAL PYTHONLIBS_VERSION_STRING) - message(FATAL_ERROR - "Python executable and library must have the same version!" - " Found Python ${PYTHON_VERSION_STRING} and" - " PythonLibs ${PYTHONLIBS_VERSION_STRING}" - ) - endif() -endif() - -set(CMAKE_THREAD_PREFER_PTHREAD 1) -find_package(Threads) -if(CMAKE_USE_PTHREADS_INIT) - list(APPEND APP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) -endif() -# XXX android and C++, is this still needed in cmake? -# case "$host" in -# *android*) -# android_build=yes -# # android does not need -pthread, but needs followng 3 libs for C++ -# APPLDFLAGS="$APPLDFLAGS -lstdc++ -latomic -lsupc++" - -# dl: openssl requires libdl when it is statically linked. -# XXX shouldn't ${CMAKE_DL_LIBS} be appended to OPENSSL_LIBRARIES instead of -# APP_LIBRARIES if it is really specific to OpenSSL? - -find_package(CUnit 2.1) -enable_testing() -set(HAVE_CUNIT ${CUNIT_FOUND}) -if(HAVE_CUNIT) - add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) -endif() - -# openssl (for src) -set(HAVE_OPENSSL ${OPENSSL_FOUND}) -if(OPENSSL_FOUND) - set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) -else() - set(OPENSSL_INCLUDE_DIRS "") - set(OPENSSL_LIBRARIES "") -endif() -# libev (for src) -set(HAVE_LIBEV ${LIBEV_FOUND}) -set(HAVE_ZLIB ${ZLIB_FOUND}) -set(HAVE_LIBEVENT_OPENSSL ${LIBEVENT_FOUND}) -if(LIBEVENT_FOUND) - # Must both link the core and openssl libraries. - set(LIBEVENT_OPENSSL_LIBRARIES ${LIBEVENT_LIBRARIES}) -endif() -# jansson (for src/nghttp, src/deflatehd and src/inflatehd) -set(HAVE_JANSSON ${JANSSON_FOUND}) -# libxml2 (for src/nghttp) -set(HAVE_LIBXML2 ${LIBXML2_FOUND}) -if(LIBXML2_FOUND) - set(LIBXML2_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR}) -else() - set(LIBXML2_INCLUDE_DIRS "") - set(LIBXML2_LIBRARIES "") -endif() -# jemalloc -set(HAVE_JEMALLOC ${JEMALLOC_FOUND}) -# spdylay (for src/nghttpx and src/h2load) -set(HAVE_SPDYLAY ${SPDYLAY_FOUND}) - -if(ENABLE_ASIO_LIB) - find_package(Boost 1.54.0 REQUIRED system thread) -endif() - -# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL and libev -if(ENABLE_APP AND NOT (ZLIB_FOUND AND OPENSSL_FOUND AND LIBEV_FOUND)) - message(FATAL_ERROR "Applications were requested (ENABLE_APP=1) but dependencies are not met.") -endif() - -# HPACK tools requires jansson -if(ENABLE_HPACK_TOOLS AND NOT HAVE_JANSSON) - message(FATAL_ERROR "HPACK tools were requested (ENABLE_HPACK_TOOLS=1) but dependencies are not met.") -endif() - -# C++ library libnghttp2_asio -if(ENABLE_EXAMPLES AND NOT (OPENSSL_FOUND AND LIBEVENT_OPENSSL_FOUND)) - message(FATAL_ERROR "examples were requested (ENABLE_EXAMPLES=1) but dependencies are not met.") -endif() - -# third-party http-parser only be built when needed -if(ENABLE_EXAMPLES OR ENABLE_APP OR ENABLE_HPACK_TOOLS OR ENABLE_ASIO_LIB) - set(ENABLE_THIRD_PARTY 1) - # mruby (for src/nghttpx) - set(HAVE_MRUBY ${WITH_MRUBY}) - set(HAVE_NEVERBLEED ${WITH_NEVERBLEED}) -else() - set(HAVE_MRUBY 0) - set(HAVE_NEVERBLEED 0) -endif() - -# Checks for header files. -include(CheckIncludeFile) -check_include_file("arpa/inet.h" HAVE_ARPA_INET_H) -check_include_file("fcntl.h" HAVE_FCNTL_H) -check_include_file("inttypes.h" HAVE_INTTYPES_H) -check_include_file("limits.h" HAVE_LIMITS_H) -check_include_file("netdb.h" HAVE_NETDB_H) -check_include_file("netinet/in.h" HAVE_NETINET_IN_H) -check_include_file("pwd.h" HAVE_PWD_H) -check_include_file("sys/socket.h" HAVE_SYS_SOCKET_H) -check_include_file("sys/time.h" HAVE_SYS_TIME_H) -check_include_file("syslog.h" HAVE_SYSLOG_H) -check_include_file("time.h" HAVE_TIME_H) -check_include_file("unistd.h" HAVE_UNISTD_H) - -include(CheckTypeSize) -# Checks for typedefs, structures, and compiler characteristics. -# AC_TYPE_SIZE_T -check_type_size("ssize_t" SIZEOF_SSIZE_T) -if(SIZEOF_SSIZE_T STREQUAL "") - # ssize_t is a signed type in POSIX storing at least -1. - # Set it to "int" to match the behavior of AC_TYPE_SSIZE_T (autotools). - set(ssize_t int) -endif() -# 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 -# XXX To support inline for crappy compilers, see https://cmake.org/Wiki/CMakeTestInline -# AC_C_INLINE -# XXX is AC_SYS_LARGEFILE still needed for modern systems? -# add_definitions(-D_FILE_OFFSET_BITS=64) - -include(CheckStructHasMember) -check_struct_has_member("struct tm" tm_gmtoff time.h HAVE_STRUCT_TM_TM_GMTOFF) - -# Check size of pointer to decide we need 8 bytes alignment adjustment. -check_type_size("int *" SIZEOF_INT_P) -check_type_size("time_t" SIZEOF_TIME_T) - -# Checks for library functions. -include(CheckFunctionExists) -check_function_exists(_Exit HAVE__EXIT) -check_function_exists(accept4 HAVE_ACCEPT4) - -# timerfd_create was added in linux kernel 2.6.25 -include(CheckSymbolExists) -# XXX does this correctly detect initgroups (un)availability on cygwin? -check_symbol_exists(initgroups grp.h HAVE_DECL_INITGROUPS) -if(NOT HAVE_DECL_INITGROUPS AND HAVE_UNISTD_H) - # FreeBSD declares initgroups() in unistd.h - check_symbol_exists(initgroups unistd.h HAVE_DECL_INITGROUPS2) - if(HAVE_DECL_INITGROUPS2) - set(HAVE_DECL_INITGROUPS 1) - endif() -endif() - -check_function_exists(timerfd_create HAVE_TIMERFD_CREATE) -# Checks for epoll availability, primarily for examples/tiny-nghttpd -check_symbol_exists(epoll_create sys/epoll.h HAVE_EPOLL) -if(HAVE_EPOLL AND HAVE_TIMERFD_CREATE) - set(ENABLE_TINY_NGHTTPD 1) -endif() - -set(WARNCFLAGS) -set(WARNCXXFLAGS) -if(CMAKE_C_COMPILER_ID MATCHES "MSVC") - if(ENABLE_WERROR) - set(WARNCFLAGS /WX) - set(WARNCXXFLAGS /WX) - endif() -else() - if(ENABLE_WERROR) - extract_valid_c_flags(WARNCFLAGS -Werror) - extract_valid_c_flags(WARNCXXFLAGS -Werror) - endif() - - # For C compiler - extract_valid_c_flags(WARNCFLAGS - -Wall - -Wextra - -Wmissing-prototypes - -Wstrict-prototypes - -Wmissing-declarations - -Wpointer-arith - -Wdeclaration-after-statement - -Wformat-security - -Wwrite-strings - -Wshadow - -Winline - -Wnested-externs - -Wfloat-equal - -Wundef - -Wendif-labels - -Wempty-body - -Wcast-align - -Wclobbered - -Wvla - -Wpragmas - -Wunreachable-code - -Waddress - -Wattributes - -Wdiv-by-zero - -Wshorten-64-to-32 - - -Wconversion - -Wextended-offsetof - -Wformat-nonliteral - -Wlanguage-extension-token - -Wmissing-field-initializers - -Wmissing-noreturn - -Wmissing-variable-declarations - # Not used because we cannot change public structs - # -Wpadded - -Wsign-conversion - # Not used because this basically disallows default case - # -Wswitch-enum - -Wunreachable-code-break - -Wunused-macros - -Wunused-parameter - -Wredundant-decls - # Only work with Clang for the moment - -Wheader-guard - # This is required because we pass format string as "const char*. - -Wno-format-nonliteral - ) - - extract_valid_cxx_flags(WARNCXXFLAGS - # For C++ compiler - -Wall - -Wformat-security - ) -endif() - -if(ENABLE_DEBUG) - set(DEBUGBUILD 1) -endif() - -# Some platform does not have working std::future. We disable -# threading for those platforms. -if(NOT ENABLE_THREADS OR NOT HAVE_STD_FUTURE) - set(NOTHREADS 1) -endif() - -add_definitions(-DHAVE_CONFIG_H) -configure_file(cmakeconfig.h.in config.h) -# autotools-compatible names -# Sphinx expects relative paths in the .rst files. Use the fact that the files -# below are all one directory level deep. -file(RELATIVE_PATH top_srcdir "${CMAKE_BINARY_DIR}/dir" "${CMAKE_SOURCE_DIR}") -file(RELATIVE_PATH top_builddir "${CMAKE_BINARY_DIR}/dir" "${CMAKE_BINARY_DIR}") -set(abs_top_srcdir "${CMAKE_SOURCE_DIR}") -set(abs_top_builddir "${CMAKE_BINARY_DIR}") -# libnghttp2.pc (pkg-config file) -set(prefix "${CMAKE_INSTALL_PREFIX}") -set(exec_prefix "${CMAKE_INSTALL_PREFIX}") -set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}") -set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}") -set(VERSION "${PACKAGE_VERSION}") -# For init scripts and systemd service file (in contrib/) -set(bindir "${CMAKE_INSTALL_FULL_BINDIR}") -set(sbindir "${CMAKE_INSTALL_FULL_SBINDIR}") -foreach(name - lib/libnghttp2.pc - lib/includes/nghttp2/nghttp2ver.h - src/libnghttp2_asio.pc - python/setup.py - integration-tests/config.go - integration-tests/setenv - doc/conf.py - doc/index.rst - doc/package_README.rst - doc/tutorial-client.rst - doc/tutorial-server.rst - doc/tutorial-hpack.rst - doc/nghttpx-howto.rst - doc/h2load-howto.rst - doc/libnghttp2_asio.rst - doc/python-apiref.rst - doc/building-android-binary.rst - doc/nghttp2.h.rst - doc/nghttp2ver.h.rst - doc/asio_http2.h.rst - doc/asio_http2_server.h.rst - doc/asio_http2_client.h.rst - doc/contribute.rst -) - configure_file("${name}.in" "${name}" @ONLY) -endforeach() - -include_directories( - "${CMAKE_BINARY_DIR}" # for config.h -) -# For use in src/CMakeLists.txt -set(PKGDATADIR "${CMAKE_INSTALL_FULL_DATADIR}/${CMAKE_PROJECT_NAME}") - -install(FILES README.rst DESTINATION "${CMAKE_INSTALL_DOCDIR}") - -add_subdirectory(lib) -#add_subdirectory(lib/includes) -add_subdirectory(third-party) -add_subdirectory(src) -#add_subdirectory(src/includes) -add_subdirectory(examples) -add_subdirectory(python) -add_subdirectory(tests) -#add_subdirectory(tests/testdata) -add_subdirectory(integration-tests) -add_subdirectory(doc) -add_subdirectory(contrib) -add_subdirectory(script) - - -string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type) -message(STATUS "summary of build options: - - Package version: ${VERSION} - Library version: ${LT_CURRENT}:${LT_REVISION}:${LT_AGE} - Install prefix: ${CMAKE_INSTALL_PREFIX} - Target system: ${CMAKE_SYSTEM_NAME} - Compiler: - Build type: ${CMAKE_BUILD_TYPE} - C compiler: ${CMAKE_C_COMPILER} - CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS} - C++ compiler: ${CMAKE_CXX_COMPILER} - CXXFLAGS: ${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS} - WARNCFLAGS: ${WARNCFLAGS} - CXX1XCXXFLAGS: ${CXX1XCXXFLAGS} - Python: - Python: ${PYTHON_EXECUTABLE} - PYTHON_VERSION: ${PYTHON_VERSION_STRING} - Library version:${PYTHONLIBS_VERSION_STRING} - Cython: ${CYTHON_EXECUTABLE} - Test: - CUnit: ${HAVE_CUNIT} (LIBS='${CUNIT_LIBRARIES}') - Failmalloc: ${ENABLE_FAILMALLOC} - Libs: - OpenSSL: ${HAVE_OPENSSL} (LIBS='${OPENSSL_LIBRARIES}') - Libxml2: ${HAVE_LIBXML2} (LIBS='${LIBXML2_LIBRARIES}') - Libev: ${HAVE_LIBEV} (LIBS='${LIBEV_LIBRARIES}') - Libevent(SSL): ${HAVE_LIBEVENT_OPENSSL} (LIBS='${LIBEVENT_OPENSSL_LIBRARIES}') - Spdylay: ${HAVE_SPDYLAY} (LIBS='${SPDYLAY_LIBRARIES}') - Jansson: ${HAVE_JANSSON} (LIBS='${JANSSON_LIBRARIES}') - Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}') - Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}') - Boost::System: ${Boost_SYSTEM_LIBRARY} - Boost::Thread: ${Boost_THREAD_LIBRARY} - Third-party: - http-parser: ${ENABLE_THIRD_PARTY} - MRuby: ${HAVE_MRUBY} - Neverbleed: ${HAVE_NEVERBLEED} - Features: - Applications: ${ENABLE_APP} - HPACK tools: ${ENABLE_HPACK_TOOLS} - Libnghttp2_asio:${ENABLE_ASIO_LIB} - Examples: ${ENABLE_EXAMPLES} - Python bindings:${ENABLE_PYTHON_BINDINGS} - Threading: ${ENABLE_THREADS} -") -if(ENABLE_LIB_ONLY_DISABLED_OTHERS) - message("Only the library will be built. To build other components " - "(such as applications and examples), set ENABLE_LIB_ONLY=OFF.") -endif() diff -Nru nghttp2-1.13.0/CMakeOptions.txt nghttp2-0.6.7/CMakeOptions.txt --- nghttp2-1.13.0/CMakeOptions.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/CMakeOptions.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -# Features that can be enabled for cmake (see CMakeLists.txt) - -option(ENABLE_WERROR "Turn on compile time warnings") -option(ENABLE_DEBUG "Turn on debug output") -option(ENABLE_THREADS "Turn on threading in apps" ON) -option(ENABLE_APP "Build applications (nghttp, nghttpd, nghttpx and h2load)" - ${ENABLE_APP_DEFAULT}) -option(ENABLE_HPACK_TOOLS "Build HPACK tools" - ${ENABLE_HPACK_TOOLS_DEFAULT}) -option(ENABLE_ASIO_LIB "Build C++ libnghttp2_asio library") -option(ENABLE_EXAMPLES "Build examples" - ${ENABLE_EXAMPLES_DEFAULT}) -option(ENABLE_PYTHON_BINDINGS "Build Python bindings" - ${ENABLE_PYTHON_BINDINGS_DEFAULT}) -option(ENABLE_FAILMALLOC "Build failmalloc test program" ON) -option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENABLE_APP=0 -DENABLE_EXAMPLES=0 -DENABLE_HPACK_TOOLS=0 -DENABLE_PYTHON_BINDINGS=0") - -option(WITH_LIBXML2 "Use libxml2" - ${WITH_LIBXML2_DEFAULT}) -option(WITH_JEMALLOC "Use jemalloc" - ${WITH_JEMALLOC_DEFAULT}) -option(WITH_SPDYLAY "Use spdylay" - ${WITH_SPDYLAY_DEFAULT}) -option(WITH_MRUBY "Use mruby") -option(WITH_NEVERBLEED "Use neverbleed") - -# vim: ft=cmake: diff -Nru nghttp2-1.13.0/compile nghttp2-0.6.7/compile --- nghttp2-1.13.0/compile 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/compile 2014-11-30 14:15:34.000000000 +0000 @@ -3,7 +3,7 @@ scriptversion=2012-10-14.11; # UTC -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2013 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify diff -Nru nghttp2-1.13.0/config.guess nghttp2-0.6.7/config.guess --- nghttp2-1.13.0/config.guess 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/config.guess 2014-11-30 14:15:34.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2014 Free Software Foundation, Inc. -timestamp='2016-04-02' +timestamp='2014-03-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -24,12 +24,12 @@ # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # -# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# Originally written by Per Bothner. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # -# Please send patches to . +# Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` @@ -50,7 +50,7 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -168,27 +168,20 @@ # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - /sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || \ - echo unknown)` + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; - earmv*) - arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` - endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` - machine=${arch}${endian}-unknown - ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in - arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) + arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ @@ -204,13 +197,6 @@ os=netbsd ;; esac - # Determine ABI tags. - case "${UNAME_MACHINE_ARCH}" in - earm*) - expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` - ;; - esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need @@ -221,13 +207,13 @@ release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}${abi}" + echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` @@ -237,10 +223,6 @@ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; - *:LibertyBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} - exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; @@ -253,9 +235,6 @@ *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; - *:Sortix:*:*) - echo ${UNAME_MACHINE}-unknown-sortix - exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -272,42 +251,42 @@ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE=alpha ;; + UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") - UNAME_MACHINE=alpha ;; + UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") - UNAME_MACHINE=alpha ;; + UNAME_MACHINE="alpha" ;; "EV5 (21164)") - UNAME_MACHINE=alphaev5 ;; + UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") - UNAME_MACHINE=alphaev56 ;; + UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") - UNAME_MACHINE=alphapca56 ;; + UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") - UNAME_MACHINE=alphapca57 ;; + UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") - UNAME_MACHINE=alphaev6 ;; + UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") - UNAME_MACHINE=alphaev67 ;; + UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") - UNAME_MACHINE=alphaev68 ;; + UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") - UNAME_MACHINE=alphaev68 ;; + UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") - UNAME_MACHINE=alphaev68 ;; + UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE=alphaev69 ;; + UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") - UNAME_MACHINE=alphaev7 ;; + UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") - UNAME_MACHINE=alphaev79 ;; + UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 @@ -380,16 +359,16 @@ exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build - SUN_ARCH=i386 + SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH=x86_64 + SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` @@ -414,7 +393,7 @@ exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} @@ -600,9 +579,8 @@ else IBM_ARCH=powerpc fi - if [ -x /usr/bin/lslpp ] ; then - IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | - awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi @@ -639,13 +617,13 @@ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in - 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 - 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in - 32) HP_ARCH=hppa2.0n ;; - 64) HP_ARCH=hppa2.0w ;; - '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi @@ -684,11 +662,11 @@ exit (0); } EOF - (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = hppa2.0w ] + if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build @@ -701,12 +679,12 @@ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH=hppa2.0w + HP_ARCH="hppa2.0w" else - HP_ARCH=hppa64 + HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} @@ -811,14 +789,14 @@ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) @@ -900,7 +878,7 @@ exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix @@ -923,7 +901,7 @@ EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) @@ -954,9 +932,6 @@ crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; - e2k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; @@ -969,9 +944,6 @@ ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; - k1om:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; @@ -1048,7 +1020,7 @@ echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} @@ -1127,7 +1099,7 @@ # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configure will decide that + # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; @@ -1276,9 +1248,6 @@ SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; - SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux${UNAME_RELEASE} - exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; @@ -1292,9 +1261,9 @@ UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in @@ -1316,7 +1285,7 @@ exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = x86; then + if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi @@ -1347,7 +1316,7 @@ # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = 386; then + if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" @@ -1389,7 +1358,7 @@ echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos @@ -1400,9 +1369,6 @@ x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; - amd64:Isilon\ OneFS:*:*) - echo x86_64-unknown-onefs - exit ;; esac cat >&2 < header file. */ #undef HAVE_ARPA_INET_H @@ -24,35 +21,15 @@ /* define if the Boost::Thread library is available */ #undef HAVE_BOOST_THREAD -/* Define to 1 if your system has a working `chown' function. */ -#undef HAVE_CHOWN +/* Define to 1 if you have the `clock_gettime`. */ +#undef HAVE_CLOCK_GETTIME /* define if the compiler supports basic C++11 syntax */ #undef HAVE_CXX11 -/* Define to 1 if you have the declaration of `initgroups', and to 0 if you - don't. */ -#undef HAVE_DECL_INITGROUPS - -/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you - don't. */ -#undef HAVE_DECL_STRERROR_R - /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H -/* Define to 1 if you have the `dup2' function. */ -#undef HAVE_DUP2 - -/* Define to 1 if you have the header file. */ -#undef HAVE_FCNTL_H - -/* Define to 1 if you have the `fork' function. */ -#undef HAVE_FORK - -/* Define to 1 if you have the `getcwd' function. */ -#undef HAVE_GETCWD - /* Define to 1 if you have the `getpwnam' function. */ #undef HAVE_GETPWNAM @@ -65,14 +42,9 @@ /* Define to 1 if you have `libxml2` library. */ #undef HAVE_LIBXML2 -/* Define to 1 if you have the header file. */ -#undef HAVE_LIMITS_H - -/* Define to 1 if you have the `localtime_r' function. */ -#undef HAVE_LOCALTIME_R - -/* Define to 1 if you have the `memchr' function. */ -#undef HAVE_MEMCHR +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE @@ -83,18 +55,9 @@ /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET -/* Define to 1 if you have `mruby` library. */ -#undef HAVE_MRUBY - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETDB_H - /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H -/* Define to 1 if you have `neverbleed` library. */ -#undef HAVE_NEVERBLEED - /* Define to 1 if the system has the type `ptrdiff_t'. */ #undef HAVE_PTRDIFF_T @@ -104,15 +67,9 @@ /* If available, contains the Python version number currently in use. */ #undef HAVE_PYTHON -/* Define to 1 if you have the `socket' function. */ -#undef HAVE_SOCKET - /* Define to 1 if you have `spdylay` library. */ #undef HAVE_SPDYLAY -/* Define to 1 if you have the `sqrt' function. */ -#undef HAVE_SQRT - /* Define to 1 if you have the header file. */ #undef HAVE_STDDEF_H @@ -125,20 +82,8 @@ /* Define to 1 if you have the `std::future`. */ #undef HAVE_STD_FUTURE -/* Define to 1 if you have the `std::map::emplace`. */ -#undef HAVE_STD_MAP_EMPLACE - -/* Define to 1 if you have the `strchr' function. */ -#undef HAVE_STRCHR - -/* Define to 1 if you have the `strdup' function. */ -#undef HAVE_STRDUP - -/* Define to 1 if you have the `strerror' function. */ -#undef HAVE_STRERROR - -/* Define to 1 if you have the `strerror_r' function. */ -#undef HAVE_STRERROR_R +/* Define to 1 if you have the `std::chrono::steady_clock`. */ +#undef HAVE_STEADY_CLOCK /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H @@ -146,33 +91,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H -/* Define to 1 if you have the `strndup' function. */ -#undef HAVE_STRNDUP - -/* Define to 1 if you have the `strstr' function. */ -#undef HAVE_STRSTR - -/* Define to 1 if you have the `strtol' function. */ -#undef HAVE_STRTOL - -/* Define to 1 if you have the `strtoul' function. */ -#undef HAVE_STRTOUL - /* Define to 1 if you have `struct tm.tm_gmtoff` member. */ #undef HAVE_STRUCT_TM_TM_GMTOFF -/* Define to 1 if you have the header file. */ -#undef HAVE_SYSLOG_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SOCKET_H - /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TIME_H - /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H @@ -185,30 +109,19 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* Define to 1 if you have the `vfork' function. */ -#undef HAVE_VFORK - -/* Define to 1 if you have the header file. */ -#undef HAVE_VFORK_H - -/* Define to 1 if `fork' works. */ -#undef HAVE_WORKING_FORK - -/* Define to 1 if `vfork' works. */ -#undef HAVE_WORKING_VFORK +/* Define to 1 if you have the header file. */ +#undef HAVE_WINSOCK2_H /* Define to 1 if you have the `_Exit' function. */ #undef HAVE__EXIT -/* Define to the sub-directory where libtool stores uninstalled libraries. */ +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ #undef LT_OBJDIR /* Define to 1 if assertions should be disabled. */ #undef NDEBUG -/* Hint to the compiler that a function never return */ -#undef NGHTTP2_NORETURN - /* Define to 1 if you want to disable threads. */ #undef NOTHREADS @@ -233,40 +146,9 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* The size of `int *', as computed by sizeof. */ -#undef SIZEOF_INT_P - -/* The size of `time_t', as computed by sizeof. */ -#undef SIZEOF_TIME_T - /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS -/* Define to 1 if strerror_r returns char *. */ -#undef STRERROR_R_CHAR_P - -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -# undef _ALL_SOURCE -#endif -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# undef _GNU_SOURCE -#endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -# undef _POSIX_PTHREAD_SEMANTICS -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -# undef _TANDEM_SOURCE -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# undef __EXTENSIONS__ -#endif - - /* Version number of package */ #undef VERSION @@ -293,16 +175,6 @@ /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES -/* Define to 1 if on MINIX. */ -#undef _MINIX - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -#undef _POSIX_1_SOURCE - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -#undef _POSIX_SOURCE - /* Define for Solaris 2.5.1 so the uint32_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ @@ -318,39 +190,11 @@ #define below would cause a syntax error. */ #undef _UINT8_T -/* Hint to the compiler that a function parameter is not used */ +/* Hint to the compiler that a function parameters is not used */ #undef _U_ -/* Define to `int' if doesn't define. */ -#undef gid_t - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif - -/* Define to the type of a signed integer type of width exactly 16 bits if - such a type exists and the standard includes do not define it. */ -#undef int16_t - -/* Define to the type of a signed integer type of width exactly 32 bits if - such a type exists and the standard includes do not define it. */ -#undef int32_t - -/* Define to the type of a signed integer type of width exactly 64 bits if - such a type exists and the standard includes do not define it. */ -#undef int64_t - -/* Define to the type of a signed integer type of width exactly 8 bits if such - a type exists and the standard includes do not define it. */ -#undef int8_t - -/* Define to `long int' if does not define. */ -#undef off_t - -/* Define to `int' if does not define. */ -#undef pid_t +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc /* Define to `unsigned int' if does not define. */ #undef size_t @@ -358,9 +202,6 @@ /* Define to `int' if does not define. */ #undef ssize_t -/* Define to `int' if doesn't define. */ -#undef uid_t - /* Define to the type of an unsigned integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ #undef uint16_t @@ -376,6 +217,3 @@ /* Define to the type of an unsigned integer type of width exactly 8 bits if such a type exists and the standard includes do not define it. */ #undef uint8_t - -/* Define as `fork' if `vfork' does not work. */ -#undef vfork diff -Nru nghttp2-1.13.0/config.sub nghttp2-0.6.7/config.sub --- nghttp2-1.13.0/config.sub 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/config.sub 2014-11-30 14:15:34.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2014 Free Software Foundation, Inc. -timestamp='2016-03-30' +timestamp='2014-09-11' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ # of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches to . +# Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. @@ -33,7 +33,7 @@ # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -53,7 +53,8 @@ me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS Canonicalize a configuration name. @@ -67,7 +68,7 @@ version="\ GNU config.sub ($timestamp) -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -116,7 +117,7 @@ case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os @@ -254,13 +255,12 @@ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ - | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ + | epiphany \ + | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ @@ -305,7 +305,7 @@ | riscv32 | riscv64 \ | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -313,7 +313,6 @@ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) @@ -328,9 +327,6 @@ c6x) basic_machine=tic6x-unknown ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none @@ -376,13 +372,12 @@ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ - | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ + | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ @@ -429,13 +424,12 @@ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ - | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ @@ -443,7 +437,6 @@ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ - | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -520,9 +513,6 @@ basic_machine=i386-pc os=-aros ;; - asmjs) - basic_machine=asmjs-unknown - ;; aux) basic_machine=m68k-apple os=-aux @@ -784,9 +774,6 @@ basic_machine=m68k-isi os=-sysv ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` - ;; m68knommu) basic_machine=m68k-unknown os=-linux @@ -1378,11 +1365,11 @@ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* | -cloudabi* | -sortix* \ + | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ @@ -1398,8 +1385,7 @@ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1531,8 +1517,6 @@ ;; -nacl*) ;; - -ios) - ;; -none) ;; *) diff -Nru nghttp2-1.13.0/configure nghttp2-0.6.7/configure --- nghttp2-1.13.0/configure 2016-07-21 13:48:00.000000000 +0000 +++ nghttp2-0.6.7/configure 2014-11-30 14:15:33.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for nghttp2 1.13.0. +# Generated by GNU Autoconf 2.69 for nghttp2 0.6.7. # # Report bugs to . # @@ -198,7 +198,6 @@ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' @@ -206,7 +205,8 @@ ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ - || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='nghttp2' PACKAGE_TARNAME='nghttp2' -PACKAGE_VERSION='1.13.0' -PACKAGE_STRING='nghttp2 1.13.0' +PACKAGE_VERSION='0.6.7' +PACKAGE_STRING='nghttp2 0.6.7' PACKAGE_BUGREPORT='t-tujikawa@users.sourceforge.net' PACKAGE_URL='' @@ -634,13 +634,8 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS -APPLDFLAGS -TESTLDADD -ENABLE_STATIC_FALSE -ENABLE_STATIC_TRUE -EXTRACFLAG -WARNCXXFLAGS -WARNCFLAGS +SRC_LIBS +TESTS_LIBS ENABLE_TINY_NGHTTPD_FALSE ENABLE_TINY_NGHTTPD_TRUE LIBOBJS @@ -650,14 +645,6 @@ HAVE_CYTHON_TRUE ENABLE_PYTHON_BINDINGS_FALSE ENABLE_PYTHON_BINDINGS_TRUE -HAVE_NEVERBLEED_FALSE -HAVE_NEVERBLEED_TRUE -HAVE_MRUBY_FALSE -HAVE_MRUBY_TRUE -ENABLE_THIRD_PARTY_FALSE -ENABLE_THIRD_PARTY_TRUE -LIBMRUBY_CFLAGS -LIBMRUBY_LIBS ENABLE_EXAMPLES_FALSE ENABLE_EXAMPLES_TRUE ENABLE_ASIO_LIB_FALSE @@ -687,15 +674,12 @@ LIBEVENT_OPENSSL_CFLAGS OPENSSL_LIBS OPENSSL_CFLAGS -LIBEV_CFLAGS -LIBEV_LIBS HAVE_CUNIT_FALSE HAVE_CUNIT_TRUE CUNIT_LIBS CUNIT_CFLAGS ZLIB_LIBS ZLIB_CFLAGS -CXX1XCXXFLAGS HAVE_CXX11 PYTHON_EXTRA_LDFLAGS PYTHON_EXTRA_LIBS @@ -722,10 +706,6 @@ CXXFLAGS CXX CYTHON -PACKAGE_VERSION_NUM -LT_AGE -LT_REVISION -LT_CURRENT AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V @@ -765,7 +745,11 @@ target_vendor target_cpu target -LT_SYS_LIBRARY_PATH +PACKAGE_VERSION_NUM +LT_AGE +LT_REVISION +LT_CURRENT +CPP OTOOL64 OTOOL LIPO @@ -785,7 +769,16 @@ DUMPBIN LD FGREP +EGREP +GREP SED +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC host_os host_vendor host_cpu @@ -795,16 +788,6 @@ build_cpu build LIBTOOL -EGREP -GREP -CPP -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC target_alias host_alias build_alias @@ -824,7 +807,6 @@ docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -851,7 +833,6 @@ enable_static with_pic enable_fast_install -with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock @@ -866,12 +847,9 @@ enable_examples enable_python_bindings enable_failmalloc -enable_lib_only with_libxml2 with_jemalloc with_spdylay -with_mruby -with_neverbleed with_cython with_xml_prefix with_xml_exec_prefix @@ -893,7 +871,6 @@ LIBS CPPFLAGS CPP -LT_SYS_LIBRARY_PATH CYTHON CXX CXXFLAGS @@ -954,7 +931,6 @@ sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1207,15 +1183,6 @@ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1353,7 +1320,7 @@ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1466,7 +1433,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures nghttp2 1.13.0 to adapt to many kinds of systems. +\`configure' configures nghttp2 0.6.7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1506,7 +1473,6 @@ --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1538,7 +1504,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of nghttp2 1.13.0:";; + short | recursive ) echo "Configuration of nghttp2 0.6.7:";; esac cat <<\_ACEOF @@ -1560,17 +1526,14 @@ --enable-werror Turn on compile time warnings --enable-debug Turn on debug output --disable-threads Turn off threading in apps - --enable-app Build applications (nghttp, nghttpd, nghttpx and - h2load) [default=check] + --enable-app Build applications (nghttp, nghttpd and nghttpx) + [default=check] --enable-hpack-tools Build HPACK tools [default=check] --enable-asio-lib Build C++ libnghttp2_asio library [default=no] --enable-examples Build examples [default=check] --enable-python-bindings Build Python bindings [default=check] - --disable-failmalloc Do not build failmalloc test program - --enable-lib-only Build libnghttp2 only. This is a short hand for - --disable-app --disable-examples - --disable-hpack-tools --disable-python-bindings + --enable-failmalloc Build failmalloc test program [default=no] --disable-xmltest Do not try to compile and run a test LIBXML program --disable-assert turn off assertions --disable-largefile omit support for large files @@ -1580,17 +1543,12 @@ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] - --with-aix-soname=aix|svr4|both - shared library versioning (aka "SONAME") variant to - provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-sysroot[=DIR] Search for dependent libraries within DIR (or the - compiler's sysroot if not specified). + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). --with-libxml2 Use libxml2 [default=check] --with-jemalloc Use jemalloc [default=check] --with-spdylay Use spdylay [default=check] - --with-mruby Use mruby [default=no] - --with-neverbleed Use neverbleed [default=no] --with-cython=PATH Use cython in given PATH --with-xml-prefix=PFX Prefix where libxml is installed (optional) --with-xml-exec-prefix=PFX Exec prefix where libxml is installed (optional) @@ -1625,8 +1583,6 @@ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor - LT_SYS_LIBRARY_PATH - User-defined run-time library search path. CYTHON the Cython executable CXX C++ compiler command CXXFLAGS C++ compiler flags @@ -1729,7 +1685,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -nghttp2 configure 1.13.0 +nghttp2 configure 0.6.7 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1781,20 +1737,21 @@ } # ac_fn_c_try_compile -# ac_fn_c_try_cpp LINENO -# ---------------------- -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_cpp () +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 @@ -1802,112 +1759,97 @@ mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_retval=1 + ac_retval=1 fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval -} # ac_fn_c_try_cpp +} # ac_fn_c_try_link -# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- -# Tests whether HEADER exists, giving a warning if it cannot be compiled using -# the include files in INCLUDES and setting the cache variable VAR -# accordingly. -ac_fn_c_check_header_mongrel () +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } else - # Is the header compilable? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 -$as_echo_n "checking $2 usability... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ac_header_compiler=yes + eval "$3=yes" else - ac_header_compiler=no + eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 -$as_echo_n "checking $2 presence... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <$2> -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - ac_header_preproc=yes -else - ac_header_preproc=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( - yes:no: ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; - no:yes:* ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( $as_echo "## ----------------------------------------------- ## -## Report this to t-tujikawa@users.sourceforge.net ## -## ----------------------------------------------- ##" - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval -} # ac_fn_c_check_header_mongrel +} # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- @@ -1951,83 +1893,6 @@ } # ac_fn_c_try_run -# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists and can be compiled using the include files in -# INCLUDES, setting the cache variable VAR accordingly. -ac_fn_c_check_header_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_compile - -# ac_fn_c_try_link LINENO -# ----------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_link - # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly @@ -2216,16 +2081,107 @@ } # ac_fn_cxx_try_link -# ac_fn_c_check_type LINENO TYPE VAR INCLUDES -# ------------------------------------------- -# Tests whether TYPE exists after having included INCLUDES, setting cache -# variable VAR accordingly. -ac_fn_c_check_type () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ----------------------------------------------- ## +## Report this to t-tujikawa@users.sourceforge.net ## +## ----------------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" @@ -2324,82 +2280,6 @@ } # ac_fn_c_find_uintX_t -# ac_fn_c_find_intX_t LINENO BITS VAR -# ----------------------------------- -# Finds a signed integer type with width BITS, setting cache variable VAR -# accordingly. -ac_fn_c_find_intX_t () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 -$as_echo_n "checking for int$2_t... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=no" - # Order is important - never check a type that is potentially smaller - # than half of the expected target width. - for ac_type in int$2_t 'int' 'long int' \ - 'long long int' 'short int' 'signed char'; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default - enum { N = $2 / 2 - 1 }; -int -main () -{ -static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default - enum { N = $2 / 2 - 1 }; -int -main () -{ -static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) - < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - case $ac_type in #( - int$2_t) : - eval "$3=yes" ;; #( - *) : - eval "$3=\$ac_type" ;; -esac -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - if eval test \"x\$"$3"\" = x"no"; then : - -else - break -fi - done -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_find_intX_t - # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including @@ -2456,281 +2336,52 @@ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. -# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES -# -------------------------------------------- -# Tries to find the compile-time value of EXPR in a program that includes -# INCLUDES, setting VAR accordingly. Returns whether the value could be -# computed -ac_fn_c_compute_int () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if test "$cross_compiling" = yes; then - # Depending upon the size, compute the lo and hi bounds. -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -static int test_array [1 - 2 * !(($2) >= 0)]; -test_array [0] = 0; -return test_array [0]; +It was created by nghttp2 $as_me 0.6.7, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ - ; - return 0; -} _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_lo=0 ac_mid=0 - while :; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () +exec 5>>config.log { -static int test_array [1 - 2 * !(($2) <= $ac_mid)]; -test_array [0] = 0; -return test_array [0]; +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_hi=$ac_mid; break -else - as_fn_arith $ac_mid + 1 && ac_lo=$as_val - if test $ac_lo -le $ac_mid; then - ac_lo= ac_hi= - break - fi - as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" done -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -static int test_array [1 - 2 * !(($2) < 0)]; -test_array [0] = 0; -return test_array [0]; +IFS=$as_save_IFS - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_hi=-1 ac_mid=-1 - while :; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -static int test_array [1 - 2 * !(($2) >= $ac_mid)]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_lo=$ac_mid; break -else - as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val - if test $ac_mid -le $ac_hi; then - ac_lo= ac_hi= - break - fi - as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - ac_lo= ac_hi= -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -# Binary search between lo and hi bounds. -while test "x$ac_lo" != "x$ac_hi"; do - as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -static int test_array [1 - 2 * !(($2) <= $ac_mid)]; -test_array [0] = 0; -return test_array [0]; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_hi=$ac_mid -else - as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -done -case $ac_lo in #(( -?*) eval "$3=\$ac_lo"; ac_retval=0 ;; -'') ac_retval=1 ;; -esac - else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -static long int longval () { return $2; } -static unsigned long int ulongval () { return $2; } -#include -#include -int -main () -{ - - FILE *f = fopen ("conftest.val", "w"); - if (! f) - return 1; - if (($2) < 0) - { - long int i = longval (); - if (i != ($2)) - return 1; - fprintf (f, "%ld", i); - } - else - { - unsigned long int i = ulongval (); - if (i != ($2)) - return 1; - fprintf (f, "%lu", i); - } - /* Do not output a trailing newline, as this causes \r\n confusion - on some platforms. */ - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - echo >>conftest.val; read $3 &5 -$as_echo_n "checking whether $as_decl_name is declared... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -#ifndef $as_decl_name -#ifdef __cplusplus - (void) $as_decl_use; -#else - (void) $as_decl_name; -#endif -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_decl -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by nghttp2 $as_me 1.13.0, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" - done -IFS=$as_save_IFS - -} >&5 +} >&5 cat >&5 <<_ACEOF @@ -3037,8 +2688,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + ac_aux_dir= -for ac_dir in . "$srcdir"/.; do +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" @@ -3054,7 +2706,7 @@ fi done if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in . \"$srcdir\"/." "$LINENO" 5 + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, @@ -3066,75 +2718,237 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac -ac_config_headers="$ac_config_headers config.h" -# Expand $ac_aux_dir to an absolute path. -am_aux_dir=`cd "$ac_aux_dir" && pwd` -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : +macro_version='2.4.2' +macro_revision='1.3337' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3920,143 +3734,86 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if ${ac_cv_prog_CPP+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi else - # Broken: fails on valid input. -continue + ac_cv_path_SED=$SED fi -rm -f conftest.err conftest.i conftest.$ac_ext - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break fi -rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - done - ac_cv_prog_CPP=$CPP -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 @@ -4189,437 +3946,613 @@ EGREP="$ac_cv_path_EGREP" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi else - ac_cv_header_stdc=no + ac_cv_path_FGREP=$FGREP fi -rm -f conftest* + fi fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : +test -z "$GREP" && GREP=grep -else - ac_cv_header_stdc=no -fi -rm -f conftest* -fi -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then -$as_echo "#define STDC_HEADERS 1" >>confdefs.h -fi -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF -fi -done - ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" -if test "x$ac_cv_header_minix_config_h" = xyes; then : - MINIX=yes -else - MINIX= -fi - if test "$MINIX" = yes; then -$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h -$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h - - -$as_echo "#define _MINIX 1" >>confdefs.h - - fi - +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 -$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } -if ${ac_cv_safe_to_define___extensions__+:} false; then : +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -# define __EXTENSIONS__ 1 - $ac_includes_default -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_safe_to_define___extensions__=yes + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 -$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } - test $ac_cv_safe_to_define___extensions__ = yes && - $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h - $as_echo "#define _ALL_SOURCE 1" >>confdefs.h - - $as_echo "#define _GNU_SOURCE 1" >>confdefs.h +LD="$lt_cv_path_LD" +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld - $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h - $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h -case `pwd` in - *\ * | *\ *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 -$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; -esac -macro_version='2.4.6' -macro_revision='2.4.6' +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + test -n "$ac_ct_DUMPBIN" && break +done + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm -ltmain=$ac_aux_dir/ltmain.sh -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if ${ac_cv_build+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 - + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if ${ac_cv_host+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 -fi - + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" -# Backslashify metacharacters that are still active within -# double-quoted strings. -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; -ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 -$as_echo_n "checking how to print strings... " >&6; } -# Test print first, because it will be a builtin if present. -if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ - test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='print -r --' -elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='printf %s\n' -else - # Use this function as a fallback that always works. - func_fallback_echo () - { - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' - } - ECHO='func_fallback_echo' -fi + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "" -} + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; -case $ECHO in - printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 -$as_echo "printf" >&6; } ;; - print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 -$as_echo "print -r" >&6; } ;; - *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 -$as_echo "cat" >&6; } ;; -esac + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +fi +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 -$as_echo_n "checking for a sed that does not truncate output... " >&6; } -if ${ac_cv_path_SED+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ - for ac_i in 1 2 3 4 5 6 7; do - ac_script="$ac_script$as_nl$ac_script" - done - echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed - { ac_script=; unset ac_script;} - if test -z "$SED"; then - ac_path_SED_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_SED" || continue -# Check for GNU ac_path_SED and select it if it is found. - # Check for GNU $ac_path_SED -case `"$ac_path_SED" --version 2>&1` in -*GNU*) - ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo '' >> "conftest.nl" - "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_SED_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_SED="$ac_path_SED" - ac_path_SED_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_SED_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_SED"; then - as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 - fi +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset else - ac_cv_path_SED=$SED + lt_unset=false fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 -$as_echo "$ac_cv_path_SED" >&6; } - SED="$ac_cv_path_SED" - rm -f conftest.sed -test -z "$SED" && SED=sed -Xsed="$SED -e 1s/^X//" +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + @@ -4628,84 +4561,109 @@ -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 -$as_echo_n "checking for fgrep... " >&6; } -if ${ac_cv_path_FGREP+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else - if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 - then ac_cv_path_FGREP="$GREP -F" - else - if test -z "$FGREP"; then - ac_path_FGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in fgrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_FGREP" || continue -# Check for GNU ac_path_FGREP and select it if it is found. - # Check for GNU $ac_path_FGREP -case `"$ac_path_FGREP" --version 2>&1` in -*GNU*) - ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'FGREP' >> "conftest.nl" - "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_FGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_FGREP="$ac_path_FGREP" - ac_path_FGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; esac - $ac_path_FGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_FGREP"; then - as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_FGREP=$FGREP fi - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 -$as_echo "$ac_cv_path_FGREP" >&6; } - FGREP="$ac_cv_path_FGREP" +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } -test -z "$GREP" && GREP=grep +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +fi +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac @@ -4715,236 +4673,56 @@ -# Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 else - with_gnu_ld=no -fi - -ac_prog=ld -if test yes = "$GCC"; then - # Check if gcc -print-prog-name=ld gives a path. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 -$as_echo_n "checking for ld used by $CC... " >&6; } - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return, which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [\\/]* | ?:[\\/]*) - re_direlt='/[^/][^/]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD=$ac_prog - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test yes = "$with_gnu_ld"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 -$as_echo_n "checking for GNU ld... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 -$as_echo_n "checking for non-GNU ld... " >&6; } -fi -if ${lt_cv_path_LD+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$LD"; then - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD=$ac_dir/$ac_prog - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &5 -$as_echo "$LD" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 -$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if ${lt_cv_prog_gnu_ld+:} false; then : - $as_echo_n "(cached) " >&6 -else - # I'd rather use --version here, but apparently some GNU lds only accept -v. -case `$LD -v 2>&1 &5 -$as_echo "$lt_cv_prog_gnu_ld" >&6; } -with_gnu_ld=$lt_cv_prog_gnu_ld - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 -$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } -if ${lt_cv_path_NM+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM=$NM -else - lt_nm_to_check=${ac_tool_prefix}nm - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS=$lt_save_ifs - test -z "$ac_dir" && ac_dir=. - tmp_nm=$ac_dir/$lt_tmp_nm - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the 'sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty - case $build_os in - mingw*) lt_bad_file=conftest.nm/nofile ;; - *) lt_bad_file=/dev/null ;; - esac - case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in - *$lt_bad_file* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break 2 - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break 2 - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS=$lt_save_ifs - done - : ${lt_cv_path_NM=no} -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 -$as_echo "$lt_cv_path_NM" >&6; } -if test no != "$lt_cv_path_NM"; then - NM=$lt_cv_path_NM -else - # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$DUMPBIN"; then : - # Let the user override the test. - else - if test -n "$ac_tool_prefix"; then - for ac_prog in dumpbin "link -dump" - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DUMPBIN+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DUMPBIN"; then - ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS fi fi -DUMPBIN=$ac_cv_prog_DUMPBIN -if test -n "$DUMPBIN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 -$as_echo "$DUMPBIN" >&6; } +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - test -n "$DUMPBIN" && break - done fi -if test -z "$DUMPBIN"; then - ac_ct_DUMPBIN=$DUMPBIN - for ac_prog in dumpbin "link -dump" -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$ac_ct_DUMPBIN"; then - ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH @@ -4953,7 +4731,7 @@ test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -4963,21 +4741,17 @@ fi fi -ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN -if test -n "$ac_ct_DUMPBIN"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 -$as_echo "$ac_ct_DUMPBIN" >&6; } +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - - test -n "$ac_ct_DUMPBIN" && break -done - - if test "x$ac_ct_DUMPBIN" = x; then - DUMPBIN=":" + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) @@ -4985,348 +4759,253 @@ $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac - DUMPBIN=$ac_ct_DUMPBIN + OBJDUMP=$ac_ct_OBJDUMP fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" fi - case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in - *COFF*) - DUMPBIN="$DUMPBIN -symbols -headers" - ;; - *) - DUMPBIN=: - ;; - esac - fi +test -z "$OBJDUMP" && OBJDUMP=objdump - if test : != "$DUMPBIN"; then - NM=$DUMPBIN - fi -fi -test -z "$NM" && NM=nm -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 -$as_echo_n "checking the name lister ($NM) interface... " >&6; } -if ${lt_cv_nm_interface+:} false; then : + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else - lt_cv_nm_interface="BSD nm" - echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) - (eval "$ac_compile" 2>conftest.err) - cat conftest.err >&5 - (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) - (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) - cat conftest.err >&5 - (eval echo "\"\$as_me:$LINENO: output\"" >&5) - cat conftest.out >&5 - if $GREP 'External.*some_variable' conftest.out > /dev/null; then - lt_cv_nm_interface="MS dumpbin" - fi - rm -f conftest* -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 -$as_echo "$lt_cv_nm_interface" >&6; } - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 -$as_echo_n "checking whether ln -s works... " >&6; } -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 -$as_echo "no, using $LN_S" >&6; } -fi + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. -# find the maximum length of command line arguments -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 -$as_echo_n "checking the maximum length of command line arguments... " >&6; } -if ${lt_cv_sys_max_cmd_len+:} false; then : - $as_echo_n "(cached) " >&6 -else - i=0 - teststring=ABCD +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; +beos*) + lt_cv_deplibs_check_method=pass_all + ;; - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; - cygwin* | mingw* | cegcc*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; - mint*) - # On MiNT this can take a long time and run out of memory. - lt_cv_sys_max_cmd_len=8192; - ;; +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; - bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; - os2*) - # The test takes a long time on OS/2. - lt_cv_sys_max_cmd_len=8192 - ;; +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len" && \ - test undefined != "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - # Make teststring a little bigger before we do anything with it. - # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8; do - teststring=$teststring$teststring - done - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while { test X`env echo "$teststring$teststring" 2>/dev/null` \ - = "X$teststring$teststring"; } >/dev/null 2>&1 && - test 17 != "$i" # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - # Only check the string length outside the loop. - lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` - teststring= - # Add a significant safety factor because C++ compilers can tack on - # massive amounts of additional arguments before passing them to the - # linker. It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac + ;; -fi - -if test -n "$lt_cv_sys_max_cmd_len"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 -$as_echo "$lt_cv_sys_max_cmd_len" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 -$as_echo "none" >&6; } -fi -max_cmd_len=$lt_cv_sys_max_cmd_len - +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; -: ${CP="cp -f"} -: ${MV="mv -f"} -: ${RM="rm -f"} +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - lt_unset=unset -else - lt_unset=false -fi +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; -# test EBCDIC or ASCII -case `echo X|tr X '\101'` in - A) # ASCII based system - # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr - lt_SP2NL='tr \040 \012' - lt_NL2SP='tr \015\012 \040\040' +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac ;; - *) # EBCDIC based system - lt_SP2NL='tr \100 \n' - lt_NL2SP='tr \r\n \100\100' + +tpf*) + lt_cv_deplibs_check_method=pass_all ;; esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 -$as_echo_n "checking how to convert $build file names to $host format... " >&6; } -if ${lt_cv_to_host_file_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 - ;; - esac - ;; - *-*-cygwin* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin - ;; - esac - ;; - * ) # unhandled hosts (and "normal" native builds) - lt_cv_to_host_file_cmd=func_convert_file_noop +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi ;; -esac - + esac fi -to_host_file_cmd=$lt_cv_to_host_file_cmd -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 -$as_echo "$lt_cv_to_host_file_cmd" >&6; } +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 -$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } -if ${lt_cv_to_tool_file_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - #assume ordinary cross tools, or native build. -lt_cv_to_tool_file_cmd=func_convert_file_noop -case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 - ;; - esac - ;; -esac -fi -to_tool_file_cmd=$lt_cv_to_tool_file_cmd -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 -$as_echo "$lt_cv_to_tool_file_cmd" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 -$as_echo_n "checking for $LD option to reload object files... " >&6; } -if ${lt_cv_ld_reload_flag+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ld_reload_flag='-r' -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 -$as_echo "$lt_cv_ld_reload_flag" >&6; } -reload_flag=$lt_cv_ld_reload_flag -case $reload_flag in -"" | " "*) ;; -*) reload_flag=" $reload_flag" ;; -esac -reload_cmds='$LD$reload_flag -o $output$reload_objs' -case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - if test yes != "$GCC"; then - reload_cmds=false - fi - ;; - darwin*) - if test yes = "$GCC"; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' - else - reload_cmds='$LD$reload_flag -o $output$reload_objs' - fi - ;; -esac @@ -5337,15 +5016,15 @@ if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. -set dummy ${ac_tool_prefix}objdump; ac_word=$2 + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_OBJDUMP+:} false; then : +if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$OBJDUMP"; then - ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH @@ -5354,7 +5033,7 @@ test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5364,10 +5043,10 @@ fi fi -OBJDUMP=$ac_cv_prog_OBJDUMP -if test -n "$OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 -$as_echo "$OBJDUMP" >&6; } +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -5375,17 +5054,17 @@ fi -if test -z "$ac_cv_prog_OBJDUMP"; then - ac_ct_OBJDUMP=$OBJDUMP - # Extract the first word of "objdump", so it can be a program name with args. -set dummy objdump; ac_word=$2 +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$ac_ct_OBJDUMP"; then - ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH @@ -5394,7 +5073,7 @@ test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_OBJDUMP="objdump" + ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5404,17 +5083,17 @@ fi fi -ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP -if test -n "$ac_ct_OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 -$as_echo "$ac_ct_OBJDUMP" >&6; } +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - if test "x$ac_ct_OBJDUMP" = x; then - OBJDUMP="false" + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) @@ -5422,13 +5101,13 @@ $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac - OBJDUMP=$ac_ct_OBJDUMP + DLLTOOL=$ac_ct_DLLTOOL fi else - OBJDUMP="$ac_cv_prog_OBJDUMP" + DLLTOOL="$ac_cv_prog_DLLTOOL" fi -test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$DLLTOOL" && DLLTOOL=dlltool @@ -5438,240 +5117,38 @@ -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 -$as_echo_n "checking how to recognize dependent libraries... " >&6; } -if ${lt_cv_deplibs_check_method+:} false; then : + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else - lt_cv_file_magic_cmd='$MAGIC_CMD' -lt_cv_file_magic_test_file= -lt_cv_deplibs_check_method='unknown' -# Need to set the preceding variable on all platforms that support -# interlibrary dependencies. -# 'none' -- dependencies not supported. -# 'unknown' -- same as none, but documents that we really don't know. -# 'pass_all' -- all dependencies passed with no checks. -# 'test_compile' -- check by making test program. -# 'file_magic [[regex]]' -- check by looking for files in library path -# that responds to the $file_magic_cmd with a given extended regex. -# If you have 'file' or equivalent on your system and you're not sure -# whether 'pass_all' will *always* work, you probably want this one. + lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in -aix[4-9]*) - lt_cv_deplibs_check_method=pass_all +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac ;; - -beos*) - lt_cv_deplibs_check_method=pass_all +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; +esac -bsdi[45]*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' - lt_cv_file_magic_test_file=/shlib/libc.so - ;; - -cygwin*) - # func_win32_libid is a shell function defined in ltmain.sh - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - ;; - -mingw* | pw32*) - # Base MSYS/MinGW do not provide the 'file' command needed by - # func_win32_libid shell function, so use a weaker test based on 'objdump', - # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - # Keep this pattern in sync with the one in func_win32_libid. - lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -cegcc*) - # use the weaker test based on 'objdump'. See mingw*. - lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -haiku*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[3-9]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd* | netbsdelf*-gnu) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -*nto* | *qnx*) - lt_cv_deplibs_check_method=pass_all - ;; - -openbsd* | bitrig*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -tpf*) - lt_cv_deplibs_check_method=pass_all - ;; -os2*) - lt_cv_deplibs_check_method=pass_all - ;; -esac - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 -$as_echo "$lt_cv_deplibs_check_method" >&6; } - -file_magic_glob= -want_nocaseglob=no -if test "$build" = "$host"; then - case $host_os in - mingw* | pw32*) - if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then - want_nocaseglob=yes - else - file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` - fi - ;; - esac -fi - -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - - - - - - - - - - - - - - +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO @@ -5681,15 +5158,17 @@ if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. -set dummy ${ac_tool_prefix}dlltool; ac_word=$2 + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DLLTOOL+:} false; then : +if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$DLLTOOL"; then - ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH @@ -5698,7 +5177,7 @@ test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5708,28 +5187,32 @@ fi fi -DLLTOOL=$ac_cv_prog_DLLTOOL -if test -n "$DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 -$as_echo "$DLLTOOL" >&6; } +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi + test -n "$AR" && break + done fi -if test -z "$ac_cv_prog_DLLTOOL"; then - ac_ct_DLLTOOL=$DLLTOOL - # Extract the first word of "dlltool", so it can be a program name with args. -set dummy dlltool; ac_word=$2 +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : +if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$ac_ct_DLLTOOL"; then - ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH @@ -5738,7 +5221,7 @@ test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_DLLTOOL="dlltool" + ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5748,17 +5231,21 @@ fi fi -ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL -if test -n "$ac_ct_DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 -$as_echo "$ac_ct_DLLTOOL" >&6; } +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - if test "x$ac_ct_DLLTOOL" = x; then - DLLTOOL="false" + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" else case $cross_compiling:$ac_tool_warned in yes:) @@ -5766,163 +5253,12 @@ $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac - DLLTOOL=$ac_ct_DLLTOOL + AR=$ac_ct_AR fi -else - DLLTOOL="$ac_cv_prog_DLLTOOL" fi -test -z "$DLLTOOL" && DLLTOOL=dlltool - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 -$as_echo_n "checking how to associate runtime and link libraries... " >&6; } -if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_sharedlib_from_linklib_cmd='unknown' - -case $host_os in -cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh; - # decide which one to use based on capabilities of $DLLTOOL - case `$DLLTOOL --help 2>&1` in - *--identify-strict*) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib - ;; - *) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback - ;; - esac - ;; -*) - # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd=$ECHO - ;; -esac - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 -$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } -sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd -test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO - - - - - - - -if test -n "$ac_tool_prefix"; then - for ac_prog in ar - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AR="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AR" && break - done -fi -if test -z "$AR"; then - ac_ct_AR=$AR - for ac_prog in ar -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_AR"; then - ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_AR="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_AR=$ac_cv_prog_ac_ct_AR -if test -n "$ac_ct_AR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -$as_echo "$ac_ct_AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_AR" && break -done - - if test "x$ac_ct_AR" = x; then - AR="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - AR=$ac_ct_AR - fi -fi - -: ${AR=ar} -: ${AR_FLAGS=cru} +: ${AR=ar} +: ${AR_FLAGS=cru} @@ -5959,7 +5295,7 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - if test 0 -eq "$ac_status"; then + if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 @@ -5967,7 +5303,7 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - if test 0 -ne "$ac_status"; then + if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi @@ -5980,7 +5316,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } -if test no = "$lt_cv_ar_at_file"; then +if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file @@ -6197,7 +5533,7 @@ if test -n "$RANLIB"; then case $host_os in - bitrig* | openbsd*) + openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) @@ -6329,7 +5665,7 @@ symcode='[ABCDGISTW]' ;; hpux*) - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; @@ -6362,44 +5698,14 @@ symcode='[ABCDGIRSTW]' ;; esac -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Gets list of data symbols to import. - lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" - # Adjust the below global symbol transforms to fixup imported variables. - lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" - lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" - lt_c_name_lib_hook="\ - -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ - -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" -else - # Disable hooks by default. - lt_cv_sys_global_symbol_to_import= - lt_cdecl_hook= - lt_c_name_hook= - lt_c_name_lib_hook= -fi - # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n"\ -$lt_cdecl_hook\ -" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ -$lt_c_name_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" - -# Transform an extracted symbol line into symbol name with lib prefix and -# symbol address. -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ -$lt_c_name_lib_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -6417,24 +5723,21 @@ # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function, - # D for any global variable and I for any imported variable. + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ -" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ -" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ -" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ -" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ -" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" @@ -6482,11 +5785,11 @@ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE -/* DATA imports from DLLs on WIN32 can't be const, because runtime +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST -#elif defined __osf__ +#elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else @@ -6512,7 +5815,7 @@ { { "@PROGRAM@", (void *) 0 }, _LT_EOF - $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; @@ -6532,13 +5835,13 @@ mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS - LIBS=conftstm.$ac_objext + LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest$ac_exeext; then + test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS @@ -6559,7 +5862,7 @@ rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. - if test yes = "$pipe_works"; then + if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= @@ -6612,16 +5915,6 @@ - - - - - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } @@ -6634,9 +5927,9 @@ lt_sysroot= -case $with_sysroot in #( +case ${with_sysroot} in #( yes) - if test yes = "$GCC"; then + if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( @@ -6646,8 +5939,8 @@ no|'') ;; #( *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 -$as_echo "$with_sysroot" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac @@ -6659,99 +5952,18 @@ -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 -$as_echo_n "checking for a working dd... " >&6; } -if ${ac_cv_path_lt_DD+:} false; then : - $as_echo_n "(cached) " >&6 -else - printf 0123456789abcdef0123456789abcdef >conftest.i -cat conftest.i conftest.i >conftest2.i -: ${lt_DD:=$DD} -if test -z "$lt_DD"; then - ac_path_lt_DD_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in dd; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_lt_DD" || continue -if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: -fi - $ac_path_lt_DD_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_lt_DD"; then - : - fi -else - ac_cv_path_lt_DD=$lt_DD -fi - -rm -f conftest.i conftest2.i conftest.out -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 -$as_echo "$ac_cv_path_lt_DD" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 -$as_echo_n "checking how to truncate binary pipes... " >&6; } -if ${lt_cv_truncate_bin+:} false; then : - $as_echo_n "(cached) " >&6 -else - printf 0123456789abcdef0123456789abcdef >conftest.i -cat conftest.i conftest.i >conftest2.i -lt_cv_truncate_bin= -if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" -fi -rm -f conftest.i conftest2.i conftest.out -test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 -$as_echo "$lt_cv_truncate_bin" >&6; } - - - - - - - -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in $*""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} - # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi -test no = "$enable_libtool_lock" || enable_libtool_lock=yes +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) - # Find out what ABI is being produced by ac_compile, and set mode - # options accordingly. + # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -6760,25 +5972,24 @@ test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) - HPUX_IA64_MODE=32 + HPUX_IA64_MODE="32" ;; *ELF-64*) - HPUX_IA64_MODE=64 + HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. + # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - if test yes = "$lt_cv_prog_gnu_ld"; then + if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" @@ -6807,50 +6018,9 @@ rm -rf conftest* ;; -mips64*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo '#line '$LINENO' "configure"' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - emul=elf - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - emul="${emul}32" - ;; - *64-bit*) - emul="${emul}64" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *MSB*) - emul="${emul}btsmip" - ;; - *LSB*) - emul="${emul}ltsmip" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *N32*) - emul="${emul}n32" - ;; - esac - LD="${LD-ld} -m $emul" - fi - rm -rf conftest* - ;; - x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. Note that the listed cases only cover the - # situations where additional linker options are needed (such as when - # doing 32-bit compilation for a host where ld defaults to 64-bit, or - # vice versa); the common cases where no linker options are needed do - # not appear in the list. + # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -6873,10 +6043,10 @@ ;; esac ;; - powerpc64le-*linux*) + powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; - powerpc64-*linux*) + powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -6895,10 +6065,10 @@ x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - powerpcle-*linux*) + powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; - powerpc-*linux*) + powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -6916,7 +6086,7 @@ *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS=$CFLAGS + SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } @@ -6956,14 +6126,13 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } - if test yes != "$lt_cv_cc_needs_belf"; then + if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS=$SAVE_CFLAGS + CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. + # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -6975,7 +6144,7 @@ case $lt_cv_prog_gnu_ld in yes*) case $host in - i?86-*-solaris*|x86_64-*-solaris*) + i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) @@ -6984,7 +6153,7 @@ esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD=${LD-ld}_sol2 + LD="${LD-ld}_sol2" fi ;; *) @@ -7000,7 +6169,7 @@ ;; esac -need_locks=$enable_libtool_lock +need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. @@ -7111,7 +6280,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } -if test yes != "$lt_cv_path_mainfest_tool"; then +if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi @@ -7614,7 +6783,7 @@ $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no - if test -z "$LT_MULTI_MODULE"; then + if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the @@ -7632,7 +6801,7 @@ cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. - elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 @@ -7671,7 +6840,7 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS + LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 @@ -7700,7 +6869,7 @@ _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 - elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&5 @@ -7713,32 +6882,32 @@ $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) - _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; - 10.[012][,.]*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac - if test yes = "$lt_cv_apple_cc_single_mod"; then + if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi - if test yes = "$lt_cv_ld_exported_symbols_list"; then - _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi - if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -7746,235 +6915,417 @@ ;; esac -# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x$2 in - x) - ;; - *:) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" - ;; - x:*) - eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" - ;; - *) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" - ;; - esac -} - -for ac_header in dlfcn.h -do : - ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default -" -if test "x$ac_cv_header_dlfcn_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_DLFCN_H 1 -_ACEOF - +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : -done - - - - - -# Set options - - - - enable_dlopen=no - - - enable_win32_dll=no - - - # Check whether --enable-shared was given. -if test "${enable_shared+set}" = set; then : - enableval=$enable_shared; p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS=$lt_save_ifs - ;; - esac else - enable_shared=yes + # Broken: fails on valid input. +continue fi +rm -f conftest.err conftest.i conftest.$ac_ext - - - - - - - - - # Check whether --enable-static was given. -if test "${enable_static+set}" = set; then : - enableval=$enable_static; p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS=$lt_save_ifs - ;; - esac + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue else - enable_static=yes + # Passes both tests. +ac_preproc_ok=: +break fi +rm -f conftest.err conftest.i conftest.$ac_ext +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + done + ac_cv_prog_CPP=$CPP +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : - - - - - - -# Check whether --with-pic was given. -if test "${with_pic+set}" = set; then : - withval=$with_pic; lt_p=${PACKAGE-default} - case $withval in - yes|no) pic_mode=$withval ;; - *) - pic_mode=default - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for lt_pkg in $withval; do - IFS=$lt_save_ifs - if test "X$lt_pkg" = "X$lt_p"; then - pic_mode=yes - fi - done - IFS=$lt_save_ifs - ;; - esac else - pic_mode=default + # Broken: fails on valid input. +continue fi +rm -f conftest.err conftest.i conftest.$ac_ext + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +int +main () +{ - # Check whether --enable-fast-install was given. -if test "${enable_fast_install+set}" = set; then : - enableval=$enable_fast_install; p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for pkg in $enableval; do - IFS=$lt_save_ifs - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS=$lt_save_ifs - ;; - esac + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes else - enable_fast_install=yes + ac_cv_header_stdc=no fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : +else + ac_cv_header_stdc=no +fi +rm -f conftest* +fi +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : - - shared_archive_member_spec= -case $host,$enable_shared in -power*-*-aix[5-9]*,yes) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 -$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } - -# Check whether --with-aix-soname was given. -if test "${with_aix_soname+set}" = set; then : - withval=$with_aix_soname; case $withval in - aix|svr4|both) - ;; - *) - as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 - ;; - esac - lt_cv_with_aix_soname=$with_aix_soname else - if ${lt_cv_with_aix_soname+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_with_aix_soname=aix + ac_cv_header_stdc=no fi +rm -f conftest* - with_aix_soname=$lt_cv_with_aix_soname fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 -$as_echo "$with_aix_soname" >&6; } - if test aix != "$with_aix_soname"; then - # For the AIX way of multilib, we name the shared archive member - # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', - # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. - # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, - # the AIX toolchain works better with OBJECT_MODE set (default 32). - if test 64 = "${OBJECT_MODE-32}"; then - shared_archive_member_spec=shr_64 - else - shared_archive_member_spec=shr - fi - fi - ;; -*) - with_aix_soname=aix - ;; -esac +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for lt_pkg in $withval; do + IFS="$lt_save_ifs" + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + @@ -7986,7 +7337,7 @@ # This can be used to rebuild libtool when needed -LIBTOOL_DEPS=$ltmain +LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' @@ -8035,7 +7386,7 @@ -if test -n "${ZSH_VERSION+set}"; then +if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi @@ -8074,7 +7425,7 @@ # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. - if test set != "${COLLECT_NAMES+set}"; then + if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -8085,14 +7436,14 @@ ofile=libtool can_build_shared=yes -# All known linkers require a '.a' archive for static linking (except MSVC, +# All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a -with_gnu_ld=$lt_cv_prog_gnu_ld +with_gnu_ld="$lt_cv_prog_gnu_ld" -old_CC=$CC -old_CFLAGS=$CFLAGS +old_CC="$CC" +old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc @@ -8101,8 +7452,15 @@ test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o -func_cc_basename $compiler -cc_basename=$func_cc_basename_result +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it @@ -8117,22 +7475,22 @@ else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD=$MAGIC_CMD - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/${ac_tool_prefix}file"; then - lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD=$lt_cv_path_MAGIC_CMD + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -8155,13 +7513,13 @@ break fi done - IFS=$lt_save_ifs - MAGIC_CMD=$lt_save_MAGIC_CMD + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi -MAGIC_CMD=$lt_cv_path_MAGIC_CMD +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } @@ -8183,22 +7541,22 @@ else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD=$MAGIC_CMD - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/file"; then - lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD=$lt_cv_path_MAGIC_CMD + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -8221,13 +7579,13 @@ break fi done - IFS=$lt_save_ifs - MAGIC_CMD=$lt_save_MAGIC_CMD + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi -MAGIC_CMD=$lt_cv_path_MAGIC_CMD +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } @@ -8248,7 +7606,7 @@ # Use C for the default configuration in the libtool script -lt_save_CC=$CC +lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -8310,7 +7668,7 @@ lt_prog_compiler_no_builtin_flag= -if test yes = "$GCC"; then +if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; @@ -8326,7 +7684,7 @@ lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -8356,7 +7714,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } -if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : @@ -8374,18 +7732,17 @@ lt_prog_compiler_static= - if test yes = "$GCC"; then + if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi - lt_prog_compiler_pic='-fPIC' ;; amigaos*) @@ -8396,8 +7753,8 @@ ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -8413,11 +7770,6 @@ # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' - case $host_os in - os2*) - lt_prog_compiler_static='$wl-static' - ;; - esac ;; darwin* | rhapsody*) @@ -8488,7 +7840,7 @@ case $host_os in aix*) lt_prog_compiler_wl='-Wl,' - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else @@ -8496,29 +7848,10 @@ fi ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic='-fno-common' - case $cc_basename in - nagfor*) - # NAG Fortran compiler - lt_prog_compiler_wl='-Wl,-Wl,,' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - esac - ;; - mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' - case $host_os in - os2*) - lt_prog_compiler_static='$wl-static' - ;; - esac ;; hpux9* | hpux10* | hpux11*) @@ -8534,7 +7867,7 @@ ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='$wl-a ${wl}archive' + lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) @@ -8545,7 +7878,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in - # old Intel for x86_64, which still supported -KPIC. + # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' @@ -8570,12 +7903,6 @@ lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) @@ -8673,7 +8000,7 @@ ;; sysv4*MP*) - if test -d /usr/nec; then + if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi @@ -8702,7 +8029,7 @@ fi case $host_os in - # For platforms that do not support PIC, -DPIC is meaningless: + # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; @@ -8734,7 +8061,7 @@ lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -8764,7 +8091,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } -if test yes = "$lt_cv_prog_compiler_pic_works"; then +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; @@ -8796,7 +8123,7 @@ $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no - save_LDFLAGS=$LDFLAGS + save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -8815,13 +8142,13 @@ fi fi $RM -r conftest* - LDFLAGS=$save_LDFLAGS + LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } -if test yes = "$lt_cv_prog_compiler_static_works"; then +if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= @@ -8941,8 +8268,8 @@ -hard_links=nottested -if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } @@ -8954,9 +8281,9 @@ ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } - if test no = "$hard_links"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else @@ -8999,9 +8326,9 @@ # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ' (' and ')$', so one must not match beginning or - # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', - # as well as any symbol that contains 'd'. + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if @@ -9016,7 +8343,7 @@ # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. - if test yes != "$GCC"; then + if test "$GCC" != yes; then with_gnu_ld=no fi ;; @@ -9024,7 +8351,7 @@ # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; - openbsd* | bitrig*) + openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) @@ -9037,7 +8364,7 @@ # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no - if test yes = "$with_gnu_ld"; then + if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility @@ -9059,24 +8386,24 @@ esac fi - if test yes = "$lt_use_gnu_ld_interface"; then + if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='$wl' + wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - export_dynamic_flag_spec='$wl--export-dynamic' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no - case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... @@ -9089,7 +8416,7 @@ case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken - if test ia64 != "$host_cpu"; then + if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 @@ -9108,7 +8435,7 @@ case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -9124,7 +8451,7 @@ allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi @@ -9134,7 +8461,7 @@ # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' - export_dynamic_flag_spec='$wl--export-all-symbols' + export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes @@ -9142,89 +8469,61 @@ exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - shrext_cmds=.dll - archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - enable_shared_with_static_runtimes=yes - ;; - interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='$wl-rpath,$libdir' - export_dynamic_flag_spec='$wl-E' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no - if test linux-dietlibc = "$host_os"; then + if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test no = "$tmp_diet" + && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -9235,47 +8534,42 @@ lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; - nagfor*) # NAGFOR 5.3 - tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 - whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac - archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test yes = "$supports_anon_versioning"; then + if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in - tcc*) - export_dynamic_flag_spec='-rdynamic' - ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test yes = "$supports_anon_versioning"; then + if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -9289,8 +8583,8 @@ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -9308,8 +8602,8 @@ _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -9321,7 +8615,7 @@ ld_shlibs=no cat <<_LT_EOF 1>&2 -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify @@ -9336,9 +8630,9 @@ # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -9355,15 +8649,15 @@ *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac - if test no = "$ld_shlibs"; then + if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= @@ -9379,7 +8673,7 @@ # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes - if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported @@ -9387,57 +8681,34 @@ ;; aix[4-9]*) - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag= + no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive + # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do - if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi ;; esac @@ -9456,21 +8727,13 @@ hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes - file_list_spec='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # traditional, no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - hardcode_direct=no - hardcode_direct_absolute=no - ;; - esac + file_list_spec='${wl}-f,' - if test yes = "$GCC"; then + if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` + collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -9489,42 +8752,36 @@ ;; esac shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag="$shared_flag "'$wl-G' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' + link_all_deplibs=no else # not using gcc - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' else - shared_flag='$wl-bM:SRE' + shared_flag='${wl}-bM:SRE' fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' fi fi - export_dynamic_flag_spec='$wl-bexpall' + export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. - if test set = "${lt_cv_aix_libpath+set}"; then + if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : @@ -9559,7 +8816,7 @@ rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=/usr/lib:/lib + lt_cv_aix_libpath_="/usr/lib:/lib" fi fi @@ -9567,17 +8824,17 @@ aix_libpath=$lt_cv_aix_libpath_ fi - hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else - if test ia64 = "$host_cpu"; then - hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. - if test set = "${lt_cv_aix_libpath+set}"; then + if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : @@ -9612,7 +8869,7 @@ rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=/usr/lib:/lib + lt_cv_aix_libpath_="/usr/lib:/lib" fi fi @@ -9620,33 +8877,21 @@ aix_libpath=$lt_cv_aix_libpath_ fi - hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - no_undefined_flag=' $wl-bernotok' - allow_undefined_flag=' $wl-berok' - if test yes = "$with_gnu_ld"; then + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes - archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; @@ -9655,7 +8900,7 @@ case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -9685,17 +8930,16 @@ # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll + shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes @@ -9704,18 +8948,18 @@ # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # Assume MSVC wrapper @@ -9724,7 +8968,7 @@ # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll + shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. @@ -9743,24 +8987,24 @@ hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported - if test yes = "$lt_cv_ld_force_load"; then - whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes - allow_undefined_flag=$_lt_dar_allow_undefined + allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in - ifort*|nagfor*) _lt_dar_can_shared=yes ;; + ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test yes = "$_lt_dar_can_shared"; then + if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all - archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" - module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no @@ -9802,33 +9046,33 @@ ;; hpux9*) - if test yes = "$GCC"; then - archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else - archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi - hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes - export_dynamic_flag_spec='$wl-E' + export_dynamic_flag_spec='${wl}-E' ;; hpux10*) - if test yes,no = "$GCC,$with_gnu_ld"; then - archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi - if test no = "$with_gnu_ld"; then - hardcode_libdir_flag_spec='$wl+b $wl$libdir' + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='$wl-E' + export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes @@ -9836,25 +9080,25 @@ ;; hpux11*) - if test yes,no = "$GCC,$with_gnu_ld"; then + if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) - archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) - archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) @@ -9866,7 +9110,7 @@ $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no - save_LDFLAGS=$LDFLAGS + save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -9885,14 +9129,14 @@ fi fi $RM -r conftest* - LDFLAGS=$save_LDFLAGS + LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } -if test yes = "$lt_cv_prog_compiler__b"; then - archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi @@ -9900,8 +9144,8 @@ ;; esac fi - if test no = "$with_gnu_ld"; then - hardcode_libdir_flag_spec='$wl+b $wl$libdir' + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in @@ -9912,7 +9156,7 @@ *) hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='$wl-E' + export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. @@ -9923,8 +9167,8 @@ ;; irix5* | irix6* | nonstopux*) - if test yes = "$GCC"; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + if test "$GCC" = yes; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. @@ -9934,8 +9178,8 @@ if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } @@ -9947,35 +9191,24 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS + LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } - if test yes = "$lt_cv_irix_exported_symbol"; then - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi - link_all_deplibs=no else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; - linux*) - case $cc_basename in - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - ld_shlibs=yes - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out @@ -9990,7 +9223,7 @@ newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; @@ -9998,19 +9231,27 @@ *nto* | *qnx*) ;; - openbsd* | bitrig*) + openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='$wl-rpath,$libdir' - export_dynamic_flag_spec='$wl-E' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' else - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='$wl-rpath,$libdir' + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac fi else ld_shlibs=no @@ -10021,53 +9262,33 @@ hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported - shrext_cmds=.dll - archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - enable_shared_with_static_runtimes=yes + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) - if test yes = "$GCC"; then - allow_undefined_flag=' $wl-expect_unresolved $wl\*' - archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag - if test yes = "$GCC"; then - allow_undefined_flag=' $wl-expect_unresolved $wl\*' - archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' @@ -10078,24 +9299,24 @@ solaris*) no_undefined_flag=' -z defs' - if test yes = "$GCC"; then - wlarc='$wl' - archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' - archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) - wlarc='$wl' - archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi @@ -10105,11 +9326,11 @@ solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. GCC discards it without '$wl', + # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - if test yes = "$GCC"; then - whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi @@ -10119,10 +9340,10 @@ ;; sunos4*) - if test sequent = "$host_vendor"; then + if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. - archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -10171,43 +9392,43 @@ ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag='$wl-z,text' + no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' - if test yes = "$GCC"; then - archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not + # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - no_undefined_flag='$wl-z,text' - allow_undefined_flag='$wl-z,nodefs' + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes - export_dynamic_flag_spec='$wl-Bexport' + export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' - if test yes = "$GCC"; then - archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; @@ -10222,10 +9443,10 @@ ;; esac - if test sni = "$host_vendor"; then + if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - export_dynamic_flag_spec='$wl-Blargedynsym' + export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi @@ -10233,7 +9454,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } -test no = "$ld_shlibs" && can_build_shared=no +test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld @@ -10259,7 +9480,7 @@ # Assume -lc should be added archive_cmds_need_lc=yes - if test yes,yes = "$GCC,$enable_shared"; then + if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -10474,14 +9695,14 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } -if test yes = "$GCC"; then +if test "$GCC" = yes; then case $host_os in - darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; - *) lt_awk_arg='/^libraries:/' ;; + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in - mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; - *) lt_sed_strip_eq='s|=/|/|g' ;; + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in @@ -10497,35 +9718,28 @@ ;; esac # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary... + # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= - lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - # ...but if some path component already ends with the multilib dir we assume - # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). - case "$lt_multi_os_dir; $lt_search_path_spec " in - "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) - lt_multi_os_dir= - ;; - esac + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" - elif test -n "$lt_multi_os_dir"; then + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS = " "; FS = "/|\n";} { - lt_foo = ""; - lt_count = 0; +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { - lt_foo = "/" $lt_i lt_foo; + lt_foo="/" $lt_i lt_foo; } else { lt_count--; } @@ -10539,7 +9753,7 @@ # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else @@ -10548,7 +9762,7 @@ library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=.so +shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -10565,16 +9779,14 @@ # flags to be left without arguments need_version=unknown - - case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='$libname$release$shared_ext$major' + soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) @@ -10582,91 +9794,41 @@ need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 supports IA64 - library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line '#! .'. This would cause the generated library to - # depend on '.', always an invalid library. This was fixed in + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # Using Import Files as archive members, it is possible to support - # filename-based versioning of shared library archives on AIX. While - # this would work for both with and without runtime linking, it will - # prevent static linking of such archives. So we do filename-based - # shared library versioning with .so extension only, which is used - # when both runtime linking and shared linking is enabled. - # Unfortunately, runtime linking may impact performance, so we do - # not want this to be the default eventually. Also, we use the - # versioned .so libs for executables only if there is the -brtl - # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. - # To allow for filename-based versioning support, we need to create - # libNAME.so.V as an archive file, containing: - # *) an Import File, referring to the versioned filename of the - # archive as well as the shared archive member, telling the - # bitwidth (32 or 64) of that shared object, and providing the - # list of exported symbols of that shared object, eventually - # decorated with the 'weak' keyword - # *) the shared object with the F_LOADONLY flag set, to really avoid - # it being seen by the linker. - # At run time we better use the real file rather than another symlink, - # but for link time we create the symlink libNAME.so -> libNAME.so.V - - case $with_aix_soname,$aix_use_runtimelinking in - # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - aix,yes) # traditional libtool - dynamic_linker='AIX unversionable lib.so' + if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - aix,no) # traditional AIX only - dynamic_linker='AIX lib.a(lib.so.V)' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - ;; - svr4,*) # full svr4 only - dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,yes) # both, prefer svr4 - dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # unpreferred sharedlib libNAME.a needs extra handling - postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' - postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,no) # both, prefer aix - dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling - postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' - postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' - ;; - esac + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi shlibpath_var=LIBPATH fi ;; @@ -10676,18 +9838,18 @@ powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='$libname$shared_ext' + library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; @@ -10695,8 +9857,8 @@ bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -10708,7 +9870,7 @@ cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=.dll + shrext_cmds=".dll" need_version=no need_lib_prefix=no @@ -10717,8 +9879,8 @@ # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -10734,17 +9896,17 @@ case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' @@ -10753,8 +9915,8 @@ *,cl*) # Native MSVC libname_spec='$name' - soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - library_names_spec='$libname.dll.lib' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' case $build_os in mingw*) @@ -10781,7 +9943,7 @@ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) - sys_lib_search_path_spec=$LIB + sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` @@ -10794,8 +9956,8 @@ esac # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' @@ -10808,7 +9970,7 @@ *) # Assume MSVC wrapper - library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac @@ -10821,8 +9983,8 @@ version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' - soname_spec='$libname$release$major$shared_ext' + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -10835,8 +9997,8 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -10854,13 +10016,12 @@ version_type=freebsd-$objformat case $version_type in freebsd-elf*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac @@ -10890,10 +10051,10 @@ need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=no + shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -10911,15 +10072,14 @@ dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - if test 32 = "$HPUX_IA64_MODE"; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -10927,8 +10087,8 @@ dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -10937,8 +10097,8 @@ dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... @@ -10951,8 +10111,8 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -10963,7 +10123,7 @@ case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test yes = "$lt_cv_prog_gnu_ld"; then + if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix @@ -10971,8 +10131,8 @@ esac need_lib_prefix=no need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -10991,8 +10151,8 @@ esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" - sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; @@ -11001,33 +10161,13 @@ dynamic_linker=no ;; -linux*android*) - version_type=none # Android doesn't support versioned libraries. - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext' - soname_spec='$libname$release$shared_ext' - finish_cmds= - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - dynamic_linker='Android linker' - # Don't embed -rpath directories since the linker doesn't support them. - hardcode_libdir_flag_spec='-L$libdir' - ;; - # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -11071,12 +10211,7 @@ # before this can be enabled. hardcode_into_libs=yes - # Ideally, we could use ldconfig to report *all* directores which are - # searched for libraries, however this is still not possible. Aside from not - # being certain /sbin/ldconfig is available, command - # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, - # even though it is searched at run-time. Try to do the best guess by - # appending ld.so.conf contents (and includes) to the search path. + # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" @@ -11108,12 +10243,12 @@ need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -11123,7 +10258,7 @@ newsos6) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -11132,68 +10267,58 @@ version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd* | bitrig*) +openbsd*) version_type=sunos - sys_lib_dlsearch_path_spec=/usr/lib + sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - need_version=no - else - need_version=yes - fi - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi ;; os2*) libname_spec='$name' - version_type=windows - shrext_cmds=.dll - need_version=no + shrext_cmds=".dll" need_lib_prefix=no - # OS/2 can only load a DLL with a base name of 8 characters or less. - soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; - v=$($ECHO $release$versuffix | tr -d .-); - n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); - $ECHO $n$v`$shared_ext' - library_names_spec='${libname}_dll.$libext' + library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' - shlibpath_var=BEGINLIBPATH - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' + shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) @@ -11204,8 +10329,8 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -11215,11 +10340,11 @@ sunos4*) version_type=sunos - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test yes = "$with_gnu_ld"; then + if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes @@ -11227,8 +10352,8 @@ sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -11249,24 +10374,24 @@ ;; sysv4*MP*) - if test -d /usr/nec; then + if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' - soname_spec='$libname$shared_ext.$major' + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=sco + version_type=freebsd-elf need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test yes = "$with_gnu_ld"; then + if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -11284,7 +10409,7 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes @@ -11292,8 +10417,8 @@ uts4*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -11303,35 +10428,20 @@ esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } -test no = "$dynamic_linker" && can_build_shared=no +test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test yes = "$GCC"; then +if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then - sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi - -if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then - sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi -# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... -configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec - -# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code -func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" - -# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool -configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH - - - - - - @@ -11428,15 +10538,15 @@ hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || - test yes = "$hardcode_automatic"; then + test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. - if test no != "$hardcode_direct" && + if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && - test no != "$hardcode_minus_L"; then + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else @@ -11451,12 +10561,12 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } -if test relink = "$hardcode_action" || - test yes = "$inherit_rpath"; then +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no -elif test yes = "$shlibpath_overrides_runpath" || - test no = "$enable_shared"; then +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi @@ -11466,7 +10576,7 @@ - if test yes != "$enable_dlopen"; then + if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown @@ -11476,23 +10586,23 @@ case $host_os in beos*) - lt_cv_dlopen=load_add_on + lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) - lt_cv_dlopen=LoadLibrary + lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) - lt_cv_dlopen=dlopen + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) - # if libdl is installed we need to link against it + # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : @@ -11530,10 +10640,10 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else - lt_cv_dlopen=dyld + lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes @@ -11541,18 +10651,10 @@ ;; - tpf*) - # Don't try to run any link tests for TPF. We know it's impossible - # because TPF is a cross-compiler, and we know how we open DSOs. - lt_cv_dlopen=dlopen - lt_cv_dlopen_libs= - lt_cv_dlopen_self=no - ;; - *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : - lt_cv_dlopen=shl_load + lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } @@ -11591,11 +10693,11 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : - lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : - lt_cv_dlopen=dlopen + lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } @@ -11634,7 +10736,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } @@ -11673,7 +10775,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : - lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } @@ -11712,7 +10814,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : - lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi @@ -11733,21 +10835,21 @@ ;; esac - if test no = "$lt_cv_dlopen"; then - enable_dlopen=no - else + if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes + else + enable_dlopen=no fi case $lt_cv_dlopen in dlopen) - save_CPPFLAGS=$CPPFLAGS - test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - save_LDFLAGS=$LDFLAGS + save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - save_LIBS=$LIBS + save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 @@ -11755,7 +10857,7 @@ if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else - if test yes = "$cross_compiling"; then : + if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -11802,9 +10904,9 @@ # endif #endif -/* When -fvisibility=hidden is used, assume the code has been annotated +/* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -11834,7 +10936,7 @@ (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -11854,14 +10956,14 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } - if test yes = "$lt_cv_dlopen_self"; then + if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else - if test yes = "$cross_compiling"; then : + if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -11908,9 +11010,9 @@ # endif #endif -/* When -fvisibility=hidden is used, assume the code has been annotated +/* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -11940,7 +11042,7 @@ (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -11961,9 +11063,9 @@ $as_echo "$lt_cv_dlopen_self_static" >&6; } fi - CPPFLAGS=$save_CPPFLAGS - LDFLAGS=$save_LDFLAGS - LIBS=$save_LIBS + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" ;; esac @@ -12007,7 +11109,7 @@ # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) - if test -n "$STRIP"; then + if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 @@ -12035,7 +11137,7 @@ - # Report what library types will actually be built + # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 @@ -12043,13 +11145,13 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } - test no = "$can_build_shared" && enable_shared=no + test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test yes = "$enable_shared" && enable_static=no + test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' @@ -12057,12 +11159,8 @@ ;; aix[4-9]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no fi ;; esac @@ -12072,7 +11170,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes + test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } @@ -12086,7 +11184,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -CC=$lt_save_CC +CC="$lt_save_CC" @@ -12110,6 +11208,20 @@ # Only expand once: +LT_CURRENT=7 + +LT_REVISION=2 + +LT_AGE=2 + + +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"` + + @@ -12153,7 +11265,9 @@ NONENONEs,x,x, && program_prefix=${target_alias}- -am__api_version='1.15' + + +am__api_version='1.14' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -12342,7 +11456,7 @@ $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi -if test x"${install_sh+set}" != xset; then +if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -12657,7 +11771,7 @@ # Define the identity of the package. PACKAGE='nghttp2' - VERSION='1.13.0' + VERSION='0.6.7' cat >>confdefs.h <<_ACEOF @@ -12691,8 +11805,8 @@ # mkdir_p='$(MKDIR_P)' -# We need awk for the "check" target (and possibly the TAP driver). The -# system "awk" is bad on some platforms. +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' @@ -12919,19 +12033,7 @@ AM_BACKSLASH='\' -LT_CURRENT=23 - -LT_REVISION=0 - -LT_AGE=9 - - -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_config_headers="$ac_config_headers config.h" # Check whether --enable-werror was given. @@ -13002,15 +12104,7 @@ if test "${enable_failmalloc+set}" = set; then : enableval=$enable_failmalloc; request_failmalloc=$enableval else - request_failmalloc=yes -fi - - -# Check whether --enable-lib-only was given. -if test "${enable_lib_only+set}" = set; then : - enableval=$enable_lib_only; request_lib_only=$enableval -else - request_lib_only=no + request_failmalloc=no fi @@ -13042,24 +12136,6 @@ -# Check whether --with-mruby was given. -if test "${with_mruby+set}" = set; then : - withval=$with_mruby; request_mruby=$withval -else - request_mruby=no -fi - - - -# Check whether --with-neverbleed was given. -if test "${with_neverbleed+set}" = set; then : - withval=$with_neverbleed; request_neverbleed=$withval -else - request_neverbleed=no -fi - - - # Check whether --with-cython was given. if test "${with_cython+set}" = set; then : withval=$with_cython; cython_path=$withval @@ -13927,15 +13003,15 @@ func_stripname_cnf () { - case $2 in - .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; - *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf - if test -n "$CXX" && ( test no != "$CXX" && - ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || - (test g++ != "$CXX"))); then + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -14114,7 +13190,7 @@ # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_caught_CXX_error"; then +if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" @@ -14175,39 +13251,46 @@ CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC - func_cc_basename $compiler -cc_basename=$func_cc_basename_result + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately - if test yes = "$GXX"; then + if test "$GXX" = yes; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi - if test yes = "$GXX"; then + if test "$GXX" = yes; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld -if test yes = "$GCC"; then +if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) - # gcc leaves a trailing carriage return, which upsets mingw + # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; @@ -14221,7 +13304,7 @@ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done - test -z "$LD" && LD=$ac_prog + test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. @@ -14232,7 +13315,7 @@ with_gnu_ld=unknown ;; esac -elif test yes = "$with_gnu_ld"; then +elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else @@ -14243,32 +13326,32 @@ $as_echo_n "(cached) " >&6 else if test -z "$LD"; then - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD=$ac_dir/$ac_prog + lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } @@ -14304,22 +13387,22 @@ # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. - if test yes = "$with_gnu_ld"; then - archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' - export_dynamic_flag_spec_CXX='$wl--export-dynamic' + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) - wlarc='$wl' + wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_CXX= fi @@ -14356,30 +13439,18 @@ ld_shlibs_CXX=no ;; aix[4-9]*) - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag= + no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive + # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in @@ -14389,13 +13460,6 @@ ;; esac done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi ;; esac @@ -14414,21 +13478,13 @@ hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes - file_list_spec_CXX='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - hardcode_direct_CXX=no - hardcode_direct_absolute_CXX=no - ;; - esac + file_list_spec_CXX='${wl}-f,' - if test yes = "$GXX"; then + if test "$GXX" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` + collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -14446,44 +13502,36 @@ fi esac shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag=$shared_flag' $wl-G' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' else # not using gcc - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' else - shared_flag='$wl-bM:SRE' + shared_flag='${wl}-bM:SRE' fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' fi fi - export_dynamic_flag_spec_CXX='$wl-bexpall' + export_dynamic_flag_spec_CXX='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. - # The "-G" linker flag allows undefined symbols. - no_undefined_flag_CXX='-bernotok' + allow_undefined_flag_CXX='-berok' # Determine the default libpath from the value encoded in an empty # executable. - if test set = "${lt_cv_aix_libpath+set}"; then + if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : @@ -14518,7 +13566,7 @@ rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX=/usr/lib:/lib + lt_cv_aix_libpath__CXX="/usr/lib:/lib" fi fi @@ -14526,18 +13574,18 @@ aix_libpath=$lt_cv_aix_libpath__CXX fi - hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else - if test ia64 = "$host_cpu"; then - hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. - if test set = "${lt_cv_aix_libpath+set}"; then + if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : @@ -14572,7 +13620,7 @@ rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then - lt_cv_aix_libpath__CXX=/usr/lib:/lib + lt_cv_aix_libpath__CXX="/usr/lib:/lib" fi fi @@ -14580,34 +13628,22 @@ aix_libpath=$lt_cv_aix_libpath__CXX fi - hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - no_undefined_flag_CXX=' $wl-bernotok' - allow_undefined_flag_CXX=' $wl-berok' - if test yes = "$with_gnu_ld"; then + no_undefined_flag_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes - archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared - # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. - archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' + # This is similar to how AIX traditionally builds its shared + # libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; @@ -14617,7 +13653,7 @@ allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi @@ -14645,58 +13681,57 @@ # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll + shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. - archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' - export_dynamic_flag_spec_CXX='$wl--export-all-symbols' + export_dynamic_flag_spec_CXX='${wl}--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi @@ -14710,27 +13745,27 @@ hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported - if test yes = "$lt_cv_ld_force_load"; then - whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes - allow_undefined_flag_CXX=$_lt_dar_allow_undefined + allow_undefined_flag_CXX="$_lt_dar_allow_undefined" case $cc_basename in - ifort*|nagfor*) _lt_dar_can_shared=yes ;; + ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test yes = "$_lt_dar_can_shared"; then + if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all - archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" - module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" - if test yes != "$lt_cv_apple_cc_single_mod"; then - archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" - archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + if test "$lt_cv_apple_cc_single_mod" != "yes"; then + archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi else @@ -14739,34 +13774,6 @@ ;; - os2*) - hardcode_libdir_flag_spec_CXX='-L$libdir' - hardcode_minus_L_CXX=yes - allow_undefined_flag_CXX=unsupported - shrext_cmds=.dll - archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - enable_shared_with_static_runtimes_CXX=yes - ;; - dgux*) case $cc_basename in ec++*) @@ -14802,14 +13809,14 @@ ;; haiku*) - archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) - hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: - export_dynamic_flag_spec_CXX='$wl-E' + export_dynamic_flag_spec_CXX='${wl}-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default @@ -14821,7 +13828,7 @@ ld_shlibs_CXX=no ;; aCC*) - archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. @@ -14830,11 +13837,11 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test yes = "$GXX"; then - archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + if test "$GXX" = yes; then + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no @@ -14844,15 +13851,15 @@ ;; hpux10*|hpux11*) - if test no = "$with_gnu_ld"; then - hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) - export_dynamic_flag_spec_CXX='$wl-E' + export_dynamic_flag_spec_CXX='${wl}-E' ;; esac fi @@ -14878,13 +13885,13 @@ aCC*) case $host_cpu in hppa*64*) - archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists @@ -14895,20 +13902,20 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test yes = "$GXX"; then - if test no = "$with_gnu_ld"; then + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) - archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi @@ -14923,22 +13930,22 @@ interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' - export_dynamic_flag_spec_CXX='$wl-E' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ - archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is @@ -14947,17 +13954,17 @@ old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) - if test yes = "$GXX"; then - if test no = "$with_gnu_ld"; then - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac - hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; @@ -14970,8 +13977,8 @@ # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. @@ -14980,10 +13987,10 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' - export_dynamic_flag_spec_CXX='$wl--export-dynamic' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. @@ -14997,59 +14004,59 @@ # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac - archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no - hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' - export_dynamic_flag_spec_CXX='$wl--export-dynamic' - whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols - archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac - hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' - export_dynamic_flag_spec_CXX='$wl--export-dynamic' - whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' @@ -15063,18 +14070,18 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld - hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' - export_dynamic_flag_spec_CXX='$wl--export-dynamic' - archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test yes = "$supports_anon_versioning"; then + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) @@ -15082,10 +14089,10 @@ *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' - whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on @@ -15143,17 +14150,22 @@ ld_shlibs_CXX=yes ;; - openbsd* | bitrig*) + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + + openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then - archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' - export_dynamic_flag_spec_CXX='$wl-E' - whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else @@ -15169,9 +14181,9 @@ # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. - archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using @@ -15189,17 +14201,17 @@ cxx*) case $host in osf3*) - allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' - archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' - archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ - $RM $lib.exp' + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac @@ -15214,21 +14226,21 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test yes,no = "$GXX,$with_gnu_ld"; then - allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) - archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac - hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists @@ -15274,9 +14286,9 @@ # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no @@ -15284,7 +14296,7 @@ solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. + # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; @@ -15301,30 +14313,30 @@ ;; gcx*) # Green Hills C++ Compiler - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker - if test yes,no = "$GXX,$with_gnu_ld"; then - no_undefined_flag_CXX=' $wl-z ${wl}defs' + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then - archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else - # g++ 2.7 appears to require '-G' NOT '-shared' on this + # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. - archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when @@ -15332,11 +14344,11 @@ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi - hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) - whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi @@ -15345,52 +14357,52 @@ ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag_CXX='$wl-z,text' + no_undefined_flag_CXX='${wl}-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) - archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not + # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - no_undefined_flag_CXX='$wl-z,text' - allow_undefined_flag_CXX='$wl-z,nodefs' + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no - hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' + hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes - export_dynamic_flag_spec_CXX='$wl-Bexport' + export_dynamic_flag_spec_CXX='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) - archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ - '"$old_archive_cmds_CXX" + '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ - '"$reload_cmds_CXX" + '"$reload_cmds_CXX" ;; *) - archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; @@ -15422,10 +14434,10 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } - test no = "$ld_shlibs_CXX" && can_build_shared=no + test "$ld_shlibs_CXX" = no && can_build_shared=no - GCC_CXX=$GXX - LD_CXX=$LD + GCC_CXX="$GXX" + LD_CXX="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -15469,13 +14481,13 @@ pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do - case $prev$p in + case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. - if test x-L = "$p" || - test x-R = "$p"; then + if test $p = "-L" || + test $p = "-R"; then prev=$p continue fi @@ -15491,16 +14503,16 @@ case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac - if test no = "$pre_test_object_deps_done"; then - case $prev in + if test "$pre_test_object_deps_done" = no; then + case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then - compiler_lib_search_path_CXX=$prev$p + compiler_lib_search_path_CXX="${prev}${p}" else - compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" fi ;; # The "-l" case would never come before the object being @@ -15508,9 +14520,9 @@ esac else if test -z "$postdeps_CXX"; then - postdeps_CXX=$prev$p + postdeps_CXX="${prev}${p}" else - postdeps_CXX="${postdeps_CXX} $prev$p" + postdeps_CXX="${postdeps_CXX} ${prev}${p}" fi fi prev= @@ -15525,15 +14537,15 @@ continue fi - if test no = "$pre_test_object_deps_done"; then + if test "$pre_test_object_deps_done" = no; then if test -z "$predep_objects_CXX"; then - predep_objects_CXX=$p + predep_objects_CXX="$p" else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then - postdep_objects_CXX=$p + postdep_objects_CXX="$p" else postdep_objects_CXX="$postdep_objects_CXX $p" fi @@ -15563,6 +14575,51 @@ postdep_objects_CXX= postdeps_CXX= ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; esac @@ -15571,7 +14628,7 @@ esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then - compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` + compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi @@ -15610,18 +14667,17 @@ # C++ specific cases for pic, static, wl, etc. - if test yes = "$GXX"; then + if test "$GXX" = yes; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi - lt_prog_compiler_pic_CXX='-fPIC' ;; amigaos*) @@ -15632,8 +14688,8 @@ ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -15648,11 +14704,6 @@ # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' - case $host_os in - os2*) - lt_prog_compiler_static_CXX='$wl-static' - ;; - esac ;; darwin* | rhapsody*) # PIC is the default on this platform @@ -15702,7 +14753,7 @@ case $host_os in aix[4-9]*) # All AIX code is PIC. - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else @@ -15742,14 +14793,14 @@ case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='$wl-a ${wl}archive' - if test ia64 != "$host_cpu"; then + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX='$wl-a ${wl}archive' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default @@ -15786,7 +14837,7 @@ lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) - # old Intel C++ for x86_64, which still supported -KPIC. + # old Intel C++ for x86_64 which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' @@ -15931,7 +14982,7 @@ fi case $host_os in - # For platforms that do not support PIC, -DPIC is meaningless: + # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; @@ -15963,7 +15014,7 @@ lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -15993,7 +15044,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } -if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then +if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; @@ -16019,7 +15070,7 @@ $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_CXX=no - save_LDFLAGS=$LDFLAGS + save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -16038,13 +15089,13 @@ fi fi $RM -r conftest* - LDFLAGS=$save_LDFLAGS + LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } -if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then +if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then : else lt_prog_compiler_static_CXX= @@ -16158,8 +15209,8 @@ -hard_links=nottested -if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } @@ -16171,9 +15222,9 @@ ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } - if test no = "$hard_links"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else @@ -16190,21 +15241,17 @@ case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) - export_symbols_cmds_CXX=$ltdll_cmds + export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in @@ -16227,7 +15274,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } -test no = "$ld_shlibs_CXX" && can_build_shared=no +test "$ld_shlibs_CXX" = no && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld @@ -16244,7 +15291,7 @@ # Assume -lc should be added archive_cmds_need_lc_CXX=yes - if test yes,yes = "$GCC,$enable_shared"; then + if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -16372,7 +15419,7 @@ library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=.so +shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -16389,16 +15436,14 @@ # flags to be left without arguments need_version=unknown - - case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='$libname$release$shared_ext$major' + soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) @@ -16406,91 +15451,41 @@ need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 supports IA64 - library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line '#! .'. This would cause the generated library to - # depend on '.', always an invalid library. This was fixed in + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # Using Import Files as archive members, it is possible to support - # filename-based versioning of shared library archives on AIX. While - # this would work for both with and without runtime linking, it will - # prevent static linking of such archives. So we do filename-based - # shared library versioning with .so extension only, which is used - # when both runtime linking and shared linking is enabled. - # Unfortunately, runtime linking may impact performance, so we do - # not want this to be the default eventually. Also, we use the - # versioned .so libs for executables only if there is the -brtl - # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. - # To allow for filename-based versioning support, we need to create - # libNAME.so.V as an archive file, containing: - # *) an Import File, referring to the versioned filename of the - # archive as well as the shared archive member, telling the - # bitwidth (32 or 64) of that shared object, and providing the - # list of exported symbols of that shared object, eventually - # decorated with the 'weak' keyword - # *) the shared object with the F_LOADONLY flag set, to really avoid - # it being seen by the linker. - # At run time we better use the real file rather than another symlink, - # but for link time we create the symlink libNAME.so -> libNAME.so.V - - case $with_aix_soname,$aix_use_runtimelinking in - # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - aix,yes) # traditional libtool - dynamic_linker='AIX unversionable lib.so' + if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - aix,no) # traditional AIX only - dynamic_linker='AIX lib.a(lib.so.V)' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - ;; - svr4,*) # full svr4 only - dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,yes) # both, prefer svr4 - dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # unpreferred sharedlib libNAME.a needs extra handling - postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' - postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,no) # both, prefer aix - dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling - postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' - postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' - ;; - esac + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi shlibpath_var=LIBPATH fi ;; @@ -16500,18 +15495,18 @@ powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='$libname$shared_ext' + library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; @@ -16519,8 +15514,8 @@ bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -16532,7 +15527,7 @@ cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=.dll + shrext_cmds=".dll" need_version=no need_lib_prefix=no @@ -16541,8 +15536,8 @@ # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -16558,16 +15553,16 @@ case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' @@ -16576,8 +15571,8 @@ *,cl*) # Native MSVC libname_spec='$name' - soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - library_names_spec='$libname.dll.lib' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' case $build_os in mingw*) @@ -16604,7 +15599,7 @@ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) - sys_lib_search_path_spec=$LIB + sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` @@ -16617,8 +15612,8 @@ esac # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' @@ -16631,7 +15626,7 @@ *) # Assume MSVC wrapper - library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac @@ -16644,8 +15639,8 @@ version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' - soname_spec='$libname$release$major$shared_ext' + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -16657,8 +15652,8 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -16676,13 +15671,12 @@ version_type=freebsd-$objformat case $version_type in freebsd-elf*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac @@ -16712,10 +15706,10 @@ need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=no + shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -16733,15 +15727,14 @@ dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - if test 32 = "$HPUX_IA64_MODE"; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -16749,8 +15742,8 @@ dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -16759,8 +15752,8 @@ dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... @@ -16773,8 +15766,8 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -16785,7 +15778,7 @@ case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test yes = "$lt_cv_prog_gnu_ld"; then + if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix @@ -16793,8 +15786,8 @@ esac need_lib_prefix=no need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -16813,8 +15806,8 @@ esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" - sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; @@ -16823,33 +15816,13 @@ dynamic_linker=no ;; -linux*android*) - version_type=none # Android doesn't support versioned libraries. - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext' - soname_spec='$libname$release$shared_ext' - finish_cmds= - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - dynamic_linker='Android linker' - # Don't embed -rpath directories since the linker doesn't support them. - hardcode_libdir_flag_spec_CXX='-L$libdir' - ;; - # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -16893,12 +15866,7 @@ # before this can be enabled. hardcode_into_libs=yes - # Ideally, we could use ldconfig to report *all* directores which are - # searched for libraries, however this is still not possible. Aside from not - # being certain /sbin/ldconfig is available, command - # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, - # even though it is searched at run-time. Try to do the best guess by - # appending ld.so.conf contents (and includes) to the search path. + # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" @@ -16930,12 +15898,12 @@ need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -16945,7 +15913,7 @@ newsos6) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -16954,68 +15922,58 @@ version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd* | bitrig*) +openbsd*) version_type=sunos - sys_lib_dlsearch_path_spec=/usr/lib + sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - need_version=no - else - need_version=yes - fi - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi ;; os2*) libname_spec='$name' - version_type=windows - shrext_cmds=.dll - need_version=no + shrext_cmds=".dll" need_lib_prefix=no - # OS/2 can only load a DLL with a base name of 8 characters or less. - soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; - v=$($ECHO $release$versuffix | tr -d .-); - n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); - $ECHO $n$v`$shared_ext' - library_names_spec='${libname}_dll.$libext' + library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' - shlibpath_var=BEGINLIBPATH - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' + shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) @@ -17026,8 +15984,8 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -17037,11 +15995,11 @@ sunos4*) version_type=sunos - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test yes = "$with_gnu_ld"; then + if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes @@ -17049,8 +16007,8 @@ sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -17071,24 +16029,24 @@ ;; sysv4*MP*) - if test -d /usr/nec; then + if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' - soname_spec='$libname$shared_ext.$major' + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=sco + version_type=freebsd-elf need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test yes = "$with_gnu_ld"; then + if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -17106,7 +16064,7 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes @@ -17114,8 +16072,8 @@ uts4*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -17125,32 +16083,20 @@ esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } -test no = "$dynamic_linker" && can_build_shared=no +test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test yes = "$GCC"; then +if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then - sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi - -if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then - sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi -# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... -configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec - -# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code -func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" - -# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool -configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH - - - @@ -17193,15 +16139,15 @@ hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || - test yes = "$hardcode_automatic_CXX"; then + test "X$hardcode_automatic_CXX" = "Xyes" ; then # We can hardcode non-existent directories. - if test no != "$hardcode_direct_CXX" && + if test "$hardcode_direct_CXX" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && - test no != "$hardcode_minus_L_CXX"; then + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else @@ -17216,12 +16162,12 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } -if test relink = "$hardcode_action_CXX" || - test yes = "$inherit_rpath_CXX"; then +if test "$hardcode_action_CXX" = relink || + test "$inherit_rpath_CXX" = yes; then # Fast installation is not supported enable_fast_install=no -elif test yes = "$shlibpath_overrides_runpath" || - test no = "$enable_shared"; then +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi @@ -17244,7 +16190,7 @@ lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test yes != "$_lt_caught_CXX_error" +fi # test "$_lt_caught_CXX_error" != yes ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -17381,150 +16327,13 @@ fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "checking how to run the C preprocessor... " >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if ${ac_cv_prog_CPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 -$as_echo_n "checking whether ln -s works... " >&6; } -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } @@ -17569,7 +16378,6 @@ - if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. @@ -17684,6 +16492,7 @@ fi fi +if test "x$request_python_bindings" != "xno"; then @@ -17946,15 +16755,6 @@ -if test "x$request_lib_only" = "xyes"; then - request_app=no - request_hpack_tools=no - request_examples=no - request_python_bindings=no -fi - -if test "x$request_python_bindings" != "xno"; then - # # Allow the use of a (user set) custom python version # @@ -18279,2333 +17079,375 @@ ac_save_LIBS="$LIBS" ac_save_CPPFLAGS="$CPPFLAGS" LIBS="$ac_save_LIBS $PYTHON_LDFLAGS $PYTHON_EXTRA_LDFLAGS $PYTHON_EXTRA_LIBS" - CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS" - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include -int -main () -{ -Py_Initialize(); - ; - return 0; -} - -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - pythonexists=yes -else - pythonexists=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - # turn back to default flags - CPPFLAGS="$ac_save_CPPFLAGS" - LIBS="$ac_save_LIBS" - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pythonexists" >&5 -$as_echo "$pythonexists" >&6; } - - if test ! "x$pythonexists" = "xyes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: - Could not link test program to Python. Maybe the main Python library has been - installed in some non-standard library path. If so, pass it to configure, - via the LDFLAGS environment variable. - Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\" - ============================================================================ - ERROR! - You probably have to install the development version of the Python package - for your distribution. The exact name of this package varies among them. - ============================================================================ - " >&5 -$as_echo "$as_me: WARNING: - Could not link test program to Python. Maybe the main Python library has been - installed in some non-standard library path. If so, pass it to configure, - via the LDFLAGS environment variable. - Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\" - ============================================================================ - ERROR! - You probably have to install the development version of the Python package - for your distribution. The exact name of this package varies among them. - ============================================================================ - " >&2;} - PYTHON_VERSION="" - no_python_devel=yes - fi - - # - # all done! - # - -fi # AS_IF - -if test -z "$no_python_devel"; then : - have_python_dev=yes -else - have_python_dev=no -fi - - -fi - -if test "x${cython_path}" = "x"; then - for ac_prog in cython.py cython -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CYTHON+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CYTHON"; then - ac_cv_prog_CYTHON="$CYTHON" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CYTHON="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CYTHON=$ac_cv_prog_CYTHON -if test -n "$CYTHON"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYTHON" >&5 -$as_echo "$CYTHON" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CYTHON" && break -done - -else - CYTHON=${cython_path} - -fi - -# -# If we're running GCC or clang define _U_ to be "__attribute__((unused))" -# so we can use _U_ to flag unused function parameters and not get warnings -# about them. Otherwise, define _U_ to be an empty string so that _U_ used -# to flag an unused function parameters will compile with other compilers. -# -# XXX - similar hints for other compilers? -# -if test "x$GCC" = "xyes" -o "x$CC" = "xclang" ; then - -$as_echo "#define _U_ __attribute__((unused))" >>confdefs.h - - -$as_echo "#define NGHTTP2_NORETURN __attribute__((noreturn))" >>confdefs.h - -else - -$as_echo "#define _U_ /**/" >>confdefs.h - - -$as_echo "#define NGHTTP2_NORETURN /**/" >>confdefs.h - -fi - -save_CXXFLAGS="$CXXFLAGS" -CXXFLAGS= - - ax_cxx_compile_cxx11_required=falsednl - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - ac_success=no - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5 -$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; } -if ${ax_cv_cxx_compile_cxx11+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - typedef check> right_angle_brackets; - - int a; - decltype(a) b; - - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c); - - auto d = a; - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_cxx_compile_cxx11=yes -else - ax_cv_cxx_compile_cxx11=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5 -$as_echo "$ax_cv_cxx_compile_cxx11" >&6; } - if test x$ax_cv_cxx_compile_cxx11 = xyes; then - ac_success=yes - fi - - - - if test x$ac_success = xno; then - for switch in -std=c++11 -std=c++0x; do - cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5 -$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; } -if eval \${$cachevar+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - typedef check> right_angle_brackets; - - int a; - decltype(a) b; - - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c); - - auto d = a; - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - eval $cachevar=yes -else - eval $cachevar=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS="$ac_save_CXXFLAGS" -fi -eval ac_res=\$$cachevar - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" - ac_success=yes - break - fi - done - fi - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - if test x$ax_cxx_compile_cxx11_required = xtrue; then - if test x$ac_success = xno; then - as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5 - fi - else - if test x$ac_success = xno; then - HAVE_CXX11=0 - { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5 -$as_echo "$as_me: No compiler with C++11 support was found" >&6;} - else - HAVE_CXX11=1 - -$as_echo "#define HAVE_CXX11 1" >>confdefs.h - - fi - - - fi - - -CXX1XCXXFLAGS="$CXXFLAGS" -CXXFLAGS="$save_CXXFLAGS" - - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - -save_CXXFLAGS="$CXXFLAGS" -CXXFLAGS="$CXXFLAGS $CXX1XCXXFLAGS" - -# Check that std::future is available. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether std::future is available" >&5 -$as_echo_n "checking whether std::future is available... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include - -int -main () -{ - -std::vector> v; - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define HAVE_STD_FUTURE 1" >>confdefs.h - - have_std_future=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - have_std_future=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -# Check that std::map::emplace is available for g++-4.7. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether std::map::emplace is available" >&5 -$as_echo_n "checking whether std::map::emplace is available... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include - -int -main () -{ - -std::map().emplace(1, 2); - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -$as_echo "#define HAVE_STD_MAP_EMPLACE 1" >>confdefs.h - - have_std_map_emplace=yes - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - have_std_map_emplace=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -CXXFLAGS=$save_CXXFLAGS - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -# Checks for libraries. - -# Additional libraries required for tests. -TESTLDADD= - -# Additional libraries required for programs under src directory. -APPLDFLAGS= - -case "$host" in - *android*) - android_build=yes - # android does not need -pthread, but needs followng 3 libs for C++ - APPLDFLAGS="$APPLDFLAGS -lstdc++ -latomic -lsupc++" - ;; - *) - PTHREAD_LDFLAGS="-pthread" - APPLDFLAGS="$APPLDFLAGS $PTHREAD_LDFLAGS" - ;; -esac - -# zlib - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZLIB" >&5 -$as_echo_n "checking for ZLIB... " >&6; } - -if test -n "$ZLIB_CFLAGS"; then - pkg_cv_ZLIB_CFLAGS="$ZLIB_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib >= 1.2.3\""; } >&5 - ($PKG_CONFIG --exists --print-errors "zlib >= 1.2.3") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_ZLIB_CFLAGS=`$PKG_CONFIG --cflags "zlib >= 1.2.3" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$ZLIB_LIBS"; then - pkg_cv_ZLIB_LIBS="$ZLIB_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib >= 1.2.3\""; } >&5 - ($PKG_CONFIG --exists --print-errors "zlib >= 1.2.3") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_ZLIB_LIBS=`$PKG_CONFIG --libs "zlib >= 1.2.3" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - ZLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "zlib >= 1.2.3" 2>&1` - else - ZLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "zlib >= 1.2.3" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$ZLIB_PKG_ERRORS" >&5 - - have_zlib=no -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - have_zlib=no -else - ZLIB_CFLAGS=$pkg_cv_ZLIB_CFLAGS - ZLIB_LIBS=$pkg_cv_ZLIB_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - have_zlib=yes -fi - -if test "x${have_zlib}" = "xno"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: $ZLIB_PKG_ERRORS" >&5 -$as_echo "$as_me: $ZLIB_PKG_ERRORS" >&6;} -fi - -# dl: openssl requires libdl when it is statically linked. -case "${host_os}" in - *bsd*) - # dlopen is in libc on *BSD - ;; - *) - save_LIBS=$LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 -$as_echo_n "checking for library containing dlopen... " >&6; } -if ${ac_cv_search_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -for ac_lib in '' dl; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_dlopen=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_dlopen+:} false; then : - break -fi -done -if ${ac_cv_search_dlopen+:} false; then : - -else - ac_cv_search_dlopen=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 -$as_echo "$ac_cv_search_dlopen" >&6; } -ac_res=$ac_cv_search_dlopen -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - APPLDFLAGS="-ldl $APPLDFLAGS" -fi - - LIBS=$save_LIBS - ;; -esac - -# cunit - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CUNIT" >&5 -$as_echo_n "checking for CUNIT... " >&6; } - -if test -n "$CUNIT_CFLAGS"; then - pkg_cv_CUNIT_CFLAGS="$CUNIT_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cunit >= 2.1\""; } >&5 - ($PKG_CONFIG --exists --print-errors "cunit >= 2.1") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_CUNIT_CFLAGS=`$PKG_CONFIG --cflags "cunit >= 2.1" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$CUNIT_LIBS"; then - pkg_cv_CUNIT_LIBS="$CUNIT_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cunit >= 2.1\""; } >&5 - ($PKG_CONFIG --exists --print-errors "cunit >= 2.1") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_CUNIT_LIBS=`$PKG_CONFIG --libs "cunit >= 2.1" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - CUNIT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "cunit >= 2.1" 2>&1` - else - CUNIT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "cunit >= 2.1" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$CUNIT_PKG_ERRORS" >&5 - - have_cunit=no -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - have_cunit=no -else - CUNIT_CFLAGS=$pkg_cv_CUNIT_CFLAGS - CUNIT_LIBS=$pkg_cv_CUNIT_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - have_cunit=yes -fi -# If pkg-config does not find cunit, check it using AC_CHECK_LIB. We -# do this because Debian (Ubuntu) lacks pkg-config file for cunit. -if test "x${have_cunit}" = "xno"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ${CUNIT_PKG_ERRORS}" >&5 -$as_echo "$as_me: WARNING: ${CUNIT_PKG_ERRORS}" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CU_initialize_registry in -lcunit" >&5 -$as_echo_n "checking for CU_initialize_registry in -lcunit... " >&6; } -if ${ac_cv_lib_cunit_CU_initialize_registry+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcunit $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char CU_initialize_registry (); -int -main () -{ -return CU_initialize_registry (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_cunit_CU_initialize_registry=yes -else - ac_cv_lib_cunit_CU_initialize_registry=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cunit_CU_initialize_registry" >&5 -$as_echo "$ac_cv_lib_cunit_CU_initialize_registry" >&6; } -if test "x$ac_cv_lib_cunit_CU_initialize_registry" = xyes; then : - have_cunit=yes -else - have_cunit=no -fi - - if test "x${have_cunit}" = "xyes"; then - CUNIT_LIBS="-lcunit" - CUNIT_CFLAGS="" - - - fi -fi -if test "x${have_cunit}" = "xyes"; then - # cunit in Mac OS X requires ncurses. Note that in Mac OS X, test - # program can be built without -lncurses, but it emits runtime - # error. - case "${build}" in - *-apple-darwin*) - CUNIT_LIBS="$CUNIT_LIBS -lncurses" - - ;; - esac -fi - - if test "x${have_cunit}" = "xyes" ; then - HAVE_CUNIT_TRUE= - HAVE_CUNIT_FALSE='#' -else - HAVE_CUNIT_TRUE='#' - HAVE_CUNIT_FALSE= -fi - - -# libev (for src) -# libev does not have pkg-config file. Check it in an old way. -save_LIBS=$LIBS -# android requires -lm for floor -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ev_time in -lev" >&5 -$as_echo_n "checking for ev_time in -lev... " >&6; } -if ${ac_cv_lib_ev_ev_time+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lev -lm $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char ev_time (); -int -main () -{ -return ev_time (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_ev_ev_time=yes -else - ac_cv_lib_ev_ev_time=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ev_ev_time" >&5 -$as_echo "$ac_cv_lib_ev_ev_time" >&6; } -if test "x$ac_cv_lib_ev_ev_time" = xyes; then : - have_libev=yes -else - have_libev=no -fi - -if test "x${have_libev}" = "xyes"; then - ac_fn_c_check_header_mongrel "$LINENO" "ev.h" "ac_cv_header_ev_h" "$ac_includes_default" -if test "x$ac_cv_header_ev_h" = xyes; then : - have_libev=yes -else - have_libev=no -fi - - - if test "x${have_libev}" = "xyes"; then - LIBEV_LIBS=-lev - LIBEV_CFLAGS= - - - fi -fi -LIBS=$save_LIBS - -# openssl (for src) - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5 -$as_echo_n "checking for OPENSSL... " >&6; } - -if test -n "$OPENSSL_CFLAGS"; then - pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 1.0.1\""; } >&5 - ($PKG_CONFIG --exists --print-errors "openssl >= 1.0.1") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "openssl >= 1.0.1" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$OPENSSL_LIBS"; then - pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 1.0.1\""; } >&5 - ($PKG_CONFIG --exists --print-errors "openssl >= 1.0.1") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "openssl >= 1.0.1" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl >= 1.0.1" 2>&1` - else - OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl >= 1.0.1" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$OPENSSL_PKG_ERRORS" >&5 - - have_openssl=no -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - have_openssl=no -else - OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS - OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - have_openssl=yes -fi -if test "x${have_openssl}" = "xno"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: $OPENSSL_PKG_ERRORS" >&5 -$as_echo "$as_me: $OPENSSL_PKG_ERRORS" >&6;} -fi - -# libevent_openssl (for examples) -# 2.0.8 is required because we use evconnlistener_set_error_cb() - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBEVENT_OPENSSL" >&5 -$as_echo_n "checking for LIBEVENT_OPENSSL... " >&6; } - -if test -n "$LIBEVENT_OPENSSL_CFLAGS"; then - pkg_cv_LIBEVENT_OPENSSL_CFLAGS="$LIBEVENT_OPENSSL_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libevent_openssl >= 2.0.8\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libevent_openssl >= 2.0.8") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_LIBEVENT_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "libevent_openssl >= 2.0.8" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$LIBEVENT_OPENSSL_LIBS"; then - pkg_cv_LIBEVENT_OPENSSL_LIBS="$LIBEVENT_OPENSSL_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libevent_openssl >= 2.0.8\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libevent_openssl >= 2.0.8") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_LIBEVENT_OPENSSL_LIBS=`$PKG_CONFIG --libs "libevent_openssl >= 2.0.8" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - LIBEVENT_OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libevent_openssl >= 2.0.8" 2>&1` - else - LIBEVENT_OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libevent_openssl >= 2.0.8" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$LIBEVENT_OPENSSL_PKG_ERRORS" >&5 - - have_libevent_openssl=no -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - have_libevent_openssl=no -else - LIBEVENT_OPENSSL_CFLAGS=$pkg_cv_LIBEVENT_OPENSSL_CFLAGS - LIBEVENT_OPENSSL_LIBS=$pkg_cv_LIBEVENT_OPENSSL_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - have_libevent_openssl=yes -fi -if test "x${have_libevent_openssl}" = "xno"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: $LIBEVENT_OPENSSL_PKG_ERRORS" >&5 -$as_echo "$as_me: $LIBEVENT_OPENSSL_PKG_ERRORS" >&6;} -fi - -# jansson (for src/nghttp, src/deflatehd and src/inflatehd) - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JANSSON" >&5 -$as_echo_n "checking for JANSSON... " >&6; } - -if test -n "$JANSSON_CFLAGS"; then - pkg_cv_JANSSON_CFLAGS="$JANSSON_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson >= 2.5\""; } >&5 - ($PKG_CONFIG --exists --print-errors "jansson >= 2.5") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_JANSSON_CFLAGS=`$PKG_CONFIG --cflags "jansson >= 2.5" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$JANSSON_LIBS"; then - pkg_cv_JANSSON_LIBS="$JANSSON_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson >= 2.5\""; } >&5 - ($PKG_CONFIG --exists --print-errors "jansson >= 2.5") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_JANSSON_LIBS=`$PKG_CONFIG --libs "jansson >= 2.5" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - JANSSON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "jansson >= 2.5" 2>&1` - else - JANSSON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "jansson >= 2.5" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$JANSSON_PKG_ERRORS" >&5 - - have_jansson=no -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - have_jansson=no -else - JANSSON_CFLAGS=$pkg_cv_JANSSON_CFLAGS - JANSSON_LIBS=$pkg_cv_JANSSON_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - have_jansson=yes -fi -if test "x${have_jansson}" = "xyes"; then - -$as_echo "#define HAVE_JANSSON 1" >>confdefs.h - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: $JANSSON_PKG_ERRORS" >&5 -$as_echo "$as_me: $JANSSON_PKG_ERRORS" >&6;} -fi - -# libxml2 (for src/nghttp) -have_libxml2=no -if test "x${request_libxml2}" != "xno"; then - - -# Check whether --with-xml-prefix was given. -if test "${with_xml_prefix+set}" = set; then : - withval=$with_xml_prefix; xml_config_prefix="$withval" -else - xml_config_prefix="" -fi - - -# Check whether --with-xml-exec-prefix was given. -if test "${with_xml_exec_prefix+set}" = set; then : - withval=$with_xml_exec_prefix; xml_config_exec_prefix="$withval" -else - xml_config_exec_prefix="" -fi - -# Check whether --enable-xmltest was given. -if test "${enable_xmltest+set}" = set; then : - enableval=$enable_xmltest; -else - enable_xmltest=yes -fi - - - if test x$xml_config_exec_prefix != x ; then - xml_config_args="$xml_config_args" - if test x${XML2_CONFIG+set} != xset ; then - XML2_CONFIG=$xml_config_exec_prefix/bin/xml2-config - fi - fi - if test x$xml_config_prefix != x ; then - xml_config_args="$xml_config_args --prefix=$xml_config_prefix" - if test x${XML2_CONFIG+set} != xset ; then - XML2_CONFIG=$xml_config_prefix/bin/xml2-config - fi - fi - - # Extract the first word of "xml2-config", so it can be a program name with args. -set dummy xml2-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_XML2_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $XML2_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_XML2_CONFIG="$XML2_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_XML2_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - test -z "$ac_cv_path_XML2_CONFIG" && ac_cv_path_XML2_CONFIG="no" - ;; -esac -fi -XML2_CONFIG=$ac_cv_path_XML2_CONFIG -if test -n "$XML2_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XML2_CONFIG" >&5 -$as_echo "$XML2_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - min_xml_version=2.7.7 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libxml - version >= $min_xml_version" >&5 -$as_echo_n "checking for libxml - version >= $min_xml_version... " >&6; } - no_xml="" - if test "$XML2_CONFIG" = "no" ; then - no_xml=yes - else - XML_CPPFLAGS=`$XML2_CONFIG $xml_config_args --cflags` - XML_LIBS=`$XML2_CONFIG $xml_config_args --libs` - xml_config_major_version=`$XML2_CONFIG $xml_config_args --version | \ - sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` - xml_config_minor_version=`$XML2_CONFIG $xml_config_args --version | \ - sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` - xml_config_micro_version=`$XML2_CONFIG $xml_config_args --version | \ - sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` - if test "x$enable_xmltest" = "xyes" ; then - ac_save_CPPFLAGS="$CPPFLAGS" - ac_save_LIBS="$LIBS" - CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" - LIBS="$XML_LIBS $LIBS" - rm -f conf.xmltest - if test "$cross_compiling" = yes; then : - echo $ac_n "cross compiling; assumed OK... $ac_c" -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include -#include -#include - -int -main() -{ - int xml_major_version, xml_minor_version, xml_micro_version; - int major, minor, micro; - char *tmp_version; - - system("touch conf.xmltest"); - - /* Capture xml2-config output via autoconf/configure variables */ - /* HP/UX 9 (%@#!) writes to sscanf strings */ - tmp_version = (char *)strdup("$min_xml_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string from xml2-config\n", "$min_xml_version"); - exit(1); - } - free(tmp_version); - - /* Capture the version information from the header files */ - tmp_version = (char *)strdup(LIBXML_DOTTED_VERSION); - if (sscanf(tmp_version, "%d.%d.%d", &xml_major_version, &xml_minor_version, &xml_micro_version) != 3) { - printf("%s, bad version string from libxml includes\n", "LIBXML_DOTTED_VERSION"); - exit(1); - } - free(tmp_version); - - /* Compare xml2-config output to the libxml headers */ - if ((xml_major_version != $xml_config_major_version) || - (xml_minor_version != $xml_config_minor_version) || - (xml_micro_version != $xml_config_micro_version)) - { - printf("*** libxml header files (version %d.%d.%d) do not match\n", - xml_major_version, xml_minor_version, xml_micro_version); - printf("*** xml2-config (version %d.%d.%d)\n", - $xml_config_major_version, $xml_config_minor_version, $xml_config_micro_version); - return 1; - } -/* Compare the headers to the library to make sure we match */ - /* Less than ideal -- doesn't provide us with return value feedback, - * only exits if there's a serious mismatch between header and library. - */ - LIBXML_TEST_VERSION; - - /* Test that the library is greater than our minimum version */ - if ((xml_major_version > major) || - ((xml_major_version == major) && (xml_minor_version > minor)) || - ((xml_major_version == major) && (xml_minor_version == minor) && - (xml_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** An old version of libxml (%d.%d.%d) was found.\n", - xml_major_version, xml_minor_version, xml_micro_version); - printf("*** You need a version of libxml newer than %d.%d.%d. The latest version of\n", - major, minor, micro); - printf("*** libxml is always available from ftp://ftp.xmlsoft.org.\n"); - printf("***\n"); - printf("*** If you have already installed a sufficiently new version, this error\n"); - printf("*** probably means that the wrong copy of the xml2-config shell script is\n"); - printf("*** being found. The easiest way to fix this is to remove the old version\n"); - printf("*** of LIBXML, but you can also set the XML2_CONFIG environment to point to the\n"); - printf("*** correct copy of xml2-config. (In this case, you will have to\n"); - printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); - printf("*** so that the correct libraries are found at run-time))\n"); - } - return 1; -} - -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - no_xml=yes -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - - CPPFLAGS="$ac_save_CPPFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - - if test "x$no_xml" = x ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)" >&5 -$as_echo "yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)" >&6; } - have_libxml2=yes - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - if test "$XML2_CONFIG" = "no" ; then - echo "*** The xml2-config script installed by LIBXML could not be found" - echo "*** If libxml was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the XML2_CONFIG environment variable to the" - echo "*** full path to xml2-config." - else - if test -f conf.xmltest ; then - : - else - echo "*** Could not run libxml test program, checking why..." - CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" - LIBS="$LIBS $XML_LIBS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include - -int -main () -{ - LIBXML_TEST_VERSION; return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding LIBXML or finding the wrong" - echo "*** version of LIBXML. If it is not finding LIBXML, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" -else - echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means LIBXML was incorrectly installed" - echo "*** or that you have moved LIBXML since it was installed. In the latter case, you" - echo "*** may want to edit the xml2-config script: $XML2_CONFIG" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - CPPFLAGS="$ac_save_CPPFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - - XML_CPPFLAGS="" - XML_LIBS="" - have_libxml2=no - fi - - - rm -f conf.xmltest - - - if test "x${have_libxml2}" = "xyes"; then - -$as_echo "#define HAVE_LIBXML2 1" >>confdefs.h - - fi -fi - -if test "x${request_libxml2}" = "xyes" && - test "x${have_libxml2}" != "xyes"; then - as_fn_error $? "libxml2 was requested (--with-libxml2) but not found" "$LINENO" 5 -fi - - if test "x${have_libxml2}" = "xyes" ; then - HAVE_LIBXML2_TRUE= - HAVE_LIBXML2_FALSE='#' -else - HAVE_LIBXML2_TRUE='#' - HAVE_LIBXML2_FALSE= -fi - - -# jemalloc -have_jemalloc=no -if test "x${request_jemalloc}" != "xno"; then - save_LIBS=$LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing malloc_stats_print" >&5 -$as_echo_n "checking for library containing malloc_stats_print... " >&6; } -if ${ac_cv_search_malloc_stats_print+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char malloc_stats_print (); -int -main () -{ -return malloc_stats_print (); - ; - return 0; -} -_ACEOF -for ac_lib in '' jemalloc; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $PTHREAD_LDFLAGS $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_malloc_stats_print=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_malloc_stats_print+:} false; then : - break -fi -done -if ${ac_cv_search_malloc_stats_print+:} false; then : - -else - ac_cv_search_malloc_stats_print=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_malloc_stats_print" >&5 -$as_echo "$ac_cv_search_malloc_stats_print" >&6; } -ac_res=$ac_cv_search_malloc_stats_print -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - have_jemalloc=yes -fi - - - 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 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing je_malloc_stats_print" >&5 -$as_echo_n "checking for library containing je_malloc_stats_print... " >&6; } -if ${ac_cv_search_je_malloc_stats_print+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char je_malloc_stats_print (); -int -main () -{ -return je_malloc_stats_print (); - ; - return 0; -} -_ACEOF -for ac_lib in '' jemalloc; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $PTHREAD_LDFLAGS $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_je_malloc_stats_print=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_je_malloc_stats_print+:} false; then : - break -fi -done -if ${ac_cv_search_je_malloc_stats_print+:} false; then : - -else - ac_cv_search_je_malloc_stats_print=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_je_malloc_stats_print" >&5 -$as_echo "$ac_cv_search_je_malloc_stats_print" >&6; } -ac_res=$ac_cv_search_je_malloc_stats_print -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - have_jemalloc=yes -fi - - - if test "x${have_jemalloc}" = "xyes"; then - jemalloc_libs=${ac_cv_search_je_malloc_stats_print} - fi - fi - - LIBS=$save_LIBS - - if test "x${have_jemalloc}" = "xyes" && - test "x${jemalloc_libs}" != "xnone required"; then - JEMALLOC_LIBS=${jemalloc_libs} - - fi -fi - -if test "x${request_jemalloc}" = "xyes" && - test "x${have_jemalloc}" != "xyes"; then - as_fn_error $? "jemalloc was requested (--with-jemalloc) but not found" "$LINENO" 5 -fi - -# spdylay (for src/nghttpx and src/h2load) -have_spdylay=no -if test "x${request_spdylay}" != "xno"; then - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSPDYLAY" >&5 -$as_echo_n "checking for LIBSPDYLAY... " >&6; } - -if test -n "$LIBSPDYLAY_CFLAGS"; then - pkg_cv_LIBSPDYLAY_CFLAGS="$LIBSPDYLAY_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libspdylay >= 1.3.2\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libspdylay >= 1.3.2") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_LIBSPDYLAY_CFLAGS=`$PKG_CONFIG --cflags "libspdylay >= 1.3.2" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$LIBSPDYLAY_LIBS"; then - pkg_cv_LIBSPDYLAY_LIBS="$LIBSPDYLAY_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libspdylay >= 1.3.2\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libspdylay >= 1.3.2") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_LIBSPDYLAY_LIBS=`$PKG_CONFIG --libs "libspdylay >= 1.3.2" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - LIBSPDYLAY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libspdylay >= 1.3.2" 2>&1` - else - LIBSPDYLAY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libspdylay >= 1.3.2" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$LIBSPDYLAY_PKG_ERRORS" >&5 - - have_spdylay=no -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - have_spdylay=no -else - LIBSPDYLAY_CFLAGS=$pkg_cv_LIBSPDYLAY_CFLAGS - LIBSPDYLAY_LIBS=$pkg_cv_LIBSPDYLAY_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - have_spdylay=yes -fi - if test "x${have_spdylay}" = "xyes"; then - -$as_echo "#define HAVE_SPDYLAY 1" >>confdefs.h - - else - { $as_echo "$as_me:${as_lineno-$LINENO}: $LIBSPDYLAY_PKG_ERRORS" >&5 -$as_echo "$as_me: $LIBSPDYLAY_PKG_ERRORS" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: The SPDY support in nghttpx and h2load will be disabled." >&5 -$as_echo "$as_me: The SPDY support in nghttpx and h2load will be disabled." >&6;} - fi -fi - -if test "x${request_spdylay}" = "xyes" && - test "x${have_spdylay}" != "xyes"; then - as_fn_error $? "spdylay was requested (--with-spdylay) but not found" "$LINENO" 5 -fi - - if test "x${have_spdylay}" = "xyes" ; then - HAVE_SPDYLAY_TRUE= - HAVE_SPDYLAY_FALSE='#' -else - HAVE_SPDYLAY_TRUE='#' - HAVE_SPDYLAY_FALSE= -fi - - -# Check Boost Asio library -have_asio_lib=no - -if test "x${request_asio_lib}" = "xyes"; then - - -# Check whether --with-boost was given. -if test "${with_boost+set}" = set; then : - withval=$with_boost; - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ac_boost_path="" - else - want_boost="yes" - ac_boost_path="$withval" - fi - -else - want_boost="yes" -fi - - - - -# Check whether --with-boost-libdir was given. -if test "${with_boost_libdir+set}" = set; then : - withval=$with_boost_libdir; - if test -d "$withval" - then - ac_boost_lib_path="$withval" - else - as_fn_error $? "--with-boost-libdir expected directory name" "$LINENO" 5 - fi - -else - ac_boost_lib_path="" - -fi - - -if test "x$want_boost" = "xyes"; then - boost_lib_version_req=1.54.0 - boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([0-9]*\.[0-9]*\)'` - boost_lib_version_req_major=`expr $boost_lib_version_req : '\([0-9]*\)'` - boost_lib_version_req_minor=`expr $boost_lib_version_req : '[0-9]*\.\([0-9]*\)'` - boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[0-9]*\.[0-9]*\.\([0-9]*\)'` - if test "x$boost_lib_version_req_sub_minor" = "x" ; then - boost_lib_version_req_sub_minor="0" - fi - WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for boostlib >= $boost_lib_version_req" >&5 -$as_echo_n "checking for boostlib >= $boost_lib_version_req... " >&6; } - succeeded=no - - libsubdirs="lib" - ax_arch=`uname -m` - case $ax_arch in - x86_64) - libsubdirs="lib64 libx32 lib lib64" - ;; - ppc64|s390x|sparc64|aarch64|ppc64le) - libsubdirs="lib64 lib lib64 ppc64le" - ;; - esac - - - libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs" - - case ${host_cpu} in - i?86) - libsubdirs="lib/i386-${host_os} $libsubdirs" - ;; - esac - - if test "$ac_boost_path" != ""; then - BOOST_CPPFLAGS="-I$ac_boost_path/include" - for ac_boost_path_tmp in $libsubdirs; do - if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then - BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp" - break - fi - done - elif test "$cross_compiling" != yes; then - for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then - for libsubdir in $libsubdirs ; do - if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi - done - BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir" - BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" - break; - fi - done - fi - - if test "$ac_boost_lib_path" != ""; then - BOOST_LDFLAGS="-L$ac_boost_lib_path" - fi - - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include - -int -main () -{ - - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - succeeded=yes - found_system=yes - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - - - if test "x$succeeded" != "xyes"; then - _version=0 - if test "$ac_boost_path" != ""; then - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` - V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then - _version=$_version_tmp - fi - VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` - BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" - done - fi - else - if test "$cross_compiling" != yes; then - for ac_boost_path in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` - V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then - _version=$_version_tmp - best_path=$ac_boost_path - fi - done - fi - done - - VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` - BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" - if test "$ac_boost_lib_path" = ""; then - for libsubdir in $libsubdirs ; do - if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi - done - BOOST_LDFLAGS="-L$best_path/$libsubdir" - fi - fi - - if test "x$BOOST_ROOT" != "x"; then - for libsubdir in $libsubdirs ; do - if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi - done - if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then - version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` - stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` - stage_version_shorten=`expr $stage_version : '\([0-9]*\.[0-9]*\)'` - V_CHECK=`expr $stage_version_shorten \>\= $_version` - if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: We will use a staged boost library from $BOOST_ROOT" >&5 -$as_echo "$as_me: We will use a staged boost library from $BOOST_ROOT" >&6;} - BOOST_CPPFLAGS="-I$BOOST_ROOT" - BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" - fi - fi - fi - fi - - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include - -int -main () -{ - - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - succeeded=yes - found_system=yes - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - fi - - if test "$succeeded" != "yes" ; then - if test "$_version" = "0" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation." >&5 -$as_echo "$as_me: We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation." >&6;} - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Your boost libraries seems to old (version $_version)." >&5 -$as_echo "$as_me: Your boost libraries seems to old (version $_version)." >&6;} - fi - # execute ACTION-IF-NOT-FOUND (if present): - have_boost_base=no - else - - - -$as_echo "#define HAVE_BOOST /**/" >>confdefs.h - - # execute ACTION-IF-FOUND (if present): - have_boost_base=yes - fi - - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" -fi - - - - if test "x${have_boost_base}" = "xyes"; then - - -# Check whether --with-boost-asio was given. -if test "${with_boost_asio+set}" = set; then : - withval=$with_boost_asio; - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ax_boost_user_asio_lib="" - else - want_boost="yes" - ax_boost_user_asio_lib="$withval" - fi - -else - want_boost="yes" - -fi - - - if test "x$want_boost" = "xyes"; then - - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Boost::ASIO library is available" >&5 -$as_echo_n "checking whether the Boost::ASIO library is available... " >&6; } -if ${ax_cv_boost_asio+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - #include - -int -main () -{ - - - boost::asio::io_service io; - boost::system::error_code timer_result; - boost::asio::deadline_timer t(io); - t.cancel(); - io.run_one(); - return 0; - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_boost_asio=yes -else - ax_cv_boost_asio=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_asio" >&5 -$as_echo "$ax_cv_boost_asio" >&6; } - if test "x$ax_cv_boost_asio" = "xyes"; then - -$as_echo "#define HAVE_BOOST_ASIO /**/" >>confdefs.h - - BN=boost_system - BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/[^\/]*//'` - if test "x$ax_boost_user_asio_lib" = "x"; then - for ax_lib in `ls $BOOSTLIBDIR/libboost_system*.so* $BOOSTLIBDIR/libboost_system*.dylib* $BOOSTLIBDIR/libboost_system*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_system.*\)\.so.*$;\1;' -e 's;^lib\(boost_system.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_system.*\)\.a.*$;\1;' ` ; do - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_main" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l$ax_lib" >&5 -$as_echo_n "checking for main in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -int -main () -{ -return main (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" -else - eval "$as_ac_Lib=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_ASIO_LIB="-l$ax_lib" link_thread="yes" break -else - link_thread="no" -fi - - done - else - for ax_lib in $ax_boost_user_asio_lib $BN-$ax_boost_user_asio_lib; do - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_main" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l$ax_lib" >&5 -$as_echo_n "checking for main in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -int -main () -{ -return main (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" -else - eval "$as_ac_Lib=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_ASIO_LIB="-l$ax_lib" link_asio="yes" break -else - link_asio="no" -fi - - done - - fi - if test "x$ax_lib" = "x"; then - as_fn_error $? "Could not find a version of the library!" "$LINENO" 5 - fi - if test "x$link_asio" = "xno"; then - as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5 - fi - fi - - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - fi - - - -# Check whether --with-boost-system was given. -if test "${with_boost_system+set}" = set; then : - withval=$with_boost_system; - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ax_boost_user_system_lib="" - else - want_boost="yes" - ax_boost_user_system_lib="$withval" - fi - -else - want_boost="yes" - -fi - - - if test "x$want_boost" = "xyes"; then - - - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Boost::System library is available" >&5 -$as_echo_n "checking whether the Boost::System library is available... " >&6; } -if ${ax_cv_boost_system+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - CXXFLAGS_SAVE=$CXXFLAGS + CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + + #include int main () { -boost::system::system_category +Py_Initialize(); ; return 0; } + _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_boost_system=yes +if ac_fn_c_try_link "$LINENO"; then : + pythonexists=yes else - ax_cv_boost_system=no + pythonexists=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS=$CXXFLAGS_SAVE - ac_ext=c +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu + # turn back to default flags + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_system" >&5 -$as_echo "$ax_cv_boost_system" >&6; } - if test "x$ax_cv_boost_system" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pythonexists" >&5 +$as_echo "$pythonexists" >&6; } + + if test ! "x$pythonexists" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + Could not link test program to Python. Maybe the main Python library has been + installed in some non-standard library path. If so, pass it to configure, + via the LDFLAGS environment variable. + Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\" + ============================================================================ + ERROR! + You probably have to install the development version of the Python package + for your distribution. The exact name of this package varies among them. + ============================================================================ + " >&5 +$as_echo "$as_me: WARNING: + Could not link test program to Python. Maybe the main Python library has been + installed in some non-standard library path. If so, pass it to configure, + via the LDFLAGS environment variable. + Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\" + ============================================================================ + ERROR! + You probably have to install the development version of the Python package + for your distribution. The exact name of this package varies among them. + ============================================================================ + " >&2;} + PYTHON_VERSION="" + no_python_devel=yes + fi + + # + # all done! + # +fi # AS_IF +if test -z "$no_python_devel"; then : + have_python_dev=yes +else + have_python_dev=no +fi -$as_echo "#define HAVE_BOOST_SYSTEM /**/" >>confdefs.h - BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/[^\/]*//'` +fi - LDFLAGS_SAVE=$LDFLAGS - if test "x$ax_boost_user_system_lib" = "x"; then - for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do - ax_lib=${libextension} - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 -$as_echo_n "checking for exit in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : +if test "x${cython_path}" = "x"; then + for ac_prog in cython.py cython +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CYTHON+:} false; then : $as_echo_n "(cached) " >&6 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + if test -n "$CYTHON"; then + ac_cv_prog_CYTHON="$CYTHON" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CYTHON="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char exit (); -int -main () -{ -return exit (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" +fi +fi +CYTHON=$ac_cv_prog_CYTHON +if test -n "$CYTHON"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYTHON" >&5 +$as_echo "$CYTHON" >&6; } else - eval "$as_ac_Lib=no" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS + + + test -n "$CYTHON" && break +done + +else + CYTHON=${cython_path} + fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break + +# +# If we're running GCC or clang define _U_ to be "__attribute__((unused))" +# so we can use _U_ to flag unused function parameters and not get warnings +# about them. Otherwise, define _U_ to be an empty string so that _U_ used +# to flag an unused function parameters will compile with other compilers. +# +# XXX - similar hints for other compilers? +# +if test "x$GCC" = "xyes" -o "x$CC" = "xclang" ; then + +$as_echo "#define _U_ __attribute__((unused))" >>confdefs.h + else - link_system="no" + +$as_echo "#define _U_ /**/" >>confdefs.h + fi - done - if test "x$link_system" != "xyes"; then - for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do - ax_lib=${libextension} - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 -$as_echo_n "checking for exit in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : + ax_cxx_compile_cxx11_required=falsednl + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + ac_success=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5 +$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; } +if ${ax_cv_cxx_compile_cxx11+:} false; then : $as_echo_n "(cached) " >&6 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char exit (); -int -main () -{ -return exit (); - ; - return 0; -} + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); + + auto d = a; + _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" +if ac_fn_cxx_try_compile "$LINENO"; then : + ax_cv_cxx_compile_cxx11=yes else - eval "$as_ac_Lib=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS + ax_cv_cxx_compile_cxx11=no fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break -else - link_system="no" +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - - done - fi - - else - for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 -$as_echo_n "checking for exit in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5 +$as_echo "$ax_cv_cxx_compile_cxx11" >&6; } + if test x$ax_cv_cxx_compile_cxx11 = xyes; then + ac_success=yes + fi + + + + if test x$ac_success = xno; then + for switch in -std=c++11 -std=c++0x; do + cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5 +$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; } +if eval \${$cachevar+:} false; then : $as_echo_n "(cached) " >&6 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char exit (); -int -main () -{ -return exit (); - ; - return 0; -} + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); + + auto d = a; + _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" +if ac_fn_cxx_try_compile "$LINENO"; then : + eval $cachevar=yes else - eval "$as_ac_Lib=no" + eval $cachevar=no fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CXXFLAGS="$ac_save_CXXFLAGS" fi -eval ac_res=\$$as_ac_Lib +eval ac_res=\$$cachevar { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break -else - link_system="no" -fi + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu - done + if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ac_success = xno; then + as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5 + fi + else + if test x$ac_success = xno; then + HAVE_CXX11=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5 +$as_echo "$as_me: No compiler with C++11 support was found" >&6;} + else + HAVE_CXX11=1 - fi - if test "x$ax_lib" = "x"; then - as_fn_error $? "Could not find a version of the library!" "$LINENO" 5 - fi - if test "x$link_system" = "xno"; then - as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5 - fi - fi +$as_echo "#define HAVE_CXX11 1" >>confdefs.h - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - fi + fi + fi -# Check whether --with-boost-thread was given. -if test "${with_boost_thread+set}" = set; then : - withval=$with_boost_thread; - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ax_boost_user_thread_lib="" - else - want_boost="yes" - ax_boost_user_thread_lib="$withval" - fi -else - want_boost="yes" +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -fi +# Check that std::chrono::steady_clock is available. In particular, +# gcc 4.6 does not have one, but has monotonic_clock which is the old +# name existed in the pre-standard draft. If steady_clock is not +# available, don't define HAVE_STEADY_CLOCK and replace steady_clock +# with monotonic_clock. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether std::chrono::steady_clock is available" >&5 +$as_echo_n "checking whether std::chrono::steady_clock is available... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include - if test "x$want_boost" = "xyes"; then +int +main () +{ +auto tp = std::chrono::steady_clock::now(); - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS +$as_echo "#define HAVE_STEADY_CLOCK 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Boost::Thread library is available" >&5 -$as_echo_n "checking whether the Boost::Thread library is available... " >&6; } -if ${ax_cv_boost_thread+:} false; then : - $as_echo_n "(cached) " >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } else - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - CXXFLAGS_SAVE=$CXXFLAGS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - if test "x$host_os" = "xsolaris" ; then - CXXFLAGS="-pthreads $CXXFLAGS" - elif test "x$host_os" = "xmingw32" ; then - CXXFLAGS="-mthreads $CXXFLAGS" - else - CXXFLAGS="-pthread $CXXFLAGS" - fi - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +# Check that std::future is available. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether std::future is available" >&5 +$as_echo_n "checking whether std::future is available... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + +#include +#include + int main () { -boost::thread_group thrds; - return 0; + +std::vector> v; + ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_boost_thread=yes + +$as_echo "#define HAVE_STD_FUTURE 1" >>confdefs.h + + have_std_future=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } else - ax_cv_boost_thread=no + have_std_future=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS=$CXXFLAGS_SAVE - ac_ext=c + +ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_thread" >&5 -$as_echo "$ax_cv_boost_thread" >&6; } - if test "x$ax_cv_boost_thread" = "xyes"; then - if test "x$host_os" = "xsolaris" ; then - BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS" - elif test "x$host_os" = "xmingw32" ; then - BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS" - else - BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS" - fi - - - +# Checks for libraries. -$as_echo "#define HAVE_BOOST_THREAD /**/" >>confdefs.h +# Additional libraries required for tests. +TESTS_LIBS= - BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/[^\/]*//'` +# Additional libraries required for programs under src directory. +SRC_LIBS= - LDFLAGS_SAVE=$LDFLAGS - case "x$host_os" in - *bsd* ) - LDFLAGS="-pthread $LDFLAGS" - break; - ;; - esac - if test "x$ax_boost_user_thread_lib" = "x"; then - for libextension in `ls -r $BOOSTLIBDIR/libboost_thread* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'`; do - ax_lib=${libextension} - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 -$as_echo_n "checking for exit in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : +LIBS_OLD=$LIBS +# Search for dlsym function, which is used in tests. Linux needs -ldl, +# but netbsd does not need it. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlsym" >&5 +$as_echo_n "checking for library containing dlsym... " >&6; } +if ${ac_cv_search_dlsym+:} false; then : $as_echo_n "(cached) " >&6 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" + ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20615,45 +17457,57 @@ #ifdef __cplusplus extern "C" #endif -char exit (); +char dlsym (); int main () { -return exit (); +return dlsym (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" -else - eval "$as_ac_Lib=no" +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_dlsym=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS + conftest$ac_exeext + if ${ac_cv_search_dlsym+:} false; then : + break fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_THREAD_LIB="-l$ax_lib"; link_thread="yes"; break +done +if ${ac_cv_search_dlsym+:} false; then : + else - link_thread="no" + ac_cv_search_dlsym=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlsym" >&5 +$as_echo "$ac_cv_search_dlsym" >&6; } +ac_res=$ac_cv_search_dlsym +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - done - if test "x$link_thread" != "xyes"; then - for libextension in `ls -r $BOOSTLIBDIR/boost_thread* 2>/dev/null | sed 's,.*/,,' | sed 's,\..*,,'`; do - ax_lib=${libextension} - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 -$as_echo_n "checking for exit in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : +fi + +TESTS_LIBS="$LIBS $TESTS_LIBS" +LIBS=$LIBS_OLD + +LIBS_OLD=$LIBS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : $as_echo_n "(cached) " >&6 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" + ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20663,46 +17517,232 @@ #ifdef __cplusplus extern "C" #endif -char exit (); +char clock_gettime (); int main () { -return exit (); +return clock_gettime (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" -else - eval "$as_ac_Lib=no" +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_clock_gettime=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS + conftest$ac_exeext + if ${ac_cv_search_clock_gettime+:} false; then : + break fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_THREAD_LIB="-l$ax_lib"; link_thread="yes"; break +done +if ${ac_cv_search_clock_gettime+:} false; then : + else - link_thread="no" + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - done - fi +$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h - else - for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 -$as_echo_n "checking for exit in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : +fi + +SRC_LIBS="$LIBS $SRC_LIBS" +LIBS=$LIBS_OLD + +case "$host" in + *android*) + android_build=yes + # android does not need -pthread, but needs followng 2 libs for C++ + SRC_LIBS="$SRC_LIBS -lstdc++ -lsupc++" + ;; + *) + PTHREAD_LDFLAGS="-pthread" + SRC_LIBS="$SRC_LIBS $PTHREAD_LDFLAGS" + ;; +esac + +# zlib +if test "x$android_build" = "xyes"; then + # Use zlib provided by NDK + SRC_LIBS="-lz $SRC_LIBS" + have_zlib=yes +else + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZLIB" >&5 +$as_echo_n "checking for ZLIB... " >&6; } + +if test -n "$ZLIB_CFLAGS"; then + pkg_cv_ZLIB_CFLAGS="$ZLIB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib >= 1.2.3\""; } >&5 + ($PKG_CONFIG --exists --print-errors "zlib >= 1.2.3") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ZLIB_CFLAGS=`$PKG_CONFIG --cflags "zlib >= 1.2.3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$ZLIB_LIBS"; then + pkg_cv_ZLIB_LIBS="$ZLIB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib >= 1.2.3\""; } >&5 + ($PKG_CONFIG --exists --print-errors "zlib >= 1.2.3") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ZLIB_LIBS=`$PKG_CONFIG --libs "zlib >= 1.2.3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + ZLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "zlib >= 1.2.3" 2>&1` + else + ZLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "zlib >= 1.2.3" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$ZLIB_PKG_ERRORS" >&5 + + have_zlib=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_zlib=no +else + ZLIB_CFLAGS=$pkg_cv_ZLIB_CFLAGS + ZLIB_LIBS=$pkg_cv_ZLIB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_zlib=yes +fi + + if test "x${have_zlib}" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ZLIB_PKG_ERRORS" >&5 +$as_echo "$as_me: $ZLIB_PKG_ERRORS" >&6;} + fi +fi + +# cunit + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CUNIT" >&5 +$as_echo_n "checking for CUNIT... " >&6; } + +if test -n "$CUNIT_CFLAGS"; then + pkg_cv_CUNIT_CFLAGS="$CUNIT_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cunit >= 2.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "cunit >= 2.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CUNIT_CFLAGS=`$PKG_CONFIG --cflags "cunit >= 2.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$CUNIT_LIBS"; then + pkg_cv_CUNIT_LIBS="$CUNIT_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cunit >= 2.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "cunit >= 2.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_CUNIT_LIBS=`$PKG_CONFIG --libs "cunit >= 2.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + CUNIT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "cunit >= 2.1" 2>&1` + else + CUNIT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "cunit >= 2.1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$CUNIT_PKG_ERRORS" >&5 + + have_cunit=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_cunit=no +else + CUNIT_CFLAGS=$pkg_cv_CUNIT_CFLAGS + CUNIT_LIBS=$pkg_cv_CUNIT_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_cunit=yes +fi +# If pkg-config does not find cunit, check it using AC_CHECK_LIB. We +# do this because Debian (Ubuntu) lacks pkg-config file for cunit. +if test "x${have_cunit}" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ${CUNIT_PKG_ERRORS}" >&5 +$as_echo "$as_me: WARNING: ${CUNIT_PKG_ERRORS}" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CU_initialize_registry in -lcunit" >&5 +$as_echo_n "checking for CU_initialize_registry in -lcunit... " >&6; } +if ${ac_cv_lib_cunit_CU_initialize_registry+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" +LIBS="-lcunit $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20712,1943 +17752,2272 @@ #ifdef __cplusplus extern "C" #endif -char exit (); +char CU_initialize_registry (); int main () { -return exit (); +return CU_initialize_registry (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" + ac_cv_lib_cunit_CU_initialize_registry=yes else - eval "$as_ac_Lib=no" + ac_cv_lib_cunit_CU_initialize_registry=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_THREAD_LIB="-l$ax_lib"; link_thread="yes"; break +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cunit_CU_initialize_registry" >&5 +$as_echo "$ac_cv_lib_cunit_CU_initialize_registry" >&6; } +if test "x$ac_cv_lib_cunit_CU_initialize_registry" = xyes; then : + have_cunit=yes +else + have_cunit=no +fi + + if test "x${have_cunit}" = "xyes"; then + CUNIT_LIBS="-lcunit" + CUNIT_CFLAGS="" + + + fi +fi +if test "x${have_cunit}" = "xyes"; then + # cunit in Mac OS X requires ncurses. Note that in Mac OS X, test + # program can be built without -lncurses, but it emits runtime + # error. + case "${build}" in + *-apple-darwin*) + CUNIT_LIBS="$CUNIT_LIBS -lncurses" + + ;; + esac +fi + + if test "x${have_cunit}" = "xyes" ; then + HAVE_CUNIT_TRUE= + HAVE_CUNIT_FALSE='#' else - link_thread="no" + HAVE_CUNIT_TRUE='#' + HAVE_CUNIT_FALSE= fi - done - fi - if test "x$ax_lib" = "x"; then - as_fn_error $? "Could not find a version of the library!" "$LINENO" 5 - fi - if test "x$link_thread" = "xno"; then - as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5 - else - case "x$host_os" in - *bsd* ) - BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS" - break; - ;; - esac +# openssl (for src) - fi - fi +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5 +$as_echo_n "checking for OPENSSL... " >&6; } - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - fi +if test -n "$OPENSSL_CFLAGS"; then + pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 1.0.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl >= 1.0.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "openssl >= 1.0.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$OPENSSL_LIBS"; then + pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 1.0.1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "openssl >= 1.0.1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "openssl >= 1.0.1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi - if test "x${ax_cv_boost_asio}" = "xyes" && - test "x${ax_cv_boost_system}" = "xyes" && - test "x${ax_cv_boost_thread}" = "xyes"; then - have_asio_lib=yes - fi - fi -fi -# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL -# and libev -enable_app=no -if test "x${request_app}" != "xno" && - test "x${have_zlib}" = "xyes" && - test "x${have_openssl}" = "xyes" && - test "x${have_libev}" = "xyes"; then - enable_app=yes -fi +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } -if test "x${request_app}" = "xyes" && - test "x${enable_app}" != "xyes"; then - as_fn_error $? "applications were requested (--enable-app) but dependencies are not met." "$LINENO" 5 +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no fi + if test $_pkg_short_errors_supported = yes; then + OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl >= 1.0.1" 2>&1` + else + OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl >= 1.0.1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$OPENSSL_PKG_ERRORS" >&5 - if test "x${enable_app}" = "xyes" ; then - ENABLE_APP_TRUE= - ENABLE_APP_FALSE='#' + have_openssl=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_openssl=no else - ENABLE_APP_TRUE='#' - ENABLE_APP_FALSE= + OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS + OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_openssl=yes +fi +if test "x${have_openssl}" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $OPENSSL_PKG_ERRORS" >&5 +$as_echo "$as_me: $OPENSSL_PKG_ERRORS" >&6;} fi +# libevent_openssl (for src) +# 2.0.8 is required because we use evconnlistener_set_error_cb() + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBEVENT_OPENSSL" >&5 +$as_echo_n "checking for LIBEVENT_OPENSSL... " >&6; } -enable_hpack_tools=no -# HPACK tools requires jansson -if test "x${request_hpack_tools}" != "xno" && - test "x${have_jansson}" = "xyes"; then - enable_hpack_tools=yes +if test -n "$LIBEVENT_OPENSSL_CFLAGS"; then + pkg_cv_LIBEVENT_OPENSSL_CFLAGS="$LIBEVENT_OPENSSL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libevent_openssl >= 2.0.8\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libevent_openssl >= 2.0.8") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBEVENT_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "libevent_openssl >= 2.0.8" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes fi - -if test "x${request_hpack_tools}" = "xyes" && - test "x${enable_hpack_tools}" != "xyes"; then - as_fn_error $? "HPACK tools were requested (--enable-hpack-tools) but dependencies are not met." "$LINENO" 5 + else + pkg_failed=untried fi - - if test "x${enable_hpack_tools}" = "xyes" ; then - ENABLE_HPACK_TOOLS_TRUE= - ENABLE_HPACK_TOOLS_FALSE='#' +if test -n "$LIBEVENT_OPENSSL_LIBS"; then + pkg_cv_LIBEVENT_OPENSSL_LIBS="$LIBEVENT_OPENSSL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libevent_openssl >= 2.0.8\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libevent_openssl >= 2.0.8") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBEVENT_OPENSSL_LIBS=`$PKG_CONFIG --libs "libevent_openssl >= 2.0.8" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else - ENABLE_HPACK_TOOLS_TRUE='#' - ENABLE_HPACK_TOOLS_FALSE= + pkg_failed=yes +fi + else + pkg_failed=untried fi -# C++ library libnghttp2_asio -enable_asio_lib=no -if test "x${request_asio_lib}" != "xno" && - test "x${have_asio_lib}" = "xyes"; then - enable_asio_lib=yes +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no fi + if test $_pkg_short_errors_supported = yes; then + LIBEVENT_OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libevent_openssl >= 2.0.8" 2>&1` + else + LIBEVENT_OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libevent_openssl >= 2.0.8" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBEVENT_OPENSSL_PKG_ERRORS" >&5 - if test "x${enable_asio_lib}" = "xyes" ; then - ENABLE_ASIO_LIB_TRUE= - ENABLE_ASIO_LIB_FALSE='#' + have_libevent_openssl=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_libevent_openssl=no else - ENABLE_ASIO_LIB_TRUE='#' - ENABLE_ASIO_LIB_FALSE= + LIBEVENT_OPENSSL_CFLAGS=$pkg_cv_LIBEVENT_OPENSSL_CFLAGS + LIBEVENT_OPENSSL_LIBS=$pkg_cv_LIBEVENT_OPENSSL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_libevent_openssl=yes +fi +if test "x${have_libevent_openssl}" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $LIBEVENT_OPENSSL_PKG_ERRORS" >&5 +$as_echo "$as_me: $LIBEVENT_OPENSSL_PKG_ERRORS" >&6;} fi +# jansson (for src/nghttp, src/deflatehd and src/inflatehd) -# The example programs depend on OpenSSL and libevent_openssl -enable_examples=no -if test "x${request_examples}" != "xno" && - test "x${have_openssl}" = "xyes" && - test "x${have_libevent_openssl}" = "xyes"; then - enable_examples=yes -fi +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JANSSON" >&5 +$as_echo_n "checking for JANSSON... " >&6; } -if test "x${request_examples}" = "xyes" && - test "x${enable_examples}" != "xyes"; then - as_fn_error $? "examples were requested (--enable-examples) but dependencies are not met." "$LINENO" 5 +if test -n "$JANSSON_CFLAGS"; then + pkg_cv_JANSSON_CFLAGS="$JANSSON_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson >= 2.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "jansson >= 2.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_JANSSON_CFLAGS=`$PKG_CONFIG --cflags "jansson >= 2.5" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes fi - - if test "x${enable_examples}" = "xyes" ; then - ENABLE_EXAMPLES_TRUE= - ENABLE_EXAMPLES_FALSE='#' + else + pkg_failed=untried +fi +if test -n "$JANSSON_LIBS"; then + pkg_cv_JANSSON_LIBS="$JANSSON_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson >= 2.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "jansson >= 2.5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_JANSSON_LIBS=`$PKG_CONFIG --libs "jansson >= 2.5" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes else - ENABLE_EXAMPLES_TRUE='#' - ENABLE_EXAMPLES_FALSE= + pkg_failed=yes +fi + else + pkg_failed=untried fi -# third-party only be built when needed - -enable_third_party=no -have_mruby=no -have_neverbleed=no -if test "x${enable_examples}" = "xyes" || - test "x${enable_app}" = "xyes" || - test "x${enable_hpack_tools}" = "xyes" || - test "x${enable_asio_lib}" = "xyes"; then - enable_third_party=yes - - # mruby (for src/nghttpx) - if test "x${request_mruby}" = "xyes"; then - # We are going to build mruby - have_mruby=yes -$as_echo "#define HAVE_MRUBY 1" >>confdefs.h +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } - LIBMRUBY_LIBS="-lmruby -lm" - LIBMRUBY_CFLAGS= +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + JANSSON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "jansson >= 2.5" 2>&1` + else + JANSSON_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "jansson >= 2.5" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$JANSSON_PKG_ERRORS" >&5 + have_jansson=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_jansson=no +else + JANSSON_CFLAGS=$pkg_cv_JANSSON_CFLAGS + JANSSON_LIBS=$pkg_cv_JANSSON_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_jansson=yes +fi +if test "x${have_jansson}" == "xyes"; then - fi +$as_echo "#define HAVE_JANSSON 1" >>confdefs.h - # neverbleed (for src/nghttpx) - if test "x${request_neverbleed}" = "xyes"; then - have_neverbleed=yes +else + { $as_echo "$as_me:${as_lineno-$LINENO}: $JANSSON_PKG_ERRORS" >&5 +$as_echo "$as_me: $JANSSON_PKG_ERRORS" >&6;} +fi -$as_echo "#define HAVE_NEVERBLEED 1" >>confdefs.h +# libxml2 (for src/nghttp) +have_libxml2=no +if test "x${request_libxml2}" != "xno"; then - fi -fi - if test "x${enable_third_party}" = "xyes" ; then - ENABLE_THIRD_PARTY_TRUE= - ENABLE_THIRD_PARTY_FALSE='#' +# Check whether --with-xml-prefix was given. +if test "${with_xml_prefix+set}" = set; then : + withval=$with_xml_prefix; xml_config_prefix="$withval" else - ENABLE_THIRD_PARTY_TRUE='#' - ENABLE_THIRD_PARTY_FALSE= + xml_config_prefix="" fi - if test "x${have_mruby}" = "xyes"; then - HAVE_MRUBY_TRUE= - HAVE_MRUBY_FALSE='#' + +# Check whether --with-xml-exec-prefix was given. +if test "${with_xml_exec_prefix+set}" = set; then : + withval=$with_xml_exec_prefix; xml_config_exec_prefix="$withval" else - HAVE_MRUBY_TRUE='#' - HAVE_MRUBY_FALSE= + xml_config_exec_prefix="" fi - if test "x${have_neverbleed}" = "xyes"; then - HAVE_NEVERBLEED_TRUE= - HAVE_NEVERBLEED_FALSE='#' +# Check whether --enable-xmltest was given. +if test "${enable_xmltest+set}" = set; then : + enableval=$enable_xmltest; else - HAVE_NEVERBLEED_TRUE='#' - HAVE_NEVERBLEED_FALSE= + enable_xmltest=yes fi -# Python bindings -enable_python_bindings=no -if test "x${request_python_bindings}" != "xno" && - test "x${CYTHON}" != "x" && - test "x${PYTHON}" != "x:" && - test "x${have_python_dev}" = "xyes"; then - enable_python_bindings=yes -fi - -if test "x${request_python_bindings}" = "xyes" && - test "x${enable_python_bindings}" != "xyes"; then - as_fn_error $? "python bindings were requested (--enable-python-bindings) but dependencies are not met." "$LINENO" 5 -fi + if test x$xml_config_exec_prefix != x ; then + xml_config_args="$xml_config_args" + if test x${XML2_CONFIG+set} != xset ; then + XML2_CONFIG=$xml_config_exec_prefix/bin/xml2-config + fi + fi + if test x$xml_config_prefix != x ; then + xml_config_args="$xml_config_args --prefix=$xml_config_prefix" + if test x${XML2_CONFIG+set} != xset ; then + XML2_CONFIG=$xml_config_prefix/bin/xml2-config + fi + fi - if test "x${enable_python_bindings}" = "xyes"; then - ENABLE_PYTHON_BINDINGS_TRUE= - ENABLE_PYTHON_BINDINGS_FALSE='#' + # Extract the first word of "xml2-config", so it can be a program name with args. +set dummy xml2-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XML2_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 else - ENABLE_PYTHON_BINDINGS_TRUE='#' - ENABLE_PYTHON_BINDINGS_FALSE= -fi - + case $XML2_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_XML2_CONFIG="$XML2_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_XML2_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS -# Produce cython conditional, so that we can distribute generated C -# source - if test "x${CYTHON}" != "x"; then - HAVE_CYTHON_TRUE= - HAVE_CYTHON_FALSE='#' + test -z "$ac_cv_path_XML2_CONFIG" && ac_cv_path_XML2_CONFIG="no" + ;; +esac +fi +XML2_CONFIG=$ac_cv_path_XML2_CONFIG +if test -n "$XML2_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XML2_CONFIG" >&5 +$as_echo "$XML2_CONFIG" >&6; } else - HAVE_CYTHON_TRUE='#' - HAVE_CYTHON_FALSE= + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -# failmalloc tests -enable_failmalloc=no -if test "x${request_failmalloc}" = "xyes"; then - enable_failmalloc=yes -fi - - if test "x${enable_failmalloc}" = "xyes" ; then - ENABLE_FAILMALLOC_TRUE= - ENABLE_FAILMALLOC_FALSE='#' + min_xml_version=2.7.7 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libxml - version >= $min_xml_version" >&5 +$as_echo_n "checking for libxml - version >= $min_xml_version... " >&6; } + no_xml="" + if test "$XML2_CONFIG" = "no" ; then + no_xml=yes + else + XML_CPPFLAGS=`$XML2_CONFIG $xml_config_args --cflags` + XML_LIBS=`$XML2_CONFIG $xml_config_args --libs` + xml_config_major_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + xml_config_minor_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + xml_config_micro_version=`$XML2_CONFIG $xml_config_args --version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + if test "x$enable_xmltest" = "xyes" ; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" + LIBS="$XML_LIBS $LIBS" + rm -f conf.xmltest + if test "$cross_compiling" = yes; then : + echo $ac_n "cross compiling; assumed OK... $ac_c" else - ENABLE_FAILMALLOC_TRUE='#' - ENABLE_FAILMALLOC_FALSE= -fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include -# Checks for header files. +int +main() +{ + int xml_major_version, xml_minor_version, xml_micro_version; + int major, minor, micro; + char *tmp_version; - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable assertions" >&5 -$as_echo_n "checking whether to enable assertions... " >&6; } - # Check whether --enable-assert was given. -if test "${enable_assert+set}" = set; then : - enableval=$enable_assert; ac_enable_assert=$enableval - if test "x$enableval" = xno; then : + system("touch conf.xmltest"); -$as_echo "#define NDEBUG 1" >>confdefs.h + /* Capture xml2-config output via autoconf/configure variables */ + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = (char *)strdup("$min_xml_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string from xml2-config\n", "$min_xml_version"); + exit(1); + } + free(tmp_version); -elif test "x$enableval" != xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: invalid argument supplied to --enable-assert" >&5 -$as_echo "$as_me: WARNING: invalid argument supplied to --enable-assert" >&2;} - ac_enable_assert=yes -fi -else - ac_enable_assert=yes -fi + /* Capture the version information from the header files */ + tmp_version = (char *)strdup(LIBXML_DOTTED_VERSION); + if (sscanf(tmp_version, "%d.%d.%d", &xml_major_version, &xml_minor_version, &xml_micro_version) != 3) { + printf("%s, bad version string from libxml includes\n", "LIBXML_DOTTED_VERSION"); + exit(1); + } + free(tmp_version); - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_enable_assert" >&5 -$as_echo "$ac_enable_assert" >&6; } + /* Compare xml2-config output to the libxml headers */ + if ((xml_major_version != $xml_config_major_version) || + (xml_minor_version != $xml_config_minor_version) || + (xml_micro_version != $xml_config_micro_version)) + { + printf("*** libxml header files (version %d.%d.%d) do not match\n", + xml_major_version, xml_minor_version, xml_micro_version); + printf("*** xml2-config (version %d.%d.%d)\n", + $xml_config_major_version, $xml_config_minor_version, $xml_config_micro_version); + return 1; + } +/* Compare the headers to the library to make sure we match */ + /* Less than ideal -- doesn't provide us with return value feedback, + * only exits if there's a serious mismatch between header and library. + */ + LIBXML_TEST_VERSION; -for ac_header in \ - 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 \ + /* Test that the library is greater than our minimum version */ + if ((xml_major_version > major) || + ((xml_major_version == major) && (xml_minor_version > minor)) || + ((xml_major_version == major) && (xml_minor_version == minor) && + (xml_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of libxml (%d.%d.%d) was found.\n", + xml_major_version, xml_minor_version, xml_micro_version); + printf("*** You need a version of libxml newer than %d.%d.%d. The latest version of\n", + major, minor, micro); + printf("*** libxml is always available from ftp://ftp.xmlsoft.org.\n"); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the xml2-config shell script is\n"); + printf("*** being found. The easiest way to fix this is to remove the old version\n"); + printf("*** of LIBXML, but you can also set the XML2_CONFIG environment to point to the\n"); + printf("*** correct copy of xml2-config. (In this case, you will have to\n"); + printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); + printf("*** so that the correct libraries are found at run-time))\n"); + } + return 1; +} -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF +if ac_fn_c_try_run "$LINENO"; then : +else + no_xml=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi -done - + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + fi + fi -# Checks for typedefs, structures, and compiler characteristics. -ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" -if test "x$ac_cv_type_size_t" = xyes; then : + if test "x$no_xml" = x ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)" >&5 +$as_echo "yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)" >&6; } + have_libxml2=yes + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "$XML2_CONFIG" = "no" ; then + echo "*** The xml2-config script installed by LIBXML could not be found" + echo "*** If libxml was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the XML2_CONFIG environment variable to the" + echo "*** full path to xml2-config." + else + if test -f conf.xmltest ; then + : + else + echo "*** Could not run libxml test program, checking why..." + CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" + LIBS="$LIBS $XML_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -else +#include +#include -cat >>confdefs.h <<_ACEOF -#define size_t unsigned int +int +main () +{ + LIBXML_TEST_VERSION; return 0; + ; + return 0; +} _ACEOF - -fi - -ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" -if test "x$ac_cv_type_ssize_t" = xyes; then : - +if ac_fn_c_try_link "$LINENO"; then : + echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding LIBXML or finding the wrong" + echo "*** version of LIBXML. If it is not finding LIBXML, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" else - -cat >>confdefs.h <<_ACEOF -#define ssize_t int -_ACEOF - + echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means LIBXML was incorrectly installed" + echo "*** or that you have moved LIBXML since it was installed. In the latter case, you" + echo "*** may want to edit the xml2-config script: $XML2_CONFIG" fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + fi + fi -ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t" -case $ac_cv_c_uint8_t in #( - no|yes) ;; #( - *) + XML_CPPFLAGS="" + XML_LIBS="" + have_libxml2=no + fi -$as_echo "#define _UINT8_T 1" >>confdefs.h + rm -f conf.xmltest -cat >>confdefs.h <<_ACEOF -#define uint8_t $ac_cv_c_uint8_t -_ACEOF -;; - esac + if test "x${have_libxml2}" = "xyes"; then -ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t" -case $ac_cv_c_uint16_t in #( - no|yes) ;; #( - *) +$as_echo "#define HAVE_LIBXML2 1" >>confdefs.h + fi +fi -cat >>confdefs.h <<_ACEOF -#define uint16_t $ac_cv_c_uint16_t -_ACEOF -;; - esac +if test "x${request_libxml2}" = "xyes" && + test "x${have_libxml2}" != "xyes"; then + as_fn_error $? "libxml2 was requested (--with-libxml2) but not found" "$LINENO" 5 +fi -ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" -case $ac_cv_c_uint32_t in #( - no|yes) ;; #( - *) + if test "x${have_libxml2}" = "xyes" ; then + HAVE_LIBXML2_TRUE= + HAVE_LIBXML2_FALSE='#' +else + HAVE_LIBXML2_TRUE='#' + HAVE_LIBXML2_FALSE= +fi -$as_echo "#define _UINT32_T 1" >>confdefs.h +# jemalloc +have_jemalloc=no +if test "x${request_jemalloc}" != "xno"; then + LIBS_OLD=$LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing malloc_stats_print" >&5 +$as_echo_n "checking for library containing malloc_stats_print... " >&6; } +if ${ac_cv_search_malloc_stats_print+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -cat >>confdefs.h <<_ACEOF -#define uint32_t $ac_cv_c_uint32_t +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char malloc_stats_print (); +int +main () +{ +return malloc_stats_print (); + ; + return 0; +} _ACEOF -;; - esac - -ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" -case $ac_cv_c_uint64_t in #( - no|yes) ;; #( - *) - -$as_echo "#define _UINT64_T 1" >>confdefs.h - +for ac_lib in '' jemalloc; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $PTHREAD_LDFLAGS $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_malloc_stats_print=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_malloc_stats_print+:} false; then : + break +fi +done +if ${ac_cv_search_malloc_stats_print+:} false; then : -cat >>confdefs.h <<_ACEOF -#define uint64_t $ac_cv_c_uint64_t -_ACEOF -;; - esac +else + ac_cv_search_malloc_stats_print=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_malloc_stats_print" >&5 +$as_echo "$ac_cv_search_malloc_stats_print" >&6; } +ac_res=$ac_cv_search_malloc_stats_print +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + have_jemalloc=yes +fi -ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t" -case $ac_cv_c_int8_t in #( - no|yes) ;; #( - *) + LIBS=$LIBS_OLD + 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} -cat >>confdefs.h <<_ACEOF -#define int8_t $ac_cv_c_int8_t -_ACEOF -;; -esac + fi +fi -ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t" -case $ac_cv_c_int16_t in #( - no|yes) ;; #( - *) +if test "x${request_jemalloc}" = "xyes" && + test "x${have_jemalloc}" != "xyes"; then + as_fn_error $? "jemalloc was requested (--with-jemalloc) but not found" "$LINENO" 5 +fi -cat >>confdefs.h <<_ACEOF -#define int16_t $ac_cv_c_int16_t -_ACEOF -;; -esac +# spdylay (for src/nghttpx and src/h2load) +have_spdylay=no +if test "x${request_spdylay}" != "xno"; then -ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t" -case $ac_cv_c_int32_t in #( - no|yes) ;; #( - *) +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSPDYLAY" >&5 +$as_echo_n "checking for LIBSPDYLAY... " >&6; } -cat >>confdefs.h <<_ACEOF -#define int32_t $ac_cv_c_int32_t -_ACEOF -;; -esac +if test -n "$LIBSPDYLAY_CFLAGS"; then + pkg_cv_LIBSPDYLAY_CFLAGS="$LIBSPDYLAY_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libspdylay >= 1.3.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libspdylay >= 1.3.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBSPDYLAY_CFLAGS=`$PKG_CONFIG --cflags "libspdylay >= 1.3.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBSPDYLAY_LIBS"; then + pkg_cv_LIBSPDYLAY_LIBS="$LIBSPDYLAY_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libspdylay >= 1.3.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libspdylay >= 1.3.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBSPDYLAY_LIBS=`$PKG_CONFIG --libs "libspdylay >= 1.3.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi -ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t" -case $ac_cv_c_int64_t in #( - no|yes) ;; #( - *) -cat >>confdefs.h <<_ACEOF -#define int64_t $ac_cv_c_int64_t -_ACEOF -;; -esac -ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" -if test "x$ac_cv_type_off_t" = xyes; then : +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes else - -cat >>confdefs.h <<_ACEOF -#define off_t long int -_ACEOF - + _pkg_short_errors_supported=no fi + if test $_pkg_short_errors_supported = yes; then + LIBSPDYLAY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libspdylay >= 1.3.0" 2>&1` + else + LIBSPDYLAY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libspdylay >= 1.3.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBSPDYLAY_PKG_ERRORS" >&5 -ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" -if test "x$ac_cv_type_pid_t" = xyes; then : - + have_spdylay=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_spdylay=no else + LIBSPDYLAY_CFLAGS=$pkg_cv_LIBSPDYLAY_CFLAGS + LIBSPDYLAY_LIBS=$pkg_cv_LIBSPDYLAY_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_spdylay=yes +fi + if test "x${have_spdylay}" = "xyes"; then -cat >>confdefs.h <<_ACEOF -#define pid_t int -_ACEOF +$as_echo "#define HAVE_SPDYLAY 1" >>confdefs.h + else + { $as_echo "$as_me:${as_lineno-$LINENO}: $LIBSPDYLAY_PKG_ERRORS" >&5 +$as_echo "$as_me: $LIBSPDYLAY_PKG_ERRORS" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: The SPDY support in nghttpx and h2load will be disabled." >&5 +$as_echo "$as_me: The SPDY support in nghttpx and h2load will be disabled." >&6;} + fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 -$as_echo_n "checking for uid_t in sys/types.h... " >&6; } -if ${ac_cv_type_uid_t+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include +if test "x${request_spdylay}" = "xyes" && + test "x${have_spdylay}" != "xyes"; then + as_fn_error $? "spdylay was requested (--with-spdylay) but not found" "$LINENO" 5 +fi -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "uid_t" >/dev/null 2>&1; then : - ac_cv_type_uid_t=yes + if test "x${have_spdylay}" = "xyes" ; then + HAVE_SPDYLAY_TRUE= + HAVE_SPDYLAY_FALSE='#' else - ac_cv_type_uid_t=no + HAVE_SPDYLAY_TRUE='#' + HAVE_SPDYLAY_FALSE= fi -rm -f conftest* -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 -$as_echo "$ac_cv_type_uid_t" >&6; } -if test $ac_cv_type_uid_t = no; then -$as_echo "#define uid_t int" >>confdefs.h +# Check Boost Asio library +have_asio_lib=no + +if test "x${request_asio_lib}" = "xyes"; then -$as_echo "#define gid_t int" >>confdefs.h +# Check whether --with-boost was given. +if test "${with_boost+set}" = set; then : + withval=$with_boost; + if test "$withval" = "no"; then + want_boost="no" + elif test "$withval" = "yes"; then + want_boost="yes" + ac_boost_path="" + else + want_boost="yes" + ac_boost_path="$withval" + fi +else + want_boost="yes" fi -ac_fn_c_check_type "$LINENO" "ptrdiff_t" "ac_cv_type_ptrdiff_t" "$ac_includes_default" -if test "x$ac_cv_type_ptrdiff_t" = xyes; then : -cat >>confdefs.h <<_ACEOF -#define HAVE_PTRDIFF_T 1 -_ACEOF -fi +# Check whether --with-boost-libdir was given. +if test "${with_boost_libdir+set}" = set; then : + withval=$with_boost_libdir; + if test -d "$withval" + then + ac_boost_lib_path="$withval" + else + as_fn_error $? "--with-boost-libdir expected directory name" "$LINENO" 5 + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 -$as_echo_n "checking whether byte ordering is bigendian... " >&6; } -if ${ac_cv_c_bigendian+:} false; then : - $as_echo_n "(cached) " >&6 else - ac_cv_c_bigendian=unknown - # See if we're dealing with a universal compiler. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifndef __APPLE_CC__ - not a universal capable compiler - #endif - typedef int dummy; - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : + ac_boost_lib_path="" - # Check for potential -arch flags. It is not universal unless - # there are at least two -arch flags with different values. - ac_arch= - ac_prev= - for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do - if test -n "$ac_prev"; then - case $ac_word in - i?86 | x86_64 | ppc | ppc64) - if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then - ac_arch=$ac_word - else - ac_cv_c_bigendian=universal - break - fi - ;; - esac - ac_prev= - elif test "x$ac_word" = "x-arch"; then - ac_prev=arch - fi - done fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - if test $ac_cv_c_bigendian = unknown; then - # See if sys/param.h defines the BYTE_ORDER macro. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - #include -int -main () -{ -#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ - && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ - && LITTLE_ENDIAN) - bogus endian macros - #endif - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - # It does; now see whether it defined to BIG_ENDIAN or not. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - #include +if test "x$want_boost" = "xyes"; then + boost_lib_version_req=1.54.0 + boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([0-9]*\.[0-9]*\)'` + boost_lib_version_req_major=`expr $boost_lib_version_req : '\([0-9]*\)'` + boost_lib_version_req_minor=`expr $boost_lib_version_req : '[0-9]*\.\([0-9]*\)'` + boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[0-9]*\.[0-9]*\.\([0-9]*\)'` + if test "x$boost_lib_version_req_sub_minor" = "x" ; then + boost_lib_version_req_sub_minor="0" + fi + WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for boostlib >= $boost_lib_version_req" >&5 +$as_echo_n "checking for boostlib >= $boost_lib_version_req... " >&6; } + succeeded=no -int -main () -{ -#if BYTE_ORDER != BIG_ENDIAN - not big endian - #endif + libsubdirs="lib" + ax_arch=`uname -m` + case $ax_arch in + x86_64) + libsubdirs="lib64 libx32 lib lib64" + ;; + ppc64|s390x|sparc64|aarch64|ppc64le) + libsubdirs="lib64 lib lib64 ppc64le" + ;; + esac - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_bigendian=yes -else - ac_cv_c_bigendian=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs" + + case ${host_cpu} in + i?86) + libsubdirs="lib/i386-${host_os} $libsubdirs" + ;; + esac + + if test "$ac_boost_path" != ""; then + BOOST_CPPFLAGS="-I$ac_boost_path/include" + for ac_boost_path_tmp in $libsubdirs; do + if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then + BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp" + break + fi + done + elif test "$cross_compiling" != yes; then + for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do + if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then + for libsubdir in $libsubdirs ; do + if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi + done + BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir" + BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" + break; + fi + done fi - if test $ac_cv_c_bigendian = unknown; then - # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) - bogus endian macros - #endif + if test "$ac_boost_lib_path" != ""; then + BOOST_LDFLAGS="-L$ac_boost_lib_path" + fi + + CPPFLAGS_SAVED="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" + export CPPFLAGS + + LDFLAGS_SAVED="$LDFLAGS" + LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" + export LDFLAGS + - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - # It does; now see whether it defined to _BIG_ENDIAN or not. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + + #include int main () { -#ifndef _BIG_ENDIAN - not big endian - #endif + + #if BOOST_VERSION >= $WANT_BOOST_VERSION + // Everything is okay + #else + # error Boost version is too old + #endif ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_bigendian=yes -else - ac_cv_c_bigendian=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +if ac_fn_cxx_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + succeeded=yes + found_system=yes + fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi - if test $ac_cv_c_bigendian = unknown; then - # Compile a test program. - if test "$cross_compiling" = yes; then : - # Try to guess by grepping values from an object file. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + if test "x$succeeded" != "xyes"; then + _version=0 + if test "$ac_boost_path" != ""; then + if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then + for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do + _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` + V_CHECK=`expr $_version_tmp \> $_version` + if test "$V_CHECK" = "1" ; then + _version=$_version_tmp + fi + VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` + BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" + done + fi + else + if test "$cross_compiling" != yes; then + for ac_boost_path in /usr /usr/local /opt /opt/local ; do + if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then + for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do + _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` + V_CHECK=`expr $_version_tmp \> $_version` + if test "$V_CHECK" = "1" ; then + _version=$_version_tmp + best_path=$ac_boost_path + fi + done + fi + done + + VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` + BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" + if test "$ac_boost_lib_path" = ""; then + for libsubdir in $libsubdirs ; do + if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi + done + BOOST_LDFLAGS="-L$best_path/$libsubdir" + fi + fi + + if test "x$BOOST_ROOT" != "x"; then + for libsubdir in $libsubdirs ; do + if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi + done + if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then + version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` + stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` + stage_version_shorten=`expr $stage_version : '\([0-9]*\.[0-9]*\)'` + V_CHECK=`expr $stage_version_shorten \>\= $_version` + if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: We will use a staged boost library from $BOOST_ROOT" >&5 +$as_echo "$as_me: We will use a staged boost library from $BOOST_ROOT" >&6;} + BOOST_CPPFLAGS="-I$BOOST_ROOT" + BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" + fi + fi + fi + fi + + CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" + export CPPFLAGS + LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" + export LDFLAGS + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -short int ascii_mm[] = - { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; - short int ascii_ii[] = - { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; - int use_ascii (int i) { - return ascii_mm[i] + ascii_ii[i]; - } - short int ebcdic_ii[] = - { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; - short int ebcdic_mm[] = - { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; - int use_ebcdic (int i) { - return ebcdic_mm[i] + ebcdic_ii[i]; - } - extern int foo; + + #include int main () { -return use_ascii (foo) == use_ebcdic (foo); + + #if BOOST_VERSION >= $WANT_BOOST_VERSION + // Everything is okay + #else + # error Boost version is too old + #endif + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then - ac_cv_c_bigendian=yes - fi - if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then - if test "$ac_cv_c_bigendian" = unknown; then - ac_cv_c_bigendian=no - else - # finding both strings is unlikely to happen, but who knows? - ac_cv_c_bigendian=unknown - fi - fi +if ac_fn_cxx_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + succeeded=yes + found_system=yes + fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu - /* Are we little or big endian? From Harbison&Steele. */ - union - { - long int l; - char c[sizeof (long int)]; - } u; - u.l = 1; - return u.c[sizeof (long int) - 1] == 1; + fi - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_c_bigendian=no -else - ac_cv_c_bigendian=yes -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi + if test "$succeeded" != "yes" ; then + if test "$_version" = "0" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation." >&5 +$as_echo "$as_me: We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation." >&6;} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Your boost libraries seems to old (version $_version)." >&5 +$as_echo "$as_me: Your boost libraries seems to old (version $_version)." >&6;} + fi + # execute ACTION-IF-NOT-FOUND (if present): + have_boost_base=no + else + + + +$as_echo "#define HAVE_BOOST /**/" >>confdefs.h + # execute ACTION-IF-FOUND (if present): + have_boost_base=yes fi + + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 -$as_echo "$ac_cv_c_bigendian" >&6; } - case $ac_cv_c_bigendian in #( - yes) - $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h -;; #( - no) - ;; #( - universal) -$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h - ;; #( - *) - as_fn_error $? "unknown endianness - presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; - esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 -$as_echo_n "checking for inline... " >&6; } -if ${ac_cv_c_inline+:} false; then : + if test "x${have_boost_base}" = "xyes"; then + + +# Check whether --with-boost-asio was given. +if test "${with_boost_asio+set}" = set; then : + withval=$with_boost_asio; + if test "$withval" = "no"; then + want_boost="no" + elif test "$withval" = "yes"; then + want_boost="yes" + ax_boost_user_asio_lib="" + else + want_boost="yes" + ax_boost_user_asio_lib="$withval" + fi + +else + want_boost="yes" + +fi + + + if test "x$want_boost" = "xyes"; then + + CPPFLAGS_SAVED="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" + export CPPFLAGS + + LDFLAGS_SAVED="$LDFLAGS" + LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" + export LDFLAGS + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Boost::ASIO library is available" >&5 +$as_echo_n "checking whether the Boost::ASIO library is available... " >&6; } +if ${ax_cv_boost_asio+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_c_inline=no -for ac_kw in inline __inline__ __inline; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#ifndef __cplusplus -typedef int foo_t; -static $ac_kw foo_t static_foo () {return 0; } -$ac_kw foo_t foo () {return 0; } -#endif + #include + +int +main () +{ + + + boost::asio::io_service io; + boost::system::error_code timer_result; + boost::asio::deadline_timer t(io); + t.cancel(); + io.run_one(); + return 0; + ; + return 0; +} _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_inline=$ac_kw +if ac_fn_cxx_try_compile "$LINENO"; then : + ax_cv_boost_asio=yes +else + ax_cv_boost_asio=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - test "$ac_cv_c_inline" != no && break -done - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 -$as_echo "$ac_cv_c_inline" >&6; } + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu -case $ac_cv_c_inline in - inline | yes) ;; - *) - case $ac_cv_c_inline in - no) ac_val=;; - *) ac_val=$ac_cv_c_inline;; - esac - cat >>confdefs.h <<_ACEOF -#ifndef __cplusplus -#define inline $ac_val -#endif -_ACEOF - ;; -esac -# Check whether --enable-largefile was given. -if test "${enable_largefile+set}" = set; then : - enableval=$enable_largefile; fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_asio" >&5 +$as_echo "$ax_cv_boost_asio" >&6; } + if test "x$ax_cv_boost_asio" = "xyes"; then -if test "$enable_largefile" != no; then +$as_echo "#define HAVE_BOOST_ASIO /**/" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 -$as_echo_n "checking for special C compiler options needed for large files... " >&6; } -if ${ac_cv_sys_largefile_CC+:} false; then : + BN=boost_system + BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/[^\/]*//'` + if test "x$ax_boost_user_asio_lib" = "x"; then + for ax_lib in `ls $BOOSTLIBDIR/libboost_system*.so* $BOOSTLIBDIR/libboost_system*.dylib* $BOOSTLIBDIR/libboost_system*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_system.*\)\.so.*$;\1;' -e 's;^lib\(boost_system.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_system.*\)\.a.*$;\1;' ` ; do + as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_main" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l$ax_lib" >&5 +$as_echo_n "checking for main in -l$ax_lib... " >&6; } +if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_sys_largefile_CC=no - if test "$GCC" != yes; then - ac_save_CC=$CC - while :; do - # IRIX 6.2 and later do not support large files by default, - # so use the C compiler's -n32 option if that helps. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$ax_lib $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; + + int main () { - +return main (); ; return 0; } _ACEOF - if ac_fn_c_try_compile "$LINENO"; then : - break +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" fi -rm -f core conftest.err conftest.$ac_objext - CC="$CC -n32" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_sys_largefile_CC=' -n32'; break +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -rm -f core conftest.err conftest.$ac_objext - break - done - CC=$ac_save_CC - rm -f conftest.$ac_ext - fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + BOOST_ASIO_LIB="-l$ax_lib" link_thread="yes" break +else + link_thread="no" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 -$as_echo "$ac_cv_sys_largefile_CC" >&6; } - if test "$ac_cv_sys_largefile_CC" != no; then - CC=$CC$ac_cv_sys_largefile_CC - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 -$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } -if ${ac_cv_sys_file_offset_bits+:} false; then : + done + else + for ax_lib in $ax_boost_user_asio_lib $BN-$ax_boost_user_asio_lib; do + as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_main" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -l$ax_lib" >&5 +$as_echo_n "checking for main in -l$ax_lib... " >&6; } +if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else - while :; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$ax_lib $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; + + int main () { - +return main (); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_sys_file_offset_bits=no; break +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#define _FILE_OFFSET_BITS 64 -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + BOOST_ASIO_LIB="-l$ax_lib" link_asio="yes" break +else + link_asio="no" +fi + + done + + fi + if test "x$ax_lib" = "x"; then + as_fn_error $? "Could not find a version of the library!" "$LINENO" 5 + fi + if test "x$link_asio" = "xno"; then + as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5 + fi + fi + + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + fi + + + +# Check whether --with-boost-system was given. +if test "${with_boost_system+set}" = set; then : + withval=$with_boost_system; + if test "$withval" = "no"; then + want_boost="no" + elif test "$withval" = "yes"; then + want_boost="yes" + ax_boost_user_system_lib="" + else + want_boost="yes" + ax_boost_user_system_lib="$withval" + fi + +else + want_boost="yes" + +fi + + + if test "x$want_boost" = "xyes"; then + + + CPPFLAGS_SAVED="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" + export CPPFLAGS + + LDFLAGS_SAVED="$LDFLAGS" + LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" + export LDFLAGS + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Boost::System library is available" >&5 +$as_echo_n "checking whether the Boost::System library is available... " >&6; } +if ${ax_cv_boost_system+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CXXFLAGS_SAVE=$CXXFLAGS + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include int main () { - +boost::system::system_category ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_sys_file_offset_bits=64; break +if ac_fn_cxx_try_compile "$LINENO"; then : + ax_cv_boost_system=yes +else + ax_cv_boost_system=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cv_sys_file_offset_bits=unknown - break -done + CXXFLAGS=$CXXFLAGS_SAVE + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 -$as_echo "$ac_cv_sys_file_offset_bits" >&6; } -case $ac_cv_sys_file_offset_bits in #( - no | unknown) ;; - *) -cat >>confdefs.h <<_ACEOF -#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits -_ACEOF -;; -esac -rm -rf conftest* - if test $ac_cv_sys_file_offset_bits = unknown; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 -$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } -if ${ac_cv_sys_large_files+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_system" >&5 +$as_echo "$ax_cv_boost_system" >&6; } + if test "x$ax_cv_boost_system" = "xyes"; then + + + +$as_echo "#define HAVE_BOOST_SYSTEM /**/" >>confdefs.h + + BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/[^\/]*//'` + + LDFLAGS_SAVE=$LDFLAGS + if test "x$ax_boost_user_system_lib" = "x"; then + for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do + ax_lib=${libextension} + as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 +$as_echo_n "checking for exit in -l$ax_lib... " >&6; } +if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else - while :; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$ax_lib $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char exit (); int main () { - +return exit (); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_sys_large_files=no; break +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break +else + link_system="no" +fi + + done + if test "x$link_system" != "xyes"; then + for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do + ax_lib=${libextension} + as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 +$as_echo_n "checking for exit in -l$ax_lib... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$ax_lib $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#define _LARGE_FILES 1 -#include - /* Check that off_t can represent 2**63 - 1 correctly. - We can't simply define LARGE_OFF_T to be 9223372036854775807, - since some C++ compilers masquerading as C compilers - incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) - int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 - && LARGE_OFF_T % 2147483647 == 1) - ? 1 : -1]; + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char exit (); int main () { - +return exit (); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_sys_large_files=1; break +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cv_sys_large_files=unknown - break -done +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 -$as_echo "$ac_cv_sys_large_files" >&6; } -case $ac_cv_sys_large_files in #( - no | unknown) ;; - *) -cat >>confdefs.h <<_ACEOF -#define _LARGE_FILES $ac_cv_sys_large_files -_ACEOF -;; -esac -rm -rf conftest* - fi - - +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break +else + link_system="no" fi + done + fi -ac_fn_c_check_member "$LINENO" "struct tm" "tm_gmtoff" "ac_cv_member_struct_tm_tm_gmtoff" "#include -" -if test "x$ac_cv_member_struct_tm_tm_gmtoff" = xyes; then : - have_struct_tm_tm_gmtoff=yes + else + for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do + as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 +$as_echo_n "checking for exit in -l$ax_lib... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 else - have_struct_tm_tm_gmtoff=no + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$ax_lib $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char exit (); +int +main () +{ +return exit (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break +else + link_system="no" fi + done -if test "x$have_struct_tm_tm_gmtoff" = "xyes"; then + fi + if test "x$ax_lib" = "x"; then + as_fn_error $? "Could not find a version of the library!" "$LINENO" 5 + fi + if test "x$link_system" = "xno"; then + as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5 + fi + fi -$as_echo "#define HAVE_STRUCT_TM_TM_GMTOFF 1" >>confdefs.h + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + fi -fi -# Check size of pointer to decide we need 8 bytes alignment -# adjustment. -# The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int *" >&5 -$as_echo_n "checking size of int *... " >&6; } -if ${ac_cv_sizeof_int_p+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int *))" "ac_cv_sizeof_int_p" "$ac_includes_default"; then : -else - if test "$ac_cv_type_int_p" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (int *) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_int_p=0 - fi -fi +# Check whether --with-boost-thread was given. +if test "${with_boost_thread+set}" = set; then : + withval=$with_boost_thread; + if test "$withval" = "no"; then + want_boost="no" + elif test "$withval" = "yes"; then + want_boost="yes" + ax_boost_user_thread_lib="" + else + want_boost="yes" + ax_boost_user_thread_lib="$withval" + fi + +else + want_boost="yes" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int_p" >&5 -$as_echo "$ac_cv_sizeof_int_p" >&6; } + if test "x$want_boost" = "xyes"; then -cat >>confdefs.h <<_ACEOF -#define SIZEOF_INT_P $ac_cv_sizeof_int_p -_ACEOF + CPPFLAGS_SAVED="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" + export CPPFLAGS + LDFLAGS_SAVED="$LDFLAGS" + LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" + export LDFLAGS -# The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5 -$as_echo_n "checking size of time_t... " >&6; } -if ${ac_cv_sizeof_time_t+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Boost::Thread library is available" >&5 +$as_echo_n "checking whether the Boost::Thread library is available... " >&6; } +if ${ax_cv_boost_thread+:} false; then : $as_echo_n "(cached) " >&6 else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" "$ac_includes_default"; then : + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + CXXFLAGS_SAVE=$CXXFLAGS + + if test "x$host_os" = "xsolaris" ; then + CXXFLAGS="-pthreads $CXXFLAGS" + elif test "x$host_os" = "xmingw32" ; then + CXXFLAGS="-mthreads $CXXFLAGS" + else + CXXFLAGS="-pthread $CXXFLAGS" + fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +boost::thread_group thrds; + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ax_cv_boost_thread=yes else - if test "$ac_cv_type_time_t" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (time_t) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_time_t=0 - fi + ax_cv_boost_thread=no fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CXXFLAGS=$CXXFLAGS_SAVE + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5 -$as_echo "$ac_cv_sizeof_time_t" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_thread" >&5 +$as_echo "$ax_cv_boost_thread" >&6; } + if test "x$ax_cv_boost_thread" = "xyes"; then + if test "x$host_os" = "xsolaris" ; then + BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS" + elif test "x$host_os" = "xmingw32" ; then + BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS" + else + BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS" + fi -cat >>confdefs.h <<_ACEOF -#define SIZEOF_TIME_T $ac_cv_sizeof_time_t -_ACEOF +$as_echo "#define HAVE_BOOST_THREAD /**/" >>confdefs.h -# Checks for library functions. + BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/[^\/]*//'` -# Don't check malloc, since it does not play nicely with C++ stdlib -# AC_FUNC_MALLOC + LDFLAGS_SAVE=$LDFLAGS + case "x$host_os" in + *bsd* ) + LDFLAGS="-pthread $LDFLAGS" + break; + ;; + esac + if test "x$ax_boost_user_thread_lib" = "x"; then + for libextension in `ls -r $BOOSTLIBDIR/libboost_thread* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'`; do + ax_lib=${libextension} + as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 +$as_echo_n "checking for exit in -l$ax_lib... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$ax_lib $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -for ac_header in unistd.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" -if test "x$ac_cv_header_unistd_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_UNISTD_H 1 +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char exit (); +int +main () +{ +return exit (); + ; + return 0; +} _ACEOF - +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + BOOST_THREAD_LIB="-l$ax_lib"; link_thread="yes"; break +else + link_thread="no" fi -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working chown" >&5 -$as_echo_n "checking for working chown... " >&6; } -if ${ac_cv_func_chown_works+:} false; then : + done + if test "x$link_thread" != "xyes"; then + for libextension in `ls -r $BOOSTLIBDIR/boost_thread* 2>/dev/null | sed 's,.*/,,' | sed 's,\..*,,'`; do + ax_lib=${libextension} + as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 +$as_echo_n "checking for exit in -l$ax_lib... " >&6; } +if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else - if test "$cross_compiling" = yes; then : - ac_cv_func_chown_works=no -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$ax_lib $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$ac_includes_default -#include +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char exit (); int main () { - char *f = "conftest.chown"; - struct stat before, after; - - if (creat (f, 0600) < 0) - return 1; - if (stat (f, &before) < 0) - return 1; - if (chown (f, (uid_t) -1, (gid_t) -1) == -1) - return 1; - if (stat (f, &after) < 0) - return 1; - return ! (before.st_uid == after.st_uid && before.st_gid == after.st_gid); - +return exit (); ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_func_chown_works=yes +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" else - ac_cv_func_chown_works=no + eval "$as_ac_Lib=no" fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi - -rm -f conftest.chown - +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + BOOST_THREAD_LIB="-l$ax_lib"; link_thread="yes"; break +else + link_thread="no" fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_chown_works" >&5 -$as_echo "$ac_cv_func_chown_works" >&6; } -if test $ac_cv_func_chown_works = yes; then -$as_echo "#define HAVE_CHOWN 1" >>confdefs.h - -fi + done + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for error_at_line" >&5 -$as_echo_n "checking for error_at_line... " >&6; } -if ${ac_cv_lib_error_at_line+:} false; then : + else + for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do + as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 +$as_echo_n "checking for exit in -l$ax_lib... " >&6; } +if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$ax_lib $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char exit (); int main () { -error_at_line (0, 0, "", 0, "an error occurred"); +return exit (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_error_at_line=yes + eval "$as_ac_Lib=yes" else - ac_cv_lib_error_at_line=no + eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_error_at_line" >&5 -$as_echo "$ac_cv_lib_error_at_line" >&6; } -if test $ac_cv_lib_error_at_line = no; then - case " $LIBOBJS " in - *" error.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS error.$ac_objext" - ;; -esac - +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + BOOST_THREAD_LIB="-l$ax_lib"; link_thread="yes"; break +else + link_thread="no" fi -for ac_header in vfork.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" -if test "x$ac_cv_header_vfork_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_VFORK_H 1 -_ACEOF + done -fi + fi + if test "x$ax_lib" = "x"; then + as_fn_error $? "Could not find a version of the library!" "$LINENO" 5 + fi + if test "x$link_thread" = "xno"; then + as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5 + else + case "x$host_os" in + *bsd* ) + BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS" + break; + ;; + esac -done + fi + fi -for ac_func in fork vfork -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + fi + + + if test "x${ax_cv_boost_asio}" = "xyes" && + test "x${ax_cv_boost_system}" = "xyes" && + test "x${ax_cv_boost_thread}" = "xyes"; then + have_asio_lib=yes + fi + fi +fi + +# 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 +fi +if test "x${request_app}" = "xyes" && + test "x${enable_app}" != "xyes"; then + as_fn_error $? "applications were requested (--enable-app) but dependencies are not met." "$LINENO" 5 fi -done -if test "x$ac_cv_func_fork" = xyes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 -$as_echo_n "checking for working fork... " >&6; } -if ${ac_cv_func_fork_works+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ac_cv_func_fork_works=cross + if test "x${enable_app}" = "xyes" ; then + ENABLE_APP_TRUE= + ENABLE_APP_FALSE='#' else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ + ENABLE_APP_TRUE='#' + ENABLE_APP_FALSE= +fi - /* By Ruediger Kuhlmann. */ - return fork () < 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_func_fork_works=yes -else - ac_cv_func_fork_works=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext +enable_hpack_tools=no +# HPACK tools requires jansson +if test "x${request_hpack_tools}" != "xno" && + test "x${have_jansson}" = "xyes"; then + enable_hpack_tools=yes fi +if test "x${request_hpack_tools}" = "xyes" && + test "x${enable_hpack_tools}" != "xyes"; then + as_fn_error $? "HPACK tools were requested (--enable-hpack-tools) but dependencies are not met." "$LINENO" 5 fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 -$as_echo "$ac_cv_func_fork_works" >&6; } + if test "x${enable_hpack_tools}" = "xyes" ; then + ENABLE_HPACK_TOOLS_TRUE= + ENABLE_HPACK_TOOLS_FALSE='#' else - ac_cv_func_fork_works=$ac_cv_func_fork -fi -if test "x$ac_cv_func_fork_works" = xcross; then - case $host in - *-*-amigaos* | *-*-msdosdjgpp*) - # Override, as these systems have only a dummy fork() stub - ac_cv_func_fork_works=no - ;; - *) - ac_cv_func_fork_works=yes - ;; - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 -$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} + ENABLE_HPACK_TOOLS_TRUE='#' + ENABLE_HPACK_TOOLS_FALSE= fi -ac_cv_func_vfork_works=$ac_cv_func_vfork -if test "x$ac_cv_func_vfork" = xyes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 -$as_echo_n "checking for working vfork... " >&6; } -if ${ac_cv_func_vfork_works+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ac_cv_func_vfork_works=cross -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -/* Thanks to Paul Eggert for this test. */ -$ac_includes_default -#include -#ifdef HAVE_VFORK_H -# include -#endif -/* On some sparc systems, changes by the child to local and incoming - argument registers are propagated back to the parent. The compiler - is told about this with #include , but some compilers - (e.g. gcc -O) don't grok . Test for this by using a - static variable whose address is put into a register that is - clobbered by the vfork. */ -static void -#ifdef __cplusplus -sparc_address_test (int arg) -# else -sparc_address_test (arg) int arg; -#endif -{ - static pid_t child; - if (!child) { - child = vfork (); - if (child < 0) { - perror ("vfork"); - _exit(2); - } - if (!child) { - arg = getpid(); - write(-1, "", 0); - _exit (arg); - } - } -} - -int -main () -{ - pid_t parent = getpid (); - pid_t child; - sparc_address_test (0); - child = vfork (); +# C++ library libnghttp2_asio - if (child == 0) { - /* Here is another test for sparc vfork register problems. This - test uses lots of local variables, at least as many local - variables as main has allocated so far including compiler - temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris - 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should - reuse the register of parent for one of the local variables, - since it will think that parent can't possibly be used any more - in this routine. Assigning to the local variable will thus - munge parent in the parent process. */ - pid_t - p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), - p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); - /* Convince the compiler that p..p7 are live; otherwise, it might - use the same hardware register for all 8 local variables. */ - if (p != p1 || p != p2 || p != p3 || p != p4 - || p != p5 || p != p6 || p != p7) - _exit(1); - - /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent - from child file descriptors. If the child closes a descriptor - before it execs or exits, this munges the parent's descriptor - as well. Test for this by closing stdout in the child. */ - _exit(close(fileno(stdout)) != 0); - } else { - int status; - struct stat st; +enable_asio_lib=no +if test "x${request_asio_lib}" != "xno" && + test "x${have_asio_lib}" = "xyes"; then + enable_asio_lib=yes +fi - while (wait(&status) != child) - ; - return ( - /* Was there some problem with vforking? */ - child < 0 - - /* Did the child fail? (This shouldn't happen.) */ - || status - - /* Did the vfork/compiler bug occur? */ - || parent != getpid() - - /* Did the file descriptor bug occur? */ - || fstat(fileno(stdout), &st) != 0 - ); - } -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_func_vfork_works=yes + if test "x${enable_asio_lib}" = "xyes" ; then + ENABLE_ASIO_LIB_TRUE= + ENABLE_ASIO_LIB_FALSE='#' else - ac_cv_func_vfork_works=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext + ENABLE_ASIO_LIB_TRUE='#' + ENABLE_ASIO_LIB_FALSE= fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 -$as_echo "$ac_cv_func_vfork_works" >&6; } -fi; -if test "x$ac_cv_func_fork_works" = xcross; then - ac_cv_func_vfork_works=$ac_cv_func_vfork - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 -$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} +# The example programs depend on OpenSSL and libevent_openssl +enable_examples=no +if test "x${request_examples}" != "xno" && + test "x${have_openssl}" = "xyes" && + test "x${have_libevent_openssl}" = "xyes"; then + enable_examples=yes fi -if test "x$ac_cv_func_vfork_works" = xyes; then - -$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h +if test "x${request_examples}" = "xyes" && + test "x${enable_examples}" != "xyes"; then + as_fn_error $? "examples were requested (--enable-examples) but dependencies are not met." "$LINENO" 5 +fi + if test "x${enable_examples}" = "xyes" ; then + ENABLE_EXAMPLES_TRUE= + ENABLE_EXAMPLES_FALSE='#' else + ENABLE_EXAMPLES_TRUE='#' + ENABLE_EXAMPLES_FALSE= +fi -$as_echo "#define vfork fork" >>confdefs.h +# Python bindings +enable_python_bindings=no +if test "x${request_python_bindings}" != "xno" && + test "x${CYTHON}" != "x" && + test "x${PYTHON}" != "x:" && + test "x${have_python_dev}" = "xyes"; then + enable_python_bindings=yes fi -if test "x$ac_cv_func_fork_works" = xyes; then - -$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h +if test "x${request_python_bindings}" = "xyes" && + test "x${enable_python_bindings}" != "xyes"; then + as_fn_error $? "python bindings were requested (--enable-python-bindings) but dependencies are not met." "$LINENO" 5 fi -# Don't check realloc, since LeakSanitizer detects memory leak during check -# AC_FUNC_REALLOC -ac_fn_c_check_decl "$LINENO" "strerror_r" "ac_cv_have_decl_strerror_r" "$ac_includes_default" -if test "x$ac_cv_have_decl_strerror_r" = xyes; then : - ac_have_decl=1 + if test "x${enable_python_bindings}" = "xyes"; then + ENABLE_PYTHON_BINDINGS_TRUE= + ENABLE_PYTHON_BINDINGS_FALSE='#' else - ac_have_decl=0 + ENABLE_PYTHON_BINDINGS_TRUE='#' + ENABLE_PYTHON_BINDINGS_FALSE= fi -cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_STRERROR_R $ac_have_decl -_ACEOF - -for ac_func in strerror_r -do : - ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r" -if test "x$ac_cv_func_strerror_r" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_STRERROR_R 1 -_ACEOF +# Produce cython conditional, so that we can distribute generated C +# source + if test "x${CYTHON}" != "x"; then + HAVE_CYTHON_TRUE= + HAVE_CYTHON_FALSE='#' +else + HAVE_CYTHON_TRUE='#' + HAVE_CYTHON_FALSE= fi -done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r returns char *" >&5 -$as_echo_n "checking whether strerror_r returns char *... " >&6; } -if ${ac_cv_func_strerror_r_char_p+:} false; then : - $as_echo_n "(cached) " >&6 + +# failmalloc tests + if test "x${enable_failmalloc}" = "xyes" ; then + ENABLE_FAILMALLOC_TRUE= + ENABLE_FAILMALLOC_FALSE='#' else + ENABLE_FAILMALLOC_TRUE='#' + ENABLE_FAILMALLOC_FALSE= +fi - ac_cv_func_strerror_r_char_p=no - if test $ac_cv_have_decl_strerror_r = yes; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ - char buf[100]; - char x = *strerror_r (0, buf, sizeof buf); - char *p = strerror_r (0, buf, sizeof buf); - return !p || x; +# Checks for header files. - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_func_strerror_r_char_p=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable assertions" >&5 +$as_echo_n "checking whether to enable assertions... " >&6; } + # Check whether --enable-assert was given. +if test "${enable_assert+set}" = set; then : + enableval=$enable_assert; ac_enable_assert=$enableval + if test "x$enableval" = xno; then : + +$as_echo "#define NDEBUG 1" >>confdefs.h + +elif test "x$enableval" != xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: invalid argument supplied to --enable-assert" >&5 +$as_echo "$as_me: WARNING: invalid argument supplied to --enable-assert" >&2;} + ac_enable_assert=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - else - # strerror_r is not declared. Choose between - # systems that have relatively inaccessible declarations for the - # function. BeOS and DEC UNIX 4.0 fall in this category, but the - # former has a strerror_r that returns char*, while the latter - # has a strerror_r that returns `int'. - # This test should segfault on the DEC system. - if test "$cross_compiling" = yes; then : - : else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default - extern char *strerror_r (); -int -main () -{ -char buf[100]; - char x = *strerror_r (0, buf, sizeof buf); - return ! isalpha (x); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_func_strerror_r_char_p=yes -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext + ac_enable_assert=yes fi - fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_enable_assert" >&5 +$as_echo "$ac_enable_assert" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strerror_r_char_p" >&5 -$as_echo "$ac_cv_func_strerror_r_char_p" >&6; } -if test $ac_cv_func_strerror_r_char_p = yes; then +for ac_header in \ + arpa/inet.h \ + netinet/in.h \ + pwd.h \ + stddef.h \ + stdint.h \ + stdlib.h \ + string.h \ + time.h \ + unistd.h \ -$as_echo "#define STRERROR_R_CHAR_P 1" >>confdefs.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strnlen" >&5 -$as_echo_n "checking for working strnlen... " >&6; } -if ${ac_cv_func_strnlen_working+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - # Guess no on AIX systems, yes otherwise. - case "$host_os" in - aix*) ac_cv_func_strnlen_working=no;; - *) ac_cv_func_strnlen_working=yes;; - esac -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ - -#define S "foobar" -#define S_LEN (sizeof S - 1) - - /* At least one implementation is buggy: that of AIX 4.3 would - give strnlen (S, 1) == 3. */ +done - int i; - for (i = 0; i < S_LEN + 1; ++i) - { - int expected = i <= S_LEN ? i : S_LEN; - if (strnlen (S, i) != expected) - return 1; - } - return 0; - ; - return 0; -} +case "${host}" in + *mingw*) + # For ntohl, ntohs in Windows + for ac_header in winsock2.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "$ac_includes_default" +if test "x$ac_cv_header_winsock2_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_WINSOCK2_H 1 _ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_func_strnlen_working=yes -else - ac_cv_func_strnlen_working=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strnlen_working" >&5 -$as_echo "$ac_cv_func_strnlen_working" >&6; } -test $ac_cv_func_strnlen_working = no && case " $LIBOBJS " in - *" strnlen.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS strnlen.$ac_objext" - ;; -esac +done + ;; +esac -for ac_func in \ - _Exit \ - accept4 \ - dup2 \ - getcwd \ - getpwnam \ - localtime_r \ - memchr \ - memmove \ - memset \ - socket \ - sqrt \ - strchr \ - strdup \ - strerror \ - strndup \ - strstr \ - strtol \ - strtoul \ - timegm \ +# Checks for typedefs, structures, and compiler characteristics. +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int _ACEOF fi -done - -# timerfd_create was added in linux kernel 2.6.25 +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : -ac_fn_c_check_func "$LINENO" "timerfd_create" "ac_cv_func_timerfd_create" -if test "x$ac_cv_func_timerfd_create" = xyes; then : - have_timerfd_create=yes else - have_timerfd_create=no + +cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + fi +ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t" +case $ac_cv_c_uint8_t in #( + no|yes) ;; #( + *) -# For cygwin: we can link initgroups, so AC_CHECK_FUNCS succeeds, but -# cygwin disables initgroups due to feature test macro magic with our -# configuration. FreeBSD declares initgroups() in unistd.h. -ac_fn_c_check_decl "$LINENO" "initgroups" "ac_cv_have_decl_initgroups" " - #ifdef HAVE_UNISTD_H - # include - #endif - #include +$as_echo "#define _UINT8_T 1" >>confdefs.h -" -if test "x$ac_cv_have_decl_initgroups" = xyes; then : - ac_have_decl=1 -else - ac_have_decl=0 -fi cat >>confdefs.h <<_ACEOF -#define HAVE_DECL_INITGROUPS $ac_have_decl +#define uint8_t $ac_cv_c_uint8_t _ACEOF +;; + esac +ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t" +case $ac_cv_c_uint16_t in #( + no|yes) ;; #( + *) -# Checks for epoll availability, primarily for examples/tiny-nghttpd - ax_have_epoll_cppflags="${CPPFLAGS}" - ac_fn_c_check_header_mongrel "$LINENO" "linux/version.h" "ac_cv_header_linux_version_h" "$ac_includes_default" -if test "x$ac_cv_header_linux_version_h" = xyes; then : - CPPFLAGS="${CPPFLAGS} -DHAVE_LINUX_VERSION_H" -fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Linux epoll(7) interface" >&5 -$as_echo_n "checking for Linux epoll(7) interface... " >&6; } - if ${ax_cv_have_epoll+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - #include -#ifdef HAVE_LINUX_VERSION_H -# include -# if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45) -# error linux kernel version is too old to have epoll -# endif -#endif -int -main () -{ -int fd, rc; -struct epoll_event ev; -fd = epoll_create(128); -rc = epoll_wait(fd, &ev, 1, 0); - ; - return 0; -} +cat >>confdefs.h <<_ACEOF +#define uint16_t $ac_cv_c_uint16_t _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ax_cv_have_epoll=yes -else - ax_cv_have_epoll=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi +;; + esac - CPPFLAGS="${ax_have_epoll_cppflags}" - if test "${ax_cv_have_epoll}" = "yes"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -have_epoll=yes -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -have_epoll=no -fi +ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" +case $ac_cv_c_uint32_t in #( + no|yes) ;; #( + *) +$as_echo "#define _UINT32_T 1" >>confdefs.h - if test "x${have_epoll}" = "xyes" && - test "x${have_timerfd_create}" = "xyes"; then - ENABLE_TINY_NGHTTPD_TRUE= - ENABLE_TINY_NGHTTPD_FALSE='#' -else - ENABLE_TINY_NGHTTPD_TRUE='#' - ENABLE_TINY_NGHTTPD_FALSE= -fi +cat >>confdefs.h <<_ACEOF +#define uint32_t $ac_cv_c_uint32_t +_ACEOF +;; + esac -save_CFLAGS=$CFLAGS -save_CXXFLAGS=$CXXFLAGS +ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" +case $ac_cv_c_uint64_t in #( + no|yes) ;; #( + *) -CFLAGS= -CXXFLAGS= +$as_echo "#define _UINT64_T 1" >>confdefs.h -if test "x$werror" != "xno"; then - # For C compiler - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wall" >&5 -$as_echo_n "checking whether C compiler accepts -Wall... " >&6; } -if ${ax_cv_check_cflags___Wall+:} false; then : - $as_echo_n "(cached) " >&6 -else - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wall" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ +cat >>confdefs.h <<_ACEOF +#define uint64_t $ac_cv_c_uint64_t +_ACEOF +;; + esac -int -main () -{ +ac_fn_c_check_type "$LINENO" "ptrdiff_t" "ac_cv_type_ptrdiff_t" "$ac_includes_default" +if test "x$ac_cv_type_ptrdiff_t" = xyes; then : - ; - return 0; -} +cat >>confdefs.h <<_ACEOF +#define HAVE_PTRDIFF_T 1 _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wall=yes -else - ax_cv_check_cflags___Wall=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wall" >&5 -$as_echo "$ax_cv_check_cflags___Wall" >&6; } -if test "x$ax_cv_check_cflags___Wall" = xyes; then : - CFLAGS="$CFLAGS -Wall" -else - : + + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wextra" >&5 -$as_echo_n "checking whether C compiler accepts -Wextra... " >&6; } -if ${ax_cv_check_cflags___Wextra+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wextra" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; -int -main () -{ - - ; - return 0; -} _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wextra=yes -else - ax_cv_check_cflags___Wextra=no + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wextra" >&5 -$as_echo "$ax_cv_check_cflags___Wextra" >&6; } -if test "x$ax_cv_check_cflags___Wextra" = xyes; then : - CFLAGS="$CFLAGS -Wextra" -else - : -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror" >&5 -$as_echo_n "checking whether C compiler accepts -Werror... " >&6; } -if ${ax_cv_check_cflags___Werror+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Werror" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +#include + #include int main () { +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Werror=yes -else - ax_cv_check_cflags___Werror=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror" >&5 -$as_echo "$ax_cv_check_cflags___Werror" >&6; } -if test "x$ax_cv_check_cflags___Werror" = xyes; then : - CFLAGS="$CFLAGS -Werror" -else - : -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wmissing-prototypes" >&5 -$as_echo_n "checking whether C compiler accepts -Wmissing-prototypes... " >&6; } -if ${ax_cv_check_cflags___Wmissing_prototypes+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wmissing-prototypes" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +#include + #include int main () { +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wmissing_prototypes=yes + ac_cv_c_bigendian=yes else - ax_cv_check_cflags___Wmissing_prototypes=no + ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wmissing_prototypes" >&5 -$as_echo "$ax_cv_check_cflags___Wmissing_prototypes" >&6; } -if test "x$ax_cv_check_cflags___Wmissing_prototypes" = xyes; then : - CFLAGS="$CFLAGS -Wmissing-prototypes" -else - : fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wstrict-prototypes" >&5 -$as_echo_n "checking whether C compiler accepts -Wstrict-prototypes... " >&6; } -if ${ax_cv_check_cflags___Wstrict_prototypes+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wstrict-prototypes" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +#include int main () { +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wstrict_prototypes=yes -else - ax_cv_check_cflags___Wstrict_prototypes=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wstrict_prototypes" >&5 -$as_echo "$ax_cv_check_cflags___Wstrict_prototypes" >&6; } -if test "x$ax_cv_check_cflags___Wstrict_prototypes" = xyes; then : - CFLAGS="$CFLAGS -Wstrict-prototypes" -else - : -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wmissing-declarations" >&5 -$as_echo_n "checking whether C compiler accepts -Wmissing-declarations... " >&6; } -if ${ax_cv_check_cflags___Wmissing_declarations+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wmissing-declarations" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +#include int main () { +#ifndef _BIG_ENDIAN + not big endian + #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wmissing_declarations=yes + ac_cv_c_bigendian=yes else - ax_cv_check_cflags___Wmissing_declarations=no + ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wmissing_declarations" >&5 -$as_echo "$ax_cv_check_cflags___Wmissing_declarations" >&6; } -if test "x$ax_cv_check_cflags___Wmissing_declarations" = xyes; then : - CFLAGS="$CFLAGS -Wmissing-declarations" -else - : fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wpointer-arith" >&5 -$as_echo_n "checking whether C compiler accepts -Wpointer-arith... " >&6; } -if ${ax_cv_check_cflags___Wpointer_arith+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wpointer-arith" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; int main () { - +return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wpointer_arith=yes -else - ax_cv_check_cflags___Wpointer_arith=no + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wpointer_arith" >&5 -$as_echo "$ax_cv_check_cflags___Wpointer_arith" >&6; } -if test "x$ax_cv_check_cflags___Wpointer_arith" = xyes; then : - CFLAGS="$CFLAGS -Wpointer-arith" -else - : -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wdeclaration-after-statement" >&5 -$as_echo_n "checking whether C compiler accepts -Wdeclaration-after-statement... " >&6; } -if ${ax_cv_check_cflags___Wdeclaration_after_statement+:} false; then : - $as_echo_n "(cached) " >&6 else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wdeclaration-after-statement" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +$ac_includes_default int main () { + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wdeclaration_after_statement=yes +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no else - ax_cv_check_cflags___Wdeclaration_after_statement=no + ac_cv_c_bigendian=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wdeclaration_after_statement" >&5 -$as_echo "$ax_cv_check_cflags___Wdeclaration_after_statement" >&6; } -if test "x$ax_cv_check_cflags___Wdeclaration_after_statement" = xyes; then : - CFLAGS="$CFLAGS -Wdeclaration-after-statement" -else - : + + fi fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wformat-security" >&5 -$as_echo_n "checking whether C compiler accepts -Wformat-security... " >&6; } -if ${ax_cv_check_cflags___Wformat_security+:} false; then : +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + +# Check whether --enable-largefile was given. +if test "${enable_largefile+set}" = set; then : + enableval=$enable_largefile; +fi + +if test "$enable_largefile" != no; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : $as_echo_n "(cached) " >&6 else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wformat-security" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; int main () { @@ -22657,33 +20026,44 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wformat_security=yes -else - ax_cv_check_cflags___Wformat_security=no + if ac_fn_c_try_compile "$LINENO"; then : + break fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags +rm -f core conftest.err conftest.$ac_objext + CC="$CC -n32" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_largefile_CC=' -n32'; break fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wformat_security" >&5 -$as_echo "$ax_cv_check_cflags___Wformat_security" >&6; } -if test "x$ax_cv_check_cflags___Wformat_security" = xyes; then : - CFLAGS="$CFLAGS -Wformat-security" -else - : +rm -f core conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wwrite-strings" >&5 -$as_echo_n "checking whether C compiler accepts -Wwrite-strings... " >&6; } -if ${ax_cv_check_cflags___Wwrite_strings+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wwrite-strings" + while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; int main () { @@ -22693,32 +20073,21 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wwrite_strings=yes -else - ax_cv_check_cflags___Wwrite_strings=no + ac_cv_sys_file_offset_bits=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wwrite_strings" >&5 -$as_echo "$ax_cv_check_cflags___Wwrite_strings" >&6; } -if test "x$ax_cv_check_cflags___Wwrite_strings" = xyes; then : - CFLAGS="$CFLAGS -Wwrite-strings" -else - : -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wshadow" >&5 -$as_echo_n "checking whether C compiler accepts -Wshadow... " >&6; } -if ${ax_cv_check_cflags___Wshadow+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wshadow" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; int main () { @@ -22728,32 +20097,42 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wshadow=yes -else - ax_cv_check_cflags___Wshadow=no + ac_cv_sys_file_offset_bits=64; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wshadow" >&5 -$as_echo "$ax_cv_check_cflags___Wshadow" >&6; } -if test "x$ax_cv_check_cflags___Wshadow" = xyes; then : - CFLAGS="$CFLAGS -Wshadow" -else - : + ac_cv_sys_file_offset_bits=unknown + break +done fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Winline" >&5 -$as_echo_n "checking whether C compiler accepts -Winline... " >&6; } -if ${ax_cv_check_cflags___Winline+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +case $ac_cv_sys_file_offset_bits in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF +;; +esac +rm -rf conftest* + if test $ac_cv_sys_file_offset_bits = unknown; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Winline" + while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; int main () { @@ -22763,32 +20142,21 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Winline=yes -else - ax_cv_check_cflags___Winline=no + ac_cv_sys_large_files=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Winline" >&5 -$as_echo "$ax_cv_check_cflags___Winline" >&6; } -if test "x$ax_cv_check_cflags___Winline" = xyes; then : - CFLAGS="$CFLAGS -Winline" -else - : -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wnested-externs" >&5 -$as_echo_n "checking whether C compiler accepts -Wnested-externs... " >&6; } -if ${ax_cv_check_cflags___Wnested_externs+:} false; then : - $as_echo_n "(cached) " >&6 -else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wnested-externs" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; int main () { @@ -22798,169 +20166,225 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wnested_externs=yes -else - ax_cv_check_cflags___Wnested_externs=no + ac_cv_sys_large_files=1; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags + ac_cv_sys_large_files=unknown + break +done fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wnested_externs" >&5 -$as_echo "$ax_cv_check_cflags___Wnested_externs" >&6; } -if test "x$ax_cv_check_cflags___Wnested_externs" = xyes; then : - CFLAGS="$CFLAGS -Wnested-externs" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } +case $ac_cv_sys_large_files in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF +;; +esac +rm -rf conftest* + fi + + +fi + + +ac_fn_c_check_member "$LINENO" "struct tm" "tm_gmtoff" "ac_cv_member_struct_tm_tm_gmtoff" "#include +" +if test "x$ac_cv_member_struct_tm_tm_gmtoff" = xyes; then : + have_struct_tm_tm_gmtoff=yes else - : + have_struct_tm_tm_gmtoff=no fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wfloat-equal" >&5 -$as_echo_n "checking whether C compiler accepts -Wfloat-equal... " >&6; } -if ${ax_cv_check_cflags___Wfloat_equal+:} false; then : + +if test "x$have_struct_tm_tm_gmtoff" = "xyes"; then + +$as_echo "#define HAVE_STRUCT_TM_TM_GMTOFF 1" >>confdefs.h + +fi + +# Checks for library functions. +if test "x$cross_compiling" != "xyes"; then + for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } +if ${ac_cv_func_malloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wfloat-equal" + if test "$cross_compiling" = yes; then : + ac_cv_func_malloc_0_nonnull=no +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *malloc (); +#endif int main () { - +return ! malloc (0); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wfloat_equal=yes +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_malloc_0_nonnull=yes else - ax_cv_check_cflags___Wfloat_equal=no + ac_cv_func_malloc_0_nonnull=no fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wfloat_equal" >&5 -$as_echo "$ax_cv_check_cflags___Wfloat_equal" >&6; } -if test "x$ax_cv_check_cflags___Wfloat_equal" = xyes; then : - CFLAGS="$CFLAGS -Wfloat-equal" -else - : + fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wundef" >&5 -$as_echo_n "checking whether C compiler accepts -Wundef... " >&6; } -if ${ax_cv_check_cflags___Wundef+:} false; then : - $as_echo_n "(cached) " >&6 else + $as_echo "#define HAVE_MALLOC 0" >>confdefs.h - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wundef" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac -int -main () -{ - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wundef=yes -else - ax_cv_check_cflags___Wundef=no +$as_echo "#define malloc rpl_malloc" >>confdefs.h + fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags + + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wundef" >&5 -$as_echo "$ax_cv_check_cflags___Wundef" >&6; } -if test "x$ax_cv_check_cflags___Wundef" = xyes; then : - CFLAGS="$CFLAGS -Wundef" +for ac_func in \ + _Exit \ + getpwnam \ + memmove \ + memset \ + timegm \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# timerfd_create was added in linux kernel 2.6.25 + +ac_fn_c_check_func "$LINENO" "timerfd_create" "ac_cv_func_timerfd_create" +if test "x$ac_cv_func_timerfd_create" = xyes; then : + have_timerfd_create=yes else - : + have_timerfd_create=no +fi + + + +# Checks for epoll availability, primarily for examples/tiny-nghttpd + ax_have_epoll_cppflags="${CPPFLAGS}" + ac_fn_c_check_header_mongrel "$LINENO" "linux/version.h" "ac_cv_header_linux_version_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_version_h" = xyes; then : + CPPFLAGS="${CPPFLAGS} -DHAVE_LINUX_VERSION_H" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wendif-labels" >&5 -$as_echo_n "checking whether C compiler accepts -Wendif-labels... " >&6; } -if ${ax_cv_check_cflags___Wendif_labels+:} false; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Linux epoll(7) interface" >&5 +$as_echo_n "checking for Linux epoll(7) interface... " >&6; } + if ${ax_cv_have_epoll+:} false; then : $as_echo_n "(cached) " >&6 else - - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wendif-labels" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include +#ifdef HAVE_LINUX_VERSION_H +# include +# if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45) +# error linux kernel version is too old to have epoll +# endif +#endif int main () { - +int fd, rc; +struct epoll_event ev; +fd = epoll_create(128); +rc = epoll_wait(fd, &ev, 1, 0); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wendif_labels=yes +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_have_epoll=yes else - ax_cv_check_cflags___Wendif_labels=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags + ax_cv_have_epoll=no fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wendif_labels" >&5 -$as_echo "$ax_cv_check_cflags___Wendif_labels" >&6; } -if test "x$ax_cv_check_cflags___Wendif_labels" = xyes; then : - CFLAGS="$CFLAGS -Wendif-labels" -else - : +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wempty-body" >&5 -$as_echo_n "checking whether C compiler accepts -Wempty-body... " >&6; } -if ${ax_cv_check_cflags___Wempty_body+:} false; then : - $as_echo_n "(cached) " >&6 + CPPFLAGS="${ax_have_epoll_cppflags}" + if test "${ax_cv_have_epoll}" = "yes"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +have_epoll=yes else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +have_epoll=no +fi - ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wempty-body" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wempty_body=yes -else - ax_cv_check_cflags___Wempty_body=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$ax_check_save_flags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wempty_body" >&5 -$as_echo "$ax_cv_check_cflags___Wempty_body" >&6; } -if test "x$ax_cv_check_cflags___Wempty_body" = xyes; then : - CFLAGS="$CFLAGS -Wempty-body" + if test "x${have_epoll}" = "xyes" && + test "x${have_timerfd_create}" = "xyes"; then + ENABLE_TINY_NGHTTPD_TRUE= + ENABLE_TINY_NGHTTPD_FALSE='#' else - : + ENABLE_TINY_NGHTTPD_TRUE='#' + ENABLE_TINY_NGHTTPD_FALSE= fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wcast-align" >&5 -$as_echo_n "checking whether C compiler accepts -Wcast-align... " >&6; } -if ${ax_cv_check_cflags___Wcast_align+:} false; then : + +case "${host}" in + *mingw*) + LIBS="$LIBS -lws2_32" + ;; +esac + +if test "x$werror" != "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wall" >&5 +$as_echo_n "checking whether C compiler accepts -Wall... " >&6; } +if ${ax_cv_check_cflags___Wall+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wcast-align" + CFLAGS="$CFLAGS -Wall" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -22973,29 +20397,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wcast_align=yes + ax_cv_check_cflags___Wall=yes else - ax_cv_check_cflags___Wcast_align=no + ax_cv_check_cflags___Wall=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wcast_align" >&5 -$as_echo "$ax_cv_check_cflags___Wcast_align" >&6; } -if test "x$ax_cv_check_cflags___Wcast_align" = xyes; then : - CFLAGS="$CFLAGS -Wcast-align" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wall" >&5 +$as_echo "$ax_cv_check_cflags___Wall" >&6; } +if test x"$ax_cv_check_cflags___Wall" = xyes; then : + CFLAGS="$CFLAGS -Wall" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wclobbered" >&5 -$as_echo_n "checking whether C compiler accepts -Wclobbered... " >&6; } -if ${ax_cv_check_cflags___Wclobbered+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wextra" >&5 +$as_echo_n "checking whether C compiler accepts -Wextra... " >&6; } +if ${ax_cv_check_cflags___Wextra+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wclobbered" + CFLAGS="$CFLAGS -Wextra" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23008,29 +20432,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wclobbered=yes + ax_cv_check_cflags___Wextra=yes else - ax_cv_check_cflags___Wclobbered=no + ax_cv_check_cflags___Wextra=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wclobbered" >&5 -$as_echo "$ax_cv_check_cflags___Wclobbered" >&6; } -if test "x$ax_cv_check_cflags___Wclobbered" = xyes; then : - CFLAGS="$CFLAGS -Wclobbered" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wextra" >&5 +$as_echo "$ax_cv_check_cflags___Wextra" >&6; } +if test x"$ax_cv_check_cflags___Wextra" = xyes; then : + CFLAGS="$CFLAGS -Wextra" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wvla" >&5 -$as_echo_n "checking whether C compiler accepts -Wvla... " >&6; } -if ${ax_cv_check_cflags___Wvla+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror" >&5 +$as_echo_n "checking whether C compiler accepts -Werror... " >&6; } +if ${ax_cv_check_cflags___Werror+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wvla" + CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23043,29 +20467,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wvla=yes + ax_cv_check_cflags___Werror=yes else - ax_cv_check_cflags___Wvla=no + ax_cv_check_cflags___Werror=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wvla" >&5 -$as_echo "$ax_cv_check_cflags___Wvla" >&6; } -if test "x$ax_cv_check_cflags___Wvla" = xyes; then : - CFLAGS="$CFLAGS -Wvla" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror" >&5 +$as_echo "$ax_cv_check_cflags___Werror" >&6; } +if test x"$ax_cv_check_cflags___Werror" = xyes; then : + CFLAGS="$CFLAGS -Werror" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wpragmas" >&5 -$as_echo_n "checking whether C compiler accepts -Wpragmas... " >&6; } -if ${ax_cv_check_cflags___Wpragmas+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wmissing-prototypes" >&5 +$as_echo_n "checking whether C compiler accepts -Wmissing-prototypes... " >&6; } +if ${ax_cv_check_cflags___Wmissing_prototypes+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wpragmas" + CFLAGS="$CFLAGS -Wmissing-prototypes" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23078,29 +20502,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wpragmas=yes + ax_cv_check_cflags___Wmissing_prototypes=yes else - ax_cv_check_cflags___Wpragmas=no + ax_cv_check_cflags___Wmissing_prototypes=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wpragmas" >&5 -$as_echo "$ax_cv_check_cflags___Wpragmas" >&6; } -if test "x$ax_cv_check_cflags___Wpragmas" = xyes; then : - CFLAGS="$CFLAGS -Wpragmas" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wmissing_prototypes" >&5 +$as_echo "$ax_cv_check_cflags___Wmissing_prototypes" >&6; } +if test x"$ax_cv_check_cflags___Wmissing_prototypes" = xyes; then : + CFLAGS="$CFLAGS -Wmissing-prototypes" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wunreachable-code" >&5 -$as_echo_n "checking whether C compiler accepts -Wunreachable-code... " >&6; } -if ${ax_cv_check_cflags___Wunreachable_code+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wstrict-prototypes" >&5 +$as_echo_n "checking whether C compiler accepts -Wstrict-prototypes... " >&6; } +if ${ax_cv_check_cflags___Wstrict_prototypes+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wunreachable-code" + CFLAGS="$CFLAGS -Wstrict-prototypes" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23113,29 +20537,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wunreachable_code=yes + ax_cv_check_cflags___Wstrict_prototypes=yes else - ax_cv_check_cflags___Wunreachable_code=no + ax_cv_check_cflags___Wstrict_prototypes=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wunreachable_code" >&5 -$as_echo "$ax_cv_check_cflags___Wunreachable_code" >&6; } -if test "x$ax_cv_check_cflags___Wunreachable_code" = xyes; then : - CFLAGS="$CFLAGS -Wunreachable-code" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wstrict_prototypes" >&5 +$as_echo "$ax_cv_check_cflags___Wstrict_prototypes" >&6; } +if test x"$ax_cv_check_cflags___Wstrict_prototypes" = xyes; then : + CFLAGS="$CFLAGS -Wstrict-prototypes" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Waddress" >&5 -$as_echo_n "checking whether C compiler accepts -Waddress... " >&6; } -if ${ax_cv_check_cflags___Waddress+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wmissing-declarations" >&5 +$as_echo_n "checking whether C compiler accepts -Wmissing-declarations... " >&6; } +if ${ax_cv_check_cflags___Wmissing_declarations+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Waddress" + CFLAGS="$CFLAGS -Wmissing-declarations" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23148,29 +20572,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Waddress=yes + ax_cv_check_cflags___Wmissing_declarations=yes else - ax_cv_check_cflags___Waddress=no + ax_cv_check_cflags___Wmissing_declarations=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Waddress" >&5 -$as_echo "$ax_cv_check_cflags___Waddress" >&6; } -if test "x$ax_cv_check_cflags___Waddress" = xyes; then : - CFLAGS="$CFLAGS -Waddress" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wmissing_declarations" >&5 +$as_echo "$ax_cv_check_cflags___Wmissing_declarations" >&6; } +if test x"$ax_cv_check_cflags___Wmissing_declarations" = xyes; then : + CFLAGS="$CFLAGS -Wmissing-declarations" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wattributes" >&5 -$as_echo_n "checking whether C compiler accepts -Wattributes... " >&6; } -if ${ax_cv_check_cflags___Wattributes+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wpointer-arith" >&5 +$as_echo_n "checking whether C compiler accepts -Wpointer-arith... " >&6; } +if ${ax_cv_check_cflags___Wpointer_arith+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wattributes" + CFLAGS="$CFLAGS -Wpointer-arith" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23183,29 +20607,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wattributes=yes + ax_cv_check_cflags___Wpointer_arith=yes else - ax_cv_check_cflags___Wattributes=no + ax_cv_check_cflags___Wpointer_arith=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wattributes" >&5 -$as_echo "$ax_cv_check_cflags___Wattributes" >&6; } -if test "x$ax_cv_check_cflags___Wattributes" = xyes; then : - CFLAGS="$CFLAGS -Wattributes" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wpointer_arith" >&5 +$as_echo "$ax_cv_check_cflags___Wpointer_arith" >&6; } +if test x"$ax_cv_check_cflags___Wpointer_arith" = xyes; then : + CFLAGS="$CFLAGS -Wpointer-arith" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wdiv-by-zero" >&5 -$as_echo_n "checking whether C compiler accepts -Wdiv-by-zero... " >&6; } -if ${ax_cv_check_cflags___Wdiv_by_zero+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wdeclaration-after-statement" >&5 +$as_echo_n "checking whether C compiler accepts -Wdeclaration-after-statement... " >&6; } +if ${ax_cv_check_cflags___Wdeclaration_after_statement+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wdiv-by-zero" + CFLAGS="$CFLAGS -Wdeclaration-after-statement" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23218,29 +20642,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wdiv_by_zero=yes + ax_cv_check_cflags___Wdeclaration_after_statement=yes else - ax_cv_check_cflags___Wdiv_by_zero=no + ax_cv_check_cflags___Wdeclaration_after_statement=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wdiv_by_zero" >&5 -$as_echo "$ax_cv_check_cflags___Wdiv_by_zero" >&6; } -if test "x$ax_cv_check_cflags___Wdiv_by_zero" = xyes; then : - CFLAGS="$CFLAGS -Wdiv-by-zero" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wdeclaration_after_statement" >&5 +$as_echo "$ax_cv_check_cflags___Wdeclaration_after_statement" >&6; } +if test x"$ax_cv_check_cflags___Wdeclaration_after_statement" = xyes; then : + CFLAGS="$CFLAGS -Wdeclaration-after-statement" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wshorten-64-to-32" >&5 -$as_echo_n "checking whether C compiler accepts -Wshorten-64-to-32... " >&6; } -if ${ax_cv_check_cflags___Wshorten_64_to_32+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wformat-security" >&5 +$as_echo_n "checking whether C compiler accepts -Wformat-security... " >&6; } +if ${ax_cv_check_cflags___Wformat_security+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wshorten-64-to-32" + CFLAGS="$CFLAGS -Wformat-security" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23253,30 +20677,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wshorten_64_to_32=yes + ax_cv_check_cflags___Wformat_security=yes else - ax_cv_check_cflags___Wshorten_64_to_32=no + ax_cv_check_cflags___Wformat_security=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wshorten_64_to_32" >&5 -$as_echo "$ax_cv_check_cflags___Wshorten_64_to_32" >&6; } -if test "x$ax_cv_check_cflags___Wshorten_64_to_32" = xyes; then : - CFLAGS="$CFLAGS -Wshorten-64-to-32" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wformat_security" >&5 +$as_echo "$ax_cv_check_cflags___Wformat_security" >&6; } +if test x"$ax_cv_check_cflags___Wformat_security" = xyes; then : + CFLAGS="$CFLAGS -Wformat-security" else : fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wconversion" >&5 -$as_echo_n "checking whether C compiler accepts -Wconversion... " >&6; } -if ${ax_cv_check_cflags___Wconversion+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wwrite-strings" >&5 +$as_echo_n "checking whether C compiler accepts -Wwrite-strings... " >&6; } +if ${ax_cv_check_cflags___Wwrite_strings+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wconversion" + CFLAGS="$CFLAGS -Wwrite-strings" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23289,29 +20712,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wconversion=yes + ax_cv_check_cflags___Wwrite_strings=yes else - ax_cv_check_cflags___Wconversion=no + ax_cv_check_cflags___Wwrite_strings=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wconversion" >&5 -$as_echo "$ax_cv_check_cflags___Wconversion" >&6; } -if test "x$ax_cv_check_cflags___Wconversion" = xyes; then : - CFLAGS="$CFLAGS -Wconversion" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wwrite_strings" >&5 +$as_echo "$ax_cv_check_cflags___Wwrite_strings" >&6; } +if test x"$ax_cv_check_cflags___Wwrite_strings" = xyes; then : + CFLAGS="$CFLAGS -Wwrite-strings" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wextended-offsetof" >&5 -$as_echo_n "checking whether C compiler accepts -Wextended-offsetof... " >&6; } -if ${ax_cv_check_cflags___Wextended_offsetof+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wshadow" >&5 +$as_echo_n "checking whether C compiler accepts -Wshadow... " >&6; } +if ${ax_cv_check_cflags___Wshadow+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wextended-offsetof" + CFLAGS="$CFLAGS -Wshadow" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23324,29 +20747,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wextended_offsetof=yes + ax_cv_check_cflags___Wshadow=yes else - ax_cv_check_cflags___Wextended_offsetof=no + ax_cv_check_cflags___Wshadow=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wextended_offsetof" >&5 -$as_echo "$ax_cv_check_cflags___Wextended_offsetof" >&6; } -if test "x$ax_cv_check_cflags___Wextended_offsetof" = xyes; then : - CFLAGS="$CFLAGS -Wextended-offsetof" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wshadow" >&5 +$as_echo "$ax_cv_check_cflags___Wshadow" >&6; } +if test x"$ax_cv_check_cflags___Wshadow" = xyes; then : + CFLAGS="$CFLAGS -Wshadow" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wformat-nonliteral" >&5 -$as_echo_n "checking whether C compiler accepts -Wformat-nonliteral... " >&6; } -if ${ax_cv_check_cflags___Wformat_nonliteral+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Winline" >&5 +$as_echo_n "checking whether C compiler accepts -Winline... " >&6; } +if ${ax_cv_check_cflags___Winline+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wformat-nonliteral" + CFLAGS="$CFLAGS -Winline" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23359,29 +20782,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wformat_nonliteral=yes + ax_cv_check_cflags___Winline=yes else - ax_cv_check_cflags___Wformat_nonliteral=no + ax_cv_check_cflags___Winline=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wformat_nonliteral" >&5 -$as_echo "$ax_cv_check_cflags___Wformat_nonliteral" >&6; } -if test "x$ax_cv_check_cflags___Wformat_nonliteral" = xyes; then : - CFLAGS="$CFLAGS -Wformat-nonliteral" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Winline" >&5 +$as_echo "$ax_cv_check_cflags___Winline" >&6; } +if test x"$ax_cv_check_cflags___Winline" = xyes; then : + CFLAGS="$CFLAGS -Winline" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wlanguage-extension-token" >&5 -$as_echo_n "checking whether C compiler accepts -Wlanguage-extension-token... " >&6; } -if ${ax_cv_check_cflags___Wlanguage_extension_token+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wnested-externs" >&5 +$as_echo_n "checking whether C compiler accepts -Wnested-externs... " >&6; } +if ${ax_cv_check_cflags___Wnested_externs+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wlanguage-extension-token" + CFLAGS="$CFLAGS -Wnested-externs" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23394,29 +20817,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wlanguage_extension_token=yes + ax_cv_check_cflags___Wnested_externs=yes else - ax_cv_check_cflags___Wlanguage_extension_token=no + ax_cv_check_cflags___Wnested_externs=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wlanguage_extension_token" >&5 -$as_echo "$ax_cv_check_cflags___Wlanguage_extension_token" >&6; } -if test "x$ax_cv_check_cflags___Wlanguage_extension_token" = xyes; then : - CFLAGS="$CFLAGS -Wlanguage-extension-token" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wnested_externs" >&5 +$as_echo "$ax_cv_check_cflags___Wnested_externs" >&6; } +if test x"$ax_cv_check_cflags___Wnested_externs" = xyes; then : + CFLAGS="$CFLAGS -Wnested-externs" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wmissing-field-initializers" >&5 -$as_echo_n "checking whether C compiler accepts -Wmissing-field-initializers... " >&6; } -if ${ax_cv_check_cflags___Wmissing_field_initializers+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wfloat-equal" >&5 +$as_echo_n "checking whether C compiler accepts -Wfloat-equal... " >&6; } +if ${ax_cv_check_cflags___Wfloat_equal+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wmissing-field-initializers" + CFLAGS="$CFLAGS -Wfloat-equal" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23429,29 +20852,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wmissing_field_initializers=yes + ax_cv_check_cflags___Wfloat_equal=yes else - ax_cv_check_cflags___Wmissing_field_initializers=no + ax_cv_check_cflags___Wfloat_equal=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wmissing_field_initializers" >&5 -$as_echo "$ax_cv_check_cflags___Wmissing_field_initializers" >&6; } -if test "x$ax_cv_check_cflags___Wmissing_field_initializers" = xyes; then : - CFLAGS="$CFLAGS -Wmissing-field-initializers" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wfloat_equal" >&5 +$as_echo "$ax_cv_check_cflags___Wfloat_equal" >&6; } +if test x"$ax_cv_check_cflags___Wfloat_equal" = xyes; then : + CFLAGS="$CFLAGS -Wfloat-equal" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wmissing-noreturn" >&5 -$as_echo_n "checking whether C compiler accepts -Wmissing-noreturn... " >&6; } -if ${ax_cv_check_cflags___Wmissing_noreturn+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wundef" >&5 +$as_echo_n "checking whether C compiler accepts -Wundef... " >&6; } +if ${ax_cv_check_cflags___Wundef+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wmissing-noreturn" + CFLAGS="$CFLAGS -Wundef" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23464,29 +20887,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wmissing_noreturn=yes + ax_cv_check_cflags___Wundef=yes else - ax_cv_check_cflags___Wmissing_noreturn=no + ax_cv_check_cflags___Wundef=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wmissing_noreturn" >&5 -$as_echo "$ax_cv_check_cflags___Wmissing_noreturn" >&6; } -if test "x$ax_cv_check_cflags___Wmissing_noreturn" = xyes; then : - CFLAGS="$CFLAGS -Wmissing-noreturn" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wundef" >&5 +$as_echo "$ax_cv_check_cflags___Wundef" >&6; } +if test x"$ax_cv_check_cflags___Wundef" = xyes; then : + CFLAGS="$CFLAGS -Wundef" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wmissing-variable-declarations" >&5 -$as_echo_n "checking whether C compiler accepts -Wmissing-variable-declarations... " >&6; } -if ${ax_cv_check_cflags___Wmissing_variable_declarations+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wendif-labels" >&5 +$as_echo_n "checking whether C compiler accepts -Wendif-labels... " >&6; } +if ${ax_cv_check_cflags___Wendif_labels+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wmissing-variable-declarations" + CFLAGS="$CFLAGS -Wendif-labels" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23499,31 +20922,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wmissing_variable_declarations=yes + ax_cv_check_cflags___Wendif_labels=yes else - ax_cv_check_cflags___Wmissing_variable_declarations=no + ax_cv_check_cflags___Wendif_labels=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wmissing_variable_declarations" >&5 -$as_echo "$ax_cv_check_cflags___Wmissing_variable_declarations" >&6; } -if test "x$ax_cv_check_cflags___Wmissing_variable_declarations" = xyes; then : - CFLAGS="$CFLAGS -Wmissing-variable-declarations" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wendif_labels" >&5 +$as_echo "$ax_cv_check_cflags___Wendif_labels" >&6; } +if test x"$ax_cv_check_cflags___Wendif_labels" = xyes; then : + CFLAGS="$CFLAGS -Wendif-labels" else : fi - # Not used because we cannot change public structs - # AX_CHECK_COMPILE_FLAG([-Wpadded], [CFLAGS="$CFLAGS -Wpadded"]) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wsign-conversion" >&5 -$as_echo_n "checking whether C compiler accepts -Wsign-conversion... " >&6; } -if ${ax_cv_check_cflags___Wsign_conversion+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wempty-body" >&5 +$as_echo_n "checking whether C compiler accepts -Wempty-body... " >&6; } +if ${ax_cv_check_cflags___Wempty_body+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wsign-conversion" + CFLAGS="$CFLAGS -Wempty-body" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23536,31 +20957,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wsign_conversion=yes + ax_cv_check_cflags___Wempty_body=yes else - ax_cv_check_cflags___Wsign_conversion=no + ax_cv_check_cflags___Wempty_body=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wsign_conversion" >&5 -$as_echo "$ax_cv_check_cflags___Wsign_conversion" >&6; } -if test "x$ax_cv_check_cflags___Wsign_conversion" = xyes; then : - CFLAGS="$CFLAGS -Wsign-conversion" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wempty_body" >&5 +$as_echo "$ax_cv_check_cflags___Wempty_body" >&6; } +if test x"$ax_cv_check_cflags___Wempty_body" = xyes; then : + CFLAGS="$CFLAGS -Wempty-body" else : fi - # Not used because this basically disallows default case - # AX_CHECK_COMPILE_FLAG([-Wswitch-enum], [CFLAGS="$CFLAGS -Wswitch-enum"]) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wunreachable-code-break" >&5 -$as_echo_n "checking whether C compiler accepts -Wunreachable-code-break... " >&6; } -if ${ax_cv_check_cflags___Wunreachable_code_break+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wcast-align" >&5 +$as_echo_n "checking whether C compiler accepts -Wcast-align... " >&6; } +if ${ax_cv_check_cflags___Wcast_align+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wunreachable-code-break" + CFLAGS="$CFLAGS -Wcast-align" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23573,29 +20992,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wunreachable_code_break=yes + ax_cv_check_cflags___Wcast_align=yes else - ax_cv_check_cflags___Wunreachable_code_break=no + ax_cv_check_cflags___Wcast_align=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wunreachable_code_break" >&5 -$as_echo "$ax_cv_check_cflags___Wunreachable_code_break" >&6; } -if test "x$ax_cv_check_cflags___Wunreachable_code_break" = xyes; then : - CFLAGS="$CFLAGS -Wunreachable-code-break" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wcast_align" >&5 +$as_echo "$ax_cv_check_cflags___Wcast_align" >&6; } +if test x"$ax_cv_check_cflags___Wcast_align" = xyes; then : + CFLAGS="$CFLAGS -Wcast-align" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wunused-macros" >&5 -$as_echo_n "checking whether C compiler accepts -Wunused-macros... " >&6; } -if ${ax_cv_check_cflags___Wunused_macros+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wclobbered" >&5 +$as_echo_n "checking whether C compiler accepts -Wclobbered... " >&6; } +if ${ax_cv_check_cflags___Wclobbered+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wunused-macros" + CFLAGS="$CFLAGS -Wclobbered" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23608,29 +21027,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wunused_macros=yes + ax_cv_check_cflags___Wclobbered=yes else - ax_cv_check_cflags___Wunused_macros=no + ax_cv_check_cflags___Wclobbered=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wunused_macros" >&5 -$as_echo "$ax_cv_check_cflags___Wunused_macros" >&6; } -if test "x$ax_cv_check_cflags___Wunused_macros" = xyes; then : - CFLAGS="$CFLAGS -Wunused-macros" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wclobbered" >&5 +$as_echo "$ax_cv_check_cflags___Wclobbered" >&6; } +if test x"$ax_cv_check_cflags___Wclobbered" = xyes; then : + CFLAGS="$CFLAGS -Wclobbered" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wunused-parameter" >&5 -$as_echo_n "checking whether C compiler accepts -Wunused-parameter... " >&6; } -if ${ax_cv_check_cflags___Wunused_parameter+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wvla" >&5 +$as_echo_n "checking whether C compiler accepts -Wvla... " >&6; } +if ${ax_cv_check_cflags___Wvla+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wunused-parameter" + CFLAGS="$CFLAGS -Wvla" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23643,29 +21062,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wunused_parameter=yes + ax_cv_check_cflags___Wvla=yes else - ax_cv_check_cflags___Wunused_parameter=no + ax_cv_check_cflags___Wvla=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wunused_parameter" >&5 -$as_echo "$ax_cv_check_cflags___Wunused_parameter" >&6; } -if test "x$ax_cv_check_cflags___Wunused_parameter" = xyes; then : - CFLAGS="$CFLAGS -Wunused-parameter" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wvla" >&5 +$as_echo "$ax_cv_check_cflags___Wvla" >&6; } +if test x"$ax_cv_check_cflags___Wvla" = xyes; then : + CFLAGS="$CFLAGS -Wvla" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wredundant-decls" >&5 -$as_echo_n "checking whether C compiler accepts -Wredundant-decls... " >&6; } -if ${ax_cv_check_cflags___Wredundant_decls+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wpragmas" >&5 +$as_echo_n "checking whether C compiler accepts -Wpragmas... " >&6; } +if ${ax_cv_check_cflags___Wpragmas+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wredundant-decls" + CFLAGS="$CFLAGS -Wpragmas" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23678,30 +21097,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wredundant_decls=yes + ax_cv_check_cflags___Wpragmas=yes else - ax_cv_check_cflags___Wredundant_decls=no + ax_cv_check_cflags___Wpragmas=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wredundant_decls" >&5 -$as_echo "$ax_cv_check_cflags___Wredundant_decls" >&6; } -if test "x$ax_cv_check_cflags___Wredundant_decls" = xyes; then : - CFLAGS="$CFLAGS -Wredundant-decls" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wpragmas" >&5 +$as_echo "$ax_cv_check_cflags___Wpragmas" >&6; } +if test x"$ax_cv_check_cflags___Wpragmas" = xyes; then : + CFLAGS="$CFLAGS -Wpragmas" else : fi - # Only work with Clang for the moment - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wheader-guard" >&5 -$as_echo_n "checking whether C compiler accepts -Wheader-guard... " >&6; } -if ${ax_cv_check_cflags___Wheader_guard+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wunreachable-code" >&5 +$as_echo_n "checking whether C compiler accepts -Wunreachable-code... " >&6; } +if ${ax_cv_check_cflags___Wunreachable_code+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wheader-guard" + CFLAGS="$CFLAGS -Wunreachable-code" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23714,31 +21132,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wheader_guard=yes + ax_cv_check_cflags___Wunreachable_code=yes else - ax_cv_check_cflags___Wheader_guard=no + ax_cv_check_cflags___Wunreachable_code=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wheader_guard" >&5 -$as_echo "$ax_cv_check_cflags___Wheader_guard" >&6; } -if test "x$ax_cv_check_cflags___Wheader_guard" = xyes; then : - CFLAGS="$CFLAGS -Wheader-guard" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wunreachable_code" >&5 +$as_echo "$ax_cv_check_cflags___Wunreachable_code" >&6; } +if test x"$ax_cv_check_cflags___Wunreachable_code" = xyes; then : + CFLAGS="$CFLAGS -Wunreachable-code" else : fi - - # This is required because we pass format string as "const char*. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wno-format-nonliteral" >&5 -$as_echo_n "checking whether C compiler accepts -Wno-format-nonliteral... " >&6; } -if ${ax_cv_check_cflags___Wno_format_nonliteral+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Waddress" >&5 +$as_echo_n "checking whether C compiler accepts -Waddress... " >&6; } +if ${ax_cv_check_cflags___Waddress+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -Wno-format-nonliteral" + CFLAGS="$CFLAGS -Waddress" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23751,37 +21167,29 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___Wno_format_nonliteral=yes + ax_cv_check_cflags___Waddress=yes else - ax_cv_check_cflags___Wno_format_nonliteral=no + ax_cv_check_cflags___Waddress=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wno_format_nonliteral" >&5 -$as_echo "$ax_cv_check_cflags___Wno_format_nonliteral" >&6; } -if test "x$ax_cv_check_cflags___Wno_format_nonliteral" = xyes; then : - CFLAGS="$CFLAGS -Wno-format-nonliteral" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Waddress" >&5 +$as_echo "$ax_cv_check_cflags___Waddress" >&6; } +if test x"$ax_cv_check_cflags___Waddress" = xyes; then : + CFLAGS="$CFLAGS -Waddress" else : fi - - # For C++ compiler - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Wall" >&5 -$as_echo_n "checking whether C++ compiler accepts -Wall... " >&6; } -if ${ax_cv_check_cxxflags___Wall+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wattributes" >&5 +$as_echo_n "checking whether C compiler accepts -Wattributes... " >&6; } +if ${ax_cv_check_cflags___Wattributes+:} false; then : $as_echo_n "(cached) " >&6 else - ax_check_save_flags=$CXXFLAGS - CXXFLAGS="$CXXFLAGS -Wall" + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -Wattributes" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23793,30 +21201,30 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_check_cxxflags___Wall=yes +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___Wattributes=yes else - ax_cv_check_cxxflags___Wall=no + ax_cv_check_cflags___Wattributes=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS=$ax_check_save_flags + CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Wall" >&5 -$as_echo "$ax_cv_check_cxxflags___Wall" >&6; } -if test "x$ax_cv_check_cxxflags___Wall" = xyes; then : - CXXFLAGS="$CXXFLAGS -Wall" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wattributes" >&5 +$as_echo "$ax_cv_check_cflags___Wattributes" >&6; } +if test x"$ax_cv_check_cflags___Wattributes" = xyes; then : + CFLAGS="$CFLAGS -Wattributes" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror" >&5 -$as_echo_n "checking whether C++ compiler accepts -Werror... " >&6; } -if ${ax_cv_check_cxxflags___Werror+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wdiv-by-zero" >&5 +$as_echo_n "checking whether C compiler accepts -Wdiv-by-zero... " >&6; } +if ${ax_cv_check_cflags___Wdiv_by_zero+:} false; then : $as_echo_n "(cached) " >&6 else - ax_check_save_flags=$CXXFLAGS - CXXFLAGS="$CXXFLAGS -Werror" + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -Wdiv-by-zero" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23828,30 +21236,30 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_check_cxxflags___Werror=yes +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___Wdiv_by_zero=yes else - ax_cv_check_cxxflags___Werror=no + ax_cv_check_cflags___Wdiv_by_zero=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS=$ax_check_save_flags + CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror" >&5 -$as_echo "$ax_cv_check_cxxflags___Werror" >&6; } -if test "x$ax_cv_check_cxxflags___Werror" = xyes; then : - CXXFLAGS="$CXXFLAGS -Werror" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wdiv_by_zero" >&5 +$as_echo "$ax_cv_check_cflags___Wdiv_by_zero" >&6; } +if test x"$ax_cv_check_cflags___Wdiv_by_zero" = xyes; then : + CFLAGS="$CFLAGS -Wdiv-by-zero" else : fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Wformat-security" >&5 -$as_echo_n "checking whether C++ compiler accepts -Wformat-security... " >&6; } -if ${ax_cv_check_cxxflags___Wformat_security+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wshorten-64-to-32" >&5 +$as_echo_n "checking whether C compiler accepts -Wshorten-64-to-32... " >&6; } +if ${ax_cv_check_cflags___Wshorten_64_to_32+:} false; then : $as_echo_n "(cached) " >&6 else - ax_check_save_flags=$CXXFLAGS - CXXFLAGS="$CXXFLAGS -Wformat-security" + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -Wshorten-64-to-32" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23863,48 +21271,32 @@ return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_check_cxxflags___Wformat_security=yes +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___Wshorten_64_to_32=yes else - ax_cv_check_cxxflags___Wformat_security=no + ax_cv_check_cflags___Wshorten_64_to_32=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS=$ax_check_save_flags + CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Wformat_security" >&5 -$as_echo "$ax_cv_check_cxxflags___Wformat_security" >&6; } -if test "x$ax_cv_check_cxxflags___Wformat_security" = xyes; then : - CXXFLAGS="$CXXFLAGS -Wformat-security" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wshorten_64_to_32" >&5 +$as_echo "$ax_cv_check_cflags___Wshorten_64_to_32" >&6; } +if test x"$ax_cv_check_cflags___Wshorten_64_to_32" = xyes; then : + CFLAGS="$CFLAGS -Wshorten-64-to-32" else : fi - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -fi - -WARNCFLAGS=$CFLAGS -WARNCXXFLAGS=$CXXFLAGS - -CFLAGS=$save_CFLAGS -CXXFLAGS=$save_CXXFLAGS - - - -EXTRACFLAG= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fvisibility=hidden" >&5 -$as_echo_n "checking whether C compiler accepts -fvisibility=hidden... " >&6; } -if ${ax_cv_check_cflags___fvisibility_hidden+:} false; then : + # Only work with Clang for the moment + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wheader-guard" >&5 +$as_echo_n "checking whether C compiler accepts -Wheader-guard... " >&6; } +if ${ax_cv_check_cflags___Wheader_guard+:} false; then : $as_echo_n "(cached) " >&6 else ax_check_save_flags=$CFLAGS - CFLAGS="$CFLAGS -fvisibility=hidden" + CFLAGS="$CFLAGS -Wheader-guard" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -23917,23 +21309,22 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ax_cv_check_cflags___fvisibility_hidden=yes + ax_cv_check_cflags___Wheader_guard=yes else - ax_cv_check_cflags___fvisibility_hidden=no + ax_cv_check_cflags___Wheader_guard=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$ax_check_save_flags fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fvisibility_hidden" >&5 -$as_echo "$ax_cv_check_cflags___fvisibility_hidden" >&6; } -if test "x$ax_cv_check_cflags___fvisibility_hidden" = xyes; then : - EXTRACFLAG="-fvisibility=hidden" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wheader_guard" >&5 +$as_echo "$ax_cv_check_cflags___Wheader_guard" >&6; } +if test x"$ax_cv_check_cflags___Wheader_guard" = xyes; then : + CFLAGS="$CFLAGS -Wheader-guard" else : fi - - +fi if test "x$debug" != "xno"; then @@ -23941,31 +21332,18 @@ fi -enable_threads=yes # Some platform does not have working std::future. We disable -# threading for those platforms. -if test "x$threads" != "xyes" || - test "x$have_std_future" != "xyes"; then - enable_threads=no +# threading for those platforms to exclude std::future use. +if test "x$threads" != "xyes" || test "x$have_std_future" != "xyes"; then $as_echo "#define NOTHREADS 1" >>confdefs.h fi -# propagate $enable_static to tests/Makefile.am - if test "x$enable_static" = "xyes"; then - ENABLE_STATIC_TRUE= - ENABLE_STATIC_FALSE='#' -else - ENABLE_STATIC_TRUE='#' - ENABLE_STATIC_FALSE= -fi - - -ac_config_files="$ac_config_files Makefile lib/Makefile lib/libnghttp2.pc lib/includes/Makefile lib/includes/nghttp2/nghttp2ver.h tests/Makefile tests/testdata/Makefile third-party/Makefile src/Makefile src/includes/Makefile src/libnghttp2_asio.pc examples/Makefile python/Makefile python/setup.py integration-tests/Makefile integration-tests/config.go integration-tests/setenv doc/Makefile doc/conf.py doc/index.rst doc/package_README.rst doc/tutorial-client.rst doc/tutorial-server.rst doc/tutorial-hpack.rst doc/nghttpx-howto.rst doc/h2load-howto.rst doc/libnghttp2_asio.rst doc/python-apiref.rst doc/building-android-binary.rst doc/nghttp2.h.rst doc/nghttp2ver.h.rst doc/asio_http2.h.rst doc/asio_http2_server.h.rst doc/asio_http2_client.h.rst doc/contribute.rst contrib/Makefile script/Makefile" +ac_config_files="$ac_config_files Makefile lib/Makefile lib/libnghttp2.pc lib/includes/Makefile lib/includes/nghttp2/nghttp2ver.h tests/Makefile tests/testdata/Makefile third-party/Makefile src/Makefile src/includes/Makefile src/libnghttp2_asio.pc examples/Makefile python/Makefile python/setup.py doc/Makefile doc/conf.py doc/index.rst doc/package_README.rst doc/tutorial-client.rst doc/tutorial-server.rst doc/tutorial-hpack.rst doc/nghttpx-howto.rst doc/h2load-howto.rst doc/libnghttp2_asio.rst doc/python-apiref.rst doc/building-android-binary.rst doc/nghttp2.h.rst doc/nghttp2ver.h.rst doc/asio_http2.h.rst doc/contribute.rst contrib/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -24132,18 +21510,6 @@ as_fn_error $? "conditional \"ENABLE_EXAMPLES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_THIRD_PARTY_TRUE}" && test -z "${ENABLE_THIRD_PARTY_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_THIRD_PARTY\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${HAVE_MRUBY_TRUE}" && test -z "${HAVE_MRUBY_FALSE}"; then - as_fn_error $? "conditional \"HAVE_MRUBY\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${HAVE_NEVERBLEED_TRUE}" && test -z "${HAVE_NEVERBLEED_FALSE}"; then - as_fn_error $? "conditional \"HAVE_NEVERBLEED\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${ENABLE_PYTHON_BINDINGS_TRUE}" && test -z "${ENABLE_PYTHON_BINDINGS_FALSE}"; then as_fn_error $? "conditional \"ENABLE_PYTHON_BINDINGS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -24161,10 +21527,6 @@ as_fn_error $? "conditional \"ENABLE_TINY_NGHTTPD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_STATIC_TRUE}" && test -z "${ENABLE_STATIC_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_STATIC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 @@ -24562,7 +21924,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by nghttp2 $as_me 1.13.0, which was +This file was extended by nghttp2 $as_me 0.6.7, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -24628,7 +21990,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -nghttp2 config.status 1.13.0 +nghttp2 config.status 0.6.7 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -24762,7 +22124,6 @@ enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' -shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' @@ -24812,13 +22173,10 @@ GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' -lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' -lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' @@ -24883,8 +22241,7 @@ finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' -configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' -configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' @@ -24989,12 +22346,9 @@ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ -lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ -lt_cv_nm_interface \ nm_file_list_spec \ -lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ @@ -25060,7 +22414,7 @@ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -25087,8 +22441,7 @@ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ -configure_time_dlsearch_path \ -configure_time_lt_sys_library_path \ +sys_lib_dlsearch_path_spec \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ @@ -25102,7 +22455,7 @@ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -25111,16 +22464,19 @@ done ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' -# See if we are running on zsh, and set the options that allow our +# See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}"; then +if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' @@ -25138,9 +22494,9 @@ for ac_config_target in $ac_config_targets do case $ac_config_target in - "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; "lib/libnghttp2.pc") CONFIG_FILES="$CONFIG_FILES lib/libnghttp2.pc" ;; @@ -25155,9 +22511,6 @@ "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; "python/Makefile") CONFIG_FILES="$CONFIG_FILES python/Makefile" ;; "python/setup.py") CONFIG_FILES="$CONFIG_FILES python/setup.py" ;; - "integration-tests/Makefile") CONFIG_FILES="$CONFIG_FILES integration-tests/Makefile" ;; - "integration-tests/config.go") CONFIG_FILES="$CONFIG_FILES integration-tests/config.go" ;; - "integration-tests/setenv") CONFIG_FILES="$CONFIG_FILES integration-tests/setenv" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "doc/conf.py") CONFIG_FILES="$CONFIG_FILES doc/conf.py" ;; "doc/index.rst") CONFIG_FILES="$CONFIG_FILES doc/index.rst" ;; @@ -25173,11 +22526,8 @@ "doc/nghttp2.h.rst") CONFIG_FILES="$CONFIG_FILES doc/nghttp2.h.rst" ;; "doc/nghttp2ver.h.rst") CONFIG_FILES="$CONFIG_FILES doc/nghttp2ver.h.rst" ;; "doc/asio_http2.h.rst") CONFIG_FILES="$CONFIG_FILES doc/asio_http2.h.rst" ;; - "doc/asio_http2_server.h.rst") CONFIG_FILES="$CONFIG_FILES doc/asio_http2_server.h.rst" ;; - "doc/asio_http2_client.h.rst") CONFIG_FILES="$CONFIG_FILES doc/asio_http2_client.h.rst" ;; "doc/contribute.rst") CONFIG_FILES="$CONFIG_FILES doc/contribute.rst" ;; "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; - "script/Makefile") CONFIG_FILES="$CONFIG_FILES script/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac @@ -25775,53 +23125,55 @@ case $ac_file$ac_mode in "libtool":C) - # See if we are running on zsh, and set the options that allow our + # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}"; then + if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi - cfgfile=${ofile}T + cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL -# Generated automatically by $as_me ($PACKAGE) $VERSION + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. - -# Provide generalized library-building support services. -# Written by Gordon Matzigkeit, 1996 - -# Copyright (C) 2014 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of of the License, or -# (at your option) any later version. # -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program or library that is built -# using GNU Libtool, you may include this file under the same -# distribution terms that you use for the rest of that program. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. # -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. -available_tags='CXX ' - -# Configured defaults for sys_lib_dlsearch_path munging. -: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} +available_tags="CXX " # ### BEGIN LIBTOOL CONFIG @@ -25841,9 +23193,6 @@ # Whether or not to optimize for fast installation. fast_install=$enable_fast_install -# Shared archive member basename,for filename based shared library versioning on AIX. -shared_archive_member_spec=$shared_archive_member_spec - # Shell to use when invoking shell scripts. SHELL=$lt_SHELL @@ -25961,27 +23310,18 @@ # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl -# Transform the output of nm into a list of symbols to manually relocate. -global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import - # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix -# The name lister interface. -nm_interface=$lt_lt_cv_nm_interface - # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec -# The root where to search for dependent libraries,and where our libraries should be installed. +# The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot -# Command to truncate a binary pipe. -lt_truncate_bin=$lt_lt_cv_truncate_bin - # The name of the directory that contains temporary libtool files. objdir=$objdir @@ -26072,11 +23412,8 @@ # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec -# Detected run-time system search path for libraries. -sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path - -# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. -configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen @@ -26169,13 +23506,13 @@ # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute @@ -26241,72 +23578,13 @@ _LT_EOF - cat <<'_LT_EOF' >> "$cfgfile" - -# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE - -# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x$2 in - x) - ;; - *:) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" - ;; - x:*) - eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" - ;; - *) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" - ;; - esac -} - - -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in $*""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} - - -# ### END FUNCTIONS SHARED WITH CONFIGURE - -_LT_EOF - case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. -if test set != "${COLLECT_NAMES+set}"; then +if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -26315,7 +23593,7 @@ esac -ltmain=$ac_aux_dir/ltmain.sh +ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if @@ -26325,6 +23603,165 @@ sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" @@ -26411,13 +23848,13 @@ # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX @@ -26617,125 +24054,83 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: summary of build options: - Package version: ${VERSION} - Library version: $LT_CURRENT:$LT_REVISION:$LT_AGE - Install prefix: ${prefix} - System types: - Build: ${build} - Host: ${host} - Target: ${target} - Compiler: - C compiler: ${CC} - CFLAGS: ${CFLAGS} - LDFLAGS: ${LDFLAGS} - C++ compiler: ${CXX} - CXXFLAGS: ${CXXFLAGS} - CXXCPP: ${CXXCPP} - C preprocessor: ${CPP} - CPPFLAGS: ${CPPFLAGS} - WARNCFLAGS: ${WARNCFLAGS} - CXX1XCXXFLAGS: ${CXX1XCXXFLAGS} - EXTRACFLAG: ${EXTRACFLAG} - LIBS: ${LIBS} - Library: - Shared: ${enable_shared} - Static: ${enable_static} - Python: - Python: ${PYTHON} - PYTHON_VERSION: ${PYTHON_VERSION} - pyexecdir: ${pyexecdir} - Python-dev: ${have_python_dev} - PYTHON_CPPFLAGS:${PYTHON_CPPFLAGS} - PYTHON_LDFLAGS: ${PYTHON_LDFLAGS} - Cython: ${CYTHON} - Test: - CUnit: ${have_cunit} (CFLAGS='${CUNIT_CFLAGS}' LIBS='${CUNIT_LIBS}') - Failmalloc: ${enable_failmalloc} - Libs: - OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}') - Libxml2: ${have_libxml2} (CFLAGS='${XML_CPPFLAGS}' LIBS='${XML_LIBS}') - Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}') - Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}') - Spdylay: ${have_spdylay} (CFLAGS='${LIBSPDYLAY_CFLAGS}' LIBS='${LIBSPDYLAY_LIBS}') - Jansson: ${have_jansson} (CFLAGS='${JANSSON_CFLAGS}' LIBS='${JANSSON_LIBS}') - Jemalloc: ${have_jemalloc} (LIBS='${JEMALLOC_LIBS}') - Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}') - Boost CPPFLAGS: ${BOOST_CPPFLAGS} - Boost LDFLAGS: ${BOOST_LDFLAGS} - Boost::ASIO: ${BOOST_ASIO_LIB} - Boost::System: ${BOOST_SYSTEM_LIB} - Boost::Thread: ${BOOST_THREAD_LIB} - Third-party: - http-parser: ${enable_third_party} - MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}') - Neverbleed: ${have_neverbleed} - Features: - Applications: ${enable_app} - HPACK tools: ${enable_hpack_tools} - Libnghttp2_asio:${enable_asio_lib} - Examples: ${enable_examples} - Python bindings:${enable_python_bindings} - Threading: ${enable_threads} + Version: ${VERSION} shared $LT_CURRENT:$LT_REVISION:$LT_AGE + Host type: ${host} + Install prefix: ${prefix} + C compiler: ${CC} + CFLAGS: ${CFLAGS} + LDFLAGS: ${LDFLAGS} + LIBS: ${LIBS} + CPPFLAGS: ${CPPFLAGS} + C preprocessor: ${CPP} + C++ compiler: ${CXX} + CXXFLAGS: ${CXXFLAGS} + CXXCPP: ${CXXCPP} + Library types: Shared=${enable_shared}, Static=${enable_static} + Python: ${PYTHON} + PYTHON_VERSION: ${PYTHON_VERSION} + pyexecdir: ${pyexecdir} + Python-dev: ${have_python_dev} + PYTHON_CPPFLAGS:${PYTHON_CPPFLAGS} + PYTHON_LDFLAGS: ${PYTHON_LDFLAGS} + Cython: ${CYTHON} + CUnit: ${have_cunit} + OpenSSL: ${have_openssl} + Libxml2: ${have_libxml2} + Libevent(SSL): ${have_libevent_openssl} + Spdylay: ${have_spdylay} + Jansson: ${have_jansson} + Jemalloc: ${have_jemalloc} + Boost CPPFLAGS: ${BOOST_CPPFLAGS} + Boost LDFLAGS: ${BOOST_LDFLAGS} + Boost::ASIO: ${BOOST_ASIO_LIB} + Boost::System: ${BOOST_SYSTEM_LIB} + Boost::Thread: ${BOOST_THREAD_LIB} + Applications: ${enable_app} + HPACK tools: ${enable_hpack_tools} + Libnghttp2_asio:${enable_asio_lib} + Examples: ${enable_examples} + Python bindings:${enable_python_bindings} + Failmalloc: ${request_failmalloc} " >&5 $as_echo "$as_me: summary of build options: - Package version: ${VERSION} - Library version: $LT_CURRENT:$LT_REVISION:$LT_AGE - Install prefix: ${prefix} - System types: - Build: ${build} - Host: ${host} - Target: ${target} - Compiler: - C compiler: ${CC} - CFLAGS: ${CFLAGS} - LDFLAGS: ${LDFLAGS} - C++ compiler: ${CXX} - CXXFLAGS: ${CXXFLAGS} - CXXCPP: ${CXXCPP} - C preprocessor: ${CPP} - CPPFLAGS: ${CPPFLAGS} - WARNCFLAGS: ${WARNCFLAGS} - CXX1XCXXFLAGS: ${CXX1XCXXFLAGS} - EXTRACFLAG: ${EXTRACFLAG} - LIBS: ${LIBS} - Library: - Shared: ${enable_shared} - Static: ${enable_static} - Python: - Python: ${PYTHON} - PYTHON_VERSION: ${PYTHON_VERSION} - pyexecdir: ${pyexecdir} - Python-dev: ${have_python_dev} - PYTHON_CPPFLAGS:${PYTHON_CPPFLAGS} - PYTHON_LDFLAGS: ${PYTHON_LDFLAGS} - Cython: ${CYTHON} - Test: - CUnit: ${have_cunit} (CFLAGS='${CUNIT_CFLAGS}' LIBS='${CUNIT_LIBS}') - Failmalloc: ${enable_failmalloc} - Libs: - OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}') - Libxml2: ${have_libxml2} (CFLAGS='${XML_CPPFLAGS}' LIBS='${XML_LIBS}') - Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}') - Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}') - Spdylay: ${have_spdylay} (CFLAGS='${LIBSPDYLAY_CFLAGS}' LIBS='${LIBSPDYLAY_LIBS}') - Jansson: ${have_jansson} (CFLAGS='${JANSSON_CFLAGS}' LIBS='${JANSSON_LIBS}') - Jemalloc: ${have_jemalloc} (LIBS='${JEMALLOC_LIBS}') - Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}') - Boost CPPFLAGS: ${BOOST_CPPFLAGS} - Boost LDFLAGS: ${BOOST_LDFLAGS} - Boost::ASIO: ${BOOST_ASIO_LIB} - Boost::System: ${BOOST_SYSTEM_LIB} - Boost::Thread: ${BOOST_THREAD_LIB} - Third-party: - http-parser: ${enable_third_party} - MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}') - Neverbleed: ${have_neverbleed} - Features: - Applications: ${enable_app} - HPACK tools: ${enable_hpack_tools} - Libnghttp2_asio:${enable_asio_lib} - Examples: ${enable_examples} - Python bindings:${enable_python_bindings} - Threading: ${enable_threads} + Version: ${VERSION} shared $LT_CURRENT:$LT_REVISION:$LT_AGE + Host type: ${host} + Install prefix: ${prefix} + C compiler: ${CC} + CFLAGS: ${CFLAGS} + LDFLAGS: ${LDFLAGS} + LIBS: ${LIBS} + CPPFLAGS: ${CPPFLAGS} + C preprocessor: ${CPP} + C++ compiler: ${CXX} + CXXFLAGS: ${CXXFLAGS} + CXXCPP: ${CXXCPP} + Library types: Shared=${enable_shared}, Static=${enable_static} + Python: ${PYTHON} + PYTHON_VERSION: ${PYTHON_VERSION} + pyexecdir: ${pyexecdir} + Python-dev: ${have_python_dev} + PYTHON_CPPFLAGS:${PYTHON_CPPFLAGS} + PYTHON_LDFLAGS: ${PYTHON_LDFLAGS} + Cython: ${CYTHON} + CUnit: ${have_cunit} + OpenSSL: ${have_openssl} + Libxml2: ${have_libxml2} + Libevent(SSL): ${have_libevent_openssl} + Spdylay: ${have_spdylay} + Jansson: ${have_jansson} + Jemalloc: ${have_jemalloc} + Boost CPPFLAGS: ${BOOST_CPPFLAGS} + Boost LDFLAGS: ${BOOST_LDFLAGS} + Boost::ASIO: ${BOOST_ASIO_LIB} + Boost::System: ${BOOST_SYSTEM_LIB} + Boost::Thread: ${BOOST_THREAD_LIB} + Applications: ${enable_app} + HPACK tools: ${enable_hpack_tools} + Libnghttp2_asio:${enable_asio_lib} + Examples: ${enable_examples} + Python bindings:${enable_python_bindings} + Failmalloc: ${request_failmalloc} " >&6;} diff -Nru nghttp2-1.13.0/configure.ac nghttp2-0.6.7/configure.ac --- nghttp2-1.13.0/configure.ac 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/configure.ac 2014-11-30 14:15:07.000000000 +0000 @@ -1,6 +1,6 @@ dnl nghttp2 - HTTP/2 C Library -dnl Copyright (c) 2012, 2013, 2014, 2015 Tatsuhiro Tsujikawa +dnl Copyright (c) 2012, 2013 Tatsuhiro Tsujikawa dnl Permission is hereby granted, free of charge, to any person obtaining dnl a copy of this software and associated documentation files (the @@ -20,33 +20,15 @@ dnl LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION dnl OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION dnl WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -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], [1.13.0], [t-tujikawa@users.sourceforge.net]) -AC_CONFIG_AUX_DIR([.]) -AC_CONFIG_MACRO_DIR([m4]) -AC_CONFIG_HEADERS([config.h]) -AC_USE_SYSTEM_EXTENSIONS - +AC_INIT([nghttp2], [0.6.7], [t-tujikawa@users.sourceforge.net]) LT_PREREQ([2.2.6]) LT_INIT() - -AC_CANONICAL_BUILD -AC_CANONICAL_HOST -AC_CANONICAL_TARGET - -AM_INIT_AUTOMAKE([subdir-objects]) - -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - dnl See versioning rule: dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -AC_SUBST(LT_CURRENT, 23) -AC_SUBST(LT_REVISION, 0) -AC_SUBST(LT_AGE, 9) +AC_SUBST(LT_CURRENT, 7) +AC_SUBST(LT_REVISION, 2) +AC_SUBST(LT_AGE, 2) 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"` @@ -56,6 +38,18 @@ AC_SUBST(PACKAGE_VERSION_NUM) +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE([subdir-objects]) + +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_CONFIG_HEADERS([config.h]) + dnl Checks for command-line options AC_ARG_ENABLE([werror], [AS_HELP_STRING([--enable-werror], @@ -74,7 +68,7 @@ AC_ARG_ENABLE([app], [AS_HELP_STRING([--enable-app], - [Build applications (nghttp, nghttpd, nghttpx and h2load) [default=check]])], + [Build applications (nghttp, nghttpd and nghttpx) [default=check]])], [request_app=$enableval], [request_app=check]) AC_ARG_ENABLE([hpack-tools], @@ -98,14 +92,9 @@ [request_python_bindings=$enableval], [request_python_bindings=check]) AC_ARG_ENABLE([failmalloc], - [AS_HELP_STRING([--disable-failmalloc], - [Do not build failmalloc test program])], - [request_failmalloc=$enableval], [request_failmalloc=yes]) - -AC_ARG_ENABLE([lib-only], - [AS_HELP_STRING([--enable-lib-only], - [Build libnghttp2 only. This is a short hand for --disable-app --disable-examples --disable-hpack-tools --disable-python-bindings])], - [request_lib_only=$enableval], [request_lib_only=no]) + [AS_HELP_STRING([--enable-failmalloc], + [Build failmalloc test program [default=no]])], + [request_failmalloc=$enableval], [request_failmalloc=no]) AC_ARG_WITH([libxml2], [AS_HELP_STRING([--with-libxml2], @@ -122,16 +111,6 @@ [Use spdylay [default=check]])], [request_spdylay=$withval], [request_spdylay=check]) -AC_ARG_WITH([mruby], - [AS_HELP_STRING([--with-mruby], - [Use mruby [default=no]])], - [request_mruby=$withval], [request_mruby=no]) - -AC_ARG_WITH([neverbleed], - [AS_HELP_STRING([--with-neverbleed], - [Use neverbleed [default=no]])], - [request_neverbleed=$withval], [request_neverbleed=no]) - AC_ARG_WITH([cython], [AS_HELP_STRING([--with-cython=PATH], [Use cython in given PATH])], @@ -143,24 +122,14 @@ dnl Checks for programs AC_PROG_CC AC_PROG_CXX -AC_PROG_CPP AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET -AC_PROG_MKDIR_P - +AM_PROG_CC_C_O PKG_PROG_PKG_CONFIG([0.20]) -AM_PATH_PYTHON([2.7],, [:]) - -if [test "x$request_lib_only" = "xyes"]; then - request_app=no - request_hpack_tools=no - request_examples=no - request_python_bindings=no -fi - if [test "x$request_python_bindings" != "xno"]; then + AM_PATH_PYTHON([2.7],, [:]) AX_PYTHON_DEVEL([>= '2.7']) fi @@ -181,25 +150,31 @@ # if test "x$GCC" = "xyes" -o "x$CC" = "xclang" ; then AC_DEFINE([_U_], [__attribute__((unused))], [Hint to the compiler that a function parameters is not used]) - AC_DEFINE([NGHTTP2_NORETURN], [__attribute__((noreturn))], [Hint to the compiler that a function never return]) else - AC_DEFINE([_U_], , [Hint to the compiler that a function parameter is not used]) - AC_DEFINE([NGHTTP2_NORETURN], , [Hint to the compiler that a function never return]) + AC_DEFINE([_U_], , [Hint to the compiler that a function parameters is not used]) fi -save_CXXFLAGS="$CXXFLAGS" -CXXFLAGS= - AX_CXX_COMPILE_STDCXX_11([noext], [optional]) -CXX1XCXXFLAGS="$CXXFLAGS" -CXXFLAGS="$save_CXXFLAGS" -AC_SUBST([CXX1XCXXFLAGS]) - AC_LANG_PUSH(C++) -save_CXXFLAGS="$CXXFLAGS" -CXXFLAGS="$CXXFLAGS $CXX1XCXXFLAGS" +# Check that std::chrono::steady_clock is available. In particular, +# gcc 4.6 does not have one, but has monotonic_clock which is the old +# name existed in the pre-standard draft. If steady_clock is not +# available, don't define HAVE_STEADY_CLOCK and replace steady_clock +# with monotonic_clock. +AC_MSG_CHECKING([whether std::chrono::steady_clock is available]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[[ +#include +]], +[[ +auto tp = std::chrono::steady_clock::now(); +]])], + [AC_DEFINE([HAVE_STEADY_CLOCK], [1], + [Define to 1 if you have the `std::chrono::steady_clock`.]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) # Check that std::future is available. AC_MSG_CHECKING([whether std::future is available]) @@ -218,65 +193,55 @@ [have_std_future=no AC_MSG_RESULT([no])]) -# Check that std::map::emplace is available for g++-4.7. -AC_MSG_CHECKING([whether std::map::emplace is available]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM( -[[ -#include -]], -[[ -std::map().emplace(1, 2); -]])], - [AC_DEFINE([HAVE_STD_MAP_EMPLACE], [1], - [Define to 1 if you have the `std::map::emplace`.]) - have_std_map_emplace=yes - AC_MSG_RESULT([yes])], - [have_std_map_emplace=no - AC_MSG_RESULT([no])]) - -CXXFLAGS=$save_CXXFLAGS - AC_LANG_POP() # Checks for libraries. # Additional libraries required for tests. -TESTLDADD= +TESTS_LIBS= # Additional libraries required for programs under src directory. -APPLDFLAGS= +SRC_LIBS= + +LIBS_OLD=$LIBS +# Search for dlsym function, which is used in tests. Linux needs -ldl, +# but netbsd does not need it. +AC_SEARCH_LIBS([dlsym], [dl]) +TESTS_LIBS="$LIBS $TESTS_LIBS" +LIBS=$LIBS_OLD + +LIBS_OLD=$LIBS +AC_SEARCH_LIBS([clock_gettime], [rt], + [AC_DEFINE([HAVE_CLOCK_GETTIME], [1], + [Define to 1 if you have the `clock_gettime`.])]) +SRC_LIBS="$LIBS $SRC_LIBS" +LIBS=$LIBS_OLD case "$host" in *android*) android_build=yes - # android does not need -pthread, but needs followng 3 libs for C++ - APPLDFLAGS="$APPLDFLAGS -lstdc++ -latomic -lsupc++" + # android does not need -pthread, but needs followng 2 libs for C++ + SRC_LIBS="$SRC_LIBS -lstdc++ -lsupc++" ;; *) PTHREAD_LDFLAGS="-pthread" - APPLDFLAGS="$APPLDFLAGS $PTHREAD_LDFLAGS" + SRC_LIBS="$SRC_LIBS $PTHREAD_LDFLAGS" ;; esac # zlib -PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no]) +if test "x$android_build" = "xyes"; then + # Use zlib provided by NDK + SRC_LIBS="-lz $SRC_LIBS" + have_zlib=yes +else + 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) + if test "x${have_zlib}" = "xno"; then + AC_MSG_NOTICE($ZLIB_PKG_ERRORS) + fi fi -# dl: openssl requires libdl when it is statically linked. -case "${host_os}" in - *bsd*) - # dlopen is in libc on *BSD - ;; - *) - save_LIBS=$LIBS - AC_SEARCH_LIBS([dlopen], [dl], [APPLDFLAGS="-ldl $APPLDFLAGS"], [], []) - LIBS=$save_LIBS - ;; -esac - # cunit PKG_CHECK_MODULES([CUNIT], [cunit >= 2.1], [have_cunit=yes], [have_cunit=no]) # If pkg-config does not find cunit, check it using AC_CHECK_LIB. We @@ -306,22 +271,6 @@ AM_CONDITIONAL([HAVE_CUNIT], [ test "x${have_cunit}" = "xyes" ]) -# libev (for src) -# libev does not have pkg-config file. Check it in an old way. -save_LIBS=$LIBS -# android requires -lm for floor -AC_CHECK_LIB([ev], [ev_time], [have_libev=yes], [have_libev=no], [-lm]) -if test "x${have_libev}" = "xyes"; then - AC_CHECK_HEADER([ev.h], [have_libev=yes], [have_libev=no]) - if test "x${have_libev}" = "xyes"; then - LIBEV_LIBS=-lev - LIBEV_CFLAGS= - AC_SUBST([LIBEV_LIBS]) - AC_SUBST([LIBEV_CFLAGS]) - fi -fi -LIBS=$save_LIBS - # openssl (for src) PKG_CHECK_MODULES([OPENSSL], [openssl >= 1.0.1], [have_openssl=yes], [have_openssl=no]) @@ -329,7 +278,7 @@ AC_MSG_NOTICE($OPENSSL_PKG_ERRORS) fi -# libevent_openssl (for examples) +# libevent_openssl (for src) # 2.0.8 is required because we use evconnlistener_set_error_cb() PKG_CHECK_MODULES([LIBEVENT_OPENSSL], [libevent_openssl >= 2.0.8], [have_libevent_openssl=yes], [have_libevent_openssl=no]) @@ -340,7 +289,7 @@ # jansson (for src/nghttp, src/deflatehd and src/inflatehd) PKG_CHECK_MODULES([JANSSON], [jansson >= 2.5], [have_jansson=yes], [have_jansson=no]) -if test "x${have_jansson}" = "xyes"; then +if test "x${have_jansson}" == "xyes"; then AC_DEFINE([HAVE_JANSSON], [1], [Define to 1 if you have `libjansson` library.]) else @@ -350,10 +299,7 @@ # libxml2 (for src/nghttp) have_libxml2=no if test "x${request_libxml2}" != "xno"; then - m4_ifdef([AM_PATH_XML2], - [AM_PATH_XML2(2.7.7, [have_libxml2=yes], [have_libxml2=no])], - [AC_MSG_WARN([configure was created without libxml2 detection macro; libxml2 detection is disabled])]) - + AM_PATH_XML2(2.7.7, [have_libxml2=yes], [have_libxml2=no]) if test "x${have_libxml2}" = "xyes"; then AC_DEFINE([HAVE_LIBXML2], [1], [Define to 1 if you have `libxml2` library.]) fi @@ -369,27 +315,13 @@ # jemalloc have_jemalloc=no if test "x${request_jemalloc}" != "xno"; then - save_LIBS=$LIBS + LIBS_OLD=$LIBS AC_SEARCH_LIBS([malloc_stats_print], [jemalloc], [have_jemalloc=yes], [], [$PTHREAD_LDFLAGS]) - - 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]) - - if test "x${have_jemalloc}" = "xyes"; then - jemalloc_libs=${ac_cv_search_je_malloc_stats_print} - fi - fi - - LIBS=$save_LIBS - + LIBS=$LIBS_OLD if test "x${have_jemalloc}" = "xyes" && - test "x${jemalloc_libs}" != "xnone required"; then - JEMALLOC_LIBS=${jemalloc_libs} + test "x${ac_cv_search_malloc_stats_print}" != "xnone required"; then + JEMALLOC_LIBS=${ac_cv_search_malloc_stats_print} AC_SUBST([JEMALLOC_LIBS]) fi fi @@ -402,7 +334,7 @@ # spdylay (for src/nghttpx and src/h2load) have_spdylay=no if test "x${request_spdylay}" != "xno"; then - PKG_CHECK_MODULES([LIBSPDYLAY], [libspdylay >= 1.3.2], + PKG_CHECK_MODULES([LIBSPDYLAY], [libspdylay >= 1.3.0], [have_spdylay=yes], [have_spdylay=no]) if test "x${have_spdylay}" = "xyes"; then AC_DEFINE([HAVE_SPDYLAY], [1], [Define to 1 if you have `spdylay` library.]) @@ -439,12 +371,12 @@ fi # The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL -# and libev +# 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_libev}" = "xyes"; then + test "x${have_libevent_openssl}" = "xyes"; then enable_app=yes fi @@ -494,39 +426,6 @@ AM_CONDITIONAL([ENABLE_EXAMPLES], [ test "x${enable_examples}" = "xyes" ]) -# third-party only be built when needed - -enable_third_party=no -have_mruby=no -have_neverbleed=no -if test "x${enable_examples}" = "xyes" || - test "x${enable_app}" = "xyes" || - test "x${enable_hpack_tools}" = "xyes" || - test "x${enable_asio_lib}" = "xyes"; then - enable_third_party=yes - - # mruby (for src/nghttpx) - if test "x${request_mruby}" = "xyes"; then - # We are going to build mruby - have_mruby=yes - AC_DEFINE([HAVE_MRUBY], [1], [Define to 1 if you have `mruby` library.]) - LIBMRUBY_LIBS="-lmruby -lm" - LIBMRUBY_CFLAGS= - AC_SUBST([LIBMRUBY_LIBS]) - AC_SUBST([LIBMRUBY_CFLAGS]) - fi - - # neverbleed (for src/nghttpx) - if test "x${request_neverbleed}" = "xyes"; then - have_neverbleed=yes - AC_DEFINE([HAVE_NEVERBLEED], [1], [Define to 1 if you have `neverbleed` library.]) - fi -fi - -AM_CONDITIONAL([ENABLE_THIRD_PARTY], [ test "x${enable_third_party}" = "xyes" ]) -AM_CONDITIONAL([HAVE_MRUBY], [test "x${have_mruby}" = "xyes"]) -AM_CONDITIONAL([HAVE_NEVERBLEED], [test "x${have_neverbleed}" = "xyes"]) - # Python bindings enable_python_bindings=no if test "x${request_python_bindings}" != "xno" && @@ -549,34 +448,29 @@ AM_CONDITIONAL([HAVE_CYTHON], [test "x${CYTHON}" != "x"]) # failmalloc tests -enable_failmalloc=no -if test "x${request_failmalloc}" = "xyes"; then - enable_failmalloc=yes -fi - AM_CONDITIONAL([ENABLE_FAILMALLOC], [ test "x${enable_failmalloc}" = "xyes" ]) # Checks for header files. 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 @@ -584,16 +478,8 @@ 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], @@ -604,44 +490,15 @@ [Define to 1 if you have `struct tm.tm_gmtoff` member.]) fi -# Check size of pointer to decide we need 8 bytes alignment -# adjustment. -AC_CHECK_SIZEOF([int *]) - -AC_CHECK_SIZEOF([time_t]) - # Checks for library functions. - -# Don't check malloc, since it does not play nicely with C++ stdlib -# AC_FUNC_MALLOC - -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 - +if test "x$cross_compiling" != "xyes"; then + AC_FUNC_MALLOC +fi AC_CHECK_FUNCS([ \ _Exit \ - accept4 \ - dup2 \ - getcwd \ getpwnam \ - localtime_r \ - memchr \ memmove \ memset \ - socket \ - sqrt \ - strchr \ - strdup \ - strerror \ - strndup \ - strstr \ - strtol \ - strtoul \ timegm \ ]) @@ -650,15 +507,6 @@ AC_CHECK_FUNC([timerfd_create], [have_timerfd_create=yes], [have_timerfd_create=no]) -# For cygwin: we can link initgroups, so AC_CHECK_FUNCS succeeds, but -# cygwin disables initgroups due to feature test macro magic with our -# configuration. FreeBSD declares initgroups() in unistd.h. -AC_CHECK_DECLS([initgroups], [], [], [[ - #ifdef HAVE_UNISTD_H - # include - #endif - #include -]]) # Checks for epoll availability, primarily for examples/tiny-nghttpd AX_HAVE_EPOLL([have_epoll=yes], [have_epoll=no]) @@ -667,14 +515,14 @@ [ test "x${have_epoll}" = "xyes" && test "x${have_timerfd_create}" = "xyes"]) -save_CFLAGS=$CFLAGS -save_CXXFLAGS=$CXXFLAGS - -CFLAGS= -CXXFLAGS= +dnl Windows library for winsock2 +case "${host}" in + *mingw*) + LIBS="$LIBS -lws2_32" + ;; +esac if test "x$werror" != "xno"; then - # For C compiler AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"]) AX_CHECK_COMPILE_FLAG([-Wextra], [CFLAGS="$CFLAGS -Wextra"]) AX_CHECK_COMPILE_FLAG([-Werror], [CFLAGS="$CFLAGS -Werror"]) @@ -702,68 +550,22 @@ AX_CHECK_COMPILE_FLAG([-Wdiv-by-zero], [CFLAGS="$CFLAGS -Wdiv-by-zero"]) AX_CHECK_COMPILE_FLAG([-Wshorten-64-to-32], [CFLAGS="$CFLAGS -Wshorten-64-to-32"]) - AX_CHECK_COMPILE_FLAG([-Wconversion], [CFLAGS="$CFLAGS -Wconversion"]) - AX_CHECK_COMPILE_FLAG([-Wextended-offsetof], [CFLAGS="$CFLAGS -Wextended-offsetof"]) - AX_CHECK_COMPILE_FLAG([-Wformat-nonliteral], [CFLAGS="$CFLAGS -Wformat-nonliteral"]) - AX_CHECK_COMPILE_FLAG([-Wlanguage-extension-token], [CFLAGS="$CFLAGS -Wlanguage-extension-token"]) - AX_CHECK_COMPILE_FLAG([-Wmissing-field-initializers], [CFLAGS="$CFLAGS -Wmissing-field-initializers"]) - AX_CHECK_COMPILE_FLAG([-Wmissing-noreturn], [CFLAGS="$CFLAGS -Wmissing-noreturn"]) - AX_CHECK_COMPILE_FLAG([-Wmissing-variable-declarations], [CFLAGS="$CFLAGS -Wmissing-variable-declarations"]) - # Not used because we cannot change public structs - # AX_CHECK_COMPILE_FLAG([-Wpadded], [CFLAGS="$CFLAGS -Wpadded"]) - AX_CHECK_COMPILE_FLAG([-Wsign-conversion], [CFLAGS="$CFLAGS -Wsign-conversion"]) - # Not used because this basically disallows default case - # AX_CHECK_COMPILE_FLAG([-Wswitch-enum], [CFLAGS="$CFLAGS -Wswitch-enum"]) - AX_CHECK_COMPILE_FLAG([-Wunreachable-code-break], [CFLAGS="$CFLAGS -Wunreachable-code-break"]) - AX_CHECK_COMPILE_FLAG([-Wunused-macros], [CFLAGS="$CFLAGS -Wunused-macros"]) - AX_CHECK_COMPILE_FLAG([-Wunused-parameter], [CFLAGS="$CFLAGS -Wunused-parameter"]) - AX_CHECK_COMPILE_FLAG([-Wredundant-decls], [CFLAGS="$CFLAGS -Wredundant-decls"]) # Only work with Clang for the moment AX_CHECK_COMPILE_FLAG([-Wheader-guard], [CFLAGS="$CFLAGS -Wheader-guard"]) - - # This is required because we pass format string as "const char*. - AX_CHECK_COMPILE_FLAG([-Wno-format-nonliteral], [CFLAGS="$CFLAGS -Wno-format-nonliteral"]) - - # For C++ compiler - AC_LANG_PUSH(C++) - AX_CHECK_COMPILE_FLAG([-Wall], [CXXFLAGS="$CXXFLAGS -Wall"]) - AX_CHECK_COMPILE_FLAG([-Werror], [CXXFLAGS="$CXXFLAGS -Werror"]) - AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"]) - AC_LANG_POP() fi -WARNCFLAGS=$CFLAGS -WARNCXXFLAGS=$CXXFLAGS - -CFLAGS=$save_CFLAGS -CXXFLAGS=$save_CXXFLAGS - -AC_SUBST([WARNCFLAGS]) -AC_SUBST([WARNCXXFLAGS]) - -EXTRACFLAG= -AX_CHECK_COMPILE_FLAG([-fvisibility=hidden], [EXTRACFLAG="-fvisibility=hidden"]) - -AC_SUBST([EXTRACFLAG]) - if test "x$debug" != "xno"; then AC_DEFINE([DEBUGBUILD], [1], [Define to 1 to enable debug output.]) fi -enable_threads=yes # Some platform does not have working std::future. We disable -# threading for those platforms. -if test "x$threads" != "xyes" || - test "x$have_std_future" != "xyes"; then - enable_threads=no +# threading for those platforms to exclude std::future use. +if test "x$threads" != "xyes" || test "x$have_std_future" != "xyes"; then AC_DEFINE([NOTHREADS], [1], [Define to 1 if you want to disable threads.]) fi -# propagate $enable_static to tests/Makefile.am -AM_CONDITIONAL([ENABLE_STATIC], [test "x$enable_static" = "xyes"]) - -AC_SUBST([TESTLDADD]) -AC_SUBST([APPLDFLAGS]) +AC_SUBST([TESTS_LIBS]) +AC_SUBST([SRC_LIBS]) AC_CONFIG_FILES([ Makefile @@ -780,9 +582,6 @@ examples/Makefile python/Makefile python/setup.py - integration-tests/Makefile - integration-tests/config.go - integration-tests/setenv doc/Makefile doc/conf.py doc/index.rst @@ -798,73 +597,49 @@ doc/nghttp2.h.rst doc/nghttp2ver.h.rst doc/asio_http2.h.rst - doc/asio_http2_server.h.rst - doc/asio_http2_client.h.rst doc/contribute.rst contrib/Makefile - script/Makefile ]) AC_OUTPUT AC_MSG_NOTICE([summary of build options: - Package version: ${VERSION} - Library version: $LT_CURRENT:$LT_REVISION:$LT_AGE - Install prefix: ${prefix} - System types: - Build: ${build} - Host: ${host} - Target: ${target} - Compiler: - C compiler: ${CC} - CFLAGS: ${CFLAGS} - LDFLAGS: ${LDFLAGS} - C++ compiler: ${CXX} - CXXFLAGS: ${CXXFLAGS} - CXXCPP: ${CXXCPP} - C preprocessor: ${CPP} - CPPFLAGS: ${CPPFLAGS} - WARNCFLAGS: ${WARNCFLAGS} - CXX1XCXXFLAGS: ${CXX1XCXXFLAGS} - EXTRACFLAG: ${EXTRACFLAG} - LIBS: ${LIBS} - Library: - Shared: ${enable_shared} - Static: ${enable_static} - Python: - Python: ${PYTHON} - PYTHON_VERSION: ${PYTHON_VERSION} - pyexecdir: ${pyexecdir} - Python-dev: ${have_python_dev} - PYTHON_CPPFLAGS:${PYTHON_CPPFLAGS} - PYTHON_LDFLAGS: ${PYTHON_LDFLAGS} - Cython: ${CYTHON} - Test: - CUnit: ${have_cunit} (CFLAGS='${CUNIT_CFLAGS}' LIBS='${CUNIT_LIBS}') - Failmalloc: ${enable_failmalloc} - Libs: - OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}') - Libxml2: ${have_libxml2} (CFLAGS='${XML_CPPFLAGS}' LIBS='${XML_LIBS}') - Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}') - Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}') - Spdylay: ${have_spdylay} (CFLAGS='${LIBSPDYLAY_CFLAGS}' LIBS='${LIBSPDYLAY_LIBS}') - Jansson: ${have_jansson} (CFLAGS='${JANSSON_CFLAGS}' LIBS='${JANSSON_LIBS}') - Jemalloc: ${have_jemalloc} (LIBS='${JEMALLOC_LIBS}') - Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}') - Boost CPPFLAGS: ${BOOST_CPPFLAGS} - Boost LDFLAGS: ${BOOST_LDFLAGS} - Boost::ASIO: ${BOOST_ASIO_LIB} - Boost::System: ${BOOST_SYSTEM_LIB} - Boost::Thread: ${BOOST_THREAD_LIB} - Third-party: - http-parser: ${enable_third_party} - MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}') - Neverbleed: ${have_neverbleed} - Features: - Applications: ${enable_app} - HPACK tools: ${enable_hpack_tools} - Libnghttp2_asio:${enable_asio_lib} - Examples: ${enable_examples} - Python bindings:${enable_python_bindings} - Threading: ${enable_threads} + Version: ${VERSION} shared $LT_CURRENT:$LT_REVISION:$LT_AGE + Host type: ${host} + Install prefix: ${prefix} + C compiler: ${CC} + CFLAGS: ${CFLAGS} + LDFLAGS: ${LDFLAGS} + LIBS: ${LIBS} + CPPFLAGS: ${CPPFLAGS} + C preprocessor: ${CPP} + C++ compiler: ${CXX} + CXXFLAGS: ${CXXFLAGS} + CXXCPP: ${CXXCPP} + Library types: Shared=${enable_shared}, Static=${enable_static} + Python: ${PYTHON} + PYTHON_VERSION: ${PYTHON_VERSION} + pyexecdir: ${pyexecdir} + Python-dev: ${have_python_dev} + PYTHON_CPPFLAGS:${PYTHON_CPPFLAGS} + PYTHON_LDFLAGS: ${PYTHON_LDFLAGS} + Cython: ${CYTHON} + CUnit: ${have_cunit} + OpenSSL: ${have_openssl} + Libxml2: ${have_libxml2} + Libevent(SSL): ${have_libevent_openssl} + Spdylay: ${have_spdylay} + Jansson: ${have_jansson} + Jemalloc: ${have_jemalloc} + Boost CPPFLAGS: ${BOOST_CPPFLAGS} + Boost LDFLAGS: ${BOOST_LDFLAGS} + Boost::ASIO: ${BOOST_ASIO_LIB} + Boost::System: ${BOOST_SYSTEM_LIB} + Boost::Thread: ${BOOST_THREAD_LIB} + Applications: ${enable_app} + HPACK tools: ${enable_hpack_tools} + Libnghttp2_asio:${enable_asio_lib} + Examples: ${enable_examples} + Python bindings:${enable_python_bindings} + Failmalloc: ${request_failmalloc} ]) diff -Nru nghttp2-1.13.0/contrib/CMakeLists.txt nghttp2-0.6.7/contrib/CMakeLists.txt --- nghttp2-1.13.0/contrib/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/contrib/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -set(CONFIGFILES - nghttpx-init - nghttpx.service - nghttpx-upstart.conf -) - -# Note that the execute permissions of nghttpx-init is preserved -foreach(name IN LISTS CONFIGFILES) - configure_file("${name}.in" "${name}" @ONLY) -endforeach() - -# set(EXTRA_DIST ${CONFIGFILES} nghttpx-logrotate tlsticketupdate.go) diff -Nru nghttp2-1.13.0/contrib/Makefile.am nghttp2-0.6.7/contrib/Makefile.am --- nghttp2-1.13.0/contrib/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/contrib/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -21,31 +21,19 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -configfiles = nghttpx-init nghttpx.service nghttpx-upstart.conf - -EXTRA_DIST = \ - CMakeLists.txt \ - $(configfiles:%=%.in) \ - nghttpx-logrotate \ - tlsticketupdate.go +EXTRA_DIST = nghttpx-init.in nghttpx-logrotate edit = sed -e 's|@bindir[@]|$(bindir)|g' -nghttpx-init: $(srcdir)/nghttpx-init.in +nghttpx-init: Makefile rm -f $@ $@.tmp - $(edit) $< > $@.tmp + $(edit) $(srcdir)/$@.in > $@.tmp chmod +x $@.tmp mv $@.tmp $@ -nghttpx.service: $(srcdir)/nghttpx.service.in - $(edit) $< > $@ - -nghttpx-upstart.conf: $(srcdir)/nghttpx-upstart.conf.in - $(edit) $< > $@ - -$(configfiles): Makefile +nghttpx-init: $(srcdir)/nghttpx-init.in -all-local: $(configfiles) +all-local: nghttpx-init clean-local: - -rm -f nghttpx-init.tmp $(configfiles) + -rm -f nghttpx-init nghttpx-init.tmp diff -Nru nghttp2-1.13.0/contrib/Makefile.in nghttp2-0.6.7/contrib/Makefile.in --- nghttp2-1.13.0/contrib/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/contrib/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -37,17 +37,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -112,6 +102,7 @@ host_triplet = @host@ target_triplet = @target@ subdir = contrib +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -121,13 +112,11 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -152,12 +141,10 @@ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -176,7 +163,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -192,7 +178,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -208,10 +193,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -223,7 +204,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -261,11 +241,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -320,7 +299,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -333,13 +311,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -configfiles = nghttpx-init nghttpx.service nghttpx-upstart.conf -EXTRA_DIST = \ - CMakeLists.txt \ - $(configfiles:%=%.in) \ - nghttpx-logrotate \ - tlsticketupdate.go - +EXTRA_DIST = nghttpx-init.in nghttpx-logrotate edit = sed -e 's|@bindir[@]|$(bindir)|g' all: all-am @@ -356,6 +328,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu contrib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -531,27 +504,19 @@ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am -.PRECIOUS: Makefile - -nghttpx-init: $(srcdir)/nghttpx-init.in +nghttpx-init: Makefile rm -f $@ $@.tmp - $(edit) $< > $@.tmp + $(edit) $(srcdir)/$@.in > $@.tmp chmod +x $@.tmp mv $@.tmp $@ -nghttpx.service: $(srcdir)/nghttpx.service.in - $(edit) $< > $@ - -nghttpx-upstart.conf: $(srcdir)/nghttpx-upstart.conf.in - $(edit) $< > $@ - -$(configfiles): Makefile +nghttpx-init: $(srcdir)/nghttpx-init.in -all-local: $(configfiles) +all-local: nghttpx-init clean-local: - -rm -f nghttpx-init.tmp $(configfiles) + -rm -f nghttpx-init nghttpx-init.tmp # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru nghttp2-1.13.0/contrib/nghttpx-init.in nghttp2-0.6.7/contrib/nghttpx-init.in --- nghttp2-1.13.0/contrib/nghttpx-init.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/contrib/nghttpx-init.in 2014-11-30 14:15:07.000000000 +0000 @@ -20,7 +20,7 @@ # Depending on the configuration, binary may be located under @sbindir@ DAEMON=@bindir@/$NAME PIDFILE=/var/run/$NAME.pid -DAEMON_ARGS="--conf /etc/nghttpx/nghttpx.conf --pid-file=$PIDFILE --daemon" +DAEMON_ARGS="--conf /etc/nghttpx/nghttpx.conf --pid-file=$PIDFILE" SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed @@ -83,6 +83,19 @@ return "$RETVAL" } +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} + case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" @@ -101,38 +114,34 @@ esac ;; status) - status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? - ;; + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; upgrade) - log_daemon_msg "Upgrading $DESC" "$NAME" - oldpid=`pidofproc -p $PIDFILE $NAME` - case "$?" in - 0) - log_progress_msg "Sending SIGUSR2 to $oldpid..." - kill -USR2 $oldpid - log_progress_msg "Waiting for new binary..." - for i in 1 2 3 4 5 ; do - sleep 1 - newpid=`pidofproc -p $PIDFILE $NAME` - if [ "$newpid" != "$oldpid" ] ; then - break - fi - done - if [ "$newpid" != "$oldpid" ] ; then - log_progress_msg "Sending SIGQUIT to $oldpid..." - kill -QUIT $oldpid - log_end_msg 0 - else - log_progress_msg "New binary failed to start" - log_end_msg 1 - fi - ;; - *) - log_progress_msg "pidofproc() failed" - log_end_msg 1 - ;; - esac - ;; + log_daemon_msg "Upgrade $DESC" "$NAME" + pid=`pidofproc -p $PIDFILE $NAME` + case "$?" in + 0) echo "Sending USR2 signal to $pid" + kill -USR2 $pid + echo "Waiting for new binary..." + sleep 5 + echo "Sending QUIT signal to $pid" + kill -QUIT $pid + log_end_msg 0 + ;; + *) echo "pidofproc() failed" + log_end_msg 1 + ;; + esac + ;; + #reload|force-reload) + # + # If do_reload() is not implemented then leave this commented out + # and leave 'force-reload' as an alias for 'restart'. + # + #log_daemon_msg "Reloading $DESC" "$NAME" + #do_reload + #log_end_msg $? + #;; restart|force-reload) # # If the "reload" option is implemented then remove the diff -Nru nghttp2-1.13.0/contrib/nghttpx-logrotate nghttp2-0.6.7/contrib/nghttpx-logrotate --- nghttp2-1.13.0/contrib/nghttpx-logrotate 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/contrib/nghttpx-logrotate 2014-11-30 14:15:07.000000000 +0000 @@ -1,11 +1,18 @@ /var/log/nghttpx/*.log { - weekly - rotate 52 - missingok - compress - delaycompress - notifempty - postrotate - [ -s /var/run/nghttpx.pid ] && kill -USR1 `cat /var/run/nghttpx.pid` 2> /dev/null || true - endscript + 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 } diff -Nru nghttp2-1.13.0/contrib/nghttpx.service.in nghttp2-0.6.7/contrib/nghttpx.service.in --- nghttp2-1.13.0/contrib/nghttpx.service.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/contrib/nghttpx.service.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -[Unit] -Description=HTTP/2 proxy -After=network.target - -[Service] -Type=forking -ExecStart=@bindir@/nghttpx --conf=/etc/nghttpx/nghttpx.conf --pid-file=/run/nghttpx.pid --daemon - -[Install] -WantedBy=multi-user.target diff -Nru nghttp2-1.13.0/contrib/nghttpx-upstart.conf.in nghttp2-0.6.7/contrib/nghttpx-upstart.conf.in --- nghttp2-1.13.0/contrib/nghttpx-upstart.conf.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/contrib/nghttpx-upstart.conf.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -# vim: ft=upstart: - -description "HTTP/2 reverse proxy" - -start on runlevel [2] -stop on runlevel [016] - -exec @bindir@/nghttpx diff -Nru nghttp2-1.13.0/contrib/tlsticketupdate.go nghttp2-0.6.7/contrib/tlsticketupdate.go --- nghttp2-1.13.0/contrib/tlsticketupdate.go 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/contrib/tlsticketupdate.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ -// -// nghttp2 - HTTP/2 C Library -// -// Copyright (c) 2015 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. -// -package main - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "flag" - "fmt" - "github.com/bradfitz/gomemcache/memcache" - "log" - "time" -) - -func makeKey(len int) []byte { - b := make([]byte, len) - if _, err := rand.Read(b); err != nil { - log.Fatalf("rand.Read: %v", err) - } - return b -} - -func main() { - var host = flag.String("host", "127.0.0.1", "memcached host") - var port = flag.Int("port", 11211, "memcached port") - var cipher = flag.String("cipher", "aes-128-cbc", "cipher for TLS ticket encryption") - var interval = flag.Int("interval", 3600, "interval to update TLS ticket keys") - - flag.Parse() - - var keylen int - switch *cipher { - case "aes-128-cbc": - keylen = 48 - case "aes-256-cbc": - keylen = 80 - default: - log.Fatalf("cipher: unknown cipher %v", cipher) - } - - mc := memcache.New(fmt.Sprintf("%v:%v", *host, *port)) - - keys := [][]byte{ - makeKey(keylen), // current encryption key - makeKey(keylen), // next encryption key; now decryption only - } - - for { - buf := new(bytes.Buffer) - if err := binary.Write(buf, binary.BigEndian, uint32(1)); err != nil { - log.Fatalf("failed to write version: %v", err) - } - - for _, key := range keys { - if err := binary.Write(buf, binary.BigEndian, uint16(keylen)); err != nil { - log.Fatalf("failed to write length: %v", err) - } - if _, err := buf.Write(key); err != nil { - log.Fatalf("buf.Write: %v", err) - } - } - - mc.Set(&memcache.Item{ - Key: "nghttpx:tls-ticket-key", - Value: buf.Bytes(), - Expiration: int32((*interval) + 300), - }) - - select { - case <-time.After(time.Duration(*interval) * time.Second): - } - - // rotate keys. the last key is now encryption key. - // generate new key and append it to the last, so that - // we can at least decrypt TLS ticket encrypted by new - // key on the host which does not get new key yet. - // keep at most past 11 keys as decryption only key - n := len(keys) + 1 - if n > 13 { - n = 13 - } - newKeys := make([][]byte, n) - newKeys[0] = keys[len(keys)-1] - copy(newKeys[1:], keys[0:n-2]) - newKeys[n-1] = makeKey(keylen) - - keys = newKeys - } - -} diff -Nru nghttp2-1.13.0/COPYING nghttp2-0.6.7/COPYING --- nghttp2-1.13.0/COPYING 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/COPYING 2014-11-30 14:15:07.000000000 +0000 @@ -1,7 +1,6 @@ The MIT License -Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa -Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors +Copyright (c) 2012, 2014 Tatsuhiro Tsujikawa Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -21,3 +20,22 @@ 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! diff -Nru nghttp2-1.13.0/debian/changelog nghttp2-0.6.7/debian/changelog --- nghttp2-1.13.0/debian/changelog 2016-07-24 07:12:51.000000000 +0000 +++ nghttp2-0.6.7/debian/changelog 2016-08-28 21:38:00.000000000 +0000 @@ -1,168 +1,8 @@ -nghttp2 (1.13.0-1) unstable; urgency=medium +nghttp2 (0.6.7-1~ubuntu14.04.1~wiresharkdevstable1) trusty; urgency=medium - * Imported upstream version 1.13.0 - * Drop merged upstream patches - * Update URLs + * Rebuild for Trusty - -- Tomasz Buchert Sun, 24 Jul 2016 09:06:27 +0200 - -nghttp2 (1.12.0-2) unstable; urgency=medium - - * d/patches: fix FTBFS on armel - - -- Tomasz Buchert Sun, 03 Jul 2016 23:18:42 +0200 - -nghttp2 (1.12.0-1) unstable; urgency=medium - - * Imported upstream version 1.12.0 - - -- Tomasz Buchert Sat, 02 Jul 2016 10:59:57 +0200 - -nghttp2 (1.11.1-1) unstable; urgency=medium - - * Imported upstream version 1.11.1 - - -- Tomasz Buchert Tue, 31 May 2016 23:28:27 +0200 - -nghttp2 (1.11.0-1) unstable; urgency=medium - - * Imported upstream version 1.11.0 - * d/control: bump std-ver to 3.9.8 (no changes needed) - * d/symbols: update symbol list - - -- Tomasz Buchert Sun, 29 May 2016 14:49:29 +0200 - -nghttp2 (1.10.0-1) unstable; urgency=medium - - * Imported upstream version 1.10.0 - * Fix broken default config for nghttp2-proxy - * d/symbols: update the list of symbols - - -- Tomasz Buchert Tue, 26 Apr 2016 23:29:25 +0200 - -nghttp2 (1.9.2-1) unstable; urgency=medium - - * Imported upstream version 1.9.2 - - -- Tomasz Buchert Tue, 05 Apr 2016 07:33:05 +0200 - -nghttp2 (1.9.1-1) unstable; urgency=medium - - * Imported upstream version 1.9.1 - - -- Tomasz Buchert Mon, 28 Mar 2016 11:17:23 +0200 - -nghttp2 (1.8.0-1) unstable; urgency=medium - - * Imported upstream version 1.8.0 (Closes: #811995) - * d/symbols: update symbol list - * d/control: bump std-ver to 3.9.7 (no changes needed) - - -- Tomasz Buchert Mon, 29 Feb 2016 13:28:57 +0100 - -nghttp2 (1.7.1-2) unstable; urgency=medium - - * Add missing script for OCSP stapling (Closes: #815226) - - -- Tomasz Buchert Sun, 21 Feb 2016 21:22:54 +0100 - -nghttp2 (1.7.1-1) unstable; urgency=high - - * Imported upstream version 1.7.1 (fixes CVE-2016-1544) - - -- Tomasz Buchert Sat, 13 Feb 2016 10:17:19 +0100 - -nghttp2 (1.7.0-1) unstable; urgency=medium - - * Imported upstream version 1.7.0 - - -- Tomasz Buchert Wed, 27 Jan 2016 18:10:34 +0100 - -nghttp2 (1.6.0-1) unstable; urgency=medium - - * Imported upstream version 1.6.0 - - -- Tomasz Buchert Sat, 26 Dec 2015 11:15:01 +0100 - -nghttp2 (1.5.0-2) unstable; urgency=medium - - * Update Build-Depends for cross compilation (Closes: #807849) - Patch provided by Helmut Grohne (with some minor changes) - * Split build into -arch and -indep packages - * Fix two Lintian warnings - - -- Tomasz Buchert Tue, 15 Dec 2015 11:39:36 +0100 - -nghttp2 (1.5.0-1) unstable; urgency=medium - - * Imported upstream version 1.5.0 - - -- Tomasz Buchert Sat, 05 Dec 2015 09:00:48 +0100 - -nghttp2 (1.4.0-2) unstable; urgency=medium - - * Fix systemd service - - -- Tomasz Buchert Sat, 07 Nov 2015 14:17:48 +0100 - -nghttp2 (1.4.0-1) unstable; urgency=medium - - * Imported Upstream version 1.4.0 - - -- Tomasz Buchert Sat, 31 Oct 2015 18:41:18 +0100 - -nghttp2 (1.3.4-2) unstable; urgency=medium - - * Split into subpackages: nghttp2-{client,proxy,server} (Closes: #802206) - - -- Tomasz Buchert Fri, 23 Oct 2015 17:39:22 +0200 - -nghttp2 (1.3.4-1) unstable; urgency=medium - - * Imported Upstream version 1.3.4 (Closes: #801957) - * Adding myself as Uploader - - -- Tomasz Buchert Thu, 01 Oct 2015 10:47:15 +0200 - -nghttp2 (1.3.2-0.1) unstable; urgency=medium - - * Non-maintainer upload. - * Imported Upstream version 1.3.2 - * d/patches: drop patches - - -- Tomasz Buchert Sat, 19 Sep 2015 21:39:17 +0200 - -nghttp2 (1.3.1-0.4) unstable; urgency=medium - - * Non-maintainer upload. - * Fix build problem on armel - - -- Tomasz Buchert Sun, 13 Sep 2015 09:37:02 +0200 - -nghttp2 (1.3.1-0.3) unstable; urgency=medium - - * Non-maintainer upload. - * Imported Upstream version 1.3.1 (Closes: #798598) - * d/copyright: add license for mruby - * d/conf: send errorlog to syslog - - -- Tomasz Buchert Sat, 12 Sep 2015 22:34:22 +0200 - -nghttp2 (1.3.0-0.2) unstable; urgency=medium - - * Non-maintainer upload. - * Upload to unstable (Closes: #784666, #793571) - * d/*: dropping dbg package (ddebs are coming) - - -- Tomasz Buchert Tue, 08 Sep 2015 12:38:55 +0200 - -nghttp2 (1.3.0-0.1) experimental; urgency=medium - - * Non-maintainer upload - * Imported Upstream version 1.3.0 - * Switch to dh - - -- Tomasz Buchert Wed, 02 Sep 2015 18:22:19 +0200 + -- Balint Reczey Sun, 28 Aug 2016 23:29:58 +0200 nghttp2 (0.6.7-1) unstable; urgency=medium diff -Nru nghttp2-1.13.0/debian/control nghttp2-0.6.7/debian/control --- nghttp2-1.13.0/debian/control 2016-07-24 07:12:05.000000000 +0000 +++ nghttp2-0.6.7/debian/control 2014-10-30 18:44:02.000000000 +0000 @@ -1,118 +1,66 @@ Source: nghttp2 Maintainer: Dave Beckett -Uploaders: Tomasz Buchert Section: httpd Priority: optional -Build-Depends: debhelper (>= 9.20141010), - dh-autoreconf, - dh-systemd (>= 1.5), - dpkg-dev (>= 1.17.14), - libcunit1-dev (>= 2.1) , - libev-dev (>= 1:4.15), - libevent-dev (>= 2.0.8), - libjansson-dev (>= 2.5), - libjemalloc-dev [!hurd-i386], - libspdylay-dev (>= 1.3.2), - libssl-dev (>= 1.0.1), - libxml2-dev (>= 2.7.7), - pkg-config, - zlib1g-dev (>= 1.2.3) -Build-Depends-Indep: python-sphinx -Standards-Version: 3.9.8 -Homepage: https://nghttp2.org/ -Vcs-Git: git://anonscm.debian.org/collab-maint/nghttp2.git -Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/nghttp2.git +Build-Depends: debhelper (>= 9), cdbs (>= 0.4.93~), quilt, + autotools-dev, libtool, pkg-config, + zlib1g-dev (>= 1.2.3), libssl-dev (>= 1.0.1), libxml2-dev (>= 2.7.7), + libevent-dev (>= 2.0.8), libpython-dev, + libjemalloc-dev [!hurd-i386], + python-sphinx +Standards-Version: 3.9.6 +Homepage: http://tatsuhiro-t.github.io/nghttp2/ Package: libnghttp2-dev Suggests: libnghttp2-doc Section: libdevel Architecture: any -Conflicts: libnghttp2-3-dev, libnghttp2-4-dev, libnghttp2-5-dev -Replaces: libnghttp2-3-dev, libnghttp2-4-dev, libnghttp2-5-dev -Depends: libnghttp2-14 (= ${binary:Version}), pkg-config, ${misc:Depends} -Description: library implementing HTTP/2 protocol (development files) - This is an implementation of the Hypertext Transfer Protocol version - 2 in C. The framing layer of HTTP/2 is implemented as a reusable C - library. - . - This package installs development files. +Conflicts: libnghttp2-3-dev, libnghttp2-4-dev +Replaces: libnghttp2-3-dev, libnghttp2-4-dev +Depends: ${misc:Depends}, libnghttp2-5 (= ${binary:Version}), pkg-config +Recommends: nghttp2d +Description: nghttp2 HTTP 2.0 development libraries and headers + Provides development library and headers for an experimental + implementation of Hypertext Transfer Protocol version 2.0 Package: libnghttp2-doc Section: doc Architecture: all -Depends: libjs-jquery, libjs-underscore, lynx | www-browser, ${misc:Depends} -Description: library implementing HTTP/2 protocol (documentation) - This is an implementation of the Hypertext Transfer Protocol version - 2 in C. The framing layer of HTTP/2 is implemented as a reusable C - library. - . - This package installs documentation. +Depends: ${misc:Depends}, lynx | www-browser, libjs-underscore, libjs-jquery +Description: Documentation for the nghttp2 HTTP 2.0 library + HTML documentation for the experimental nghttp2 library. -Package: libnghttp2-14 +Package: libnghttp2-5 Section: libs Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} Depends: ${misc:Depends}, ${shlibs:Depends} -Description: library implementing HTTP/2 protocol (shared library) - This is an implementation of the Hypertext Transfer Protocol version - 2 in C. The framing layer of HTTP/2 is implemented as a reusable C - library. - . - This package installs a shared library. - -Package: nghttp2-client +Description: nghttp HTTP 2.0 library + Provides a library that provides an experimental implementation of + Hypertext Transfer Protocol version 2.0. + +Package: libnghttp2-5-dbg +Priority: extra +Section: debug Architecture: any -Multi-Arch: foreign -Depends: libnghttp2-14 (= ${binary:Version}), - lsb-base (>= 3.2-14), - ${misc:Depends}, - ${shlibs:Depends} -Replaces: nghttp2 (<< 1.3.4-2~) -Breaks: nghttp2 (<< 1.3.4-2~) -Description: client implementing HTTP/2 protocol - This is a command line client implementing the HTTP/2 protocol. It - gives access to many low-level and advanced aspects of the protocol - and therefore is useful for debugging. +Multi-Arch: same +Depends: ${misc:Depends}, libnghttp2-5 (= ${binary:Version}) +Description: nghttp HTTP 2.0 library - debugging symbols + Provides a library that provides an experimental implementation of + Hypertext Transfer Protocol version 2.0. + . + This package contains the debugging symbols for debugging + applications which use libraptor2. -Package: nghttp2-proxy +Package: nghttp2 Architecture: any Multi-Arch: foreign -Depends: libnghttp2-14 (= ${binary:Version}), - lsb-base (>= 3.2-14), - ${misc:Depends}, - ${shlibs:Depends}, - openssl, - python -Replaces: nghttp2 (<< 1.3.4-2~) -Breaks: nghttp2 (<< 1.3.4-2~) -Description: reverse proxy implementing HTTP/2 protocol - This is a standalone server implementing the HTTP/2 protocol with - HTTP/1.1 fallback for clients that do not support it. It can be used - as a frontend in front of web servers that do not support HTTP/2. +Depends: ${misc:Depends}, libnghttp2-5 (= ${binary:Version}), ${shlibs:Depends}, + lsb-base (>= 3.2-14) +Description: nghttp HTTP 2.0 servers + Provides experimental implementation of Hypertext Transfer Protocol + version 2.0 including a server (nghttpd), client (nghttp) and + reverse proxy (nghttpx) for fronting other HTTP servers. -Package: nghttp2-server -Architecture: any -Multi-Arch: foreign -Depends: libnghttp2-14 (= ${binary:Version}), - lsb-base (>= 3.2-14), - ${misc:Depends}, - ${shlibs:Depends} -Replaces: nghttp2 (<< 1.3.4-2~) -Breaks: nghttp2 (<< 1.3.4-2~) -Description: server implementing HTTP/2 protocol - This is a standalone server implementing the HTTP/2 protocol with - HTTP/1.1 fallback for clients that do not support it. It can be used - to serve files from a local directory. -Package: nghttp2 -Architecture: all -Depends: nghttp2-client (>= ${binary:Version}), - nghttp2-proxy (>= ${binary:Version}), - nghttp2-server (>= ${binary:Version}), - ${misc:Depends} -Description: server, proxy and client implementing HTTP/2 - This package will install a set of programs implementing the HTTP/2 - protocol: a standalone server (nghttp2-server), a reverse proxy - (nghttp2-proxy) and a client (nghttp2-client). It provides no files - on its own and is not necessary for these programs to work. diff -Nru nghttp2-1.13.0/debian/copyright nghttp2-0.6.7/debian/copyright --- nghttp2-1.13.0/debian/copyright 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/copyright 2014-09-10 20:29:30.000000000 +0000 @@ -6,60 +6,10 @@ Files: * Copyright: 2012, 2013, 2014 Tatsuhiro Tsujikawa License: Expat - -Files: third-party/http-parser/http_parser.h -Copyright: Joyent, Inc. and other Node contributors. All rights reserved. -License: Expat - -Files: third-party/http-parser/http_parser.c -Copyright: 2002-2013 Igor Sysoev - 2011-2013 Nginx, Inc. -License: MIT -Comment: Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev. - Additional changes are licensed under the same terms as NGINX and - copyright Joyent, Inc. and other Node contributors. All rights reserved. - -Files: third-party/mruby/* -Copyright: 2015 mruby developers -License: MIT -Comment: This code is not used by the Debian package, but is kept nevertheless. - -Files: tests/nghttp2_npn_test.* -Copyright: 2012, Twist Inc. -License: Expat - -Files: m4/ax_cxx_compile_stdcxx_11.m4 -Copyright: 2008, Benjamin Kosnik , - 2012, Zack Weinberg , - 2013, Roy Stogner -License: all-permissive - -Files: m4/ax_python_devel.m4 -Copyright: 2009 Sebastian Huber , - 2009 Alan W. Irwin, - 2009 Rafael Laboissiere , - 2009 Andrew Collier, - 2009 Matteo Settenvini , - 2009 Horst Knorr , - 2013 Daniel Mullner -License: GPL-3+ with autoconf exception - -Files: doc/_themes/sphinx_rtd_theme/* -Copyright: 2013 Dave Snider -License: MIT - -Files: doc/_themes/sphinx_rtd_theme/layout_old.html doc/_themes/sphinx_rtd_theme/search.html -Copyright: 2007-2013 by the Sphinx team -License: BSD-2-clause -Comment: License details from https://bitbucket.org/birkenfeld/sphinx/src file LICENSE - -Files: doc/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf -Copyright: Dave Gandy -License: SIL-OFL-1.1 -Comment: Font Awesome by Dave Gandy - http://fontawesome.io - - -License: Expat + The MIT License + . + 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 @@ -79,7 +29,9 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -License: MIT +Files: third-party/http-parser/http_parser.h +Copyright: Joyent, Inc. and other Node contributors. All rights reserved. +License: Expat 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 @@ -98,6 +50,73 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Files: third-party/http-parser/http_parser.c +Copyright: 2002-2013 Igor Sysoev + 2011-2013 Nginx, Inc. +License: + Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev + . + Additional changes are licensed under the same terms as NGINX and + copyright Joyent, Inc. and other Node contributors. All rights reserved. + . + 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. + +Files: tests/nghttp2_npn_test.* +Copyright: 2012, Twist Inc. +License: Expat + 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. + +Files: m4/ax_cxx_compile_stdcxx_11.m4 +Copyright: 2008, Benjamin Kosnik , + 2012, Zack Weinberg , + 2013, Roy Stogner +License: + Copying and distribution of this file, with or without modification, are + permitted in any medium without royalty provided the copyright notice + and this notice are preserved. This file is offered as-is, without any + warranty. + +Files: m4/ax_python_devel.m4 +Copyright: 2009 Sebastian Huber , + 2009 Alan W. Irwin, + 2009 Rafael Laboissiere , + 2009 Andrew Collier, + 2009 Matteo Settenvini , + 2009 Horst Knorr , + 2013 Daniel Mullner License: GPL-3+ with autoconf exception This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -129,13 +148,43 @@ License version 3 can be found in the file `/usr/share/common-licenses/GPL-3'. -License: all-permissive - Copying and distribution of this file, with or without modification, are - permitted in any medium without royalty provided the copyright notice - and this notice are preserved. This file is offered as-is, without any - warranty. +Files: doc/_themes/sphinx_rtd_theme/* +Copyright: 2013 Dave Snider +License: MIT + License details from https://github.com/snide/sphinx_rtd_theme + . + The MIT License (MIT) + . + Copyright (c) 2013 Dave Snider + . + 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. +Files: doc/_themes/sphinx_rtd_theme/layout_old.html doc/_themes/sphinx_rtd_theme/search.html +Copyright: 2007-2013 by the Sphinx team License: BSD-2-clause + License details from https://bitbucket.org/birkenfeld/sphinx/src file LICENSE + . + Copyright (c) 2007-2013 by the Sphinx team (see AUTHORS file). + All rights reserved. + . Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -159,7 +208,9 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -License: SIL-OFL-1.1 +Files: doc/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf +Copyright: Font Awesome by Dave Gandy - http://fontawesome.io +License: SIL Open Font License 1.1 . License details from http://fortawesome.github.io/Font-Awesome/ @@ -181,7 +232,7 @@ . The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The - fonts, including any derivative works, can be bundled, embedded, + fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The diff -Nru nghttp2-1.13.0/debian/libnghttp2-14.install nghttp2-0.6.7/debian/libnghttp2-14.install --- nghttp2-1.13.0/debian/libnghttp2-14.install 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/libnghttp2-14.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -debian/tmp/usr/lib/*/libnghttp2*.so.* diff -Nru nghttp2-1.13.0/debian/libnghttp2-14.symbols nghttp2-0.6.7/debian/libnghttp2-14.symbols --- nghttp2-1.13.0/debian/libnghttp2-14.symbols 2016-07-02 11:38:12.000000000 +0000 +++ nghttp2-0.6.7/debian/libnghttp2-14.symbols 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -libnghttp2.so.14 libnghttp2-14 #MINVER# - nghttp2_check_header_name@Base 1.3.0 - nghttp2_check_header_value@Base 1.3.0 - nghttp2_hd_deflate_bound@Base 1.3.0 - nghttp2_hd_deflate_change_table_size@Base 1.3.0 - nghttp2_hd_deflate_del@Base 1.3.0 - nghttp2_hd_deflate_get_dynamic_table_size@Base 1.4.0 - nghttp2_hd_deflate_get_max_dynamic_table_size@Base 1.4.0 - nghttp2_hd_deflate_get_num_table_entries@Base 1.4.0 - nghttp2_hd_deflate_get_table_entry@Base 1.4.0 - nghttp2_hd_deflate_hd@Base 1.3.0 - nghttp2_hd_deflate_new2@Base 1.3.0 - nghttp2_hd_deflate_new@Base 1.3.0 - nghttp2_hd_inflate_change_table_size@Base 1.3.0 - nghttp2_hd_inflate_del@Base 1.3.0 - nghttp2_hd_inflate_end_headers@Base 1.3.0 - nghttp2_hd_inflate_get_dynamic_table_size@Base 1.4.0 - nghttp2_hd_inflate_get_max_dynamic_table_size@Base 1.4.0 - nghttp2_hd_inflate_get_num_table_entries@Base 1.4.0 - nghttp2_hd_inflate_get_table_entry@Base 1.4.0 - nghttp2_hd_inflate_hd@Base 1.3.0 - nghttp2_hd_inflate_hd2@Base 1.11.0 - nghttp2_hd_inflate_new2@Base 1.3.0 - nghttp2_hd_inflate_new@Base 1.3.0 - nghttp2_http2_strerror@Base 1.9.1 - nghttp2_is_fatal@Base 1.3.0 - nghttp2_nv_compare_name@Base 1.3.0 - nghttp2_option_del@Base 1.3.0 - nghttp2_option_new@Base 1.3.0 - nghttp2_option_set_builtin_recv_extension_type@Base 1.10.0 - nghttp2_option_set_max_reserved_remote_streams@Base 1.3.0 - nghttp2_option_set_max_send_header_block_length@Base 1.12.0 - nghttp2_option_set_no_auto_ping_ack@Base 1.9.1 - nghttp2_option_set_no_auto_window_update@Base 1.3.0 - nghttp2_option_set_no_http_messaging@Base 1.3.0 - nghttp2_option_set_no_recv_client_magic@Base 1.3.0 - nghttp2_option_set_peer_max_concurrent_streams@Base 1.3.0 - nghttp2_option_set_user_recv_extension_type@Base 1.8.0 - nghttp2_pack_settings_payload@Base 1.3.0 - nghttp2_priority_spec_check_default@Base 1.3.0 - nghttp2_priority_spec_default_init@Base 1.3.0 - nghttp2_priority_spec_init@Base 1.3.0 - nghttp2_rcbuf_decref@Base 1.9.1 - nghttp2_rcbuf_get_buf@Base 1.9.1 - nghttp2_rcbuf_incref@Base 1.9.1 - nghttp2_select_next_protocol@Base 1.3.0 - nghttp2_session_callbacks_del@Base 1.3.0 - nghttp2_session_callbacks_new@Base 1.3.0 - nghttp2_session_callbacks_set_before_frame_send_callback@Base 1.3.0 - nghttp2_session_callbacks_set_data_source_read_length_callback@Base 1.3.0 - nghttp2_session_callbacks_set_error_callback@Base 1.9.1 - nghttp2_session_callbacks_set_on_begin_frame_callback@Base 1.3.0 - nghttp2_session_callbacks_set_on_begin_headers_callback@Base 1.3.0 - nghttp2_session_callbacks_set_on_data_chunk_recv_callback@Base 1.3.0 - nghttp2_session_callbacks_set_on_extension_chunk_recv_callback@Base 1.8.0 - nghttp2_session_callbacks_set_on_frame_not_send_callback@Base 1.3.0 - nghttp2_session_callbacks_set_on_frame_recv_callback@Base 1.3.0 - nghttp2_session_callbacks_set_on_frame_send_callback@Base 1.3.0 - nghttp2_session_callbacks_set_on_header_callback@Base 1.3.0 - nghttp2_session_callbacks_set_on_header_callback2@Base 1.9.1 - nghttp2_session_callbacks_set_on_invalid_frame_recv_callback@Base 1.3.0 - nghttp2_session_callbacks_set_on_stream_close_callback@Base 1.3.0 - nghttp2_session_callbacks_set_pack_extension_callback@Base 1.8.0 - nghttp2_session_callbacks_set_recv_callback@Base 1.3.0 - nghttp2_session_callbacks_set_select_padding_callback@Base 1.3.0 - nghttp2_session_callbacks_set_send_callback@Base 1.3.0 - nghttp2_session_callbacks_set_send_data_callback@Base 1.3.0 - nghttp2_session_callbacks_set_unpack_extension_callback@Base 1.8.0 - nghttp2_session_change_stream_priority@Base 1.5.0 - nghttp2_session_check_request_allowed@Base 1.5.0 - nghttp2_session_check_server_session@Base 1.5.0 - nghttp2_session_client_new2@Base 1.3.0 - nghttp2_session_client_new3@Base 1.3.0 - nghttp2_session_client_new@Base 1.3.0 - nghttp2_session_consume@Base 1.3.0 - nghttp2_session_consume_connection@Base 1.3.0 - nghttp2_session_consume_stream@Base 1.3.0 - nghttp2_session_create_idle_stream@Base 1.6.0 - nghttp2_session_del@Base 1.3.0 - nghttp2_session_find_stream@Base 1.3.0 - nghttp2_session_get_effective_local_window_size@Base 1.3.0 - nghttp2_session_get_effective_recv_data_length@Base 1.3.0 - nghttp2_session_get_last_proc_stream_id@Base 1.3.0 - nghttp2_session_get_next_stream_id@Base 1.3.0 - nghttp2_session_get_outbound_queue_size@Base 1.3.0 - nghttp2_session_get_remote_settings@Base 1.3.0 - nghttp2_session_get_remote_window_size@Base 1.3.0 - nghttp2_session_get_root_stream@Base 1.3.0 - nghttp2_session_get_stream_effective_local_window_size@Base 1.3.0 - nghttp2_session_get_stream_effective_recv_data_length@Base 1.3.0 - nghttp2_session_get_stream_local_close@Base 1.3.0 - nghttp2_session_get_stream_remote_close@Base 1.3.0 - nghttp2_session_get_stream_remote_window_size@Base 1.3.0 - nghttp2_session_get_stream_user_data@Base 1.3.0 - nghttp2_session_mem_recv@Base 1.3.0 - nghttp2_session_mem_send@Base 1.3.0 - nghttp2_session_recv@Base 1.3.0 - nghttp2_session_resume_data@Base 1.3.0 - nghttp2_session_send@Base 1.3.0 - nghttp2_session_server_new2@Base 1.3.0 - nghttp2_session_server_new3@Base 1.3.0 - nghttp2_session_server_new@Base 1.3.0 - nghttp2_session_set_local_window_size@Base 1.12.0 - nghttp2_session_set_next_stream_id@Base 1.3.0 - nghttp2_session_set_stream_user_data@Base 1.3.0 - nghttp2_session_terminate_session2@Base 1.3.0 - nghttp2_session_terminate_session@Base 1.3.0 - nghttp2_session_upgrade2@Base 1.5.0 - nghttp2_session_upgrade@Base 1.3.0 - nghttp2_session_want_read@Base 1.3.0 - nghttp2_session_want_write@Base 1.3.0 - nghttp2_stream_get_first_child@Base 1.3.0 - nghttp2_stream_get_next_sibling@Base 1.3.0 - nghttp2_stream_get_parent@Base 1.3.0 - nghttp2_stream_get_previous_sibling@Base 1.3.0 - nghttp2_stream_get_state@Base 1.3.0 - nghttp2_stream_get_stream_id@Base 1.3.0 - nghttp2_stream_get_sum_dependency_weight@Base 1.3.0 - nghttp2_stream_get_weight@Base 1.3.0 - nghttp2_strerror@Base 1.3.0 - nghttp2_submit_altsvc@Base 1.10.0 - nghttp2_submit_data@Base 1.3.0 - nghttp2_submit_extension@Base 1.8.0 - nghttp2_submit_goaway@Base 1.3.0 - nghttp2_submit_headers@Base 1.3.0 - nghttp2_submit_ping@Base 1.3.0 - nghttp2_submit_priority@Base 1.3.0 - nghttp2_submit_push_promise@Base 1.3.0 - nghttp2_submit_request@Base 1.3.0 - nghttp2_submit_response@Base 1.3.0 - nghttp2_submit_rst_stream@Base 1.3.0 - nghttp2_submit_settings@Base 1.3.0 - nghttp2_submit_shutdown_notice@Base 1.3.0 - nghttp2_submit_trailer@Base 1.3.0 - nghttp2_submit_window_update@Base 1.3.0 - nghttp2_version@Base 1.3.0 diff -Nru nghttp2-1.13.0/debian/libnghttp2-5.install nghttp2-0.6.7/debian/libnghttp2-5.install --- nghttp2-1.13.0/debian/libnghttp2-5.install 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/debian/libnghttp2-5.install 2014-10-30 18:27:51.000000000 +0000 @@ -0,0 +1 @@ +debian/tmp/usr/lib/*/libnghttp2*.so.* diff -Nru nghttp2-1.13.0/debian/libnghttp2-5.shlibs nghttp2-0.6.7/debian/libnghttp2-5.shlibs --- nghttp2-1.13.0/debian/libnghttp2-5.shlibs 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/debian/libnghttp2-5.shlibs 2014-11-30 21:51:00.000000000 +0000 @@ -0,0 +1 @@ +libnghttp2 5 libnghttp2-5 (>= 0.6.7) diff -Nru nghttp2-1.13.0/debian/libnghttp2-5.symbols nghttp2-0.6.7/debian/libnghttp2-5.symbols --- nghttp2-1.13.0/debian/libnghttp2-5.symbols 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/debian/libnghttp2-5.symbols 2014-11-30 21:53:02.000000000 +0000 @@ -0,0 +1,293 @@ +libnghttp2.so.5 libnghttp2-5 #MINVER# + NGHTTP2_STATIC_TABLE_LENGTH@libnghttp2.so.5 0.6.0 + huff_decode_table@libnghttp2.so.5 0.6.0 + huff_sym_table@libnghttp2.so.5 0.6.0 + libnghttp2.so.5@libnghttp2.so.5 0.6.0 + nghttp2_adjust_local_window_size@libnghttp2.so.5 0.6.0 + nghttp2_buf_free@libnghttp2.so.5 0.6.0 + nghttp2_buf_init2@libnghttp2.so.5 0.6.0 + nghttp2_buf_init@libnghttp2.so.5 0.6.0 + nghttp2_buf_reserve@libnghttp2.so.5 0.6.0 + nghttp2_buf_reset@libnghttp2.so.5 0.6.0 + nghttp2_buf_wrap_init@libnghttp2.so.5 0.6.0 + nghttp2_bufs_add@libnghttp2.so.5 0.6.0 + nghttp2_bufs_addb@libnghttp2.so.5 0.6.0 + nghttp2_bufs_addb_hold@libnghttp2.so.5 0.6.0 + nghttp2_bufs_advance@libnghttp2.so.5 0.6.0 + nghttp2_bufs_free@libnghttp2.so.5 0.6.0 + nghttp2_bufs_init2@libnghttp2.so.5 0.6.0 + nghttp2_bufs_init3@libnghttp2.so.5 0.6.0 + nghttp2_bufs_init@libnghttp2.so.5 0.6.0 + nghttp2_bufs_len@libnghttp2.so.5 0.6.0 + nghttp2_bufs_next_present@libnghttp2.so.5 0.6.0 + nghttp2_bufs_orb@libnghttp2.so.5 0.6.0 + nghttp2_bufs_orb_hold@libnghttp2.so.5 0.6.0 + nghttp2_bufs_realloc@libnghttp2.so.5 0.6.0 + nghttp2_bufs_remove@libnghttp2.so.5 0.6.0 + nghttp2_bufs_reset@libnghttp2.so.5 0.6.0 + nghttp2_bufs_seek_last_present@libnghttp2.so.5 0.6.0 + nghttp2_bufs_wrap_free@libnghttp2.so.5 0.6.0 + nghttp2_bufs_wrap_init@libnghttp2.so.5 0.6.0 + nghttp2_check_header_name@libnghttp2.so.5 0.6.0 + nghttp2_check_header_value@libnghttp2.so.5 0.6.0 + nghttp2_cpymem@libnghttp2.so.5 0.6.0 + nghttp2_downcase@libnghttp2.so.5 0.6.0 + nghttp2_enable_strict_first_settings_check@libnghttp2.so.5 0.6.3 + nghttp2_frame_add_pad@libnghttp2.so.5 0.6.0 + nghttp2_frame_altsvc_free@libnghttp2.so.5 0.6.0 + nghttp2_frame_altsvc_init@libnghttp2.so.5 0.6.0 + nghttp2_frame_data_free@libnghttp2.so.5 0.6.3 + nghttp2_frame_data_init@libnghttp2.so.5 0.6.0 + nghttp2_frame_goaway_free@libnghttp2.so.5 0.6.0 + nghttp2_frame_goaway_init@libnghttp2.so.5 0.6.0 + nghttp2_frame_hd_init@libnghttp2.so.5 0.6.0 + nghttp2_frame_headers_free@libnghttp2.so.5 0.6.0 + nghttp2_frame_headers_init@libnghttp2.so.5 0.6.0 + nghttp2_frame_headers_payload_nv_offset@libnghttp2.so.5 0.6.0 + nghttp2_frame_iv_copy@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_altsvc@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_frame_hd@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_goaway@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_headers@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_ping@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_priority@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_priority_spec@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_push_promise@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_rst_stream@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_settings@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_settings_payload@libnghttp2.so.5 0.6.0 + nghttp2_frame_pack_window_update@libnghttp2.so.5 0.6.0 + nghttp2_frame_ping_free@libnghttp2.so.5 0.6.0 + nghttp2_frame_ping_init@libnghttp2.so.5 0.6.0 + nghttp2_frame_priority_free@libnghttp2.so.5 0.6.0 + nghttp2_frame_priority_init@libnghttp2.so.5 0.6.0 + nghttp2_frame_priority_len@libnghttp2.so.5 0.6.0 + nghttp2_frame_push_promise_free@libnghttp2.so.5 0.6.0 + nghttp2_frame_push_promise_init@libnghttp2.so.5 0.6.0 + nghttp2_frame_rst_stream_free@libnghttp2.so.5 0.6.0 + nghttp2_frame_rst_stream_init@libnghttp2.so.5 0.6.0 + nghttp2_frame_settings_free@libnghttp2.so.5 0.6.0 + nghttp2_frame_settings_init@libnghttp2.so.5 0.6.0 + nghttp2_frame_trail_padlen@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_altsvc_payload@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_frame_hd@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_goaway_payload2@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_goaway_payload@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_headers_payload@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_ping_payload@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_priority_payload@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_priority_spec@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_push_promise_payload@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_rst_stream_payload@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_settings_entry@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_settings_payload2@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_settings_payload@libnghttp2.so.5 0.6.0 + nghttp2_frame_unpack_window_update_payload@libnghttp2.so.5 0.6.0 + nghttp2_frame_window_update_free@libnghttp2.so.5 0.6.0 + nghttp2_frame_window_update_init@libnghttp2.so.5 0.6.0 + nghttp2_free@libnghttp2.so.5 0.6.0 + nghttp2_get_uint16@libnghttp2.so.5 0.6.0 + nghttp2_get_uint32@libnghttp2.so.5 0.6.0 + nghttp2_hd_decode_length@libnghttp2.so.5 0.5.1 + nghttp2_hd_deflate_bound@libnghttp2.so.5 0.6.0 + nghttp2_hd_deflate_change_table_size@libnghttp2.so.5 0.6.0 + nghttp2_hd_deflate_del@libnghttp2.so.5 0.6.0 + nghttp2_hd_deflate_free@libnghttp2.so.5 0.6.0 + nghttp2_hd_deflate_hd@libnghttp2.so.5 0.6.0 + nghttp2_hd_deflate_hd_bufs@libnghttp2.so.5 0.6.0 + nghttp2_hd_deflate_init2@libnghttp2.so.5 0.6.0 + nghttp2_hd_deflate_init@libnghttp2.so.5 0.6.0 + nghttp2_hd_deflate_new@libnghttp2.so.5 0.6.0 + nghttp2_hd_emit_indname_block@libnghttp2.so.5 0.6.0 + nghttp2_hd_emit_newname_block@libnghttp2.so.5 0.6.0 + nghttp2_hd_emit_table_size@libnghttp2.so.5 0.6.0 + nghttp2_hd_entry_free@libnghttp2.so.5 0.6.0 + nghttp2_hd_entry_init@libnghttp2.so.5 0.6.0 + nghttp2_hd_huff_decode@libnghttp2.so.5 0.6.0 + nghttp2_hd_huff_decode_context_init@libnghttp2.so.5 0.6.0 + nghttp2_hd_huff_encode@libnghttp2.so.5 0.6.0 + nghttp2_hd_huff_encode_count@libnghttp2.so.5 0.6.0 + nghttp2_hd_inflate_change_table_size@libnghttp2.so.5 0.6.0 + nghttp2_hd_inflate_del@libnghttp2.so.5 0.6.0 + nghttp2_hd_inflate_end_headers@libnghttp2.so.5 0.6.0 + nghttp2_hd_inflate_free@libnghttp2.so.5 0.6.0 + nghttp2_hd_inflate_hd@libnghttp2.so.5 0.6.0 + nghttp2_hd_inflate_init@libnghttp2.so.5 0.6.0 + nghttp2_hd_inflate_new@libnghttp2.so.5 0.6.0 + nghttp2_hd_table_get@libnghttp2.so.5 0.6.0 + nghttp2_is_fatal@libnghttp2.so.5 0.6.0 + nghttp2_iv_check@libnghttp2.so.5 0.6.0 + nghttp2_map_each@libnghttp2.so.5 0.6.0 + nghttp2_map_each_free@libnghttp2.so.5 0.6.0 + nghttp2_map_entry_init@libnghttp2.so.5 0.6.0 + nghttp2_map_find@libnghttp2.so.5 0.6.0 + nghttp2_map_free@libnghttp2.so.5 0.6.0 + nghttp2_map_init@libnghttp2.so.5 0.6.0 + nghttp2_map_insert@libnghttp2.so.5 0.6.0 + nghttp2_map_remove@libnghttp2.so.5 0.6.0 + nghttp2_map_size@libnghttp2.so.5 0.6.0 + nghttp2_memdup@libnghttp2.so.5 0.6.0 + nghttp2_nv_array_copy@libnghttp2.so.5 0.6.0 + nghttp2_nv_array_del@libnghttp2.so.5 0.6.0 + nghttp2_nv_array_sort@libnghttp2.so.5 0.6.0 + nghttp2_nv_compare_name@libnghttp2.so.5 0.6.0 + nghttp2_nv_equal@libnghttp2.so.5 0.6.0 + nghttp2_option_del@libnghttp2.so.5 0.6.0 + nghttp2_option_new@libnghttp2.so.5 0.6.0 + nghttp2_option_set_no_auto_window_update@libnghttp2.so.5 0.6.0 + nghttp2_option_set_peer_max_concurrent_streams@libnghttp2.so.5 0.6.0 + nghttp2_option_set_recv_client_preface@libnghttp2.so.5 0.6.2 + nghttp2_outbound_item_free@libnghttp2.so.5 0.6.0 + nghttp2_pack_settings_payload@libnghttp2.so.5 0.6.0 + nghttp2_pq_empty@libnghttp2.so.5 0.6.0 + nghttp2_pq_free@libnghttp2.so.5 0.6.0 + nghttp2_pq_init@libnghttp2.so.5 0.6.0 + nghttp2_pq_pop@libnghttp2.so.5 0.6.0 + nghttp2_pq_push@libnghttp2.so.5 0.6.0 + nghttp2_pq_size@libnghttp2.so.5 0.6.0 + nghttp2_pq_top@libnghttp2.so.5 0.6.0 + nghttp2_pq_update@libnghttp2.so.5 0.6.0 + nghttp2_priority_spec_check_default@libnghttp2.so.5 0.6.0 + nghttp2_priority_spec_default_init@libnghttp2.so.5 0.6.0 + nghttp2_priority_spec_init@libnghttp2.so.5 0.6.0 + nghttp2_put_uint16be@libnghttp2.so.5 0.6.0 + nghttp2_put_uint32be@libnghttp2.so.5 0.6.0 + nghttp2_queue_back@libnghttp2.so.5 0.6.0 + nghttp2_queue_empty@libnghttp2.so.5 0.6.0 + nghttp2_queue_free@libnghttp2.so.5 0.6.0 + nghttp2_queue_front@libnghttp2.so.5 0.6.0 + nghttp2_queue_init@libnghttp2.so.5 0.6.0 + nghttp2_queue_pop@libnghttp2.so.5 0.6.0 + nghttp2_queue_push@libnghttp2.so.5 0.6.0 + nghttp2_select_next_protocol@libnghttp2.so.5 0.6.0 + nghttp2_session_add_goaway@libnghttp2.so.5 0.6.0 + nghttp2_session_add_item@libnghttp2.so.5 0.6.3 + nghttp2_session_add_ping@libnghttp2.so.5 0.6.0 + nghttp2_session_add_rst_stream@libnghttp2.so.5 0.6.0 + nghttp2_session_add_settings@libnghttp2.so.5 0.6.0 + nghttp2_session_add_window_update@libnghttp2.so.5 0.6.0 + nghttp2_session_adjust_closed_stream@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_del@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_new@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_before_frame_send_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_data_source_read_length_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_on_begin_frame_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_on_begin_headers_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_on_data_chunk_recv_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_on_frame_not_send_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_on_frame_recv_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_on_frame_send_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_on_header_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_on_invalid_frame_recv_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_on_stream_close_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_recv_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_select_padding_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_callbacks_set_send_callback@libnghttp2.so.5 0.6.0 + nghttp2_session_can_add_closed_stream@libnghttp2.so.5 0.6.7-1 + nghttp2_session_client_new2@libnghttp2.so.5 0.6.0 + nghttp2_session_client_new@libnghttp2.so.5 0.6.0 + nghttp2_session_close_stream@libnghttp2.so.5 0.6.0 + nghttp2_session_close_stream_if_shut_rdwr@libnghttp2.so.5 0.6.0 + nghttp2_session_consume@libnghttp2.so.5 0.6.0 + nghttp2_session_del@libnghttp2.so.5 0.6.0 + nghttp2_session_destroy_stream@libnghttp2.so.5 0.6.0 +nghttp2_session_detach_closed_stream@libnghttp2.so.5 0.6.7-1 + nghttp2_session_end_headers_received@libnghttp2.so.5 0.6.0 + nghttp2_session_end_request_headers_received@libnghttp2.so.5 0.6.0 + nghttp2_session_end_response_headers_received@libnghttp2.so.5 0.6.0 + nghttp2_session_get_effective_local_window_size@libnghttp2.so.5 0.6.0 + nghttp2_session_get_effective_recv_data_length@libnghttp2.so.5 0.6.0 + nghttp2_session_get_next_ob_item@libnghttp2.so.5 0.6.0 + nghttp2_session_get_ob_pq_top@libnghttp2.so.5 0.6.0 + nghttp2_session_get_outbound_queue_size@libnghttp2.so.5 0.6.0 + nghttp2_session_get_remote_settings@libnghttp2.so.5 0.6.0 + nghttp2_session_get_remote_window_size@libnghttp2.so.5 0.6.0 + nghttp2_session_get_stream@libnghttp2.so.5 0.6.0 + nghttp2_session_get_stream_effective_local_window_size@libnghttp2.so.5 0.6.0 + nghttp2_session_get_stream_effective_recv_data_length@libnghttp2.so.5 0.6.0 + nghttp2_session_get_stream_local_close@libnghttp2.so.5 0.6.0 + nghttp2_session_get_stream_raw@libnghttp2.so.5 0.6.0 + nghttp2_session_get_stream_remote_close@libnghttp2.so.5 0.6.0 + nghttp2_session_get_stream_remote_window_size@libnghttp2.so.5 0.6.0 + nghttp2_session_get_stream_user_data@libnghttp2.so.5 0.6.0 + nghttp2_session_is_my_stream_id@libnghttp2.so.5 0.6.0 + nghttp2_session_keep_closed_stream@libnghttp2.so.5 0.6.0 + nghttp2_session_mem_recv@libnghttp2.so.5 0.6.0 + nghttp2_session_mem_send@libnghttp2.so.5 0.6.0 + nghttp2_session_on_altsvc_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_data_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_goaway_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_headers_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_ping_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_priority_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_push_promise_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_push_response_headers_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_request_headers_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_response_headers_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_rst_stream_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_settings_received@libnghttp2.so.5 0.6.0 + nghttp2_session_on_window_update_received@libnghttp2.so.5 0.6.0 + nghttp2_session_open_stream@libnghttp2.so.5 0.6.0 + nghttp2_session_outbound_item_init@libnghttp2.so.5 0.6.3 + nghttp2_session_pack_data@libnghttp2.so.5 0.6.0 + nghttp2_session_pop_next_ob_item@libnghttp2.so.5 0.6.0 + nghttp2_session_recv@libnghttp2.so.5 0.6.0 + nghttp2_session_reprioritize_stream@libnghttp2.so.5 0.6.0 + nghttp2_session_resume_data@libnghttp2.so.5 0.6.0 + nghttp2_session_send@libnghttp2.so.5 0.6.0 + nghttp2_session_server_new2@libnghttp2.so.5 0.6.0 + nghttp2_session_server_new@libnghttp2.so.5 0.6.0 + nghttp2_session_set_stream_user_data@libnghttp2.so.5 0.6.0 + nghttp2_session_terminate_session2@libnghttp2.so.5 0.6.0 + nghttp2_session_terminate_session@libnghttp2.so.5 0.6.0 + nghttp2_session_terminate_session_with_reason@libnghttp2.so.5 0.6.0 + nghttp2_session_update_local_settings@libnghttp2.so.5 0.6.0 + nghttp2_session_upgrade@libnghttp2.so.5 0.6.0 + nghttp2_session_want_read@libnghttp2.so.5 0.6.0 + nghttp2_session_want_write@libnghttp2.so.5 0.6.0 + nghttp2_should_send_window_update@libnghttp2.so.5 0.6.0 + nghttp2_stream_attach_data@libnghttp2.so.5 0.6.0 + nghttp2_stream_check_deferred_by_flow_control@libnghttp2.so.5 0.6.0 + nghttp2_stream_check_deferred_data@libnghttp2.so.5 0.6.0 + nghttp2_stream_defer_data@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_add@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_add_subtree@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_all_your_stream_are_belong_to_us@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_distributed_effective_weight@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_distributed_weight@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_insert@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_insert_subtree@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_make_root@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_remove@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_remove_subtree@libnghttp2.so.5 0.6.0 + nghttp2_stream_dep_subtree_find@libnghttp2.so.5 0.6.0 + nghttp2_stream_detach_data@libnghttp2.so.5 0.6.0 + nghttp2_stream_free@libnghttp2.so.5 0.6.0 + nghttp2_stream_get_dep_root@libnghttp2.so.5 0.6.0 + nghttp2_stream_in_dep_tree@libnghttp2.so.5 0.6.0 + nghttp2_stream_init@libnghttp2.so.5 0.6.0 + nghttp2_stream_promise_fulfilled@libnghttp2.so.5 0.6.0 + nghttp2_stream_resume_deferred_data@libnghttp2.so.5 0.6.0 + nghttp2_stream_roots_add@libnghttp2.so.5 0.6.0 + nghttp2_stream_roots_free@libnghttp2.so.5 0.6.0 + nghttp2_stream_roots_init@libnghttp2.so.5 0.6.0 + nghttp2_stream_roots_remove@libnghttp2.so.5 0.6.0 + nghttp2_stream_roots_remove_all@libnghttp2.so.5 0.6.0 + nghttp2_stream_shutdown@libnghttp2.so.5 0.6.0 + nghttp2_stream_update_local_initial_window_size@libnghttp2.so.5 0.6.0 + nghttp2_stream_update_remote_initial_window_size@libnghttp2.so.5 0.6.0 + nghttp2_strerror@libnghttp2.so.5 0.6.0 + nghttp2_submit_altsvc@libnghttp2.so.5 0.6.0 + nghttp2_submit_data@libnghttp2.so.5 0.6.0 + nghttp2_submit_goaway@libnghttp2.so.5 0.6.0 + nghttp2_submit_headers@libnghttp2.so.5 0.6.0 + nghttp2_submit_ping@libnghttp2.so.5 0.6.0 + nghttp2_submit_priority@libnghttp2.so.5 0.6.0 + nghttp2_submit_push_promise@libnghttp2.so.5 0.6.0 + nghttp2_submit_request@libnghttp2.so.5 0.6.0 + nghttp2_submit_response@libnghttp2.so.5 0.6.0 + nghttp2_submit_rst_stream@libnghttp2.so.5 0.6.0 + nghttp2_submit_settings@libnghttp2.so.5 0.6.0 + nghttp2_submit_window_update@libnghttp2.so.5 0.6.0 + nghttp2_version@libnghttp2.so.5 0.6.0 + static_table_index@libnghttp2.so.5 0.6.3 diff -Nru nghttp2-1.13.0/debian/nghttp2-client.install nghttp2-0.6.7/debian/nghttp2-client.install --- nghttp2-1.13.0/debian/nghttp2-client.install 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttp2-client.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -debian/tmp/usr/bin/nghttp usr/bin diff -Nru nghttp2-1.13.0/debian/nghttp2-client.manpages nghttp2-0.6.7/debian/nghttp2-client.manpages --- nghttp2-1.13.0/debian/nghttp2-client.manpages 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttp2-client.manpages 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -doc/nghttp.1 diff -Nru nghttp2-1.13.0/debian/nghttp2.install nghttp2-0.6.7/debian/nghttp2.install --- nghttp2-1.13.0/debian/nghttp2.install 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttp2.install 2014-10-30 16:34:57.000000000 +0000 @@ -0,0 +1,3 @@ +debian/tmp/usr/bin/*/nghttp usr/bin +debian/tmp/usr/bin/*/nghttpd usr/sbin +debian/tmp/usr/bin/*/nghttpx usr/sbin diff -Nru nghttp2-1.13.0/debian/nghttp2.manpages nghttp2-0.6.7/debian/nghttp2.manpages --- nghttp2-1.13.0/debian/nghttp2.manpages 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttp2.manpages 2014-02-17 21:10:11.000000000 +0000 @@ -0,0 +1,3 @@ +doc/nghttp.1 +doc/nghttpd.1 +doc/nghttpx.1 diff -Nru nghttp2-1.13.0/debian/nghttp2.NEWS nghttp2-0.6.7/debian/nghttp2.NEWS --- nghttp2-1.13.0/debian/nghttp2.NEWS 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttp2.NEWS 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -nghttp2 (1.3.4-2) unstable; urgency=medium - - This release introduces a split into 3 subpackages: nghttp2-client, - nghttp2-server and nghttp2-proxy. The nghttp2 package depends on all - of them, but provides no files on its own. You can customize your - nghttp2 installation by removing nghttp2-* packages that you don't - use and/or removing the generic nghttp2 package. - - -- Tomasz Buchert Fri, 23 Oct 2015 17:39:22 +0200 diff -Nru nghttp2-1.13.0/debian/nghttp2-proxy.install nghttp2-0.6.7/debian/nghttp2-proxy.install --- nghttp2-1.13.0/debian/nghttp2-proxy.install 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttp2-proxy.install 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -debian/tmp/usr/bin/nghttpx usr/sbin -debian/tmp/usr/share/nghttp2/fetch-ocsp-response usr/share/nghttp2 \ No newline at end of file diff -Nru nghttp2-1.13.0/debian/nghttp2-proxy.manpages nghttp2-0.6.7/debian/nghttp2-proxy.manpages --- nghttp2-1.13.0/debian/nghttp2-proxy.manpages 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttp2-proxy.manpages 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -doc/nghttpx.1 diff -Nru nghttp2-1.13.0/debian/nghttp2-server.install nghttp2-0.6.7/debian/nghttp2-server.install --- nghttp2-1.13.0/debian/nghttp2-server.install 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttp2-server.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -debian/tmp/usr/bin/nghttpd usr/sbin diff -Nru nghttp2-1.13.0/debian/nghttp2-server.manpages nghttp2-0.6.7/debian/nghttp2-server.manpages --- nghttp2-1.13.0/debian/nghttp2-server.manpages 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttp2-server.manpages 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -doc/nghttpd.1 diff -Nru nghttp2-1.13.0/debian/nghttpx.conf nghttp2-0.6.7/debian/nghttpx.conf --- nghttp2-1.13.0/debian/nghttpx.conf 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttpx.conf 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -# -# Sample configuration file for nghttpx. -# -# * Line staring '#' is treated as comment. -# -# * The option name in the configuration file is the long command-line -# option name with leading '--' stripped (e.g., frontend). Put '=' -# between option name and value. Don't put extra leading or trailing -# spaces. -# -# * The options which do not take argument in the command-line *take* -# argument in the configuration file. Specify 'yes' as argument -# (e.g., http2-proxy=yes). If other string is given, it disables the -# option. -# -# * To specify private key and certificate file, use private-key-file -# and certificate-file. See the examples below. -# -# * conf option cannot be used in the configuration file. It will be -# ignored. -# -# Examples: - -# Example 1 -# Proxying an HTTP server on localhost:80 to localhost:3000 (no TLS) -frontend=127.0.0.1,3000;no-tls -backend=127.0.0.1,80 -errorlog-syslog=yes -workers=1 - -# Example 2 -# Proxying localhost:80 on all interfaces, port 3000 (TLS enabled) -# frontend=0.0.0.0,3000 -# backend=127.0.0.1,80 -# private-key-file=/path/to/server.key -# certificate-file=/path/to/server.crt -# http2-proxy=no -# workers=1 - -# For comprehensive list of configuration options see "man nghttpx" diff -Nru nghttp2-1.13.0/debian/nghttpx.service nghttp2-0.6.7/debian/nghttpx.service --- nghttp2-1.13.0/debian/nghttpx.service 2016-07-02 08:58:04.000000000 +0000 +++ nghttp2-0.6.7/debian/nghttpx.service 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -[Unit] -Description=HTTP/2 proxy -After=network.target - -[Service] -Type=forking -ExecStart=/usr/sbin/nghttpx --conf=/etc/nghttpx/nghttpx.conf --pid-file=/run/nghttpx.pid --daemon - -[Install] -WantedBy=multi-user.target diff -Nru nghttp2-1.13.0/debian/patches/0001-Reformat-obfuscated-javascript-in-sphinx-theme.patch nghttp2-0.6.7/debian/patches/0001-Reformat-obfuscated-javascript-in-sphinx-theme.patch --- nghttp2-1.13.0/debian/patches/0001-Reformat-obfuscated-javascript-in-sphinx-theme.patch 2016-07-03 21:00:56.000000000 +0000 +++ nghttp2-0.6.7/debian/patches/0001-Reformat-obfuscated-javascript-in-sphinx-theme.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -From: Tomasz Buchert -Date: Mon, 26 Oct 2015 10:09:41 +0100 -Subject: Reformat obfuscated javascript in sphinx theme - -This simply reformats the javascript to look more readable. The code -still looks a bit obfuscated, but its purpose can be understood fairly -easily. ---- - doc/_themes/sphinx_rtd_theme/static/js/theme.js | 27 ++++++++++++++++++++++++- - 1 file changed, 26 insertions(+), 1 deletion(-) - -diff --git a/doc/_themes/sphinx_rtd_theme/static/js/theme.js b/doc/_themes/sphinx_rtd_theme/static/js/theme.js -index 432dc0c..8bb2e73 100644 ---- a/doc/_themes/sphinx_rtd_theme/static/js/theme.js -+++ b/doc/_themes/sphinx_rtd_theme/static/js/theme.js -@@ -1,4 +1,29 @@ --require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o debian/nghttp2/etc/init.d/nghttpx + chmod 755 debian/nghttp2/etc/init.d/nghttpx + install -d debian/nghttp2/etc/nghttpx + install -m644 nghttpx.conf.sample debian/nghttp2/etc/nghttpx/nghttpx.conf + install -d debian/nghttp2/etc/logrotate.d + install -p -m644 contrib/nghttpx-logrotate debian/nghttp2/etc/logrotate.d/nghttpx -.PHONY: custom_install_manual custom_install_init_scripts custom_install_systemd - -DOCDIR="debian/libnghttp2-doc/usr/share/doc/libnghttp2-doc" -custom_install_manual: - mkdir -p $(DOCDIR) - cp -pr doc/manual/html/* $(DOCDIR) - rm $(DOCDIR)/objects.inv - ln -sf /usr/share/javascript/jquery/jquery.js $(DOCDIR)/_static/jquery.js - ln -sf /usr/share/javascript/underscore/underscore.js $(DOCDIR)/_static/underscore.js - -ETCDIR="debian/nghttp2-proxy/etc" -custom_install_init_scripts: - install -d $(ETCDIR)/init.d - sed -e 's,^DAEMON=.*/,DAEMON=/usr/sbin/,' contrib/nghttpx-init > $(ETCDIR)/init.d/nghttpx - chmod 755 $(ETCDIR)/init.d/nghttpx - install -d $(ETCDIR)/nghttpx - # we install our own version of config - install -m644 debian/nghttpx.conf $(ETCDIR)/nghttpx/nghttpx.conf - install -d $(ETCDIR)/logrotate.d - install -p -m644 contrib/nghttpx-logrotate $(ETCDIR)/logrotate.d/nghttpx - -# Currently we install our own systemd unit because -# the original one is slightly broken -SYSTEMD="debian/nghttp2-proxy/lib/systemd/system" -custom_install_systemd: - install -d $(SYSTEMD) - install -p -m644 debian/nghttpx.service $(SYSTEMD)/nghttpx.service +install/libnghttp2-dev:: + rm -f debian/tmp/usr/lib/*/libnghttp2.la + +build/libnghttp2-doc:: + $(MAKE) html -%: - dh $@ --parallel --with=autoreconf --with=systemd +install/libnghttp2-doc:: + d=$(CURDIR)/debian/libnghttp2-doc/usr/share/doc/libnghttp2-doc; \ + mkdir -p $$d; \ + cp -pr doc/manual/html/* $$d; \ + cd $$d; \ + rm -f objects.inv; \ + cd _static; \ + ln -sf /usr/share/javascript/jquery/jquery.js; \ + ln -sf /usr/share/javascript/underscore/underscore.js diff -Nru nghttp2-1.13.0/depcomp nghttp2-0.6.7/depcomp --- nghttp2-1.13.0/depcomp 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/depcomp 2014-11-30 14:15:35.000000000 +0000 @@ -3,7 +3,7 @@ scriptversion=2013-05-30.07; # UTC -# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Copyright (C) 1999-2013 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff -Nru nghttp2-1.13.0/doc/apiref-header.rst nghttp2-0.6.7/doc/apiref-header.rst --- nghttp2-1.13.0/doc/apiref-header.rst 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/doc/apiref-header.rst 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,33 @@ +API Reference +============= + +Includes +-------- + +To use the public APIs, include ``nghttp2/nghttp2.h``:: + + #include + +The header files are also available online: :doc:`nghttp2.h` and +:doc:`nghttp2ver.h`. + +Remarks +------- + +Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send()`, +`nghttp2_session_recv()` or `nghttp2_session_mem_recv()` from the +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. diff -Nru nghttp2-1.13.0/doc/asio_http2_client.h.rst.in nghttp2-0.6.7/doc/asio_http2_client.h.rst.in --- nghttp2-1.13.0/doc/asio_http2_client.h.rst.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/asio_http2_client.h.rst.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -asio_http2_client.h -=================== - -.. literalinclude:: @top_srcdir@/src/includes/nghttp2/asio_http2_client.h - :language: cpp diff -Nru nghttp2-1.13.0/doc/asio_http2_server.h.rst.in nghttp2-0.6.7/doc/asio_http2_server.h.rst.in --- nghttp2-1.13.0/doc/asio_http2_server.h.rst.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/asio_http2_server.h.rst.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -asio_http2_server.h -=================== - -.. literalinclude:: @top_srcdir@/src/includes/nghttp2/asio_http2_server.h - :language: cpp diff -Nru nghttp2-1.13.0/doc/bash_completion/h2load nghttp2-0.6.7/doc/bash_completion/h2load --- nghttp2-1.13.0/doc/bash_completion/h2load 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/bash_completion/h2load 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -_h2load() -{ - local cur prev split=false - COMPREPLY=() - COMP_WORDBREAKS=${COMP_WORDBREAKS//=} - - cmd=${COMP_WORDS[0]} - _get_comp_words_by_ref cur prev - case $cur in - -*) - COMPREPLY=( $( compgen -W '--connection-window-bits --clients --verbose --ciphers --rate --no-tls-proto --requests --base-uri --h1 --threads --npn-list --rate-period --data --version --connection-inactivity-timeout --timing-script-file --max-concurrent-streams --connection-active-timeout --input-file --header --window-bits --help ' -- "$cur" ) ) - ;; - *) - _filedir - return 0 - esac - return 0 -} -complete -F _h2load h2load diff -Nru nghttp2-1.13.0/doc/bash_completion/nghttp nghttp2-0.6.7/doc/bash_completion/nghttp --- nghttp2-1.13.0/doc/bash_completion/nghttp 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/bash_completion/nghttp 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -_nghttp() -{ - local cur prev split=false - COMPREPLY=() - COMP_WORDBREAKS=${COMP_WORDBREAKS//=} - - cmd=${COMP_WORDS[0]} - _get_comp_words_by_ref cur prev - case $cur in - -*) - COMPREPLY=( $( compgen -W '--no-push --verbose --no-dep --get-assets --har --header-table-size --multiply --padding --hexdump --max-concurrent-streams --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 --expect-continue --stat --header ' -- "$cur" ) ) - ;; - *) - _filedir - return 0 - esac - return 0 -} -complete -F _nghttp nghttp diff -Nru nghttp2-1.13.0/doc/bash_completion/nghttpd nghttp2-0.6.7/doc/bash_completion/nghttpd --- nghttp2-1.13.0/doc/bash_completion/nghttpd 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/bash_completion/nghttpd 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -_nghttpd() -{ - local cur prev split=false - COMPREPLY=() - COMP_WORDBREAKS=${COMP_WORDBREAKS//=} - - cmd=${COMP_WORDS[0]} - _get_comp_words_by_ref cur prev - case $cur in - -*) - COMPREPLY=( $( compgen -W '--htdocs --verbose --daemon --echo-upload --error-gzip --push --header-table-size --padding --hexdump --max-concurrent-streams --no-tls --connection-window-bits --mime-types-file --no-content-length --workers --version --color --early-response --dh-param-file --trailer --address --window-bits --verify-client --help ' -- "$cur" ) ) - ;; - *) - _filedir - return 0 - esac - return 0 -} -complete -F _nghttpd nghttpd diff -Nru nghttp2-1.13.0/doc/bash_completion/nghttpx nghttp2-0.6.7/doc/bash_completion/nghttpx --- nghttp2-1.13.0/doc/bash_completion/nghttpx 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/bash_completion/nghttpx 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -_nghttpx() -{ - local cur prev split=false - COMPREPLY=() - COMP_WORDBREAKS=${COMP_WORDBREAKS//=} - - cmd=${COMP_WORDS[0]} - _get_comp_words_by_ref cur prev - case $cur in - -*) - COMPREPLY=( $( compgen -W '--worker-read-rate --include --frontend-http2-dump-response-header --tls-ticket-key-file --verify-client-cacert --max-response-header-fields --backend-request-buffer --max-request-header-fields --backend-http2-connection-window-bits --conf --backend-http2-max-concurrent-streams --worker-write-burst --npn-list --fetch-ocsp-response-file --no-via --tls-session-cache-memcached-cert-file --no-http2-cipher-black-list --mruby-file --no-server-push --stream-read-timeout --tls-ticket-key-memcached --forwarded-for --accesslog-syslog --frontend-http2-read-timeout --listener-disable-timeout --frontend-http2-connection-window-bits --ciphers --strip-incoming-x-forwarded-for --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --rlimit-nofile --tls-ticket-key-memcached-cert-file --ocsp-update-interval --forwarded-by --tls-session-cache-memcached-private-key-file --error-page --backend-write-timeout --tls-dyn-rec-warmup-threshold --tls-ticket-key-memcached-max-retry --http2-no-cookie-crumbling --worker-read-burst --dh-param-file --accesslog-format --errorlog-syslog --request-header-field-buffer --api-max-request-body --errorlog-file --frontend-http2-max-concurrent-streams --frontend-write-timeout --tls-ticket-key-cipher --read-burst --backend --insecure --backend-max-backoff --log-level --host-rewrite --tls-proto-list --tls-ticket-key-memcached-interval --frontend-http2-setting-timeout --worker-frontend-connections --syslog-facility --fastopen --no-location-rewrite --tls-session-cache-memcached --no-ocsp --backend-response-buffer --workers --add-forwarded --frontend-http2-window-bits --worker-write-rate --add-request-header --backend-http2-settings-timeout --subcert --no-kqueue --help --frontend-frame-debug --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --user --add-x-forwarded-for --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-connections-per-host --backend-http2-window-bits --response-header-field-buffer --tls-ticket-key-memcached-address-family --padding --tls-session-cache-memcached-address-family --stream-write-timeout --cacert --tls-ticket-key-memcached-private-key-file --backend-address-family --version --add-response-header --backend-read-timeout --frontend --accesslog-file --http2-proxy --client-private-key-file --client-cert-file --accept-proxy-protocol --tls-dyn-rec-idle-timeout --verify-client --read-rate --backend-connections-per-frontend --strip-incoming-forwarded ' -- "$cur" ) ) - ;; - *) - _filedir - return 0 - esac - return 0 -} -complete -F _nghttpx nghttpx diff -Nru nghttp2-1.13.0/doc/CMakeLists.txt nghttp2-0.6.7/doc/CMakeLists.txt --- nghttp2-1.13.0/doc/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,339 +0,0 @@ -# Generated documents -set(APIDOCS - 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_get_dynamic_table_size.rst - nghttp2_hd_deflate_get_max_dynamic_table_size.rst - nghttp2_hd_deflate_get_num_table_entries.rst - nghttp2_hd_deflate_get_table_entry.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_get_dynamic_table_size.rst - nghttp2_hd_inflate_get_max_dynamic_table_size.rst - nghttp2_hd_inflate_get_num_table_entries.rst - nghttp2_hd_inflate_get_table_entry.rst - nghttp2_hd_inflate_hd.rst - nghttp2_hd_inflate_new.rst - nghttp2_hd_inflate_new2.rst - nghttp2_http2_strerror.rst - nghttp2_is_fatal.rst - nghttp2_nv_compare_name.rst - nghttp2_option_del.rst - nghttp2_option_new.rst - nghttp2_option_set_builtin_recv_extension_type.rst - nghttp2_option_set_max_reserved_remote_streams.rst - nghttp2_option_set_no_auto_ping_ack.rst - nghttp2_option_set_no_auto_window_update.rst - nghttp2_option_set_no_http_messaging.rst - nghttp2_option_set_no_recv_client_magic.rst - nghttp2_option_set_peer_max_concurrent_streams.rst - nghttp2_option_set_user_recv_extension_type.rst - nghttp2_pack_settings_payload.rst - nghttp2_priority_spec_check_default.rst - nghttp2_priority_spec_default_init.rst - nghttp2_priority_spec_init.rst - nghttp2_rcbuf_decref.rst - nghttp2_rcbuf_get_buf.rst - nghttp2_rcbuf_incref.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_error_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_extension_chunk_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_header_callback2.rst - nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst - nghttp2_session_callbacks_set_on_stream_close_callback.rst - nghttp2_session_callbacks_set_pack_extension_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_callbacks_set_unpack_extension_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_create_idle_stream.rst - nghttp2_session_del.rst - nghttp2_session_find_stream.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_root_stream.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_change_stream_priority.rst - nghttp2_session_check_request_allowed.rst - nghttp2_session_check_server_session.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_upgrade2.rst - nghttp2_session_want_read.rst - nghttp2_session_want_write.rst - nghttp2_stream_get_first_child.rst - nghttp2_stream_get_next_sibling.rst - nghttp2_stream_get_parent.rst - nghttp2_stream_get_previous_sibling.rst - nghttp2_stream_get_state.rst - nghttp2_stream_get_sum_dependency_weight.rst - nghttp2_stream_get_weight.rst - nghttp2_strerror.rst - nghttp2_submit_altsvc.rst - nghttp2_submit_data.rst - nghttp2_submit_extension.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 -) - -set(MAN_PAGES - nghttp.1 - nghttpd.1 - nghttpx.1 - h2load.1 -) - -# Other .rst files from the source tree that need to be copied -# XXX move them to sources/ and create .in files? -set(RST_FILES - README.rst - programmers-guide.rst - nghttp.1.rst - nghttpd.1.rst - nghttpx.1.rst - h2load.1.rst -) - -# XXX unused for now -set(EXTRA_DIST - mkapiref.py - ${RST_FILES} - ${APIDOCS} - sources/index.rst - sources/tutorial-client.rst - sources/tutorial-server.rst - sources/tutorial-hpack.rst - sources/nghttpx-howto.rst - sources/h2load-howto.rst - sources/libnghttp2_asio.rst - sources/python-apiref.rst - sources/building-android-binary.rst - sources/contribute.rst - _exts/sphinxcontrib/LICENSE.rubydomain - _exts/sphinxcontrib/__init__.py - _exts/sphinxcontrib/rubydomain.py - _themes/sphinx_rtd_theme/__init__.py - _themes/sphinx_rtd_theme/breadcrumbs.html - _themes/sphinx_rtd_theme/footer.html - _themes/sphinx_rtd_theme/layout.html - _themes/sphinx_rtd_theme/layout_old.html - _themes/sphinx_rtd_theme/search.html - _themes/sphinx_rtd_theme/searchbox.html - _themes/sphinx_rtd_theme/static/css/badge_only.css - _themes/sphinx_rtd_theme/static/css/theme.css - _themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf - _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot - _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg - _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf - _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff - _themes/sphinx_rtd_theme/static/js/theme.js - _themes/sphinx_rtd_theme/theme.conf - _themes/sphinx_rtd_theme/versions.html - ${MAN_PAGES} - bash_completion/nghttp - bash_completion/nghttpd - bash_completion/nghttpx - bash_completion/h2load -) - -# Based on Makefile for Sphinx documentation - -# You can set these variables from the command line. -set(SPHINXOPTS) -set(SPHINXBUILD sphinx-build) -set(PAPER) -set(BUILDDIR manual) - -# Internal variables. -set(PAPEROPT_a4 -D latex_paper_size=a4) -set(PAPEROPT_letter -D latex_paper_size=letter) -set(ALLSPHINXOPTS -d ${BUILDDIR}/doctrees ${PAPEROPT_${PAPER}} ${SPHINXOPTS} .) - -# "Please use `make ' where is one of" -# " html to make standalone HTML files" -# " dirhtml to make HTML files named index.html in directories" -# " singlehtml to make a single large HTML file" -# " pickle to make pickle files" -# " json to make JSON files" -# " htmlhelp to make HTML files and a HTML help project" -# " qthelp to make HTML files and a qthelp project" -# " devhelp to make HTML files and a Devhelp project" -# " epub to make an epub" -# " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" -# " latexpdf to make LaTeX files and run them through pdflatex" -# " text to make text files" -# " man to make manual pages" -# " changes to make an overview of all changed/added/deprecated items" -# " linkcheck to check all external links for integrity" -# " doctest to run all doctests embedded in the documentation (if enabled)" - - -# Copy files for out-of-tree builds -if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) - set(RST_BUILD_FILES) - foreach(rstfile IN LISTS RST_FILES) - set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${rstfile}") - add_custom_command(OUTPUT "${outfile}" - COMMAND ${CMAKE_COMMAND} -E copy - "${CMAKE_CURRENT_SOURCE_DIR}/${rstfile}" "${outfile}" - DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${rstfile}" - ) - list(APPEND RST_BUILD_FILES "${outfile}") - endforeach() -else() - set(RST_BUILD_FILES "${RST_FILES}") -endif() - -set(apiref_SOURCES - ${CMAKE_BINARY_DIR}/lib/includes/nghttp2/nghttp2ver.h - ${CMAKE_SOURCE_DIR}/lib/includes/nghttp2/nghttp2.h -) -# Generates apiref.rst and other files -add_custom_command( - OUTPUT - apiref.rst - ${APIDOCS} - COMMAND - "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/mkapiref.py" - apiref.rst macros.rst enums.rst types.rst . - ${apiref_SOURCES} - DEPENDS - ${RST_BUILD_FILES} - ${apiref_SOURCES} -) - - - -set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${BUILDDIR}") - -# Invokes sphinx-build and prints the given messages when completed -function(sphinxbuild builder) - set(echo_commands) - foreach(message IN LISTS ARGN) - list(APPEND echo_commands COMMAND ${CMAKE_COMMAND} -E echo "${message}") - endforeach() - add_custom_target(${builder} - COMMAND "${SPHINXBUILD}" -b ${builder} ${ALLSPHINXOPTS} "${BUILDDIR}/${builder}" - COMMAND ${CMAKE_COMMAND} -E echo - ${echo_commands} - VERBATIM - DEPENDS apiref.rst - ) -endfunction() - -foreach(builder html dirhtml singlehtml) - sphinxbuild(${builder} - "Build finished. The HTML pages are in ${BUILDDIR}/${builder}.") -endforeach() -sphinxbuild(pickle "Build finished; now you can process the pickle files.") -sphinxbuild(json "Build finished; now you can process the JSON files.") -sphinxbuild(htmlhelp - "Build finished; now you can run HTML Help Workshop with the" - ".hhp project file in ${BUILDDIR}/htmlhelp." -) -sphinxbuild(qthelp - "Build finished; now you can run \"qcollectiongenerator\" with the" - ".qhcp project file in ${BUILDDIR}/qthelp, like this:" - "# qcollectiongenerator ${BUILDDIR}/qthelp/nghttp2.qhcp" - "To view the help file:" - "# assistant -collectionFile ${BUILDDIR}/qthelp/nghttp2.qhc" -) -sphinxbuild(devhelp - "Build finished." - "To view the help file:" - "# mkdir -p ~/.local/share/devhelp/nghttp2" - "# ln -s ${BUILDDIR}/devhelp ~/.local/share/devhelp/nghttp2" - "# devhelp" -) -sphinxbuild(epub "Build finished. The epub file is in ${BUILDDIR}/epub.") -sphinxbuild(latex - "Build finished; the LaTeX files are in ${BUILDDIR}/latex." - "Run `make' in that directory to run these through (pdf)latex" - "(use `make latexpdf' here to do that automatically)." -) - -# Invoke the Makefile generated by sphinx -add_custom_target(latexpdf - COMMAND ${CMAKE_COMMAND} -E echo "Running LaTeX files through pdflatex..." - COMMAND make -C "${BUILDDIR}/latex" all-pdf - COMMAND ${CMAKE_COMMAND} -E echo "pdflatex finished; the PDF files are in ${BUILDDIR}/latex." - DEPENDS latex -) - -sphinxbuild(text "Build finished. The text files are in ${BUILDDIR}/text.") -sphinxbuild(man "Build finished. The manual pages are in ${BUILDDIR}/man.") -sphinxbuild(changes "The overview file is in ${BUILDDIR}/changes.") -sphinxbuild(linkcheck - "Link check complete; look for any errors in the above output" - "or in ${BUILDDIR}/linkcheck/output.txt." -) -sphinxbuild(doctest - "Testing of doctests in the sources finished, look at the" - "results in ${BUILDDIR}/doctest/output.txt." -) - -foreach(_man_page IN LISTS MAN_PAGES) - install(FILES ${_man_page} - DESTINATION "${CMAKE_INSTALL_MANDIR}/man1" - ) -endforeach() diff -Nru nghttp2-1.13.0/doc/conf.py.in nghttp2-0.6.7/doc/conf.py.in --- nghttp2-1.13.0/doc/conf.py.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/conf.py.in 2014-11-30 14:15:07.000000000 +0000 @@ -41,8 +41,6 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) -sys.path.append(os.path.abspath('@top_srcdir@/doc/_exts')) - # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. @@ -50,7 +48,7 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinxcontrib.rubydomain'] +extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ['@top_srcdir@/_templates'] @@ -66,7 +64,7 @@ # General information about the project. project = u'nghttp2' -copyright = u'2012, 2015, 2016, Tatsuhiro Tsujikawa' +copyright = u'2012, 2014, Tatsuhiro Tsujikawa' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -244,9 +242,6 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('nghttp.1', 'nghttp', u'HTTP/2 client', [u'Tatsuhiro Tsujikawa'], 1), - ('nghttpd.1', 'nghttpd', u'HTTP/2 server', [u'Tatsuhiro Tsujikawa'], 1), - ('nghttpx.1', 'nghttpx', u'HTTP/2 proxy', [u'Tatsuhiro Tsujikawa'], 1), - ('h2load.1', 'h2load', u'HTTP/2 benchmarking tool', + ('index', 'nghttp2', u'nghttp2 Documentation', [u'Tatsuhiro Tsujikawa'], 1) ] diff -Nru nghttp2-1.13.0/doc/enums.rst nghttp2-0.6.7/doc/enums.rst --- nghttp2-1.13.0/doc/enums.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/enums.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,506 +0,0 @@ - -Enums -===== -.. type:: nghttp2_error - - - Error codes used in this library. The code range is [-999, -500], - inclusive. The following values are defined: - - .. macro:: NGHTTP2_ERR_INVALID_ARGUMENT - - (``-501``) - Invalid argument passed. - .. macro:: NGHTTP2_ERR_BUFFER_ERROR - - (``-502``) - Out of buffer space. - .. macro:: NGHTTP2_ERR_UNSUPPORTED_VERSION - - (``-503``) - The specified protocol version is not supported. - .. macro:: NGHTTP2_ERR_WOULDBLOCK - - (``-504``) - Used as a return value from :type:`nghttp2_send_callback`, - :type:`nghttp2_recv_callback` and - :type:`nghttp2_send_data_callback` to indicate that the operation - would block. - .. macro:: NGHTTP2_ERR_PROTO - - (``-505``) - General protocol error - .. macro:: NGHTTP2_ERR_INVALID_FRAME - - (``-506``) - The frame is invalid. - .. macro:: NGHTTP2_ERR_EOF - - (``-507``) - The peer performed a shutdown on the connection. - .. macro:: NGHTTP2_ERR_DEFERRED - - (``-508``) - Used as a return value from - :func:`nghttp2_data_source_read_callback` to indicate that data - transfer is postponed. See - :func:`nghttp2_data_source_read_callback` for details. - .. macro:: NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE - - (``-509``) - Stream ID has reached the maximum value. Therefore no stream ID - is available. - .. macro:: NGHTTP2_ERR_STREAM_CLOSED - - (``-510``) - The stream is already closed; or the stream ID is invalid. - .. macro:: NGHTTP2_ERR_STREAM_CLOSING - - (``-511``) - RST_STREAM has been added to the outbound queue. The stream is - in closing state. - .. macro:: NGHTTP2_ERR_STREAM_SHUT_WR - - (``-512``) - The transmission is not allowed for this stream (e.g., a frame - with END_STREAM flag set has already sent). - .. macro:: NGHTTP2_ERR_INVALID_STREAM_ID - - (``-513``) - The stream ID is invalid. - .. macro:: NGHTTP2_ERR_INVALID_STREAM_STATE - - (``-514``) - The state of the stream is not valid (e.g., DATA cannot be sent - to the stream if response HEADERS has not been sent). - .. macro:: NGHTTP2_ERR_DEFERRED_DATA_EXIST - - (``-515``) - Another DATA frame has already been deferred. - .. macro:: NGHTTP2_ERR_START_STREAM_NOT_ALLOWED - - (``-516``) - Starting new stream is not allowed (e.g., GOAWAY has been sent - and/or received). - .. macro:: NGHTTP2_ERR_GOAWAY_ALREADY_SENT - - (``-517``) - GOAWAY has already been sent. - .. macro:: NGHTTP2_ERR_INVALID_HEADER_BLOCK - - (``-518``) - The received frame contains the invalid header block (e.g., There - are duplicate header names; or the header names are not encoded - in US-ASCII character set and not lower cased; or the header name - is zero-length string; or the header value contains multiple - in-sequence NUL bytes). - .. macro:: NGHTTP2_ERR_INVALID_STATE - - (``-519``) - Indicates that the context is not suitable to perform the - requested operation. - .. macro:: NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE - - (``-521``) - The user callback function failed due to the temporal error. - .. macro:: NGHTTP2_ERR_FRAME_SIZE_ERROR - - (``-522``) - The length of the frame is invalid, either too large or too small. - .. macro:: NGHTTP2_ERR_HEADER_COMP - - (``-523``) - Header block inflate/deflate error. - .. macro:: NGHTTP2_ERR_FLOW_CONTROL - - (``-524``) - Flow control error - .. macro:: NGHTTP2_ERR_INSUFF_BUFSIZE - - (``-525``) - Insufficient buffer size given to function. - .. macro:: NGHTTP2_ERR_PAUSE - - (``-526``) - Callback was paused by the application - .. macro:: NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS - - (``-527``) - There are too many in-flight SETTING frame and no more - transmission of SETTINGS is allowed. - .. macro:: NGHTTP2_ERR_PUSH_DISABLED - - (``-528``) - The server push is disabled. - .. macro:: NGHTTP2_ERR_DATA_EXIST - - (``-529``) - DATA or HEADERS frame for a given stream has been already - submitted and has not been fully processed yet. Application - should wait for the transmission of the previously submitted - frame before submitting another. - .. macro:: NGHTTP2_ERR_SESSION_CLOSING - - (``-530``) - The current session is closing due to a connection error or - `nghttp2_session_terminate_session()` is called. - .. macro:: NGHTTP2_ERR_HTTP_HEADER - - (``-531``) - Invalid HTTP header field was received and stream is going to be - closed. - .. macro:: NGHTTP2_ERR_HTTP_MESSAGING - - (``-532``) - Violation in HTTP messaging rule. - .. macro:: NGHTTP2_ERR_REFUSED_STREAM - - (``-533``) - Stream was refused. - .. macro:: NGHTTP2_ERR_INTERNAL - - (``-534``) - Unexpected internal error, but recovered. - .. macro:: NGHTTP2_ERR_CANCEL - - (``-535``) - Indicates that a processing was canceled. - .. macro:: NGHTTP2_ERR_FATAL - - (``-900``) - The errors < :macro:`NGHTTP2_ERR_FATAL` mean that the library is - under unexpected condition and processing was terminated (e.g., - out of memory). If application receives this error code, it must - stop using that :type:`nghttp2_session` object and only allowed - operation for that object is deallocate it using - `nghttp2_session_del()`. - .. macro:: NGHTTP2_ERR_NOMEM - - (``-901``) - Out of memory. This is a fatal error. - .. macro:: NGHTTP2_ERR_CALLBACK_FAILURE - - (``-902``) - The user callback function failed. This is a fatal error. - .. macro:: NGHTTP2_ERR_BAD_CLIENT_MAGIC - - (``-903``) - Invalid client magic (see :macro:`NGHTTP2_CLIENT_MAGIC`) was - received and further processing is not possible. - .. macro:: NGHTTP2_ERR_FLOODED - - (``-904``) - Possible flooding by peer was detected in this HTTP/2 session. - Flooding is measured by how many PING and SETTINGS frames with - ACK flag set are queued for transmission. These frames are - response for the peer initiated frames, and peer can cause memory - exhaustion on server side to send these frames forever and does - not read network. - -.. type:: nghttp2_nv_flag - - - The flags for header field name/value pair. - - .. macro:: NGHTTP2_NV_FLAG_NONE - - (``0``) - No flag set. - .. macro:: NGHTTP2_NV_FLAG_NO_INDEX - - (``0x01``) - Indicates that this name/value pair must not be indexed ("Literal - Header Field never Indexed" representation must be used in HPACK - encoding). Other implementation calls this bit as "sensitive". - .. macro:: NGHTTP2_NV_FLAG_NO_COPY_NAME - - (``0x02``) - This flag is set solely by application. If this flag is set, the - library does not make a copy of header field name. This could - improve performance. - .. macro:: NGHTTP2_NV_FLAG_NO_COPY_VALUE - - (``0x04``) - This flag is set solely by application. If this flag is set, the - library does not make a copy of header field value. This could - improve performance. - -.. type:: nghttp2_frame_type - - - The frame types in HTTP/2 specification. - - .. macro:: NGHTTP2_DATA - - (``0``) - The DATA frame. - .. macro:: NGHTTP2_HEADERS - - (``0x01``) - The HEADERS frame. - .. macro:: NGHTTP2_PRIORITY - - (``0x02``) - The PRIORITY frame. - .. macro:: NGHTTP2_RST_STREAM - - (``0x03``) - The RST_STREAM frame. - .. macro:: NGHTTP2_SETTINGS - - (``0x04``) - The SETTINGS frame. - .. macro:: NGHTTP2_PUSH_PROMISE - - (``0x05``) - The PUSH_PROMISE frame. - .. macro:: NGHTTP2_PING - - (``0x06``) - The PING frame. - .. macro:: NGHTTP2_GOAWAY - - (``0x07``) - The GOAWAY frame. - .. macro:: NGHTTP2_WINDOW_UPDATE - - (``0x08``) - The WINDOW_UPDATE frame. - .. macro:: NGHTTP2_CONTINUATION - - (``0x09``) - The CONTINUATION frame. This frame type won't be passed to any - callbacks because the library processes this frame type and its - preceding HEADERS/PUSH_PROMISE as a single frame. - .. macro:: NGHTTP2_ALTSVC - - (``0x0a``) - The ALTSVC frame, which is defined in `RFC 7383 - `_. - -.. type:: nghttp2_flag - - - The flags for HTTP/2 frames. This enum defines all flags for all - frames. - - .. macro:: NGHTTP2_FLAG_NONE - - (``0``) - No flag set. - .. macro:: NGHTTP2_FLAG_END_STREAM - - (``0x01``) - The END_STREAM flag. - .. macro:: NGHTTP2_FLAG_END_HEADERS - - (``0x04``) - The END_HEADERS flag. - .. macro:: NGHTTP2_FLAG_ACK - - (``0x01``) - The ACK flag. - .. macro:: NGHTTP2_FLAG_PADDED - - (``0x08``) - The PADDED flag. - .. macro:: NGHTTP2_FLAG_PRIORITY - - (``0x20``) - The PRIORITY flag. - -.. type:: nghttp2_settings_id - - The SETTINGS ID. - - .. macro:: NGHTTP2_SETTINGS_HEADER_TABLE_SIZE - - (``0x01``) - SETTINGS_HEADER_TABLE_SIZE - .. macro:: NGHTTP2_SETTINGS_ENABLE_PUSH - - (``0x02``) - SETTINGS_ENABLE_PUSH - .. macro:: NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS - - (``0x03``) - SETTINGS_MAX_CONCURRENT_STREAMS - .. macro:: NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE - - (``0x04``) - SETTINGS_INITIAL_WINDOW_SIZE - .. macro:: NGHTTP2_SETTINGS_MAX_FRAME_SIZE - - (``0x05``) - SETTINGS_MAX_FRAME_SIZE - .. macro:: NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE - - (``0x06``) - SETTINGS_MAX_HEADER_LIST_SIZE - -.. type:: nghttp2_error_code - - The status codes for the RST_STREAM and GOAWAY frames. - - .. macro:: NGHTTP2_NO_ERROR - - (``0x00``) - No errors. - .. macro:: NGHTTP2_PROTOCOL_ERROR - - (``0x01``) - PROTOCOL_ERROR - .. macro:: NGHTTP2_INTERNAL_ERROR - - (``0x02``) - INTERNAL_ERROR - .. macro:: NGHTTP2_FLOW_CONTROL_ERROR - - (``0x03``) - FLOW_CONTROL_ERROR - .. macro:: NGHTTP2_SETTINGS_TIMEOUT - - (``0x04``) - SETTINGS_TIMEOUT - .. macro:: NGHTTP2_STREAM_CLOSED - - (``0x05``) - STREAM_CLOSED - .. macro:: NGHTTP2_FRAME_SIZE_ERROR - - (``0x06``) - FRAME_SIZE_ERROR - .. macro:: NGHTTP2_REFUSED_STREAM - - (``0x07``) - REFUSED_STREAM - .. macro:: NGHTTP2_CANCEL - - (``0x08``) - CANCEL - .. macro:: NGHTTP2_COMPRESSION_ERROR - - (``0x09``) - COMPRESSION_ERROR - .. macro:: NGHTTP2_CONNECT_ERROR - - (``0x0a``) - CONNECT_ERROR - .. macro:: NGHTTP2_ENHANCE_YOUR_CALM - - (``0x0b``) - ENHANCE_YOUR_CALM - .. macro:: NGHTTP2_INADEQUATE_SECURITY - - (``0x0c``) - INADEQUATE_SECURITY - .. macro:: NGHTTP2_HTTP_1_1_REQUIRED - - (``0x0d``) - HTTP_1_1_REQUIRED - -.. type:: nghttp2_data_flag - - - The flags used to set in *data_flags* output parameter in - :type:`nghttp2_data_source_read_callback`. - - .. macro:: NGHTTP2_DATA_FLAG_NONE - - (``0``) - No flag set. - .. macro:: NGHTTP2_DATA_FLAG_EOF - - (``0x01``) - Indicates EOF was sensed. - .. macro:: NGHTTP2_DATA_FLAG_NO_END_STREAM - - (``0x02``) - Indicates that END_STREAM flag must not be set even if - NGHTTP2_DATA_FLAG_EOF is set. Usually this flag is used to send - trailer fields with `nghttp2_submit_request()` or - `nghttp2_submit_response()`. - .. macro:: NGHTTP2_DATA_FLAG_NO_COPY - - (``0x04``) - Indicates that application will send complete DATA frame in - :type:`nghttp2_send_data_callback`. - -.. type:: nghttp2_headers_category - - - The category of HEADERS, which indicates the role of the frame. In - HTTP/2 spec, request, response, push response and other arbitrary - headers (e.g., trailer fields) are all called just HEADERS. To - give the application the role of incoming HEADERS frame, we define - several categories. - - .. macro:: NGHTTP2_HCAT_REQUEST - - (``0``) - The HEADERS frame is opening new stream, which is analogous to - SYN_STREAM in SPDY. - .. macro:: NGHTTP2_HCAT_RESPONSE - - (``1``) - The HEADERS frame is the first response headers, which is - analogous to SYN_REPLY in SPDY. - .. macro:: NGHTTP2_HCAT_PUSH_RESPONSE - - (``2``) - The HEADERS frame is the first headers sent against reserved - stream. - .. macro:: NGHTTP2_HCAT_HEADERS - - (``3``) - The HEADERS frame which does not apply for the above categories, - which is analogous to HEADERS in SPDY. If non-final response - (e.g., status 1xx) is used, final response HEADERS frame will be - categorized here. - -.. type:: nghttp2_hd_inflate_flag - - - The flags for header inflation. - - .. macro:: NGHTTP2_HD_INFLATE_NONE - - (``0``) - No flag set. - .. macro:: NGHTTP2_HD_INFLATE_FINAL - - (``0x01``) - Indicates all headers were inflated. - .. macro:: NGHTTP2_HD_INFLATE_EMIT - - (``0x02``) - Indicates a header was emitted. - -.. type:: nghttp2_stream_proto_state - - - State of stream as described in RFC 7540. - - .. macro:: NGHTTP2_STREAM_STATE_IDLE - - (``1``) - idle state. - .. macro:: NGHTTP2_STREAM_STATE_OPEN, - - open state. - .. macro:: NGHTTP2_STREAM_STATE_RESERVED_LOCAL, - - reserved (local) state. - .. macro:: NGHTTP2_STREAM_STATE_RESERVED_REMOTE, - - reserved (remote) state. - .. macro:: NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL, - - half closed (local) state. - .. macro:: NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE, - - half closed (remote) state. - .. macro:: NGHTTP2_STREAM_STATE_CLOSED - - closed state. - diff -Nru nghttp2-1.13.0/doc/_exts/sphinxcontrib/__init__.py nghttp2-0.6.7/doc/_exts/sphinxcontrib/__init__.py --- nghttp2-1.13.0/doc/_exts/sphinxcontrib/__init__.py 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_exts/sphinxcontrib/__init__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- -""" - sphinxcontrib - ~~~~~~~~~~~~~ - - This package is a namespace package that contains all extensions - distributed in the ``sphinx-contrib`` distribution. - - :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" - -__import__('pkg_resources').declare_namespace(__name__) - diff -Nru nghttp2-1.13.0/doc/_exts/sphinxcontrib/LICENSE.rubydomain nghttp2-0.6.7/doc/_exts/sphinxcontrib/LICENSE.rubydomain --- nghttp2-1.13.0/doc/_exts/sphinxcontrib/LICENSE.rubydomain 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_exts/sphinxcontrib/LICENSE.rubydomain 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -If not otherwise noted, the extensions in this package are licensed -under the following license. - -Copyright (c) 2010 by the contributors (see AUTHORS file). -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru nghttp2-1.13.0/doc/_exts/sphinxcontrib/rubydomain.py nghttp2-0.6.7/doc/_exts/sphinxcontrib/rubydomain.py --- nghttp2-1.13.0/doc/_exts/sphinxcontrib/rubydomain.py 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_exts/sphinxcontrib/rubydomain.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,704 +0,0 @@ -# -*- coding: utf-8 -*- -""" - sphinx.domains.ruby - ~~~~~~~~~~~~~~~~~~~ - - The Ruby domain. - - :copyright: Copyright 2010 by SHIBUKAWA Yoshiki - :license: BSD, see LICENSE for details. -""" - -import re - -from docutils import nodes -from docutils.parsers.rst import directives - -from sphinx import addnodes -from sphinx import version_info -from sphinx.roles import XRefRole -from sphinx.locale import l_, _ -from sphinx.domains import Domain, ObjType, Index -from sphinx.directives import ObjectDescription -from sphinx.util.nodes import make_refnode -from sphinx.util.compat import Directive -from sphinx.util.docfields import Field, GroupedField, TypedField - - -# REs for Ruby signatures -rb_sig_re = re.compile( - r'''^ ([\w.]*\.)? # class name(s) - (\$?\w+\??!?) \s* # thing name - (?: \((.*)\) # optional: arguments - (?:\s* -> \s* (.*))? # return annotation - )? $ # and nothing more - ''', re.VERBOSE) - -rb_paramlist_re = re.compile(r'([\[\],])') # split at '[', ']' and ',' - -separators = { - 'method':'#', 'attr_reader':'#', 'attr_writer':'#', 'attr_accessor':'#', - 'function':'.', 'classmethod':'.', 'class':'::', 'module':'::', - 'global':'', 'const':'::'} - -rb_separator = re.compile(r"(?:\w+)?(?:::)?(?:\.)?(?:#)?") - - -def _iteritems(d): - - for k in d: - yield k, d[k] - - -def ruby_rsplit(fullname): - items = [item for item in rb_separator.findall(fullname)] - return ''.join(items[:-2]), items[-1] - - -class RubyObject(ObjectDescription): - """ - Description of a general Ruby object. - """ - option_spec = { - 'noindex': directives.flag, - 'module': directives.unchanged, - } - - doc_field_types = [ - TypedField('parameter', label=l_('Parameters'), - names=('param', 'parameter', 'arg', 'argument'), - typerolename='obj', typenames=('paramtype', 'type')), - TypedField('variable', label=l_('Variables'), rolename='obj', - names=('var', 'ivar', 'cvar'), - typerolename='obj', typenames=('vartype',)), - GroupedField('exceptions', label=l_('Raises'), rolename='exc', - names=('raises', 'raise', 'exception', 'except'), - can_collapse=True), - Field('returnvalue', label=l_('Returns'), has_arg=False, - names=('returns', 'return')), - Field('returntype', label=l_('Return type'), has_arg=False, - names=('rtype',)), - ] - - def get_signature_prefix(self, sig): - """ - May return a prefix to put before the object name in the signature. - """ - return '' - - def needs_arglist(self): - """ - May return true if an empty argument list is to be generated even if - the document contains none. - """ - return False - - def handle_signature(self, sig, signode): - """ - Transform a Ruby signature into RST nodes. - Returns (fully qualified name of the thing, classname if any). - - If inside a class, the current class name is handled intelligently: - * it is stripped from the displayed name if present - * it is added to the full name (return value) if not present - """ - m = rb_sig_re.match(sig) - if m is None: - raise ValueError - name_prefix, name, arglist, retann = m.groups() - if not name_prefix: - name_prefix = "" - # determine module and class name (if applicable), as well as full name - modname = self.options.get( - 'module', self.env.temp_data.get('rb:module')) - classname = self.env.temp_data.get('rb:class') - if self.objtype == 'global': - add_module = False - modname = None - classname = None - fullname = name - elif classname: - add_module = False - if name_prefix and name_prefix.startswith(classname): - fullname = name_prefix + name - # class name is given again in the signature - name_prefix = name_prefix[len(classname):].lstrip('.') - else: - separator = separators[self.objtype] - fullname = classname + separator + name_prefix + name - else: - add_module = True - if name_prefix: - classname = name_prefix.rstrip('.') - fullname = name_prefix + name - else: - classname = '' - fullname = name - - signode['module'] = modname - signode['class'] = self.class_name = classname - signode['fullname'] = fullname - - sig_prefix = self.get_signature_prefix(sig) - if sig_prefix: - signode += addnodes.desc_annotation(sig_prefix, sig_prefix) - - if name_prefix: - signode += addnodes.desc_addname(name_prefix, name_prefix) - # exceptions are a special case, since they are documented in the - # 'exceptions' module. - elif add_module and self.env.config.add_module_names: - if self.objtype == 'global': - nodetext = '' - signode += addnodes.desc_addname(nodetext, nodetext) - else: - modname = self.options.get( - 'module', self.env.temp_data.get('rb:module')) - if modname and modname != 'exceptions': - nodetext = modname + separators[self.objtype] - signode += addnodes.desc_addname(nodetext, nodetext) - - signode += addnodes.desc_name(name, name) - if not arglist: - if self.needs_arglist(): - # for callables, add an empty parameter list - signode += addnodes.desc_parameterlist() - if retann: - signode += addnodes.desc_returns(retann, retann) - return fullname, name_prefix - signode += addnodes.desc_parameterlist() - - stack = [signode[-1]] - for token in rb_paramlist_re.split(arglist): - if token == '[': - opt = addnodes.desc_optional() - stack[-1] += opt - stack.append(opt) - elif token == ']': - try: - stack.pop() - except IndexError: - raise ValueError - elif not token or token == ',' or token.isspace(): - pass - else: - token = token.strip() - stack[-1] += addnodes.desc_parameter(token, token) - if len(stack) != 1: - raise ValueError - if retann: - signode += addnodes.desc_returns(retann, retann) - return fullname, name_prefix - - def get_index_text(self, modname, name): - """ - Return the text for the index entry of the object. - """ - raise NotImplementedError('must be implemented in subclasses') - - def _is_class_member(self): - return self.objtype.endswith('method') or self.objtype.startswith('attr') - - def add_target_and_index(self, name_cls, sig, signode): - if self.objtype == 'global': - modname = '' - else: - modname = self.options.get( - 'module', self.env.temp_data.get('rb:module')) - separator = separators[self.objtype] - if self._is_class_member(): - if signode['class']: - prefix = modname and modname + '::' or '' - else: - prefix = modname and modname + separator or '' - else: - prefix = modname and modname + separator or '' - fullname = prefix + name_cls[0] - # note target - if fullname not in self.state.document.ids: - signode['names'].append(fullname) - signode['ids'].append(fullname) - signode['first'] = (not self.names) - self.state.document.note_explicit_target(signode) - objects = self.env.domaindata['rb']['objects'] - if fullname in objects: - self.env.warn( - self.env.docname, - 'duplicate object description of %s, ' % fullname + - 'other instance in ' + - self.env.doc2path(objects[fullname][0]), - self.lineno) - objects[fullname] = (self.env.docname, self.objtype) - - indextext = self.get_index_text(modname, name_cls) - if indextext: - self.indexnode['entries'].append( - _make_index('single', indextext, fullname, fullname)) - - def before_content(self): - # needed for automatic qualification of members (reset in subclasses) - self.clsname_set = False - - def after_content(self): - if self.clsname_set: - self.env.temp_data['rb:class'] = None - - -class RubyModulelevel(RubyObject): - """ - Description of an object on module level (functions, data). - """ - - def needs_arglist(self): - return self.objtype == 'function' - - def get_index_text(self, modname, name_cls): - if self.objtype == 'function': - if not modname: - return _('%s() (global function)') % name_cls[0] - return _('%s() (module function in %s)') % (name_cls[0], modname) - else: - return '' - - -class RubyGloballevel(RubyObject): - """ - Description of an object on module level (functions, data). - """ - - def get_index_text(self, modname, name_cls): - if self.objtype == 'global': - return _('%s (global variable)') % name_cls[0] - else: - return '' - - -class RubyEverywhere(RubyObject): - """ - Description of a class member (methods, attributes). - """ - - def needs_arglist(self): - return self.objtype == 'method' - - def get_index_text(self, modname, name_cls): - name, cls = name_cls - add_modules = self.env.config.add_module_names - if self.objtype == 'method': - try: - clsname, methname = ruby_rsplit(name) - except ValueError: - if modname: - return _('%s() (in module %s)') % (name, modname) - else: - return '%s()' % name - if modname and add_modules: - return _('%s() (%s::%s method)') % (methname, modname, - clsname) - else: - return _('%s() (%s method)') % (methname, clsname) - else: - return '' - - -class RubyClasslike(RubyObject): - """ - Description of a class-like object (classes, exceptions). - """ - - def get_signature_prefix(self, sig): - return self.objtype + ' ' - - def get_index_text(self, modname, name_cls): - if self.objtype == 'class': - if not modname: - return _('%s (class)') % name_cls[0] - return _('%s (class in %s)') % (name_cls[0], modname) - elif self.objtype == 'exception': - return name_cls[0] - else: - return '' - - def before_content(self): - RubyObject.before_content(self) - if self.names: - self.env.temp_data['rb:class'] = self.names[0][0] - self.clsname_set = True - - -class RubyClassmember(RubyObject): - """ - Description of a class member (methods, attributes). - """ - - def needs_arglist(self): - return self.objtype.endswith('method') - - def get_signature_prefix(self, sig): - if self.objtype == 'classmethod': - return "classmethod %s." % self.class_name - elif self.objtype == 'attr_reader': - return "attribute [R] " - elif self.objtype == 'attr_writer': - return "attribute [W] " - elif self.objtype == 'attr_accessor': - return "attribute [R/W] " - return '' - - def get_index_text(self, modname, name_cls): - name, cls = name_cls - add_modules = self.env.config.add_module_names - if self.objtype == 'classmethod': - try: - clsname, methname = ruby_rsplit(name) - except ValueError: - return '%s()' % name - if modname: - return _('%s() (%s.%s class method)') % (methname, modname, - clsname) - else: - return _('%s() (%s class method)') % (methname, clsname) - elif self.objtype.startswith('attr'): - try: - clsname, attrname = ruby_rsplit(name) - except ValueError: - return name - if modname and add_modules: - return _('%s (%s.%s attribute)') % (attrname, modname, clsname) - else: - return _('%s (%s attribute)') % (attrname, clsname) - else: - return '' - - def before_content(self): - RubyObject.before_content(self) - lastname = self.names and self.names[-1][1] - if lastname and not self.env.temp_data.get('rb:class'): - self.env.temp_data['rb:class'] = lastname.strip('.') - self.clsname_set = True - - -class RubyModule(Directive): - """ - Directive to mark description of a new module. - """ - - has_content = False - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = False - option_spec = { - 'platform': lambda x: x, - 'synopsis': lambda x: x, - 'noindex': directives.flag, - 'deprecated': directives.flag, - } - - def run(self): - env = self.state.document.settings.env - modname = self.arguments[0].strip() - noindex = 'noindex' in self.options - env.temp_data['rb:module'] = modname - env.domaindata['rb']['modules'][modname] = \ - (env.docname, self.options.get('synopsis', ''), - self.options.get('platform', ''), 'deprecated' in self.options) - targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True) - self.state.document.note_explicit_target(targetnode) - ret = [targetnode] - # XXX this behavior of the module directive is a mess... - if 'platform' in self.options: - platform = self.options['platform'] - node = nodes.paragraph() - node += nodes.emphasis('', _('Platforms: ')) - node += nodes.Text(platform, platform) - ret.append(node) - # the synopsis isn't printed; in fact, it is only used in the - # modindex currently - if not noindex: - indextext = _('%s (module)') % modname - inode = addnodes.index(entries=[_make_index( - 'single', indextext, 'module-' + modname, modname)]) - ret.append(inode) - return ret - -def _make_index(entrytype, entryname, target, ignored, key=None): - # Sphinx 1.4 introduced backward incompatible changes, it now - # requires 5 tuples. Last one is categorization key. See - # http://www.sphinx-doc.org/en/stable/extdev/nodes.html#sphinx.addnodes.index - if version_info >= (1, 4, 0, '', 0): - return (entrytype, entryname, target, ignored, key) - else: - return (entrytype, entryname, target, ignored) - -class RubyCurrentModule(Directive): - """ - This directive is just to tell Sphinx that we're documenting - stuff in module foo, but links to module foo won't lead here. - """ - - has_content = False - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = False - option_spec = {} - - def run(self): - env = self.state.document.settings.env - modname = self.arguments[0].strip() - if modname == 'None': - env.temp_data['rb:module'] = None - else: - env.temp_data['rb:module'] = modname - return [] - - -class RubyXRefRole(XRefRole): - def process_link(self, env, refnode, has_explicit_title, title, target): - if not has_explicit_title: - title = title.lstrip('.') # only has a meaning for the target - title = title.lstrip('#') - if title.startswith("::"): - title = title[2:] - target = target.lstrip('~') # only has a meaning for the title - # if the first character is a tilde, don't display the module/class - # parts of the contents - if title[0:1] == '~': - m = re.search(r"(?:\.)?(?:#)?(?:::)?(.*)\Z", title) - if m: - title = m.group(1) - if not title.startswith("$"): - refnode['rb:module'] = env.temp_data.get('rb:module') - refnode['rb:class'] = env.temp_data.get('rb:class') - # if the first character is a dot, search more specific namespaces first - # else search builtins first - if target[0:1] == '.': - target = target[1:] - refnode['refspecific'] = True - return title, target - - -class RubyModuleIndex(Index): - """ - Index subclass to provide the Ruby module index. - """ - - name = 'modindex' - localname = l_('Ruby Module Index') - shortname = l_('modules') - - def generate(self, docnames=None): - content = {} - # list of prefixes to ignore - ignores = self.domain.env.config['modindex_common_prefix'] - ignores = sorted(ignores, key=len, reverse=True) - # list of all modules, sorted by module name - modules = sorted(_iteritems(self.domain.data['modules']), - key=lambda x: x[0].lower()) - # sort out collapsable modules - prev_modname = '' - num_toplevels = 0 - for modname, (docname, synopsis, platforms, deprecated) in modules: - if docnames and docname not in docnames: - continue - - for ignore in ignores: - if modname.startswith(ignore): - modname = modname[len(ignore):] - stripped = ignore - break - else: - stripped = '' - - # we stripped the whole module name? - if not modname: - modname, stripped = stripped, '' - - entries = content.setdefault(modname[0].lower(), []) - - package = modname.split('::')[0] - if package != modname: - # it's a submodule - if prev_modname == package: - # first submodule - make parent a group head - entries[-1][1] = 1 - elif not prev_modname.startswith(package): - # submodule without parent in list, add dummy entry - entries.append([stripped + package, 1, '', '', '', '', '']) - subtype = 2 - else: - num_toplevels += 1 - subtype = 0 - - qualifier = deprecated and _('Deprecated') or '' - entries.append([stripped + modname, subtype, docname, - 'module-' + stripped + modname, platforms, - qualifier, synopsis]) - prev_modname = modname - - # apply heuristics when to collapse modindex at page load: - # only collapse if number of toplevel modules is larger than - # number of submodules - collapse = len(modules) - num_toplevels < num_toplevels - - # sort by first letter - content = sorted(_iteritems(content)) - - return content, collapse - - -class RubyDomain(Domain): - """Ruby language domain.""" - name = 'rb' - label = 'Ruby' - object_types = { - 'function': ObjType(l_('function'), 'func', 'obj'), - 'global': ObjType(l_('global variable'), 'global', 'obj'), - 'method': ObjType(l_('method'), 'meth', 'obj'), - 'class': ObjType(l_('class'), 'class', 'obj'), - 'exception': ObjType(l_('exception'), 'exc', 'obj'), - 'classmethod': ObjType(l_('class method'), 'meth', 'obj'), - 'attr_reader': ObjType(l_('attribute'), 'attr', 'obj'), - 'attr_writer': ObjType(l_('attribute'), 'attr', 'obj'), - 'attr_accessor': ObjType(l_('attribute'), 'attr', 'obj'), - 'const': ObjType(l_('const'), 'const', 'obj'), - 'module': ObjType(l_('module'), 'mod', 'obj'), - } - - directives = { - 'function': RubyModulelevel, - 'global': RubyGloballevel, - 'method': RubyEverywhere, - 'const': RubyEverywhere, - 'class': RubyClasslike, - 'exception': RubyClasslike, - 'classmethod': RubyClassmember, - 'attr_reader': RubyClassmember, - 'attr_writer': RubyClassmember, - 'attr_accessor': RubyClassmember, - 'module': RubyModule, - 'currentmodule': RubyCurrentModule, - } - - roles = { - 'func': RubyXRefRole(fix_parens=False), - 'global':RubyXRefRole(), - 'class': RubyXRefRole(), - 'exc': RubyXRefRole(), - 'meth': RubyXRefRole(fix_parens=False), - 'attr': RubyXRefRole(), - 'const': RubyXRefRole(), - 'mod': RubyXRefRole(), - 'obj': RubyXRefRole(), - } - initial_data = { - 'objects': {}, # fullname -> docname, objtype - 'modules': {}, # modname -> docname, synopsis, platform, deprecated - } - indices = [ - RubyModuleIndex, - ] - - def clear_doc(self, docname): - for fullname, (fn, _) in list(self.data['objects'].items()): - if fn == docname: - del self.data['objects'][fullname] - for modname, (fn, _, _, _) in list(self.data['modules'].items()): - if fn == docname: - del self.data['modules'][modname] - - def find_obj(self, env, modname, classname, name, type, searchorder=0): - """ - Find a Ruby object for "name", perhaps using the given module and/or - classname. - """ - # skip parens - if name[-2:] == '()': - name = name[:-2] - - if not name: - return None, None - - objects = self.data['objects'] - - newname = None - if searchorder == 1: - if modname and classname and \ - modname + '::' + classname + '#' + name in objects: - newname = modname + '::' + classname + '#' + name - elif modname and classname and \ - modname + '::' + classname + '.' + name in objects: - newname = modname + '::' + classname + '.' + name - elif modname and modname + '::' + name in objects: - newname = modname + '::' + name - elif modname and modname + '#' + name in objects: - newname = modname + '#' + name - elif modname and modname + '.' + name in objects: - newname = modname + '.' + name - elif classname and classname + '.' + name in objects: - newname = classname + '.' + name - elif classname and classname + '#' + name in objects: - newname = classname + '#' + name - elif name in objects: - newname = name - else: - if name in objects: - newname = name - elif classname and classname + '.' + name in objects: - newname = classname + '.' + name - elif classname and classname + '#' + name in objects: - newname = classname + '#' + name - elif modname and modname + '::' + name in objects: - newname = modname + '::' + name - elif modname and modname + '#' + name in objects: - newname = modname + '#' + name - elif modname and modname + '.' + name in objects: - newname = modname + '.' + name - elif modname and classname and \ - modname + '::' + classname + '#' + name in objects: - newname = modname + '::' + classname + '#' + name - elif modname and classname and \ - modname + '::' + classname + '.' + name in objects: - newname = modname + '::' + classname + '.' + name - # special case: object methods - elif type in ('func', 'meth') and '.' not in name and \ - 'object.' + name in objects: - newname = 'object.' + name - if newname is None: - return None, None - return newname, objects[newname] - - def resolve_xref(self, env, fromdocname, builder, - typ, target, node, contnode): - if (typ == 'mod' or - typ == 'obj' and target in self.data['modules']): - docname, synopsis, platform, deprecated = \ - self.data['modules'].get(target, ('','','', '')) - if not docname: - return None - else: - title = '%s%s%s' % ((platform and '(%s) ' % platform), - synopsis, - (deprecated and ' (deprecated)' or '')) - return make_refnode(builder, fromdocname, docname, - 'module-' + target, contnode, title) - else: - modname = node.get('rb:module') - clsname = node.get('rb:class') - searchorder = node.hasattr('refspecific') and 1 or 0 - name, obj = self.find_obj(env, modname, clsname, - target, typ, searchorder) - if not obj: - return None - else: - return make_refnode(builder, fromdocname, obj[0], name, - contnode, name) - - def get_objects(self): - for modname, info in _iteritems(self.data['modules']): - yield (modname, modname, 'module', info[0], 'module-' + modname, 0) - for refname, (docname, type) in _iteritems(self.data['objects']): - yield (refname, refname, type, docname, refname, 1) - - -def setup(app): - app.add_domain(RubyDomain) diff -Nru nghttp2-1.13.0/doc/h2load.1 nghttp2-0.6.7/doc/h2load.1 --- nghttp2-1.13.0/doc/h2load.1 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/h2load.1 2014-11-30 14:15:07.000000000 +0000 @@ -1,423 +1,75 @@ -.\" Man page generated from reStructuredText. -. -.TH "H2LOAD" "1" "Jul 21, 2016" "1.13.0" "nghttp2" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.4. +.TH H2LOAD "1" "November 2014" "h2load nghttp2/0.6.7" "User Commands" .SH NAME h2load \- HTTP/2 benchmarking tool -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. .SH SYNOPSIS -.sp -\fBh2load\fP [OPTIONS]... [URI]... +.B h2load +[\fI\,OPTIONS\/\fR]... [\fI\,URI\/\fR]... .SH DESCRIPTION -.sp benchmarking tool for HTTP/2 and SPDY server -.INDENT 0.0 .TP -.B -Specify URI to access. Multiple URIs can be specified. -URIs are used in this order for each client. All URIs -are used, then first URI is used and then 2nd URI, and -so on. The scheme, host and port in the subsequent -URIs, if present, are ignored. Those in the first URI -are used solely. Definition of a base URI overrides all -scheme, host or port values. -.UNINDENT + +Specify URI to access. Multiple URIs can be +specified. URIs are used in this order for each +client. All URIs are used, then first URI is +used and then 2nd URI, and so on. The scheme, +host and port in the subsequent URIs, if present, +are ignored. Those in the first URI are used +solely. .SH OPTIONS -.INDENT 0.0 +.HP +\fB\-n\fR, \fB\-\-requests=\fR Number of requests. Default: 1 .TP -.B \-n, \-\-requests= -Number of requests across all clients. If it is used -with \fI\%\-\-timing\-script\-file\fP option, this option specifies -the number of requests each client performs rather than -the number of requests across all clients. -.sp -Default: \fB1\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-c, \-\-clients= -Number of concurrent clients. With \fI\%\-r\fP option, this -specifies the maximum number of connections to be made. -.sp -Default: \fB1\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-t, \-\-threads= -Number of native threads. -.sp -Default: \fB1\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-i, \-\-input\-file= -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 , URIs will be read from stdin. -URIs are used in this order for each client. All URIs -are used, then first URI is used and then 2nd URI, and -so on. The scheme, host and port in the subsequent -URIs, if present, are ignored. Those in the first URI -are used solely. Definition of a base URI overrides all -scheme, host or port values. -.UNINDENT -.INDENT 0.0 -.TP -.B \-m, \-\-max\-concurrent\-streams= -Max concurrent streams to issue per session. When -http/1.1 is used, this specifies the number of HTTP -pipelining requests in\-flight. -.sp -Default: \fB1\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-w, \-\-window\-bits= -Sets the stream level initial window size to (2**)\-1. -For SPDY, 2** is used instead. -.sp -Default: \fB30\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-W, \-\-connection\-window\-bits= -Sets the connection level initial window size to -(2**)\-1. For SPDY, if is strictly less than 16, -this option is ignored. Otherwise 2** is used for -SPDY. -.sp -Default: \fB30\fP -.UNINDENT -.INDENT 0.0 +\fB\-c\fR, \fB\-\-clients=\fR +Number of concurrent clients. Default: 1 .TP -.B \-H, \-\-header=
+\fB\-t\fR, \fB\-\-threads=\fR +Number of native threads. Default: 1 +.TP +\fB\-i\fR, \fB\-\-input\-file=\fR +Path of a file with multiple URIs are seperated +by EOLs. This option will disable URIs getting +from command\-line. If '\-' is given as , +URIs will be read from stdin. URIs are used in +this order for each client. All URIs are used, +then first URI is used and then 2nd URI, and so +on. The scheme, host and port in the subsequent +URIs, if present, are ignored. Those in the +first URI are used solely. +.TP +\fB\-m\fR, \fB\-\-max\-concurrent\-streams=\fR(auto|) +Max concurrent streams to issue per session. If +"auto" is given, the number of given URIs is +used. Default: auto +.TP +\fB\-w\fR, \fB\-\-window\-bits=\fR +Sets the stream level initial window size to +(2**)\-1. For SPDY, 2** is used instead. +.TP +\fB\-W\fR, \fB\-\-connection\-window\-bits=\fR +Sets the connection level initial window size to +(2**)\-1. For SPDY, if is strictly less +than 16, this option is ignored. Otherwise +2** is used for SPDY. +.TP +\fB\-H\fR, \fB\-\-header=\fR
Add/Override a header to the requests. -.UNINDENT -.INDENT 0.0 .TP -.B \-\-ciphers= -Set allowed cipher list. The format of the string is -described in OpenSSL ciphers(1). -.UNINDENT -.INDENT 0.0 -.TP -.B \-p, \-\-no\-tls\-proto= -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, h2c and -http/1.1 -.sp -Default: \fBh2c\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-d, \-\-data= -Post FILE to server. The request method is changed to -POST. For http/1.1 connection, if \fI\%\-d\fP is used, the -maximum number of in\-flight pipelined requests is set to -1. -.UNINDENT -.INDENT 0.0 -.TP -.B \-r, \-\-rate= -Specifies the fixed rate at which connections are -created. The rate must be a positive integer, -representing the number of connections to be made per -rate period. The maximum number of connections to be -made is given in \fI\%\-c\fP option. This rate will be -distributed among threads as evenly as possible. For -example, with \fI\%\-t\fP2 and \fI\%\-r\fP4, each thread gets 2 -connections per period. When the rate is 0, the program -will run as it normally does, creating connections at -whatever variable rate it wants. The default value for -this option is 0. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-rate\-period= -Specifies the time period between creating connections. -The period must be a positive number, representing the -length of the period in time. This option is ignored if -the rate option is not used. The default value for this -option is 1s. -.UNINDENT -.INDENT 0.0 -.TP -.B \-T, \-\-connection\-active\-timeout= -Specifies the maximum time that h2load is willing to -keep a connection open, regardless of the activity on -said connection. must be a positive integer, -specifying the amount of time to wait. When no timeout -value is set (either active or inactive), h2load will -keep a connection open indefinitely, waiting for a -response. -.UNINDENT -.INDENT 0.0 -.TP -.B \-N, \-\-connection\-inactivity\-timeout= -Specifies the amount of time that h2load is willing to -wait to see activity on a given connection. -must be a positive integer, specifying the amount of -time to wait. When no timeout value is set (either -active or inactive), h2load will keep a connection open -indefinitely, waiting for a response. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-timing\-script\-file= -Path of a file containing one or more lines separated by -EOLs. Each script line is composed of two tab\-separated -fields. The first field represents the time offset from -the start of execution, expressed as a positive value of -milliseconds with microsecond resolution. The second -field represents the URI. This option will disable URIs -getting from command\-line. If \(aq\-\(aq is given as , -script lines will be read from stdin. Script lines are -used in order for each client. If \fI\%\-n\fP is given, it must -be less than or equal to the number of script lines, -larger values are clamped to the number of script lines. -If \fI\%\-n\fP is not given, the number of requests will default -to the number of script lines. The scheme, host and -port defined in the first URI are used solely. Values -contained in other URIs, if present, are ignored. -Definition of a base URI overrides all scheme, host or -port values. -.UNINDENT -.INDENT 0.0 -.TP -.B \-B, \-\-base\-uri=(|unix:) -Specify URI from which the scheme, host and port will be -used for all requests. The base URI overrides all -values defined either at the command line or inside -input files. If argument starts with "unix:", then the -rest of the argument will be treated as UNIX domain -socket path. The connection is made through that path -instead of TCP. In this case, scheme is inferred from -the first URI appeared in the command line or inside -input files as usual. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-npn\-list= -Comma delimited list of ALPN protocol identifier sorted -in the order of preference. That means most desirable -protocol comes first. This is used in both ALPN and -NPN. The parameter must be delimited by a single comma -only and any white spaces are treated as a part of -protocol string. -.sp -Default: \fBh2,h2\-16,h2\-14,spdy/3.1,spdy/3,spdy/2,http/1.1\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-h1 -Short hand for \fI\%\-\-npn\-list\fP=http/1.1 -\fI\%\-\-no\-tls\-proto\fP=http/1.1, which effectively force -http/1.1 for both http and https URI. -.UNINDENT -.INDENT 0.0 +\fB\-p\fR, \fB\-\-no\-tls\-proto=\fR +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 +Default: h2c\-14 .TP -.B \-v, \-\-verbose +\fB\-v\fR, \fB\-\-verbose\fR Output debug information. -.UNINDENT -.INDENT 0.0 .TP -.B \-\-version +\fB\-\-version\fR Display version information and exit. -.UNINDENT -.INDENT 0.0 .TP -.B \-h, \-\-help +\fB\-h\fR, \fB\-\-help\fR Display this help and exit. -.UNINDENT -.sp -The 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 OUTPUT -.INDENT 0.0 -.TP -.B requests -.INDENT 7.0 -.TP -.B total -The number of requests h2load was instructed to make. -.TP -.B started -The number of requests h2load has started. -.TP -.B done -The number of requests completed. -.TP -.B succeeded -The number of requests completed successfully. Only HTTP status -code 2xx or3xx are considered as success. -.TP -.B failed -The number of requests failed, including HTTP level failures -(non\-successful HTTP status code). -.TP -.B errored -The number of requests failed, except for HTTP level failures. -This is the subset of the number reported in \fBfailed\fP and most -likely the network level failures or stream was reset by -RST_STREAM. -.TP -.B timeout -The number of requests whose connection timed out before they were -completed. This is the subset of the number reported in -\fBerrored\fP\&. -.UNINDENT -.TP -.B status codes -The number of status code h2load received. -.TP -.B traffic -.INDENT 7.0 -.TP -.B total -The number of bytes received from the server "on the wire". If -requests were made via TLS, this value is the number of decrypted -bytes. -.TP -.B headers -The number of response header bytes from the server without -decompression. The \fBspace savings\fP shows efficiency of header -compression. Let \fBdecompressed(headers)\fP to the number of bytes -used for header fields after decompression. The \fBspace savings\fP -is calculated by (1 \- \fBheaders\fP / \fBdecompressed(headers)\fP) * -100. For HTTP/1.1, this is usually 0.00%, since it does not have -header compression. For HTTP/2 and SPDY, it shows some insightful -numbers. -.TP -.B data -The number of response body bytes received from the server. -.UNINDENT -.TP -.B time for request -.INDENT 7.0 -.TP -.B min -The minimum time taken for request and response. -.TP -.B max -The maximum time taken for request and response. -.TP -.B mean -The mean time taken for request and response. -.TP -.B sd -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 -.TP -.B req/s -.INDENT 7.0 -.TP -.B min -The minimum request per second among all clients. -.TP -.B max -The maximum request per second among all clients. -.TP -.B mean -The mean request per second among all clients. -.TP -.B sd -The standard deviation of request per second among all clients. -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 -\fBnghttp(1)\fP, \fBnghttpd(1)\fP, \fBnghttpx(1)\fP -.SH AUTHOR -Tatsuhiro Tsujikawa -.SH COPYRIGHT -2012, 2015, 2016, Tatsuhiro Tsujikawa -.\" Generated by docutils manpage writer. -. +.SH "SEE ALSO" + +nghttp(1), nghttpd(1), nghttpx(1) diff -Nru nghttp2-1.13.0/doc/h2load.1.rst nghttp2-0.6.7/doc/h2load.1.rst --- nghttp2-1.13.0/doc/h2load.1.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/h2load.1.rst 2014-11-30 14:15:07.000000000 +0000 @@ -1,341 +1,113 @@ - -.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY. +.. DO NOT MODIFY THIS FILE! It was generated by man2rst.py .. program:: h2load h2load(1) ========= +NAME +---- +h2load - HTTP/2 benchmarking tool + SYNOPSIS -------- - **h2load** [OPTIONS]... [URI]... DESCRIPTION ----------- - benchmarking tool for HTTP/2 and SPDY server -.. describe:: +.. option:: URI - Specify URI to access. Multiple URIs can be specified. - URIs are used in this order for each client. All URIs - are used, then first URI is used and then 2nd URI, and - so on. The scheme, host and port in the subsequent - URIs, if present, are ignored. Those in the first URI - are used solely. Definition of a base URI overrides all - scheme, host or port values. + Specify URI to access. Multiple URIs can be + specified. URIs are used in this order for each + client. All URIs are used, then first URI is + used and then 2nd URI, and so on. The scheme, + host and port in the subsequent URIs, if present, + are ignored. Those in the first URI are used + solely. OPTIONS ------- .. option:: -n, --requests= - Number of requests across all clients. If it is used - with :option:`--timing-script-file` option, this option specifies - the number of requests each client performs rather than - the number of requests across all clients. - - Default: ``1`` + Number of requests. Default: 1 .. option:: -c, --clients= - Number of concurrent clients. With :option:`-r` option, this - specifies the maximum number of connections to be made. - - Default: ``1`` + + Number of concurrent clients. Default: 1 .. option:: -t, --threads= - Number of native threads. - - Default: ``1`` - -.. option:: -i, --input-file= - - Path of a file with multiple URIs are separated by EOLs. - This option will disable URIs getting from command-line. - If '-' is given as , URIs will be read from stdin. - URIs are used in this order for each client. All URIs - are used, then first URI is used and then 2nd URI, and - so on. The scheme, host and port in the subsequent - URIs, if present, are ignored. Those in the first URI - are used solely. Definition of a base URI overrides all - scheme, host or port values. + + Number of native threads. Default: 1 -.. option:: -m, --max-concurrent-streams= +.. option:: -i, --input-file= - Max concurrent streams to issue per session. When - http/1.1 is used, this specifies the number of HTTP - pipelining requests in-flight. - - Default: ``1`` + + Path of a file with multiple URIs are seperated + by EOLs. This option will disable URIs getting + from command-line. If '-' is given as , + URIs will be read from stdin. URIs are used in + this order for each client. All URIs are used, + then first URI is used and then 2nd URI, and so + on. The scheme, host and port in the subsequent + URIs, if present, are ignored. Those in the + first URI are used solely. + +.. option:: -m, --max-concurrent-streams=(auto|) + + + Max concurrent streams to issue per session. If + "auto" is given, the number of given URIs is + used. Default: auto .. option:: -w, --window-bits= - Sets the stream level initial window size to (2\*\*)-1. - For SPDY, 2** is used instead. - - Default: ``30`` + + Sets the stream level initial window size to + (2\*\*)-1. For SPDY, 2\*\* is used instead. .. option:: -W, --connection-window-bits= - Sets the connection level initial window size to - (2**)-1. For SPDY, if is strictly less than 16, - this option is ignored. Otherwise 2\*\* is used for - SPDY. - - Default: ``30`` + + Sets the connection level initial window size to + (2\*\*)-1. For SPDY, if is strictly less + than 16, this option is ignored. Otherwise + 2\*\* is used for SPDY. .. option:: -H, --header=
+ Add/Override a header to the requests. -.. option:: --ciphers= - - Set allowed cipher list. The format of the string is - described in OpenSSL ciphers(1). - .. option:: -p, --no-tls-proto= - 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, h2c and - http/1.1 - - Default: ``h2c`` - -.. option:: -d, --data= - - Post FILE to server. The request method is changed to - POST. For http/1.1 connection, if :option:`-d` is used, the - maximum number of in-flight pipelined requests is set to - 1. - -.. option:: -r, --rate= - - Specifies the fixed rate at which connections are - created. The rate must be a positive integer, - representing the number of connections to be made per - rate period. The maximum number of connections to be - made is given in :option:`-c` option. This rate will be - distributed among threads as evenly as possible. For - example, with :option:`-t`\2 and :option:`-r`\4, each thread gets 2 - connections per period. When the rate is 0, the program - will run as it normally does, creating connections at - whatever variable rate it wants. The default value for - this option is 0. - -.. option:: --rate-period= - - Specifies the time period between creating connections. - The period must be a positive number, representing the - length of the period in time. This option is ignored if - the rate option is not used. The default value for this - option is 1s. - -.. option:: -T, --connection-active-timeout= - - Specifies the maximum time that h2load is willing to - keep a connection open, regardless of the activity on - said connection. must be a positive integer, - specifying the amount of time to wait. When no timeout - value is set (either active or inactive), h2load will - keep a connection open indefinitely, waiting for a - response. - -.. option:: -N, --connection-inactivity-timeout= - - Specifies the amount of time that h2load is willing to - wait to see activity on a given connection. - must be a positive integer, specifying the amount of - time to wait. When no timeout value is set (either - active or inactive), h2load will keep a connection open - indefinitely, waiting for a response. - -.. option:: --timing-script-file= - - Path of a file containing one or more lines separated by - EOLs. Each script line is composed of two tab-separated - fields. The first field represents the time offset from - the start of execution, expressed as a positive value of - milliseconds with microsecond resolution. The second - field represents the URI. This option will disable URIs - getting from command-line. If '-' is given as , - script lines will be read from stdin. Script lines are - used in order for each client. If :option:`-n` is given, it must - be less than or equal to the number of script lines, - larger values are clamped to the number of script lines. - If :option:`-n` is not given, the number of requests will default - to the number of script lines. The scheme, host and - port defined in the first URI are used solely. Values - contained in other URIs, if present, are ignored. - Definition of a base URI overrides all scheme, host or - port values. - -.. option:: -B, --base-uri=(|unix:) - - Specify URI from which the scheme, host and port will be - used for all requests. The base URI overrides all - values defined either at the command line or inside - input files. If argument starts with "unix:", then the - rest of the argument will be treated as UNIX domain - socket path. The connection is made through that path - instead of TCP. In this case, scheme is inferred from - the first URI appeared in the command line or inside - input files as usual. - -.. option:: --npn-list= - - Comma delimited list of ALPN protocol identifier sorted - in the order of preference. That means most desirable - protocol comes first. This is used in both ALPN and - NPN. The parameter must be delimited by a single comma - only and any white spaces are treated as a part of - protocol string. - - Default: ``h2,h2-16,h2-14,spdy/3.1,spdy/3,spdy/2,http/1.1`` - -.. option:: --h1 - - Short hand for :option:`--npn-list`\=http/1.1 - :option:`--no-tls-proto`\=http/1.1, which effectively force - http/1.1 for both http and https URI. + + 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 + Default: h2c-14 .. option:: -v, --verbose + Output debug information. .. option:: --version + Display version information and exit. .. option:: -h, --help + Display this help and exit. - - -The 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. - -.. _h2load-1-output: - -OUTPUT ------- - -requests - total - The number of requests h2load was instructed to make. - started - The number of requests h2load has started. - done - The number of requests completed. - succeeded - The number of requests completed successfully. Only HTTP status - code 2xx or3xx are considered as success. - failed - The number of requests failed, including HTTP level failures - (non-successful HTTP status code). - errored - The number of requests failed, except for HTTP level failures. - This is the subset of the number reported in ``failed`` and most - likely the network level failures or stream was reset by - RST_STREAM. - timeout - The number of requests whose connection timed out before they were - completed. This is the subset of the number reported in - ``errored``. - -status codes - The number of status code h2load received. - -traffic - total - The number of bytes received from the server "on the wire". If - requests were made via TLS, this value is the number of decrypted - bytes. - headers - The number of response header bytes from the server without - decompression. The ``space savings`` shows efficiency of header - compression. Let ``decompressed(headers)`` to the number of bytes - used for header fields after decompression. The ``space savings`` - is calculated by (1 - ``headers`` / ``decompressed(headers)``) * - 100. For HTTP/1.1, this is usually 0.00%, since it does not have - header compression. For HTTP/2 and SPDY, it shows some insightful - numbers. - data - The number of response body bytes received from the server. - -time for request - min - The minimum time taken for request and response. - max - The maximum time taken for request and response. - mean - The mean time taken for request and response. - sd - 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. - -req/s - min - The minimum request per second among all clients. - max - The maximum request per second among all clients. - mean - The mean request per second among all clients. - sd - The standard deviation of request per second among all clients. - 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 -------- -:manpage:`nghttp(1)`, :manpage:`nghttpd(1)`, :manpage:`nghttpx(1)` +nghttp(1), nghttpd(1), nghttpx(1) diff -Nru nghttp2-1.13.0/doc/macros.rst nghttp2-0.6.7/doc/macros.rst --- nghttp2-1.13.0/doc/macros.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/macros.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ - -Macros -====== -.. macro:: NGHTTP2_VERSION - - Version number of the nghttp2 library release -.. macro:: NGHTTP2_VERSION_NUM - - Numerical representation of the version number of the nghttp2 library - release. This is a 24 bit number with 8 bits for major number, 8 bits - for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. -.. macro:: NGHTTP2_PROTO_VERSION_ID - - - The protocol version identification string of this library - supports. This identifier is used if HTTP/2 is used over TLS. -.. macro:: NGHTTP2_PROTO_VERSION_ID_LEN - - - The length of :macro:`NGHTTP2_PROTO_VERSION_ID`. -.. macro:: NGHTTP2_PROTO_ALPN - - - The serialized form of ALPN protocol identifier this library - supports. Notice that first byte is the length of following - protocol identifier. This is the same wire format of `TLS ALPN - extension `_. This is useful - to process incoming ALPN tokens in wire format. -.. macro:: NGHTTP2_PROTO_ALPN_LEN - - - The length of :macro:`NGHTTP2_PROTO_ALPN`. -.. macro:: NGHTTP2_CLEARTEXT_PROTO_VERSION_ID - - - The protocol version identification string of this library - supports. This identifier is used if HTTP/2 is used over cleartext - TCP. -.. macro:: NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN - - - The length of :macro:`NGHTTP2_CLEARTEXT_PROTO_VERSION_ID`. -.. macro:: NGHTTP2_VERSION_AGE - - - The age of :type:`nghttp2_info` -.. macro:: NGHTTP2_DEFAULT_WEIGHT - - - The default weight of stream dependency. -.. macro:: NGHTTP2_MAX_WEIGHT - - - The maximum weight of stream dependency. -.. macro:: NGHTTP2_MIN_WEIGHT - - - The minimum weight of stream dependency. -.. macro:: NGHTTP2_MAX_WINDOW_SIZE - - - The maximum window size -.. macro:: NGHTTP2_INITIAL_WINDOW_SIZE - - - The initial window size for stream level flow control. -.. macro:: NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE - - - The initial window size for connection level flow control. -.. macro:: NGHTTP2_DEFAULT_HEADER_TABLE_SIZE - - - The default header table size. -.. macro:: NGHTTP2_CLIENT_MAGIC - - - The client magic string, which is the first 24 bytes byte string of - client connection preface. -.. macro:: NGHTTP2_CLIENT_MAGIC_LEN - - - The length of :macro:`NGHTTP2_CLIENT_MAGIC`. -.. macro:: NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS - - - Default maximum number of incoming concurrent streams. Use - `nghttp2_submit_settings()` with - :macro:`NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS` to change the - maximum number of incoming concurrent streams. - - .. note:: - - The maximum number of outgoing concurrent streams is 100 by - default. diff -Nru nghttp2-1.13.0/doc/Makefile.am nghttp2-0.6.7/doc/Makefile.am --- nghttp2-1.13.0/doc/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -23,158 +23,14 @@ man_MANS = nghttp.1 nghttpd.1 nghttpx.1 h2load.1 -APIDOCS= \ - 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_get_dynamic_table_size.rst \ - nghttp2_hd_deflate_get_max_dynamic_table_size.rst \ - nghttp2_hd_deflate_get_num_table_entries.rst \ - nghttp2_hd_deflate_get_table_entry.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_get_dynamic_table_size.rst \ - nghttp2_hd_inflate_get_max_dynamic_table_size.rst \ - nghttp2_hd_inflate_get_num_table_entries.rst \ - nghttp2_hd_inflate_get_table_entry.rst \ - nghttp2_hd_inflate_hd.rst \ - nghttp2_hd_inflate_hd2.rst \ - nghttp2_hd_inflate_new.rst \ - nghttp2_hd_inflate_new2.rst \ - nghttp2_http2_strerror.rst \ - nghttp2_is_fatal.rst \ - nghttp2_nv_compare_name.rst \ - nghttp2_option_del.rst \ - nghttp2_option_new.rst \ - nghttp2_option_set_builtin_recv_extension_type.rst \ - nghttp2_option_set_max_reserved_remote_streams.rst \ - nghttp2_option_set_max_send_header_block_length.rst \ - nghttp2_option_set_no_auto_ping_ack.rst \ - nghttp2_option_set_no_auto_window_update.rst \ - nghttp2_option_set_no_http_messaging.rst \ - nghttp2_option_set_no_recv_client_magic.rst \ - nghttp2_option_set_peer_max_concurrent_streams.rst \ - nghttp2_option_set_user_recv_extension_type.rst \ - nghttp2_pack_settings_payload.rst \ - nghttp2_priority_spec_check_default.rst \ - nghttp2_priority_spec_default_init.rst \ - nghttp2_priority_spec_init.rst \ - nghttp2_rcbuf_decref.rst \ - nghttp2_rcbuf_get_buf.rst \ - nghttp2_rcbuf_incref.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_error_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_extension_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_header_callback2.rst \ - nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst \ - nghttp2_session_callbacks_set_on_stream_close_callback.rst \ - nghttp2_session_callbacks_set_pack_extension_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_callbacks_set_unpack_extension_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_create_idle_stream.rst \ - nghttp2_session_del.rst \ - nghttp2_session_find_stream.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_root_stream.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_change_stream_priority.rst \ - nghttp2_session_check_request_allowed.rst \ - nghttp2_session_check_server_session.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_local_window_size.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_upgrade2.rst \ - nghttp2_session_want_read.rst \ - nghttp2_session_want_write.rst \ - nghttp2_stream_get_first_child.rst \ - nghttp2_stream_get_next_sibling.rst \ - nghttp2_stream_get_parent.rst \ - nghttp2_stream_get_previous_sibling.rst \ - nghttp2_stream_get_state.rst \ - nghttp2_stream_get_sum_dependency_weight.rst \ - nghttp2_stream_get_weight.rst \ - nghttp2_strerror.rst \ - nghttp2_submit_altsvc.rst \ - nghttp2_submit_data.rst \ - nghttp2_submit_extension.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 - -RST_FILES = \ +EXTRA_DIST = \ + mkapiref.py \ README.rst \ - programmers-guide.rst \ + apiref-header.rst \ nghttp.1.rst \ nghttpd.1.rst \ nghttpx.1.rst \ - h2load.1.rst - -EXTRA_DIST = \ - CMakeLists.txt \ - mkapiref.py \ - $(RST_FILES) \ - $(APIDOCS) \ + h2load.1.rst \ sources/index.rst \ sources/tutorial-client.rst \ sources/tutorial-server.rst \ @@ -185,31 +41,24 @@ sources/python-apiref.rst \ sources/building-android-binary.rst \ sources/contribute.rst \ - _exts/sphinxcontrib/LICENSE.rubydomain \ - _exts/sphinxcontrib/__init__.py \ - _exts/sphinxcontrib/rubydomain.py \ - _themes/sphinx_rtd_theme/__init__.py \ - _themes/sphinx_rtd_theme/breadcrumbs.html \ _themes/sphinx_rtd_theme/footer.html \ - _themes/sphinx_rtd_theme/layout.html \ + _themes/sphinx_rtd_theme/theme.conf \ _themes/sphinx_rtd_theme/layout_old.html \ + _themes/sphinx_rtd_theme/__init__.py \ + _themes/sphinx_rtd_theme/layout.html \ _themes/sphinx_rtd_theme/search.html \ + _themes/sphinx_rtd_theme/breadcrumbs.html \ + _themes/sphinx_rtd_theme/versions.html \ _themes/sphinx_rtd_theme/searchbox.html \ - _themes/sphinx_rtd_theme/static/css/badge_only.css \ - _themes/sphinx_rtd_theme/static/css/theme.css \ _themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf \ - _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot \ _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg \ - _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf \ _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff \ + _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot \ + _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf \ _themes/sphinx_rtd_theme/static/js/theme.js \ - _themes/sphinx_rtd_theme/theme.conf \ - _themes/sphinx_rtd_theme/versions.html \ - $(man_MANS) \ - bash_completion/nghttp \ - bash_completion/nghttpd \ - bash_completion/nghttpx \ - bash_completion/h2load + _themes/sphinx_rtd_theme/static/css/theme.css \ + _themes/sphinx_rtd_theme/static/css/badge_only.css \ + $(man_MANS) # Makefile for Sphinx documentation # @@ -246,22 +95,16 @@ @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 \ - $(top_srcdir)/lib/includes/nghttp2/nghttp2.h - for i in $(RST_FILES); do [ -e $(builddir)/$$i ] || cp $(srcdir)/$$i $(builddir); done +apiref.rst: $(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \ + $(top_builddir)/lib/includes/nghttp2/nghttp2.h $(PYTHON) $(top_srcdir)/doc/mkapiref.py \ - apiref.rst macros.rst enums.rst types.rst . $^ - -$(APIDOCS): apiref.rst + --header $(top_srcdir)/doc/apiref-header.rst $^ > $@ clean-local: - [ $(srcdir) = $(builddir) ] || for i in $(RST_FILES); do [ -e $(builddir)/$$i ] && rm $(builddir)/$$i; done - -rm -f apiref.rst - -rm -f $(APIDOCS) + -rm apiref.rst -rm -rf $(BUILDDIR)/* -html-local: apiref.rst +html: apiref.rst $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -333,7 +176,7 @@ @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." -man: apiref.rst +man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." diff -Nru nghttp2-1.13.0/doc/Makefile.in nghttp2-0.6.7/doc/Makefile.in --- nghttp2-1.13.0/doc/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/doc/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -37,17 +37,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -112,6 +102,17 @@ host_triplet = @host@ target_triplet = @target@ subdir = doc +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(srcdir)/conf.py.in $(srcdir)/index.rst.in \ + $(srcdir)/package_README.rst.in \ + $(srcdir)/tutorial-client.rst.in \ + $(srcdir)/tutorial-server.rst.in \ + $(srcdir)/tutorial-hpack.rst.in $(srcdir)/nghttpx-howto.rst.in \ + $(srcdir)/h2load-howto.rst.in $(srcdir)/libnghttp2_asio.rst.in \ + $(srcdir)/python-apiref.rst.in \ + $(srcdir)/building-android-binary.rst.in \ + $(srcdir)/nghttp2.h.rst.in $(srcdir)/nghttp2ver.h.rst.in \ + $(srcdir)/asio_http2.h.rst.in $(srcdir)/contribute.rst.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -121,21 +122,18 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = conf.py index.rst package_README.rst \ tutorial-client.rst tutorial-server.rst tutorial-hpack.rst \ nghttpx-howto.rst h2load-howto.rst libnghttp2_asio.rst \ python-apiref.rst building-android-binary.rst nghttp2.h.rst \ - nghttp2ver.h.rst asio_http2.h.rst asio_http2_server.h.rst \ - asio_http2_client.h.rst contribute.rst + nghttp2ver.h.rst asio_http2.h.rst contribute.rst CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) @@ -188,23 +186,10 @@ NROFF = nroff MANS = $(man_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/asio_http2.h.rst.in \ - $(srcdir)/asio_http2_client.h.rst.in \ - $(srcdir)/asio_http2_server.h.rst.in \ - $(srcdir)/building-android-binary.rst.in $(srcdir)/conf.py.in \ - $(srcdir)/contribute.rst.in $(srcdir)/h2load-howto.rst.in \ - $(srcdir)/index.rst.in $(srcdir)/libnghttp2_asio.rst.in \ - $(srcdir)/nghttp2.h.rst.in $(srcdir)/nghttp2ver.h.rst.in \ - $(srcdir)/nghttpx-howto.rst.in $(srcdir)/package_README.rst.in \ - $(srcdir)/python-apiref.rst.in \ - $(srcdir)/tutorial-client.rst.in \ - $(srcdir)/tutorial-hpack.rst.in \ - $(srcdir)/tutorial-server.rst.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -223,7 +208,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -239,7 +223,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -255,10 +238,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -270,7 +249,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -308,11 +286,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -367,7 +344,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -381,158 +357,14 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ man_MANS = nghttp.1 nghttpd.1 nghttpx.1 h2load.1 -APIDOCS = \ - 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_get_dynamic_table_size.rst \ - nghttp2_hd_deflate_get_max_dynamic_table_size.rst \ - nghttp2_hd_deflate_get_num_table_entries.rst \ - nghttp2_hd_deflate_get_table_entry.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_get_dynamic_table_size.rst \ - nghttp2_hd_inflate_get_max_dynamic_table_size.rst \ - nghttp2_hd_inflate_get_num_table_entries.rst \ - nghttp2_hd_inflate_get_table_entry.rst \ - nghttp2_hd_inflate_hd.rst \ - nghttp2_hd_inflate_hd2.rst \ - nghttp2_hd_inflate_new.rst \ - nghttp2_hd_inflate_new2.rst \ - nghttp2_http2_strerror.rst \ - nghttp2_is_fatal.rst \ - nghttp2_nv_compare_name.rst \ - nghttp2_option_del.rst \ - nghttp2_option_new.rst \ - nghttp2_option_set_builtin_recv_extension_type.rst \ - nghttp2_option_set_max_reserved_remote_streams.rst \ - nghttp2_option_set_max_send_header_block_length.rst \ - nghttp2_option_set_no_auto_ping_ack.rst \ - nghttp2_option_set_no_auto_window_update.rst \ - nghttp2_option_set_no_http_messaging.rst \ - nghttp2_option_set_no_recv_client_magic.rst \ - nghttp2_option_set_peer_max_concurrent_streams.rst \ - nghttp2_option_set_user_recv_extension_type.rst \ - nghttp2_pack_settings_payload.rst \ - nghttp2_priority_spec_check_default.rst \ - nghttp2_priority_spec_default_init.rst \ - nghttp2_priority_spec_init.rst \ - nghttp2_rcbuf_decref.rst \ - nghttp2_rcbuf_get_buf.rst \ - nghttp2_rcbuf_incref.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_error_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_extension_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_header_callback2.rst \ - nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst \ - nghttp2_session_callbacks_set_on_stream_close_callback.rst \ - nghttp2_session_callbacks_set_pack_extension_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_callbacks_set_unpack_extension_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_create_idle_stream.rst \ - nghttp2_session_del.rst \ - nghttp2_session_find_stream.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_root_stream.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_change_stream_priority.rst \ - nghttp2_session_check_request_allowed.rst \ - nghttp2_session_check_server_session.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_local_window_size.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_upgrade2.rst \ - nghttp2_session_want_read.rst \ - nghttp2_session_want_write.rst \ - nghttp2_stream_get_first_child.rst \ - nghttp2_stream_get_next_sibling.rst \ - nghttp2_stream_get_parent.rst \ - nghttp2_stream_get_previous_sibling.rst \ - nghttp2_stream_get_state.rst \ - nghttp2_stream_get_sum_dependency_weight.rst \ - nghttp2_stream_get_weight.rst \ - nghttp2_strerror.rst \ - nghttp2_submit_altsvc.rst \ - nghttp2_submit_data.rst \ - nghttp2_submit_extension.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 - -RST_FILES = \ +EXTRA_DIST = \ + mkapiref.py \ README.rst \ - programmers-guide.rst \ + apiref-header.rst \ nghttp.1.rst \ nghttpd.1.rst \ nghttpx.1.rst \ - h2load.1.rst - -EXTRA_DIST = \ - CMakeLists.txt \ - mkapiref.py \ - $(RST_FILES) \ - $(APIDOCS) \ + h2load.1.rst \ sources/index.rst \ sources/tutorial-client.rst \ sources/tutorial-server.rst \ @@ -543,31 +375,24 @@ sources/python-apiref.rst \ sources/building-android-binary.rst \ sources/contribute.rst \ - _exts/sphinxcontrib/LICENSE.rubydomain \ - _exts/sphinxcontrib/__init__.py \ - _exts/sphinxcontrib/rubydomain.py \ - _themes/sphinx_rtd_theme/__init__.py \ - _themes/sphinx_rtd_theme/breadcrumbs.html \ _themes/sphinx_rtd_theme/footer.html \ - _themes/sphinx_rtd_theme/layout.html \ + _themes/sphinx_rtd_theme/theme.conf \ _themes/sphinx_rtd_theme/layout_old.html \ + _themes/sphinx_rtd_theme/__init__.py \ + _themes/sphinx_rtd_theme/layout.html \ _themes/sphinx_rtd_theme/search.html \ + _themes/sphinx_rtd_theme/breadcrumbs.html \ + _themes/sphinx_rtd_theme/versions.html \ _themes/sphinx_rtd_theme/searchbox.html \ - _themes/sphinx_rtd_theme/static/css/badge_only.css \ - _themes/sphinx_rtd_theme/static/css/theme.css \ _themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf \ - _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot \ _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg \ - _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf \ _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff \ + _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot \ + _themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf \ _themes/sphinx_rtd_theme/static/js/theme.js \ - _themes/sphinx_rtd_theme/theme.conf \ - _themes/sphinx_rtd_theme/versions.html \ - $(man_MANS) \ - bash_completion/nghttp \ - bash_completion/nghttpd \ - bash_completion/nghttpx \ - bash_completion/h2load + _themes/sphinx_rtd_theme/static/css/theme.css \ + _themes/sphinx_rtd_theme/static/css/badge_only.css \ + $(man_MANS) # Makefile for Sphinx documentation @@ -598,6 +423,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -643,10 +469,6 @@ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ asio_http2.h.rst: $(top_builddir)/config.status $(srcdir)/asio_http2.h.rst.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -asio_http2_server.h.rst: $(top_builddir)/config.status $(srcdir)/asio_http2_server.h.rst.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -asio_http2_client.h.rst: $(top_builddir)/config.status $(srcdir)/asio_http2_client.h.rst.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ contribute.rst: $(top_builddir)/config.status $(srcdir)/contribute.rst.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ @@ -784,9 +606,7 @@ dvi-am: -html: html-am - -html-am: html-local +html-am: info: info-am @@ -844,19 +664,17 @@ .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ - distclean-libtool distdir dvi dvi-am html html-am html-local \ - info info-am install install-am install-data install-data-am \ - install-dvi install-dvi-am install-exec install-exec-am \ - install-html install-html-am install-info install-info-am \ - install-man install-man1 install-pdf install-pdf-am install-ps \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man1 install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags-am uninstall uninstall-am uninstall-man \ uninstall-man1 -.PRECIOUS: Makefile - .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest @@ -879,22 +697,16 @@ @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 \ - $(top_srcdir)/lib/includes/nghttp2/nghttp2.h - for i in $(RST_FILES); do [ -e $(builddir)/$$i ] || cp $(srcdir)/$$i $(builddir); done +apiref.rst: $(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \ + $(top_builddir)/lib/includes/nghttp2/nghttp2.h $(PYTHON) $(top_srcdir)/doc/mkapiref.py \ - apiref.rst macros.rst enums.rst types.rst . $^ - -$(APIDOCS): apiref.rst + --header $(top_srcdir)/doc/apiref-header.rst $^ > $@ clean-local: - [ $(srcdir) = $(builddir) ] || for i in $(RST_FILES); do [ -e $(builddir)/$$i ] && rm $(builddir)/$$i; done - -rm -f apiref.rst - -rm -f $(APIDOCS) + -rm apiref.rst -rm -rf $(BUILDDIR)/* -html-local: apiref.rst +html: apiref.rst $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -966,7 +778,7 @@ @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." -man: apiref.rst +man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." diff -Nru nghttp2-1.13.0/doc/mkapiref.py nghttp2-0.6.7/doc/mkapiref.py --- nghttp2-1.13.0/doc/mkapiref.py 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/mkapiref.py 2014-11-30 14:15:07.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # nghttp2 - HTTP/2 C Library # Copyright (c) 2012 Tatsuhiro Tsujikawa @@ -24,24 +23,20 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # Generates API reference from C source code. - -from __future__ import unicode_literals from __future__ import print_function # At least python 2.6 is required -import re, sys, argparse, os.path +import re, sys, argparse 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): - out.write('.. {}:: {}\n'.format(self.domain, self.name)) - out.write('\n') + print('''.. {}:: {}'''.format(self.domain, self.name)) + print('') for line in self.content: - out.write(' {}\n'.format(line)) + print(' {}'.format(line)) class StructDoc: def __init__(self, name, content, members, member_domain): @@ -52,17 +47,17 @@ def write(self, out): if self.name: - out.write('.. type:: {}\n'.format(self.name)) - out.write('\n') + print('''.. type:: {}'''.format(self.name)) + print('') for line in self.content: - out.write(' {}\n'.format(line)) - out.write('\n') + print(' {}'.format(line)) + print('') for name, content in self.members: - out.write(' .. {}:: {}\n'.format(self.member_domain, name)) - out.write('\n') + print(''' .. {}:: {}'''.format(self.member_domain, name)) + print('') for line in content: - out.write(' {}\n'.format(line)) - out.write('\n') + print(''' {}'''.format(line)) + print('') class MacroDoc: def __init__(self, name, content): @@ -70,10 +65,10 @@ self.content = content def write(self, out): - out.write('''.. macro:: {}\n'''.format(self.name)) - out.write('\n') + print('''.. macro:: {}'''.format(self.name)) + print('') for line in self.content: - out.write(' {}\n'.format(line)) + print(' {}'.format(line)) def make_api_ref(infiles): macros = [] @@ -98,65 +93,19 @@ 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)] - -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 * - -'''.format(funcname=doc.funcname, secul='='*len(doc.funcname))) - doc.write(f) + 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 process_macro(infile): content = read_content(infile) @@ -225,7 +174,6 @@ 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): @@ -251,30 +199,12 @@ if __name__ == '__main__': parser = argparse.ArgumentParser(description="Generate API reference") - 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('--header', type=argparse.FileType('r'), + help='header inserted at the top of the page') parser.add_argument('files', nargs='+', type=argparse.FileType('r'), help='source file') args = parser.parse_args() - macros = [] - enums = [] - types = [] - funcs = [] + if args.header: + print(args.header.read()) for infile in 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) + make_api_ref(args.files) diff -Nru nghttp2-1.13.0/doc/nghttp.1 nghttp2-0.6.7/doc/nghttp.1 --- nghttp2-1.13.0/doc/nghttp.1 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp.1 2014-11-30 14:15:07.000000000 +0000 @@ -1,309 +1,123 @@ -.\" Man page generated from reStructuredText. -. -.TH "NGHTTP" "1" "Jul 21, 2016" "1.13.0" "nghttp2" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.4. +.TH NGHTTP "1" "November 2014" "nghttp nghttp2/0.6.7" "User Commands" .SH NAME -nghttp \- HTTP/2 client -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. +nghttp \- HTTP/2 experimental client .SH SYNOPSIS -.sp -\fBnghttp\fP [OPTIONS]... ... +.B nghttp +[\fI\,OPTIONS\/\fR]... \fI\,\/\fR... .SH DESCRIPTION -.sp -HTTP/2 client -.INDENT 0.0 +HTTP/2 experimental client .TP -.B + Specify URI to access. -.UNINDENT .SH OPTIONS -.INDENT 0.0 .TP -.B \-v, \-\-verbose -Print debug information such as reception and -transmission of frames and name/value pairs. Specifying -this option multiple times increases verbosity. -.UNINDENT -.INDENT 0.0 +\fB\-v\fR, \fB\-\-verbose\fR +Print debug information such as reception and +transmission of frames and name/value pairs. +Specifying this option multiple times increases +verbosity. .TP -.B \-n, \-\-null\-out +\fB\-n\fR, \fB\-\-null\-out\fR Discard downloaded data. -.UNINDENT -.INDENT 0.0 .TP -.B \-O, \-\-remote\-name -Save download data in the current directory. The -filename is derived from URI. If URI ends with \(aq\fI/\fP\(aq, -\(aqindex.html\(aq is used as a filename. Not implemented -yet. -.UNINDENT -.INDENT 0.0 -.TP -.B \-t, \-\-timeout= -Timeout each request after . Set 0 to disable -timeout. -.UNINDENT -.INDENT 0.0 -.TP -.B \-w, \-\-window\-bits= -Sets the stream level initial window size to 2**\-1. -.UNINDENT -.INDENT 0.0 +\fB\-O\fR, \fB\-\-remote\-name\fR +Save download data in the current directory. The +filename is dereived from URI. If URI ends with +\&'/', 'index.html' is used as a filename. Not +implemented yet. .TP -.B \-W, \-\-connection\-window\-bits= -Sets the connection level initial window size to +\fB\-t\fR, \fB\-\-timeout=\fR +Timeout each request after seconds. +.TP +\fB\-w\fR, \fB\-\-window\-bits=\fR +Sets the stream level initial window size to +2**\-1. +.TP +\fB\-W\fR, \fB\-\-connection\-window\-bits=\fR +Sets the connection level initial window size to 2**\-1. -.UNINDENT -.INDENT 0.0 .TP -.B \-a, \-\-get\-assets -Download assets such as stylesheets, images and script -files linked from the downloaded resource. Only links -whose origins are the same with the linking resource -will be downloaded. nghttp prioritizes resources using -HTTP/2 dependency based priority. The priority order, -from highest to lowest, is html itself, css, javascript -and images. -.UNINDENT -.INDENT 0.0 +\fB\-a\fR, \fB\-\-get\-assets\fR +Download assets such as stylesheets, images and +script files linked from the downloaded resource. +Only links whose origins are the same with the +linking resource will be downloaded. nghttp +prioritizes resources using HTTP/2 dependency +based priority. The priority order, from highest +to lowest, is html itself, css, javascript and +images. .TP -.B \-s, \-\-stat +\fB\-s\fR, \fB\-\-stat\fR Print statistics. -.UNINDENT -.INDENT 0.0 .TP -.B \-H, \-\-header=
-Add a header to the requests. Example: \fI\%\-H\fP\(aq:method: PUT\(aq -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-trailer=
-Add a trailer header to the requests.
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. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-cert= -Use the specified client certificate file. The file -must be in PEM format. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-key= -Use the client private key file. The file must be in -PEM format. -.UNINDENT -.INDENT 0.0 -.TP -.B \-d, \-\-data= -Post FILE to server. If \(aq\-\(aq is given, data will be read -from stdin. -.UNINDENT -.INDENT 0.0 -.TP -.B \-m, \-\-multiply= -Request each URI times. By default, same URI is not -requested twice. This option disables it too. -.UNINDENT -.INDENT 0.0 -.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 -HTTP upgrade request is performed with OPTIONS method. -.UNINDENT -.INDENT 0.0 -.TP -.B \-p, \-\-weight= -Sets priority group weight. The valid value range is -[1, 256], inclusive. -.sp -Default: \fB16\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-M, \-\-peer\-max\-concurrent\-streams= -Use as SETTINGS_MAX_CONCURRENT_STREAMS value of -remote endpoint as if it is received in SETTINGS frame. -.sp -Default: \fB100\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-c, \-\-header\-table\-size= -Specify decoder header table size. If this option is -used multiple times, and the minimum value among the -given values except for last one is strictly less than -the last value, that minimum value is set in SETTINGS -frame payload before the last value, to simulate -multiple header table size change. -.UNINDENT -.INDENT 0.0 -.TP -.B \-b, \-\-padding= -Add at most bytes to a frame payload as padding. -Specify 0 to disable padding. -.UNINDENT -.INDENT 0.0 -.TP -.B \-r, \-\-har= -Output HTTP transactions in HAR format. If \(aq\-\(aq -is given, data is written to stdout. -.UNINDENT -.INDENT 0.0 +\fB\-H\fR, \fB\-\-header=\fR
+Add a header to the requests. Example: +\fB\-H\fR':method: PUT' +.TP +\fB\-\-cert=\fR +Use the specified client certificate file. The +file must be in PEM format. +.TP +\fB\-\-key=\fR +Use the client private key file. The file must +be in PEM format. +.TP +\fB\-d\fR, \fB\-\-data=\fR +Post FILE to server. If '\-' is given, data will +be read from stdin. +.TP +\fB\-m\fR, \fB\-\-multiply=\fR Request each URI times. +By default, same URI +is not requested twice. This option disables it +too. +.TP +\fB\-u\fR, \fB\-\-upgrade\fR +Perform HTTP Upgrade for HTTP/2. This option is +ignored if the request URI has https scheme. If +\fB\-d\fR is used, the HTTP upgrade request is performed +with OPTIONS method. +.TP +\fB\-p\fR, \fB\-\-weight=\fR +Sets priority group weight. The valid value +range is [1, 256], inclusive. +Default: 16 +.TP +\fB\-M\fR, \fB\-\-peer\-max\-concurrent\-streams=\fR +Use as SETTINGS_MAX_CONCURRENT_STREAMS value +of remote endpoint as if it is received in +SETTINGS frame. The default is large enough as +it is seen as unlimited. +.TP +\fB\-c\fR, \fB\-\-header\-table\-size=\fR +Specify decoder header table size. +.TP +\fB\-b\fR, \fB\-\-padding=\fR +Add at most bytes to a frame payload as +padding. Specify 0 to disable padding. +.TP +\fB\-r\fR, \fB\-\-har=\fR +Output HTTP transactions in HAR format. +If '\-' is given, data is written to stdout. .TP -.B \-\-color +\fB\-\-color\fR Force colored log output. -.UNINDENT -.INDENT 0.0 .TP -.B \-\-continuation +\fB\-\-continuation\fR Send large header to test CONTINUATION. -.UNINDENT -.INDENT 0.0 .TP -.B \-\-no\-content\-length -Don\(aqt send content\-length header field. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-no\-dep -Don\(aqt send dependency based priority hint to server. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-hexdump -Display the incoming traffic in hexadecimal (Canonical -hex+ASCII display). If SSL/TLS is used, decrypted data -are used. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-no\-push -Disable server push. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-max\-concurrent\-streams= -The number of concurrent pushed streams this client -accepts. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-expect\-continue -Perform an Expect/Continue handshake: wait to send DATA -(up to a short timeout) until the server sends a 100 -Continue interim response. This option is ignored unless -combined with the \fI\%\-d\fP option. -.UNINDENT -.INDENT 0.0 +\fB\-\-no\-content\-length\fR +Don't send content\-length header field. +.TP +\fB\-\-no\-dep\fR +Don't send dependency based priority hint to +server. .TP -.B \-\-version +\fB\-\-version\fR Display version information and exit. -.UNINDENT -.INDENT 0.0 .TP -.B \-h, \-\-help +\fB\-h\fR, \fB\-\-help\fR Display this help and exit. -.UNINDENT -.sp -The 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 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 -\fBnghttpd(1)\fP, \fBnghttpx(1)\fP, \fBh2load(1)\fP -.SH AUTHOR -Tatsuhiro Tsujikawa -.SH COPYRIGHT -2012, 2015, 2016, Tatsuhiro Tsujikawa -.\" Generated by docutils manpage writer. -. +.SH "SEE ALSO" + +nghttpd(1), nghttpx(1), h2load(1) diff -Nru nghttp2-1.13.0/doc/nghttp.1.rst nghttp2-0.6.7/doc/nghttp.1.rst --- nghttp2-1.13.0/doc/nghttp.1.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp.1.rst 2014-11-30 14:15:07.000000000 +0000 @@ -1,22 +1,23 @@ - -.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY. +.. DO NOT MODIFY THIS FILE! It was generated by man2rst.py .. program:: nghttp nghttp(1) ========= +NAME +---- +nghttp - HTTP/2 experimental client + SYNOPSIS -------- - **nghttp** [OPTIONS]... ... DESCRIPTION ----------- +HTTP/2 experimental client -HTTP/2 client - -.. describe:: +.. option:: URI Specify URI to access. @@ -25,229 +26,162 @@ .. option:: -v, --verbose - Print debug information such as reception and - transmission of frames and name/value pairs. Specifying - this option multiple times increases verbosity. + + Print debug information such as reception and + transmission of frames and name/value pairs. + Specifying this option multiple times increases + verbosity. .. option:: -n, --null-out + Discard downloaded data. .. option:: -O, --remote-name - Save download data in the current directory. The - filename is derived from URI. If URI ends with '*/*', - 'index.html' is used as a filename. Not implemented - yet. + + Save download data in the current directory. The + filename is dereived from URI. If URI ends with + '/', 'index.html' is used as a filename. Not + implemented yet. -.. option:: -t, --timeout= +.. option:: -t, --timeout= - Timeout each request after . Set 0 to disable - timeout. + + Timeout each request after seconds. .. option:: -w, --window-bits= - Sets the stream level initial window size to 2\*\*-1. + + Sets the stream level initial window size to + 2\*\*-1. .. option:: -W, --connection-window-bits= - Sets the connection level initial window size to + + Sets the connection level initial window size to 2\*\*-1. .. option:: -a, --get-assets - Download assets such as stylesheets, images and script - files linked from the downloaded resource. Only links - whose origins are the same with the linking resource - will be downloaded. nghttp prioritizes resources using - HTTP/2 dependency based priority. The priority order, - from highest to lowest, is html itself, css, javascript - and images. + + Download assets such as stylesheets, images and + script files linked from the downloaded resource. + Only links whose origins are the same with the + linking resource will be downloaded. nghttp + prioritizes resources using HTTP/2 dependency + based priority. The priority order, from highest + to lowest, is html itself, css, javascript and + images. .. option:: -s, --stat + Print statistics. .. option:: -H, --header=
- Add a header to the requests. Example: :option:`-H`\':method: PUT' - -.. option:: --trailer=
- - Add a trailer header to the requests.
must not - include pseudo header field (header field name starting - with ':'). To send trailer, one must use :option:`-d` option to - send request body. Example: :option:`--trailer` 'foo: bar'. + + Add a header to the requests. Example: + -H':method: PUT' .. option:: --cert= - Use the specified client certificate file. The file - must be in PEM format. + + Use the specified client certificate file. The + file must be in PEM format. .. option:: --key= - Use the client private key file. The file must be in - PEM format. - -.. option:: -d, --data= - - Post FILE to server. If '-' is given, data will be read - from stdin. + + Use the client private key file. The file must + be in PEM format. + +.. option:: -d, --data= + + + Post FILE to server. If '-' is given, data will + be read from stdin. .. option:: -m, --multiply= - Request each URI times. By default, same URI is not - requested twice. This option disables it too. + Request each URI times. + By default, same URI + is not requested twice. This option disables it + too. .. option:: -u, --upgrade - Perform HTTP Upgrade for HTTP/2. This option is ignored - if the request URI has https scheme. If :option:`-d` is used, the - HTTP upgrade request is performed with OPTIONS method. + + Perform HTTP Upgrade for HTTP/2. This option is + ignored if the request URI has https scheme. If + :option:`-d` is used, the HTTP upgrade request is performed + with OPTIONS method. .. option:: -p, --weight= - Sets priority group weight. The valid value range is - [1, 256], inclusive. - - Default: ``16`` + + Sets priority group weight. The valid value + range is [1, 256], inclusive. + Default: 16 .. option:: -M, --peer-max-concurrent-streams= - Use as SETTINGS_MAX_CONCURRENT_STREAMS value of - remote endpoint as if it is received in SETTINGS frame. + + Use as SETTINGS_MAX_CONCURRENT_STREAMS value + of remote endpoint as if it is received in + SETTINGS frame. The default is large enough as + it is seen as unlimited. - Default: ``100`` +.. option:: -c, --header-table-size= -.. option:: -c, --header-table-size= - - Specify decoder header table size. If this option is - used multiple times, and the minimum value among the - given values except for last one is strictly less than - the last value, that minimum value is set in SETTINGS - frame payload before the last value, to simulate - multiple header table size change. + + Specify decoder header table size. .. option:: -b, --padding= - Add at most bytes to a frame payload as padding. - Specify 0 to disable padding. - -.. option:: -r, --har= - - Output HTTP transactions in HAR format. If '-' - is given, data is written to stdout. + + Add at most bytes to a frame payload as + padding. Specify 0 to disable padding. + +.. option:: -r, --har= + + + Output HTTP transactions in HAR format. + If '-' is given, data is written to stdout. .. option:: --color + Force colored log output. .. option:: --continuation + Send large header to test CONTINUATION. .. option:: --no-content-length + Don't send content-length header field. .. option:: --no-dep - Don't send dependency based priority hint to server. - -.. 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:: --max-concurrent-streams= - - The number of concurrent pushed streams this client - accepts. - -.. option:: --expect-continue - - Perform an Expect/Continue handshake: wait to send DATA - (up to a short timeout) until the server sends a 100 - Continue interim response. This option is ignored unless - combined with the :option:`-d` option. + + Don't send dependency based priority hint to + server. .. option:: --version + Display version information and exit. .. option:: -h, --help + Display this help and exit. - - -The argument is an integer and an optional unit (e.g., 10K is -10 * 1024). Units are K, M and G (powers of 1024). - -The 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: - -.. code-block:: text - - +-----+ - |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 -------- -:manpage:`nghttpd(1)`, :manpage:`nghttpx(1)`, :manpage:`h2load(1)` +nghttpd(1), nghttpx(1), h2load(1) diff -Nru nghttp2-1.13.0/doc/nghttp2_check_header_name.rst nghttp2-0.6.7/doc/nghttp2_check_header_name.rst --- nghttp2-1.13.0/doc/nghttp2_check_header_name.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_check_header_name.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ - -nghttp2_check_header_name -========================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_check_header_name(const uint8_t *name, size_t len) - - - Returns nonzero if HTTP header field name *name* of length *len* is - valid according to http://tools.ietf.org/html/rfc7230#section-3.2 - - Because this is a header field name in HTTP2, the upper cased alphabet - is treated as error. diff -Nru nghttp2-1.13.0/doc/nghttp2_check_header_value.rst nghttp2-0.6.7/doc/nghttp2_check_header_value.rst --- nghttp2-1.13.0/doc/nghttp2_check_header_value.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_check_header_value.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_check_header_value -========================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_check_header_value(const uint8_t *value, size_t len) - - - Returns nonzero if HTTP header field value *value* of length *len* - is valid according to - http://tools.ietf.org/html/rfc7230#section-3.2 diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_deflate_bound.rst nghttp2-0.6.7/doc/nghttp2_hd_deflate_bound.rst --- nghttp2-1.13.0/doc/nghttp2_hd_deflate_bound.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_deflate_bound.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_hd_deflate_bound -======================== - -Synopsis --------- - -*#include * - -.. function:: size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, const nghttp2_nv *nva, size_t nvlen) - - - Returns an upper bound on the compressed size after deflation of - *nva* of length *nvlen*. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_deflate_change_table_size.rst nghttp2-0.6.7/doc/nghttp2_hd_deflate_change_table_size.rst --- nghttp2-1.13.0/doc/nghttp2_hd_deflate_change_table_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_deflate_change_table_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ - -nghttp2_hd_deflate_change_table_size -==================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater, size_t settings_hd_table_bufsize_max) - - - Changes header table size of the *deflater* to - *settings_hd_table_bufsize_max* bytes. This may trigger eviction - in the dynamic table. - - The *settings_hd_table_bufsize_max* should be the value received in - SETTINGS_HEADER_TABLE_SIZE. - - The deflater never uses more memory than - ``deflate_hd_table_bufsize_max`` bytes specified in - `nghttp2_hd_deflate_new()`. Therefore, if - *settings_hd_table_bufsize_max* > ``deflate_hd_table_bufsize_max``, - resulting maximum table size becomes - ``deflate_hd_table_bufsize_max``. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_deflate_del.rst nghttp2-0.6.7/doc/nghttp2_hd_deflate_del.rst --- nghttp2-1.13.0/doc/nghttp2_hd_deflate_del.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_deflate_del.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_hd_deflate_del -====================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) - - - Deallocates any resources allocated for *deflater*. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_deflate_get_dynamic_table_size.rst nghttp2-0.6.7/doc/nghttp2_hd_deflate_get_dynamic_table_size.rst --- nghttp2-1.13.0/doc/nghttp2_hd_deflate_get_dynamic_table_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_deflate_get_dynamic_table_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_hd_deflate_get_dynamic_table_size -========================================= - -Synopsis --------- - -*#include * - -.. function:: size_t nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater) - - - Returns the used dynamic table size, including the overhead 32 - bytes per entry described in RFC 7541. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_deflate_get_max_dynamic_table_size.rst nghttp2-0.6.7/doc/nghttp2_hd_deflate_get_max_dynamic_table_size.rst --- nghttp2-1.13.0/doc/nghttp2_hd_deflate_get_max_dynamic_table_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_deflate_get_max_dynamic_table_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_hd_deflate_get_max_dynamic_table_size -============================================= - -Synopsis --------- - -*#include * - -.. function:: size_t nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater) - - - Returns the maximum dynamic table size. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_deflate_get_num_table_entries.rst nghttp2-0.6.7/doc/nghttp2_hd_deflate_get_num_table_entries.rst --- nghttp2-1.13.0/doc/nghttp2_hd_deflate_get_num_table_entries.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_deflate_get_num_table_entries.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_hd_deflate_get_num_table_entries -======================================== - -Synopsis --------- - -*#include * - -.. function:: size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater) - - - Returns the number of entries that header table of *deflater* - contains. This is the sum of the number of static table and - dynamic table, so the return value is at least 61. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_deflate_get_table_entry.rst nghttp2-0.6.7/doc/nghttp2_hd_deflate_get_table_entry.rst --- nghttp2-1.13.0/doc/nghttp2_hd_deflate_get_table_entry.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_deflate_get_table_entry.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - -nghttp2_hd_deflate_get_table_entry -================================== - -Synopsis --------- - -*#include * - -.. function:: const nghttp2_nv * nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx) - - - Returns the table entry denoted by *idx* from header table of - *deflater*. The *idx* is 1-based, and idx=1 returns first entry of - static table. idx=62 returns first entry of dynamic table if it - exists. Specifying idx=0 is error, and this function returns NULL. - If *idx* is strictly greater than the number of entries the tables - contain, this function returns NULL. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_deflate_hd.rst nghttp2-0.6.7/doc/nghttp2_hd_deflate_hd.rst --- nghttp2-1.13.0/doc/nghttp2_hd_deflate_hd.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_deflate_hd.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ - -nghttp2_hd_deflate_hd -===================== - -Synopsis --------- - -*#include * - -.. function:: ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, size_t buflen, const nghttp2_nv *nva, size_t nvlen) - - - Deflates the *nva*, which has the *nvlen* name/value pairs, into - the *buf* of length *buflen*. - - If *buf* is not large enough to store the deflated header block, - this function fails with :macro:`NGHTTP2_ERR_INSUFF_BUFSIZE`. The - caller should use `nghttp2_hd_deflate_bound()` to know the upper - bound of buffer size required to deflate given header name/value - pairs. - - Once this function fails, subsequent call of this function always - returns :macro:`NGHTTP2_ERR_HEADER_COMP`. - - After this function returns, it is safe to delete the *nva*. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_HEADER_COMP` - Deflation process has failed. - :macro:`NGHTTP2_ERR_INSUFF_BUFSIZE` - The provided *buflen* size is too small to hold the output. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_deflate_new2.rst nghttp2-0.6.7/doc/nghttp2_hd_deflate_new2.rst --- nghttp2-1.13.0/doc/nghttp2_hd_deflate_new2.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_deflate_new2.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ - -nghttp2_hd_deflate_new2 -======================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr, size_t deflate_hd_table_bufsize_max, nghttp2_mem *mem) - - - Like `nghttp2_hd_deflate_new()`, but with additional custom memory - allocator specified in the *mem*. - - The *mem* can be ``NULL`` and the call is equivalent to - `nghttp2_hd_deflate_new()`. - - This function does not take ownership *mem*. The application is - responsible for freeing *mem*. - - The library code does not refer to *mem* pointer after this - function returns, so the application can safely free it. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_deflate_new.rst nghttp2-0.6.7/doc/nghttp2_hd_deflate_new.rst --- nghttp2-1.13.0/doc/nghttp2_hd_deflate_new.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_deflate_new.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ - -nghttp2_hd_deflate_new -====================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, size_t deflate_hd_table_bufsize_max) - - - Initializes *\*deflater_ptr* for deflating name/values pairs. - - The *deflate_hd_table_bufsize_max* is the upper bound of header - table size the deflater will use. - - If this function fails, *\*deflater_ptr* is left untouched. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_change_table_size.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_change_table_size.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_change_table_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_change_table_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ - -nghttp2_hd_inflate_change_table_size -==================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater, size_t settings_hd_table_bufsize_max) - - - Changes header table size in the *inflater*. This may trigger - eviction in the dynamic table. - - The *settings_hd_table_bufsize_max* should be the value transmitted - in SETTINGS_HEADER_TABLE_SIZE. - - This function must not be called while header block is being - inflated. In other words, this function must be called after - initialization of *inflater*, but before calling - `nghttp2_hd_inflate_hd2()`, or after - `nghttp2_hd_inflate_end_headers()`. Otherwise, - `NGHTTP2_ERR_INVALID_STATE` was returned. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_STATE` - The function is called while header block is being inflated. - Probably, application missed to call - `nghttp2_hd_inflate_end_headers()`. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_del.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_del.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_del.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_del.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_hd_inflate_del -====================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater) - - - Deallocates any resources allocated for *inflater*. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_end_headers.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_end_headers.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_end_headers.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_end_headers.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ - -nghttp2_hd_inflate_end_headers -============================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) - - - Signals the end of decompression for one header block. - - This function returns 0 if it succeeds. Currently this function - always succeeds. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_get_dynamic_table_size.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_get_dynamic_table_size.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_get_dynamic_table_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_get_dynamic_table_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_hd_inflate_get_dynamic_table_size -========================================= - -Synopsis --------- - -*#include * - -.. function:: size_t nghttp2_hd_inflate_get_dynamic_table_size(nghttp2_hd_inflater *inflater) - - - Returns the used dynamic table size, including the overhead 32 - bytes per entry described in RFC 7541. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_get_max_dynamic_table_size.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_get_max_dynamic_table_size.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_get_max_dynamic_table_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_get_max_dynamic_table_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_hd_inflate_get_max_dynamic_table_size -============================================= - -Synopsis --------- - -*#include * - -.. function:: size_t nghttp2_hd_inflate_get_max_dynamic_table_size(nghttp2_hd_inflater *inflater) - - - Returns the maximum dynamic table size. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_get_num_table_entries.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_get_num_table_entries.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_get_num_table_entries.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_get_num_table_entries.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_hd_inflate_get_num_table_entries -======================================== - -Synopsis --------- - -*#include * - -.. function:: size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater) - - - Returns the number of entries that header table of *inflater* - contains. This is the sum of the number of static table and - dynamic table, so the return value is at least 61. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_get_table_entry.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_get_table_entry.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_get_table_entry.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_get_table_entry.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - -nghttp2_hd_inflate_get_table_entry -================================== - -Synopsis --------- - -*#include * - -.. function:: const nghttp2_nv * nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx) - - - Returns the table entry denoted by *idx* from header table of - *inflater*. The *idx* is 1-based, and idx=1 returns first entry of - static table. idx=62 returns first entry of dynamic table if it - exists. Specifying idx=0 is error, and this function returns NULL. - If *idx* is strictly greater than the number of entries the tables - contain, this function returns NULL. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_hd2.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_hd2.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_hd2.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_hd2.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ - -nghttp2_hd_inflate_hd2 -====================== - -Synopsis --------- - -*#include * - -.. function:: ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, int *inflate_flags, const uint8_t *in, size_t inlen, int in_final) - - - Inflates name/value block stored in *in* with length *inlen*. This - function performs decompression. For each successful emission of - header name/value pair, :macro:`NGHTTP2_HD_INFLATE_EMIT` is set in - *\*inflate_flags* and name/value pair is assigned to the *nv_out* - and the function returns. The caller must not free the members of - *nv_out*. - - The *nv_out* may include pointers to the memory region in the *in*. - The caller must retain the *in* while the *nv_out* is used. - - The application should call this function repeatedly until the - ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and - return value is non-negative. This means the all input values are - processed successfully. Then the application must call - `nghttp2_hd_inflate_end_headers()` to prepare for the next header - block input. - - The caller can feed complete compressed header block. It also can - feed it in several chunks. The caller must set *in_final* to - nonzero if the given input is the last block of the compressed - header. - - This function returns the number of bytes processed if it succeeds, - or one of the following negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_HEADER_COMP` - Inflation process has failed. - :macro:`NGHTTP2_ERR_BUFFER_ERROR` - The header field name or value is too large. - - Example follows:: - - int inflate_header_block(nghttp2_hd_inflater *hd_inflater, - uint8_t *in, size_t inlen, int final) - { - ssize_t rv; - - for(;;) { - nghttp2_nv nv; - int inflate_flags = 0; - - rv = nghttp2_hd_inflate_hd2(hd_inflater, &nv, &inflate_flags, - in, inlen, final); - - if(rv < 0) { - fprintf(stderr, "inflate failed with error code %zd", rv); - return -1; - } - - in += rv; - inlen -= rv; - - if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { - fwrite(nv.name, nv.namelen, 1, stderr); - fprintf(stderr, ": "); - fwrite(nv.value, nv.valuelen, 1, stderr); - fprintf(stderr, "\n"); - } - if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) { - nghttp2_hd_inflate_end_headers(hd_inflater); - break; - } - if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && - inlen == 0) { - break; - } - } - - return 0; - } - diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_hd.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_hd.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_hd.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_hd.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ - -nghttp2_hd_inflate_hd -===================== - -Synopsis --------- - -*#include * - -.. function:: ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, int *inflate_flags, uint8_t *in, size_t inlen, int in_final) - - - .. warning:: - - Deprecated. Use `nghttp2_hd_inflate_hd2()` instead. - - Inflates name/value block stored in *in* with length *inlen*. This - function performs decompression. For each successful emission of - header name/value pair, :macro:`NGHTTP2_HD_INFLATE_EMIT` is set in - *\*inflate_flags* and name/value pair is assigned to the *nv_out* - and the function returns. The caller must not free the members of - *nv_out*. - - The *nv_out* may include pointers to the memory region in the *in*. - The caller must retain the *in* while the *nv_out* is used. - - The application should call this function repeatedly until the - ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and - return value is non-negative. This means the all input values are - processed successfully. Then the application must call - `nghttp2_hd_inflate_end_headers()` to prepare for the next header - block input. - - The caller can feed complete compressed header block. It also can - feed it in several chunks. The caller must set *in_final* to - nonzero if the given input is the last block of the compressed - header. - - This function returns the number of bytes processed if it succeeds, - or one of the following negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_HEADER_COMP` - Inflation process has failed. - :macro:`NGHTTP2_ERR_BUFFER_ERROR` - The header field name or value is too large. - - Example follows:: - - int inflate_header_block(nghttp2_hd_inflater *hd_inflater, - uint8_t *in, size_t inlen, int final) - { - ssize_t rv; - - for(;;) { - nghttp2_nv nv; - int inflate_flags = 0; - - rv = nghttp2_hd_inflate_hd(hd_inflater, &nv, &inflate_flags, - in, inlen, final); - - if(rv < 0) { - fprintf(stderr, "inflate failed with error code %zd", rv); - return -1; - } - - in += rv; - inlen -= rv; - - if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { - fwrite(nv.name, nv.namelen, 1, stderr); - fprintf(stderr, ": "); - fwrite(nv.value, nv.valuelen, 1, stderr); - fprintf(stderr, "\n"); - } - if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) { - nghttp2_hd_inflate_end_headers(hd_inflater); - break; - } - if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && - inlen == 0) { - break; - } - } - - return 0; - } - diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_new2.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_new2.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_new2.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_new2.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ - -nghttp2_hd_inflate_new2 -======================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr, nghttp2_mem *mem) - - - Like `nghttp2_hd_inflate_new()`, but with additional custom memory - allocator specified in the *mem*. - - The *mem* can be ``NULL`` and the call is equivalent to - `nghttp2_hd_inflate_new()`. - - This function does not take ownership *mem*. The application is - responsible for freeing *mem*. - - The library code does not refer to *mem* pointer after this - function returns, so the application can safely free it. diff -Nru nghttp2-1.13.0/doc/nghttp2_hd_inflate_new.rst nghttp2-0.6.7/doc/nghttp2_hd_inflate_new.rst --- nghttp2-1.13.0/doc/nghttp2_hd_inflate_new.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_hd_inflate_new.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ - -nghttp2_hd_inflate_new -====================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr) - - - Initializes *\*inflater_ptr* for inflating name/values pairs. - - If this function fails, *\*inflater_ptr* is left untouched. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_http2_strerror.rst nghttp2-0.6.7/doc/nghttp2_http2_strerror.rst --- nghttp2-1.13.0/doc/nghttp2_http2_strerror.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_http2_strerror.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ - -nghttp2_http2_strerror -====================== - -Synopsis --------- - -*#include * - -.. function:: const char *nghttp2_http2_strerror(uint32_t error_code) - - - Returns string representation of HTTP/2 error code *error_code* - (e.g., ``PROTOCOL_ERROR`` is returned if ``error_code == - NGHTTP2_PROTOCOL_ERROR``). If string representation is unknown for - given *error_code*, this function returns string ``unknown``. diff -Nru nghttp2-1.13.0/doc/nghttp2_is_fatal.rst nghttp2-0.6.7/doc/nghttp2_is_fatal.rst --- nghttp2-1.13.0/doc/nghttp2_is_fatal.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_is_fatal.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_is_fatal -================ - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_is_fatal(int lib_error_code) - - - Returns nonzero if the :type:`nghttp2_error` library error code - *lib_error* is fatal. diff -Nru nghttp2-1.13.0/doc/nghttp2_nv_compare_name.rst nghttp2-0.6.7/doc/nghttp2_nv_compare_name.rst --- nghttp2-1.13.0/doc/nghttp2_nv_compare_name.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_nv_compare_name.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ - -nghttp2_nv_compare_name -======================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs) - - - Compares ``lhs->name`` of length ``lhs->namelen`` bytes and - ``rhs->name`` of length ``rhs->namelen`` bytes. Returns negative - integer if ``lhs->name`` is found to be less than ``rhs->name``; or - returns positive integer if ``lhs->name`` is found to be greater - than ``rhs->name``; or returns 0 otherwise. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_del.rst nghttp2-0.6.7/doc/nghttp2_option_del.rst --- nghttp2-1.13.0/doc/nghttp2_option_del.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_del.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_option_del -================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_option_del(nghttp2_option *option) - - - Frees any resources allocated for *option*. If *option* is - ``NULL``, this function does nothing. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_new.rst nghttp2-0.6.7/doc/nghttp2_option_new.rst --- nghttp2-1.13.0/doc/nghttp2_option_new.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_new.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ - -nghttp2_option_new -================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_option_new(nghttp2_option **option_ptr) - - - Initializes *\*option_ptr* with default values. - - When the application finished using this object, it can use - `nghttp2_option_del()` to free its memory. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_set_builtin_recv_extension_type.rst nghttp2-0.6.7/doc/nghttp2_option_set_builtin_recv_extension_type.rst --- nghttp2-1.13.0/doc/nghttp2_option_set_builtin_recv_extension_type.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_set_builtin_recv_extension_type.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ - -nghttp2_option_set_builtin_recv_extension_type -============================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option, uint8_t type) - - - Sets extension frame type the application is willing to receive - using builtin handler. The *type* is the extension frame type to - receive, and must be strictly greater than 0x9. Otherwise, this - function does nothing. The application can call this function - multiple times to set more than one frame type to receive. The - application does not have to call this function if it just sends - extension frames. - - If same frame type is passed to both - `nghttp2_option_set_builtin_recv_extension_type()` and - `nghttp2_option_set_user_recv_extension_type()`, the latter takes - precedence. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_set_max_reserved_remote_streams.rst nghttp2-0.6.7/doc/nghttp2_option_set_max_reserved_remote_streams.rst --- nghttp2-1.13.0/doc/nghttp2_option_set_max_reserved_remote_streams.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_set_max_reserved_remote_streams.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ - -nghttp2_option_set_max_reserved_remote_streams -============================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option, uint32_t val) - - - RFC 7540 does not enforce any limit on the number of incoming - reserved streams (in RFC 7540 terms, streams in reserved (remote) - state). This only affects client side, since only server can push - streams. Malicious server can push arbitrary number of streams, - and make client's memory exhausted. This option can set the - maximum number of such incoming streams to avoid possible memory - exhaustion. If this option is set, and pushed streams are - automatically closed on reception, without calling user provided - callback, if they exceed the given limit. The default value is - 200. If session is configured as server side, this option has no - effect. Server can control the number of streams to push. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_set_max_send_header_block_length.rst nghttp2-0.6.7/doc/nghttp2_option_set_max_send_header_block_length.rst --- nghttp2-1.13.0/doc/nghttp2_option_set_max_send_header_block_length.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_set_max_send_header_block_length.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ - -nghttp2_option_set_max_send_header_block_length -=============================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_option_set_max_send_header_block_length(nghttp2_option *option, size_t val) - - - This option sets the maximum length of header block (a set of - header fields per one HEADERS frame) to send. The length of a - given set of header fields is calculated using - `nghttp2_hd_deflate_bound()`. The default value is 64KiB. If - application attempts to send header fields larger than this limit, - the transmission of the frame fails with error code - :macro:`NGHTTP2_ERR_FRAME_SIZE_ERROR`. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_set_no_auto_ping_ack.rst nghttp2-0.6.7/doc/nghttp2_option_set_no_auto_ping_ack.rst --- nghttp2-1.13.0/doc/nghttp2_option_set_no_auto_ping_ack.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_set_no_auto_ping_ack.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ - -nghttp2_option_set_no_auto_ping_ack -=================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option, int val) - - - This option prevents the library from sending PING frame with ACK - flag set automatically when PING frame without ACK flag set is - received. If this option is set to nonzero, the library won't send - PING frame with ACK flag set in the response for incoming PING - frame. The application can send PING frame with ACK flag set using - `nghttp2_submit_ping()` with :macro:`NGHTTP2_FLAG_ACK` as flags - parameter. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_set_no_auto_window_update.rst nghttp2-0.6.7/doc/nghttp2_option_set_no_auto_window_update.rst --- nghttp2-1.13.0/doc/nghttp2_option_set_no_auto_window_update.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_set_no_auto_window_update.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - -nghttp2_option_set_no_auto_window_update -======================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val) - - - This option prevents the library from sending WINDOW_UPDATE for a - connection automatically. If this option is set to nonzero, the - library won't send WINDOW_UPDATE for DATA until application calls - `nghttp2_session_consume()` to indicate the consumed amount of - data. Don't use `nghttp2_submit_window_update()` for this purpose. - By default, this option is set to zero. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_set_no_http_messaging.rst nghttp2-0.6.7/doc/nghttp2_option_set_no_http_messaging.rst --- nghttp2-1.13.0/doc/nghttp2_option_set_no_http_messaging.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_set_no_http_messaging.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - -nghttp2_option_set_no_http_messaging -==================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_option_set_no_http_messaging(nghttp2_option *option, int val) - - - By default, nghttp2 library enforces subset of HTTP Messaging rules - described in `HTTP/2 specification, section 8 - `_. See - :ref:`http-messaging` section for details. For those applications - who use nghttp2 library as non-HTTP use, give nonzero to *val* to - disable this enforcement. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_set_no_recv_client_magic.rst nghttp2-0.6.7/doc/nghttp2_option_set_no_recv_client_magic.rst --- nghttp2-1.13.0/doc/nghttp2_option_set_no_recv_client_magic.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_set_no_recv_client_magic.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ - -nghttp2_option_set_no_recv_client_magic -======================================= - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val) - - - By default, nghttp2 library, if configured as server, requires - first 24 bytes of client magic byte string (MAGIC). In most cases, - this will simplify the implementation of server. But sometimes - server may want to detect the application protocol based on first - few bytes on clear text communication. - - If this option is used with nonzero *val*, nghttp2 library does not - handle MAGIC. It still checks following SETTINGS frame. This - means that applications should deal with MAGIC by themselves. - - If this option is not used or used with zero value, if MAGIC does - not match :macro:`NGHTTP2_CLIENT_MAGIC`, `nghttp2_session_recv()` - and `nghttp2_session_mem_recv()` will return error - :macro:`NGHTTP2_ERR_BAD_CLIENT_MAGIC`, which is fatal error. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_set_peer_max_concurrent_streams.rst nghttp2-0.6.7/doc/nghttp2_option_set_peer_max_concurrent_streams.rst --- nghttp2-1.13.0/doc/nghttp2_option_set_peer_max_concurrent_streams.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_set_peer_max_concurrent_streams.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ - -nghttp2_option_set_peer_max_concurrent_streams -============================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option, uint32_t val) - - - This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of - remote endpoint as if it is received in SETTINGS frame. Without - specifying this option, before the local endpoint receives - SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote - endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may - cause problem if local endpoint submits lots of requests initially - and sending them at once to the remote peer may lead to the - rejection of some requests. Specifying this option to the sensible - value, say 100, may avoid this kind of issue. This value will be - overwritten if the local endpoint receives - SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint. diff -Nru nghttp2-1.13.0/doc/nghttp2_option_set_user_recv_extension_type.rst nghttp2-0.6.7/doc/nghttp2_option_set_user_recv_extension_type.rst --- nghttp2-1.13.0/doc/nghttp2_option_set_user_recv_extension_type.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_option_set_user_recv_extension_type.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ - -nghttp2_option_set_user_recv_extension_type -=========================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_option_set_user_recv_extension_type(nghttp2_option *option, uint8_t type) - - - Sets extension frame type the application is willing to handle with - user defined callbacks (see - :type:`nghttp2_on_extension_chunk_recv_callback` and - :type:`nghttp2_unpack_extension_callback`). The *type* is - extension frame type, and must be strictly greater than 0x9. - Otherwise, this function does nothing. The application can call - this function multiple times to set more than one frame type to - receive. The application does not have to call this function if it - just sends extension frames. diff -Nru nghttp2-1.13.0/doc/nghttp2_pack_settings_payload.rst nghttp2-0.6.7/doc/nghttp2_pack_settings_payload.rst --- nghttp2-1.13.0/doc/nghttp2_pack_settings_payload.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_pack_settings_payload.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ - -nghttp2_pack_settings_payload -============================= - -Synopsis --------- - -*#include * - -.. function:: ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv) - - - Serializes the SETTINGS values *iv* in the *buf*. The size of the - *buf* is specified by *buflen*. The number of entries in the *iv* - array is given by *niv*. The required space in *buf* for the *niv* - entries is ``8*niv`` bytes and if the given buffer is too small, an - error is returned. This function is used mainly for creating a - SETTINGS payload to be sent with the ``HTTP2-Settings`` header - field in an HTTP Upgrade request. The data written in *buf* is NOT - base64url encoded and the application is responsible for encoding. - - This function returns the number of bytes written in *buf*, or one - of the following negative error codes: - - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *iv* contains duplicate settings ID or invalid value. - - :macro:`NGHTTP2_ERR_INSUFF_BUFSIZE` - The provided *buflen* size is too small to hold the output. diff -Nru nghttp2-1.13.0/doc/nghttp2_priority_spec_check_default.rst nghttp2-0.6.7/doc/nghttp2_priority_spec_check_default.rst --- nghttp2-1.13.0/doc/nghttp2_priority_spec_check_default.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_priority_spec_check_default.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_priority_spec_check_default -=================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec) - - - Returns nonzero if the *pri_spec* is filled with default values. diff -Nru nghttp2-1.13.0/doc/nghttp2_priority_spec_default_init.rst nghttp2-0.6.7/doc/nghttp2_priority_spec_default_init.rst --- nghttp2-1.13.0/doc/nghttp2_priority_spec_default_init.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_priority_spec_default_init.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_priority_spec_default_init -================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec) - - - Initializes *pri_spec* with the default values. The default values - are: stream_id = 0, weight = :macro:`NGHTTP2_DEFAULT_WEIGHT` and - exclusive = 0. diff -Nru nghttp2-1.13.0/doc/nghttp2_priority_spec_init.rst nghttp2-0.6.7/doc/nghttp2_priority_spec_init.rst --- nghttp2-1.13.0/doc/nghttp2_priority_spec_init.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_priority_spec_init.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - -nghttp2_priority_spec_init -========================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec, int32_t stream_id, int32_t weight, int exclusive) - - - Initializes *pri_spec* with the *stream_id* of the stream to depend - on with *weight* and its exclusive flag. If *exclusive* is - nonzero, exclusive flag is set. - - The *weight* must be in [:macro:`NGHTTP2_MIN_WEIGHT`, - :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. diff -Nru nghttp2-1.13.0/doc/nghttp2_rcbuf_decref.rst nghttp2-0.6.7/doc/nghttp2_rcbuf_decref.rst --- nghttp2-1.13.0/doc/nghttp2_rcbuf_decref.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_rcbuf_decref.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_rcbuf_decref -==================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf) - - - Decrements the reference count of *rcbuf* by 1. If the reference - count becomes zero, the object pointed by *rcbuf* will be freed. - In this case, application must not use *rcbuf* again. diff -Nru nghttp2-1.13.0/doc/nghttp2_rcbuf_get_buf.rst nghttp2-0.6.7/doc/nghttp2_rcbuf_get_buf.rst --- nghttp2-1.13.0/doc/nghttp2_rcbuf_get_buf.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_rcbuf_get_buf.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_rcbuf_get_buf -===================== - -Synopsis --------- - -*#include * - -.. function:: nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf) - - - Returns the underlying buffer managed by *rcbuf*. diff -Nru nghttp2-1.13.0/doc/nghttp2_rcbuf_incref.rst nghttp2-0.6.7/doc/nghttp2_rcbuf_incref.rst --- nghttp2-1.13.0/doc/nghttp2_rcbuf_incref.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_rcbuf_incref.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_rcbuf_incref -==================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_rcbuf_incref(nghttp2_rcbuf *rcbuf) - - - Increments the reference count of *rcbuf* by 1. diff -Nru nghttp2-1.13.0/doc/nghttp2_select_next_protocol.rst nghttp2-0.6.7/doc/nghttp2_select_next_protocol.rst --- nghttp2-1.13.0/doc/nghttp2_select_next_protocol.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_select_next_protocol.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ - -nghttp2_select_next_protocol -============================ - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen) - - - A helper function for dealing with NPN in client side or ALPN in - server side. The *in* contains peer's protocol list in preferable - order. The format of *in* is length-prefixed and not - null-terminated. For example, ``h2`` and - ``http/1.1`` stored in *in* like this:: - - in[0] = 2 - in[1..2] = "h2" - in[3] = 8 - in[4..11] = "http/1.1" - inlen = 12 - - The selection algorithm is as follows: - - 1. If peer's list contains HTTP/2 protocol the library supports, - it is selected and returns 1. The following step is not taken. - - 2. If peer's list contains ``http/1.1``, this function selects - ``http/1.1`` and returns 0. The following step is not taken. - - 3. This function selects nothing and returns -1 (So called - non-overlap case). In this case, *out* and *outlen* are left - untouched. - - Selecting ``h2`` means that ``h2`` is written into *\*out* and its - length (which is 2) is assigned to *\*outlen*. - - For ALPN, refer to https://tools.ietf.org/html/rfc7301 - - See http://technotes.googlecode.com/git/nextprotoneg.html for more - details about NPN. - - For NPN, to use this method you should do something like:: - - static int select_next_proto_cb(SSL* ssl, - unsigned char **out, - unsigned char *outlen, - const unsigned char *in, - unsigned int inlen, - void *arg) - { - int rv; - rv = nghttp2_select_next_protocol(out, outlen, in, inlen); - if (rv == -1) { - return SSL_TLSEXT_ERR_NOACK; - } - if (rv == 1) { - ((MyType*)arg)->http2_selected = 1; - } - return SSL_TLSEXT_ERR_OK; - } - ... - SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj); - diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_del.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_del.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_del.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_del.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_del -============================= - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks) - - - Frees any resources allocated for *callbacks*. If *callbacks* is - ``NULL``, this function does nothing. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_new.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_new.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_new.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_new.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ - -nghttp2_session_callbacks_new -============================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr) - - - Initializes *\*callbacks_ptr* with NULL values. - - The initialized object can be used when initializing multiple - :type:`nghttp2_session` objects. - - When the application finished using this object, it can use - `nghttp2_session_callbacks_del()` to free its memory. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_before_frame_send_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_before_frame_send_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_before_frame_send_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_before_frame_send_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_session_callbacks_set_before_frame_send_callback -======================================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_before_frame_send_callback( nghttp2_session_callbacks *cbs, nghttp2_before_frame_send_callback before_frame_send_callback) - - - Sets callback function invoked before a non-DATA frame is sent. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_data_source_read_length_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_data_source_read_length_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_data_source_read_length_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_data_source_read_length_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_set_data_source_read_length_callback -============================================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_data_source_read_length_callback( nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback data_source_read_length_callback) - - - Sets callback function determine the length allowed in - :type:`nghttp2_data_source_read_callback`. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_error_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_error_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_error_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_error_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_set_error_callback -============================================ - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_error_callback( nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback) - - - Sets callback function invoked when library tells error message to - the application. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_begin_frame_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_begin_frame_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_begin_frame_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_begin_frame_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_session_callbacks_set_on_begin_frame_callback -===================================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_begin_frame_callback( nghttp2_session_callbacks *cbs, nghttp2_on_begin_frame_callback on_begin_frame_callback) - - - Sets callback function invoked when a frame header is received. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_begin_headers_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_begin_headers_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_begin_headers_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_begin_headers_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_set_on_begin_headers_callback -======================================================= - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_begin_headers_callback( nghttp2_session_callbacks *cbs, nghttp2_on_begin_headers_callback on_begin_headers_callback) - - - Sets callback function invoked when the reception of header block - in HEADERS or PUSH_PROMISE is started. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_set_on_data_chunk_recv_callback -========================================================= - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_data_chunk_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback) - - - Sets callback function invoked when a chunk of data in DATA frame - is received. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_extension_chunk_recv_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_extension_chunk_recv_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_extension_chunk_recv_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_extension_chunk_recv_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_set_on_extension_chunk_recv_callback -============================================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_extension_chunk_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback) - - - Sets callback function invoked when chunk of extension frame - payload is received. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_frame_not_send_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_frame_not_send_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_frame_not_send_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_frame_not_send_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_set_on_frame_not_send_callback -======================================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_frame_not_send_callback( nghttp2_session_callbacks *cbs, nghttp2_on_frame_not_send_callback on_frame_not_send_callback) - - - Sets callback function invoked when a non-DATA frame is not sent - because of an error. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_frame_recv_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_frame_recv_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_frame_recv_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_frame_recv_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_set_on_frame_recv_callback -==================================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_frame_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_on_frame_recv_callback on_frame_recv_callback) - - - Sets callback function invoked by `nghttp2_session_recv()` and - `nghttp2_session_mem_recv()` when a frame is received. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_frame_send_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_frame_send_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_frame_send_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_frame_send_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_session_callbacks_set_on_frame_send_callback -==================================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_frame_send_callback( nghttp2_session_callbacks *cbs, nghttp2_on_frame_send_callback on_frame_send_callback) - - - Sets callback function invoked after a frame is sent. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_header_callback2.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_header_callback2.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_header_callback2.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_header_callback2.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_set_on_header_callback2 -================================================= - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_header_callback2( nghttp2_session_callbacks *cbs, nghttp2_on_header_callback2 on_header_callback2) - - - Sets callback function invoked when a header name/value pair is - received. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_header_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_header_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_header_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_header_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ - -nghttp2_session_callbacks_set_on_header_callback -================================================ - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_header_callback( nghttp2_session_callbacks *cbs, nghttp2_on_header_callback on_header_callback) - - - Sets callback function invoked when a header name/value pair is - received. If both - `nghttp2_session_callbacks_set_on_header_callback()` and - `nghttp2_session_callbacks_set_on_header_callback2()` are used to - set callbacks, the latter has the precedence. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_session_callbacks_set_on_invalid_frame_recv_callback -============================================================ - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback) - - - Sets callback function invoked by `nghttp2_session_recv()` and - `nghttp2_session_mem_recv()` when an invalid non-DATA frame is - received. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_stream_close_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_stream_close_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_on_stream_close_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_on_stream_close_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_session_callbacks_set_on_stream_close_callback -====================================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_on_stream_close_callback( nghttp2_session_callbacks *cbs, nghttp2_on_stream_close_callback on_stream_close_callback) - - - Sets callback function invoked when the stream is closed. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_pack_extension_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_pack_extension_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_pack_extension_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_pack_extension_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_set_pack_extension_callback -===================================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_pack_extension_callback( nghttp2_session_callbacks *cbs, nghttp2_pack_extension_callback pack_extension_callback) - - - Sets callback function invoked when the library asks the - application to pack extension frame payload in wire format. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_recv_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_recv_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_recv_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_recv_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ - -nghttp2_session_callbacks_set_recv_callback -=========================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback) - - - Sets callback function invoked when the a session wants to receive - data from the remote peer. This callback is not necessary if the - application uses solely `nghttp2_session_mem_recv()` to process - received data. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_select_padding_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_select_padding_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_select_padding_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_select_padding_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_session_callbacks_set_select_padding_callback -===================================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_select_padding_callback( nghttp2_session_callbacks *cbs, nghttp2_select_padding_callback select_padding_callback) - - - Sets callback function invoked when the library asks application - how many padding bytes are required for the transmission of the - given frame. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_send_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_send_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_send_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_send_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ - -nghttp2_session_callbacks_set_send_callback -=========================================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_send_callback( nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback) - - - Sets callback function invoked when a session wants to send data to - the remote peer. This callback is not necessary if the application - uses solely `nghttp2_session_mem_send()` to serialize data to - transmit. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_send_data_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_send_data_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_send_data_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_send_data_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_session_callbacks_set_send_data_callback -================================================ - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_send_data_callback( nghttp2_session_callbacks *cbs, nghttp2_send_data_callback send_data_callback) - - - Sets callback function invoked when - :macro:`NGHTTP2_DATA_FLAG_NO_COPY` is used in - :type:`nghttp2_data_source_read_callback` to avoid data copy. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_unpack_extension_callback.rst nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_unpack_extension_callback.rst --- nghttp2-1.13.0/doc/nghttp2_session_callbacks_set_unpack_extension_callback.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_callbacks_set_unpack_extension_callback.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_callbacks_set_unpack_extension_callback -======================================================= - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_callbacks_set_unpack_extension_callback( nghttp2_session_callbacks *cbs, nghttp2_unpack_extension_callback unpack_extension_callback) - - - Sets callback function invoked when the library asks the - application to unpack extension frame payload from wire format. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_change_stream_priority.rst nghttp2-0.6.7/doc/nghttp2_session_change_stream_priority.rst --- nghttp2-1.13.0/doc/nghttp2_session_change_stream_priority.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_change_stream_priority.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ - -nghttp2_session_change_stream_priority -====================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_change_stream_priority(nghttp2_session *session, int32_t stream_id, const nghttp2_priority_spec *pri_spec) - - - Changes priority of existing stream denoted by *stream_id*. The - new priority specification is *pri_spec*. - - The priority is changed silently and instantly, and no PRIORITY - frame will be sent to notify the peer of this change. This - function may be useful for server to change the priority of pushed - stream. - - If *session* is initialized as server, and ``pri_spec->stream_id`` - points to the idle stream, the idle stream is created if it does - not exist. The created idle stream will depend on root stream - (stream 0) with weight 16. - - Otherwise, if stream denoted by ``pri_spec->stream_id`` is not - found, we use default priority instead of given *pri_spec*. That - is make stream depend on root stream with weight 16. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - Attempted to depend on itself; or no stream exist for the given - *stream_id*; or *stream_id* is 0 diff -Nru nghttp2-1.13.0/doc/nghttp2_session_check_request_allowed.rst nghttp2-0.6.7/doc/nghttp2_session_check_request_allowed.rst --- nghttp2-1.13.0/doc/nghttp2_session_check_request_allowed.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_check_request_allowed.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ - -nghttp2_session_check_request_allowed -===================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_check_request_allowed(nghttp2_session *session) - - - Returns nonzero if new request can be sent from local endpoint. - - This function return 0 if request is not allowed for this session. - There are several reasons why request is not allowed. Some of the - reasons are: session is server; stream ID has been spent; GOAWAY - has been sent or received. - - The application can call `nghttp2_submit_request()` without - consulting this function. In that case, `nghttp2_submit_request()` - may return error. Or, request is failed to sent, and - :type:`nghttp2_on_stream_close_callback` is called. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_check_server_session.rst nghttp2-0.6.7/doc/nghttp2_session_check_server_session.rst --- nghttp2-1.13.0/doc/nghttp2_session_check_server_session.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_check_server_session.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_session_check_server_session -==================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_check_server_session(nghttp2_session *session) - - - Returns nonzero if *session* is initialized as server side session. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_client_new2.rst nghttp2-0.6.7/doc/nghttp2_session_client_new2.rst --- nghttp2-1.13.0/doc/nghttp2_session_client_new2.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_client_new2.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ - -nghttp2_session_client_new2 -=========================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_client_new2(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data, const nghttp2_option *option) - - - Like `nghttp2_session_client_new()`, but with additional options - specified in the *option*. - - The *option* can be ``NULL`` and the call is equivalent to - `nghttp2_session_client_new()`. - - This function does not take ownership *option*. The application is - responsible for freeing *option* if it finishes using the object. - - The library code does not refer to *option* after this function - returns. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_client_new3.rst nghttp2-0.6.7/doc/nghttp2_session_client_new3.rst --- nghttp2-1.13.0/doc/nghttp2_session_client_new3.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_client_new3.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ - -nghttp2_session_client_new3 -=========================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_client_new3( nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data, const nghttp2_option *option, nghttp2_mem *mem) - - - Like `nghttp2_session_client_new2()`, but with additional custom - memory allocator specified in the *mem*. - - The *mem* can be ``NULL`` and the call is equivalent to - `nghttp2_session_client_new2()`. - - This function does not take ownership *mem*. The application is - responsible for freeing *mem*. - - The library code does not refer to *mem* pointer after this - function returns, so the application can safely free it. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_client_new.rst nghttp2-0.6.7/doc/nghttp2_session_client_new.rst --- nghttp2-1.13.0/doc/nghttp2_session_client_new.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_client_new.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ - -nghttp2_session_client_new -========================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_client_new(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data) - - - Initializes *\*session_ptr* for client use. The all members of - *callbacks* are copied to *\*session_ptr*. Therefore *\*session_ptr* - does not store *callbacks*. The *user_data* is an arbitrary user - supplied data, which will be passed to the callback functions. - - The :type:`nghttp2_send_callback` must be specified. If the - application code uses `nghttp2_session_recv()`, the - :type:`nghttp2_recv_callback` must be specified. The other members - of *callbacks* can be ``NULL``. - - If this function fails, *\*session_ptr* is left untouched. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_consume_connection.rst nghttp2-0.6.7/doc/nghttp2_session_consume_connection.rst --- nghttp2-1.13.0/doc/nghttp2_session_consume_connection.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_consume_connection.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ - -nghttp2_session_consume_connection -================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_consume_connection(nghttp2_session *session, size_t size) - - - Like `nghttp2_session_consume()`, but this only tells library that - *size* bytes were consumed only for connection level. Note that - HTTP/2 maintains connection and stream level flow control windows - independently. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_STATE` - Automatic WINDOW_UPDATE is not disabled. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_consume.rst nghttp2-0.6.7/doc/nghttp2_session_consume.rst --- nghttp2-1.13.0/doc/nghttp2_session_consume.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_consume.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ - -nghttp2_session_consume -======================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_consume(nghttp2_session *session, int32_t stream_id, size_t size) - - - Tells the *session* that *size* bytes for a stream denoted by - *stream_id* were consumed by application and are ready to - WINDOW_UPDATE. The consumed bytes are counted towards both - connection and stream level WINDOW_UPDATE (see - `nghttp2_session_consume_connection()` and - `nghttp2_session_consume_stream()` to update consumption - independently). This function is intended to be used without - automatic window update (see - `nghttp2_option_set_no_auto_window_update()`). - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *stream_id* is 0. - :macro:`NGHTTP2_ERR_INVALID_STATE` - Automatic WINDOW_UPDATE is not disabled. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_consume_stream.rst nghttp2-0.6.7/doc/nghttp2_session_consume_stream.rst --- nghttp2-1.13.0/doc/nghttp2_session_consume_stream.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_consume_stream.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ - -nghttp2_session_consume_stream -============================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_consume_stream(nghttp2_session *session, int32_t stream_id, size_t size) - - - Like `nghttp2_session_consume()`, but this only tells library that - *size* bytes were consumed only for stream denoted by *stream_id*. - Note that HTTP/2 maintains connection and stream level flow control - windows independently. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *stream_id* is 0. - :macro:`NGHTTP2_ERR_INVALID_STATE` - Automatic WINDOW_UPDATE is not disabled. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_create_idle_stream.rst nghttp2-0.6.7/doc/nghttp2_session_create_idle_stream.rst --- nghttp2-1.13.0/doc/nghttp2_session_create_idle_stream.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_create_idle_stream.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ - -nghttp2_session_create_idle_stream -================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_create_idle_stream(nghttp2_session *session, int32_t stream_id, const nghttp2_priority_spec *pri_spec) - - - Creates idle stream with the given *stream_id*, and priority - *pri_spec*. - - The stream creation is done without sending PRIORITY frame, which - means that peer does not know about the existence of this idle - stream in the local endpoint. - - RFC 7540 does not disallow the use of creation of idle stream with - odd or even stream ID regardless of client or server. So this - function can create odd or even stream ID regardless of client or - server. But probably it is a bit safer to use the stream ID the - local endpoint can initiate (in other words, use odd stream ID for - client, and even stream ID for server), to avoid potential - collision from peer's instruction. Also we can use - `nghttp2_session_set_next_stream_id()` to avoid to open created - idle streams accidentally if we follow this recommendation. - - If *session* is initialized as server, and ``pri_spec->stream_id`` - points to the idle stream, the idle stream is created if it does - not exist. The created idle stream will depend on root stream - (stream 0) with weight 16. - - Otherwise, if stream denoted by ``pri_spec->stream_id`` is not - found, we use default priority instead of given *pri_spec*. That - is make stream depend on root stream with weight 16. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - Attempted to depend on itself; or stream denoted by *stream_id* - already exists; or *stream_id* cannot be used to create idle - stream (in other words, local endpoint has already opened - stream ID greater than or equal to the given stream ID; or - *stream_id* is 0 diff -Nru nghttp2-1.13.0/doc/nghttp2_session_del.rst nghttp2-0.6.7/doc/nghttp2_session_del.rst --- nghttp2-1.13.0/doc/nghttp2_session_del.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_del.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_del -=================== - -Synopsis --------- - -*#include * - -.. function:: void nghttp2_session_del(nghttp2_session *session) - - - Frees any resources allocated for *session*. If *session* is - ``NULL``, this function does nothing. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_find_stream.rst nghttp2-0.6.7/doc/nghttp2_session_find_stream.rst --- nghttp2-1.13.0/doc/nghttp2_session_find_stream.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_find_stream.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ - -nghttp2_session_find_stream -=========================== - -Synopsis --------- - -*#include * - -.. function:: nghttp2_stream * nghttp2_session_find_stream(nghttp2_session *session, int32_t stream_id) - - - Returns pointer to :type:`nghttp2_stream` object denoted by - *stream_id*. If stream was not found, returns NULL. - - Returns imaginary root stream (see - `nghttp2_session_get_root_stream()`) if 0 is given in *stream_id*. - - Unless *stream_id* == 0, the returned pointer is valid until next - call of `nghttp2_session_send()`, `nghttp2_session_mem_send()`, - `nghttp2_session_recv()`, and `nghttp2_session_mem_recv()`. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_effective_local_window_size.rst nghttp2-0.6.7/doc/nghttp2_session_get_effective_local_window_size.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_effective_local_window_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_effective_local_window_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - -nghttp2_session_get_effective_local_window_size -=============================================== - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_session_get_effective_local_window_size(nghttp2_session *session) - - - Returns the local (receive) window size for a connection. The - local window size can be adjusted by - `nghttp2_submit_window_update()`. This function takes into account - that and returns effective window size. - - This function returns -1 if it fails. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_effective_recv_data_length.rst nghttp2-0.6.7/doc/nghttp2_session_get_effective_recv_data_length.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_effective_recv_data_length.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_effective_recv_data_length.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ - -nghttp2_session_get_effective_recv_data_length -============================================== - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_session_get_effective_recv_data_length(nghttp2_session *session) - - - Returns the number of DATA payload in bytes received without - WINDOW_UPDATE transmission for a connection. The local (receive) - window size can be adjusted by `nghttp2_submit_window_update()`. - This function takes into account that and returns effective data - length. In particular, if the local window size is reduced by - submitting negative window_size_increment with - `nghttp2_submit_window_update()`, this function returns the number - of bytes less than actually received. - - This function returns -1 if it fails. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_last_proc_stream_id.rst nghttp2-0.6.7/doc/nghttp2_session_get_last_proc_stream_id.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_last_proc_stream_id.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_last_proc_stream_id.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ - -nghttp2_session_get_last_proc_stream_id -======================================= - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_session_get_last_proc_stream_id(nghttp2_session *session) - - - Returns the last stream ID of a stream for which - :type:`nghttp2_on_frame_recv_callback` was invoked most recently. - The returned value can be used as last_stream_id parameter for - `nghttp2_submit_goaway()` and - `nghttp2_session_terminate_session2()`. - - This function always succeeds. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_next_stream_id.rst nghttp2-0.6.7/doc/nghttp2_session_get_next_stream_id.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_next_stream_id.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_next_stream_id.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_session_get_next_stream_id -================================== - -Synopsis --------- - -*#include * - -.. function:: uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session) - - - Returns the next outgoing stream ID. Notice that return type is - uint32_t. If we run out of stream ID for this session, this - function returns 1 << 31. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_outbound_queue_size.rst nghttp2-0.6.7/doc/nghttp2_session_get_outbound_queue_size.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_outbound_queue_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_outbound_queue_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_get_outbound_queue_size -======================================= - -Synopsis --------- - -*#include * - -.. function:: size_t nghttp2_session_get_outbound_queue_size(nghttp2_session *session) - - - Returns the number of frames in the outbound queue. This does not - include the deferred DATA frames. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_remote_settings.rst nghttp2-0.6.7/doc/nghttp2_session_get_remote_settings.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_remote_settings.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_remote_settings.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_session_get_remote_settings -=================================== - -Synopsis --------- - -*#include * - -.. function:: uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session, nghttp2_settings_id id) - - - Returns the value of SETTINGS *id* notified by a remote endpoint. - The *id* must be one of values defined in - :macro:`nghttp2_settings_id`. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_remote_window_size.rst nghttp2-0.6.7/doc/nghttp2_session_get_remote_window_size.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_remote_window_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_remote_window_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_session_get_remote_window_size -====================================== - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_session_get_remote_window_size(nghttp2_session *session) - - - Returns the remote window size for a connection. - - This function always succeeds. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_root_stream.rst nghttp2-0.6.7/doc/nghttp2_session_get_root_stream.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_root_stream.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_root_stream.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_session_get_root_stream -=============================== - -Synopsis --------- - -*#include * - -.. function:: nghttp2_stream * nghttp2_session_get_root_stream(nghttp2_session *session) - - - Returns root of dependency tree, which is imaginary stream with - stream ID 0. The returned pointer is valid until *session* is - freed by `nghttp2_session_del()`. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_stream_effective_local_window_size.rst nghttp2-0.6.7/doc/nghttp2_session_get_stream_effective_local_window_size.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_stream_effective_local_window_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_stream_effective_local_window_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - -nghttp2_session_get_stream_effective_local_window_size -====================================================== - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_session_get_stream_effective_local_window_size(nghttp2_session *session, int32_t stream_id) - - - Returns the local (receive) window size for the stream *stream_id*. - The local window size can be adjusted by - `nghttp2_submit_window_update()`. This function takes into account - that and returns effective window size. - - This function returns -1 if it fails. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_stream_effective_recv_data_length.rst nghttp2-0.6.7/doc/nghttp2_session_get_stream_effective_recv_data_length.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_stream_effective_recv_data_length.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_stream_effective_recv_data_length.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ - -nghttp2_session_get_stream_effective_recv_data_length -===================================================== - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_session_get_stream_effective_recv_data_length(nghttp2_session *session, int32_t stream_id) - - - Returns the number of DATA payload in bytes received without - WINDOW_UPDATE transmission for the stream *stream_id*. The local - (receive) window size can be adjusted by - `nghttp2_submit_window_update()`. This function takes into account - that and returns effective data length. In particular, if the - local window size is reduced by submitting negative - window_size_increment with `nghttp2_submit_window_update()`, this - function returns the number of bytes less than actually received. - - This function returns -1 if it fails. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_stream_local_close.rst nghttp2-0.6.7/doc/nghttp2_session_get_stream_local_close.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_stream_local_close.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_stream_local_close.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_get_stream_local_close -====================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_get_stream_local_close(nghttp2_session *session, int32_t stream_id) - - - Returns 1 if local peer half closed the given stream *stream_id*. - Returns 0 if it did not. Returns -1 if no such stream exists. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_stream_remote_close.rst nghttp2-0.6.7/doc/nghttp2_session_get_stream_remote_close.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_stream_remote_close.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_stream_remote_close.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_session_get_stream_remote_close -======================================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_get_stream_remote_close(nghttp2_session *session, int32_t stream_id) - - - Returns 1 if remote peer half closed the given stream *stream_id*. - Returns 0 if it did not. Returns -1 if no such stream exists. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_stream_remote_window_size.rst nghttp2-0.6.7/doc/nghttp2_session_get_stream_remote_window_size.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_stream_remote_window_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_stream_remote_window_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ - -nghttp2_session_get_stream_remote_window_size -============================================= - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session *session, int32_t stream_id) - - - Returns the remote window size for a given stream *stream_id*. - - This is the amount of flow-controlled payload (e.g., DATA) that the - local endpoint can send without stream level WINDOW_UPDATE. There - is also connection level flow control, so the effective size of - payload that the local endpoint can actually send is - min(`nghttp2_session_get_stream_remote_window_size()`, - `nghttp2_session_get_remote_window_size()`). - - This function returns -1 if it fails. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_get_stream_user_data.rst nghttp2-0.6.7/doc/nghttp2_session_get_stream_user_data.rst --- nghttp2-1.13.0/doc/nghttp2_session_get_stream_user_data.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_get_stream_user_data.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ - -nghttp2_session_get_stream_user_data -==================================== - -Synopsis --------- - -*#include * - -.. function:: void * nghttp2_session_get_stream_user_data(nghttp2_session *session, int32_t stream_id) - - - Returns stream_user_data for the stream *stream_id*. The - stream_user_data is provided by `nghttp2_submit_request()`, - `nghttp2_submit_headers()` or - `nghttp2_session_set_stream_user_data()`. Unless it is set using - `nghttp2_session_set_stream_user_data()`, if the stream is - initiated by the remote endpoint, stream_user_data is always - ``NULL``. If the stream does not exist, this function returns - ``NULL``. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_mem_recv.rst nghttp2-0.6.7/doc/nghttp2_session_mem_recv.rst --- nghttp2-1.13.0/doc/nghttp2_session_mem_recv.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_mem_recv.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ - -nghttp2_session_mem_recv -======================== - -Synopsis --------- - -*#include * - -.. function:: ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, size_t inlen) - - - Processes data *in* as an input from the remote endpoint. The - *inlen* indicates the number of bytes in the *in*. - - This function behaves like `nghttp2_session_recv()` except that it - does not use :type:`nghttp2_recv_callback` to receive data; the - *in* is the only data for the invocation of this function. If all - bytes are processed, this function returns. The other callbacks - are called in the same way as they are in `nghttp2_session_recv()`. - - In the current implementation, this function always tries to - processes all input data unless either an error occurs or - :macro:`NGHTTP2_ERR_PAUSE` is returned from - :type:`nghttp2_on_header_callback` or - :type:`nghttp2_on_data_chunk_recv_callback`. If - :macro:`NGHTTP2_ERR_PAUSE` is used, the return value includes the - number of bytes which was used to produce the data or frame for the - callback. - - This function returns the number of processed bytes, or one of the - following negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` - The callback function failed. - :macro:`NGHTTP2_ERR_BAD_CLIENT_MAGIC` - Invalid client magic was detected. This error only returns - when *session* was configured as server and - `nghttp2_option_set_no_recv_client_magic()` is not used with - nonzero value. - :macro:`NGHTTP2_ERR_FLOODED` - Flooding was detected in this HTTP/2 session, and it must be - closed. This is most likely caused by misbehaviour of peer. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_mem_send.rst nghttp2-0.6.7/doc/nghttp2_session_mem_send.rst --- nghttp2-1.13.0/doc/nghttp2_session_mem_send.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_mem_send.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ - -nghttp2_session_mem_send -======================== - -Synopsis --------- - -*#include * - -.. function:: ssize_t nghttp2_session_mem_send(nghttp2_session *session, const uint8_t **data_ptr) - - - Returns the serialized data to send. - - This function behaves like `nghttp2_session_send()` except that it - does not use :type:`nghttp2_send_callback` to transmit data. - Instead, it assigns the pointer to the serialized data to the - *\*data_ptr* and returns its length. The other callbacks are called - in the same way as they are in `nghttp2_session_send()`. - - If no data is available to send, this function returns 0. - - This function may not return all serialized data in one invocation. - To get all data, call this function repeatedly until it returns 0 - or one of negative error codes. - - The assigned *\*data_ptr* is valid until the next call of - `nghttp2_session_mem_send()` or `nghttp2_session_send()`. - - The caller must send all data before sending the next chunk of - data. - - This function returns the length of the data pointed by the - *\*data_ptr* if it succeeds, or one of the following negative error - codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - - .. note:: - - This function may produce very small byte string. If that is the - case, and application disables Nagle algorithm (``TCP_NODELAY``), - then writing this small chunk leads to very small packet, and it - is very inefficient. An application should be responsible to - buffer up small chunks of data as necessary to avoid this - situation. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_recv.rst nghttp2-0.6.7/doc/nghttp2_session_recv.rst --- nghttp2-1.13.0/doc/nghttp2_session_recv.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_recv.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ - -nghttp2_session_recv -==================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_recv(nghttp2_session *session) - - - Receives frames from the remote peer. - - This function receives as many frames as possible until the user - callback :type:`nghttp2_recv_callback` returns - :macro:`NGHTTP2_ERR_WOULDBLOCK`. This function calls several - callback functions which are passed when initializing the - *session*. Here is the simple time chart which tells when each - callback is invoked: - - 1. :type:`nghttp2_recv_callback` is invoked one or more times to - receive frame header. - - 2. When frame header is received, - :type:`nghttp2_on_begin_frame_callback` is invoked. - - 3. If the frame is DATA frame: - - 1. :type:`nghttp2_recv_callback` is invoked to receive DATA - payload. For each chunk of data, - :type:`nghttp2_on_data_chunk_recv_callback` is invoked. - - 2. If one DATA frame is completely received, - :type:`nghttp2_on_frame_recv_callback` is invoked. If the - reception of the frame triggers the closure of the stream, - :type:`nghttp2_on_stream_close_callback` is invoked. - - 4. If the frame is the control frame: - - 1. :type:`nghttp2_recv_callback` is invoked one or more times to - receive whole frame. - - 2. If the received frame is valid, then following actions are - taken. If the frame is either HEADERS or PUSH_PROMISE, - :type:`nghttp2_on_begin_headers_callback` is invoked. Then - :type:`nghttp2_on_header_callback` is invoked for each header - name/value pair. After all name/value pairs are emitted - successfully, :type:`nghttp2_on_frame_recv_callback` is - invoked. For other frames, - :type:`nghttp2_on_frame_recv_callback` is invoked. If the - reception of the frame triggers the closure of the stream, - :type:`nghttp2_on_stream_close_callback` is invoked. - - 3. If the received frame is unpacked but is interpreted as - invalid, :type:`nghttp2_on_invalid_frame_recv_callback` is - invoked. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_EOF` - The remote peer did shutdown on the connection. - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` - The callback function failed. - :macro:`NGHTTP2_ERR_BAD_CLIENT_MAGIC` - Invalid client magic was detected. This error only returns - when *session* was configured as server and - `nghttp2_option_set_no_recv_client_magic()` is not used with - nonzero value. - :macro:`NGHTTP2_ERR_FLOODED` - Flooding was detected in this HTTP/2 session, and it must be - closed. This is most likely caused by misbehaviour of peer. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_resume_data.rst nghttp2-0.6.7/doc/nghttp2_session_resume_data.rst --- nghttp2-1.13.0/doc/nghttp2_session_resume_data.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_resume_data.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ - -nghttp2_session_resume_data -=========================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id) - - - Puts back previously deferred DATA frame in the stream *stream_id* - to the outbound queue. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The stream does not exist; or no deferred data exist. - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_send.rst nghttp2-0.6.7/doc/nghttp2_session_send.rst --- nghttp2-1.13.0/doc/nghttp2_session_send.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_send.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ - -nghttp2_session_send -==================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_send(nghttp2_session *session) - - - Sends pending frames to the remote peer. - - This function retrieves the highest prioritized frame from the - outbound queue and sends it to the remote peer. It does this as - many as possible until the user callback - :type:`nghttp2_send_callback` returns - :macro:`NGHTTP2_ERR_WOULDBLOCK` or the outbound queue becomes empty. - This function calls several callback functions which are passed - when initializing the *session*. Here is the simple time chart - which tells when each callback is invoked: - - 1. Get the next frame to send from outbound queue. - - 2. Prepare transmission of the frame. - - 3. If the control frame cannot be sent because some preconditions - are not met (e.g., request HEADERS cannot be sent after GOAWAY), - :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort - the following steps. - - 4. If the frame is HEADERS, PUSH_PROMISE or DATA, - :type:`nghttp2_select_padding_callback` is invoked. - - 5. If the frame is request HEADERS, the stream is opened here. - - 6. :type:`nghttp2_before_frame_send_callback` is invoked. - - 7. If :macro:`NGHTTP2_ERR_CANCEL` is returned from - :type:`nghttp2_before_frame_send_callback`, the current frame - transmission is canceled, and - :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort - the following steps. - - 8. :type:`nghttp2_send_callback` is invoked one or more times to - send the frame. - - 9. :type:`nghttp2_on_frame_send_callback` is invoked. - - 10. If the transmission of the frame triggers closure of the - stream, the stream is closed and - :type:`nghttp2_on_stream_close_callback` is invoked. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` - The callback function failed. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_server_new2.rst nghttp2-0.6.7/doc/nghttp2_session_server_new2.rst --- nghttp2-1.13.0/doc/nghttp2_session_server_new2.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_server_new2.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ - -nghttp2_session_server_new2 -=========================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_server_new2(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data, const nghttp2_option *option) - - - Like `nghttp2_session_server_new()`, but with additional options - specified in the *option*. - - The *option* can be ``NULL`` and the call is equivalent to - `nghttp2_session_server_new()`. - - This function does not take ownership *option*. The application is - responsible for freeing *option* if it finishes using the object. - - The library code does not refer to *option* after this function - returns. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_server_new3.rst nghttp2-0.6.7/doc/nghttp2_session_server_new3.rst --- nghttp2-1.13.0/doc/nghttp2_session_server_new3.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_server_new3.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ - -nghttp2_session_server_new3 -=========================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_server_new3( nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data, const nghttp2_option *option, nghttp2_mem *mem) - - - Like `nghttp2_session_server_new2()`, but with additional custom - memory allocator specified in the *mem*. - - The *mem* can be ``NULL`` and the call is equivalent to - `nghttp2_session_server_new2()`. - - This function does not take ownership *mem*. The application is - responsible for freeing *mem*. - - The library code does not refer to *mem* pointer after this - function returns, so the application can safely free it. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_server_new.rst nghttp2-0.6.7/doc/nghttp2_session_server_new.rst --- nghttp2-1.13.0/doc/nghttp2_session_server_new.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_server_new.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ - -nghttp2_session_server_new -========================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_server_new(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data) - - - Initializes *\*session_ptr* for server use. The all members of - *callbacks* are copied to *\*session_ptr*. Therefore *\*session_ptr* - does not store *callbacks*. The *user_data* is an arbitrary user - supplied data, which will be passed to the callback functions. - - The :type:`nghttp2_send_callback` must be specified. If the - application code uses `nghttp2_session_recv()`, the - :type:`nghttp2_recv_callback` must be specified. The other members - of *callbacks* can be ``NULL``. - - If this function fails, *\*session_ptr* is left untouched. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_set_local_window_size.rst nghttp2-0.6.7/doc/nghttp2_session_set_local_window_size.rst --- nghttp2-1.13.0/doc/nghttp2_session_set_local_window_size.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_set_local_window_size.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ - -nghttp2_session_set_local_window_size -===================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags, int32_t stream_id, int32_t window_size) - - - Set local window size (local endpoints's window size) to the given - *window_size* for the given stream denoted by *stream_id*. To - change connection level window size, specify 0 to *stream_id*. To - increase window size, this function may submit WINDOW_UPDATE frame - to transmission queue. - - The *flags* is currently ignored and should be - :macro:`NGHTTP2_FLAG_NONE`. - - This sounds similar to `nghttp2_submit_window_update()`, but there - are 2 differences. The first difference is that this function - takes the absolute value of window size to set, rather than the - delta. To change the window size, this may be easier to use since - the application just declares the intended window size, rather than - calculating delta. The second difference is that - `nghttp2_submit_window_update()` affects the received bytes count - which has not acked yet. By the specification of - `nghttp2_submit_window_update()`, to strictly increase the local - window size, we have to submit delta including all received bytes - count, which might not be desirable in some cases. On the other - hand, this function does not affect the received bytes count. It - just sets the local window size to the given value. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *stream_id* is negative. - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_set_next_stream_id.rst nghttp2-0.6.7/doc/nghttp2_session_set_next_stream_id.rst --- nghttp2-1.13.0/doc/nghttp2_session_set_next_stream_id.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_set_next_stream_id.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ - -nghttp2_session_set_next_stream_id -================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_set_next_stream_id(nghttp2_session *session, int32_t next_stream_id) - - - Tells the *session* that next stream ID is *next_stream_id*. The - *next_stream_id* must be equal or greater than the value returned - by `nghttp2_session_get_next_stream_id()`. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *next_stream_id* is strictly less than the value - `nghttp2_session_get_next_stream_id()` returns; or - *next_stream_id* is invalid (e.g., even integer for client, or - odd integer for server). diff -Nru nghttp2-1.13.0/doc/nghttp2_session_set_stream_user_data.rst nghttp2-0.6.7/doc/nghttp2_session_set_stream_user_data.rst --- nghttp2-1.13.0/doc/nghttp2_session_set_stream_user_data.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_set_stream_user_data.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ - -nghttp2_session_set_stream_user_data -==================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_set_stream_user_data(nghttp2_session *session, int32_t stream_id, void *stream_user_data) - - - Sets the *stream_user_data* to the stream denoted by the - *stream_id*. If a stream user data is already set to the stream, - it is replaced with the *stream_user_data*. It is valid to specify - ``NULL`` in the *stream_user_data*, which nullifies the associated - data pointer. - - It is valid to set the *stream_user_data* to the stream reserved by - PUSH_PROMISE frame. - - This function returns 0 if it succeeds, or one of following - negative error codes: - - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The stream does not exist diff -Nru nghttp2-1.13.0/doc/nghttp2_session_terminate_session2.rst nghttp2-0.6.7/doc/nghttp2_session_terminate_session2.rst --- nghttp2-1.13.0/doc/nghttp2_session_terminate_session2.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_terminate_session2.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ - -nghttp2_session_terminate_session2 -================================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_terminate_session2(nghttp2_session *session, int32_t last_stream_id, uint32_t error_code) - - - Signals the session so that the connection should be terminated. - - This function behaves like `nghttp2_session_terminate_session()`, - but the last stream ID can be specified by the application for fine - grained control of stream. The HTTP/2 specification does not allow - last_stream_id to be increased. So the actual value sent as - last_stream_id is the minimum value between the given - *last_stream_id* and the last_stream_id we have previously sent to - the peer. - - The *last_stream_id* is peer's stream ID or 0. So if *session* is - initialized as client, *last_stream_id* must be even or 0. If - *session* is initialized as server, *last_stream_id* must be odd or - 0. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *last_stream_id* is invalid. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_terminate_session.rst nghttp2-0.6.7/doc/nghttp2_session_terminate_session.rst --- nghttp2-1.13.0/doc/nghttp2_session_terminate_session.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_terminate_session.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ - -nghttp2_session_terminate_session -================================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_terminate_session(nghttp2_session *session, uint32_t error_code) - - - Signals the session so that the connection should be terminated. - - The last stream ID is the minimum value between the stream ID of a - stream for which :type:`nghttp2_on_frame_recv_callback` was called - most recently and the last stream ID we have sent to the peer - previously. - - The *error_code* is the error code of this GOAWAY frame. The - pre-defined error code is one of :macro:`nghttp2_error_code`. - - After the transmission, both `nghttp2_session_want_read()` and - `nghttp2_session_want_write()` return 0. - - This function should be called when the connection should be - terminated after sending GOAWAY. If the remaining streams should - be processed after GOAWAY, use `nghttp2_submit_goaway()` instead. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_upgrade2.rst nghttp2-0.6.7/doc/nghttp2_session_upgrade2.rst --- nghttp2-1.13.0/doc/nghttp2_session_upgrade2.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_upgrade2.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ - -nghttp2_session_upgrade2 -======================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_upgrade2(nghttp2_session *session, const uint8_t *settings_payload, size_t settings_payloadlen, int head_request, void *stream_user_data) - - - Performs post-process of HTTP Upgrade request. This function can - be called from both client and server, but the behavior is very - different in each other. - - If called from client side, the *settings_payload* must be the - value sent in ``HTTP2-Settings`` header field and must be decoded - by base64url decoder. The *settings_payloadlen* is the length of - *settings_payload*. The *settings_payload* is unpacked and its - setting values will be submitted using `nghttp2_submit_settings()`. - This means that the client application code does not need to submit - SETTINGS by itself. The stream with stream ID=1 is opened and the - *stream_user_data* is used for its stream_user_data. The opened - stream becomes half-closed (local) state. - - If called from server side, the *settings_payload* must be the - value received in ``HTTP2-Settings`` header field and must be - decoded by base64url decoder. The *settings_payloadlen* is the - length of *settings_payload*. It is treated as if the SETTINGS - frame with that payload is received. Thus, callback functions for - the reception of SETTINGS frame will be invoked. The stream with - stream ID=1 is opened. The *stream_user_data* is ignored. The - opened stream becomes half-closed (remote). - - If the request method is HEAD, pass nonzero value to - *head_request*. Otherwise, pass 0. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *settings_payload* is badly formed. - :macro:`NGHTTP2_ERR_PROTO` - The stream ID 1 is already used or closed; or is not available. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_upgrade.rst nghttp2-0.6.7/doc/nghttp2_session_upgrade.rst --- nghttp2-1.13.0/doc/nghttp2_session_upgrade.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_upgrade.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ - -nghttp2_session_upgrade -======================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_upgrade(nghttp2_session *session, const uint8_t *settings_payload, size_t settings_payloadlen, void *stream_user_data) - - - Performs post-process of HTTP Upgrade request. This function can - be called from both client and server, but the behavior is very - different in each other. - - .. warning:: - - This function is deprecated in favor of - `nghttp2_session_upgrade2()`, because this function lacks the - parameter to tell the library the request method used in the - original HTTP request. This information is required for client - to validate actual response body length against content-length - header field (see `nghttp2_option_set_no_http_messaging()`). If - HEAD is used in request, the length of response body must be 0 - regardless of value included in content-length header field. - - If called from client side, the *settings_payload* must be the - value sent in ``HTTP2-Settings`` header field and must be decoded - by base64url decoder. The *settings_payloadlen* is the length of - *settings_payload*. The *settings_payload* is unpacked and its - setting values will be submitted using `nghttp2_submit_settings()`. - This means that the client application code does not need to submit - SETTINGS by itself. The stream with stream ID=1 is opened and the - *stream_user_data* is used for its stream_user_data. The opened - stream becomes half-closed (local) state. - - If called from server side, the *settings_payload* must be the - value received in ``HTTP2-Settings`` header field and must be - decoded by base64url decoder. The *settings_payloadlen* is the - length of *settings_payload*. It is treated as if the SETTINGS - frame with that payload is received. Thus, callback functions for - the reception of SETTINGS frame will be invoked. The stream with - stream ID=1 is opened. The *stream_user_data* is ignored. The - opened stream becomes half-closed (remote). - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *settings_payload* is badly formed. - :macro:`NGHTTP2_ERR_PROTO` - The stream ID 1 is already used or closed; or is not available. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_want_read.rst nghttp2-0.6.7/doc/nghttp2_session_want_read.rst --- nghttp2-1.13.0/doc/nghttp2_session_want_read.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_want_read.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - -nghttp2_session_want_read -========================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_want_read(nghttp2_session *session) - - - Returns nonzero value if *session* wants to receive data from the - remote peer. - - If both `nghttp2_session_want_read()` and - `nghttp2_session_want_write()` return 0, the application should - drop the connection. diff -Nru nghttp2-1.13.0/doc/nghttp2_session_want_write.rst nghttp2-0.6.7/doc/nghttp2_session_want_write.rst --- nghttp2-1.13.0/doc/nghttp2_session_want_write.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_session_want_write.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - -nghttp2_session_want_write -========================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_session_want_write(nghttp2_session *session) - - - Returns nonzero value if *session* wants to send data to the remote - peer. - - If both `nghttp2_session_want_read()` and - `nghttp2_session_want_write()` return 0, the application should - drop the connection. diff -Nru nghttp2-1.13.0/doc/nghttp2_stream_get_first_child.rst nghttp2-0.6.7/doc/nghttp2_stream_get_first_child.rst --- nghttp2-1.13.0/doc/nghttp2_stream_get_first_child.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_stream_get_first_child.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_stream_get_first_child -============================== - -Synopsis --------- - -*#include * - -.. function:: nghttp2_stream * nghttp2_stream_get_first_child(nghttp2_stream *stream) - - - Returns the first child stream of *stream* in dependency tree. - Returns NULL if there is no such stream. diff -Nru nghttp2-1.13.0/doc/nghttp2_stream_get_next_sibling.rst nghttp2-0.6.7/doc/nghttp2_stream_get_next_sibling.rst --- nghttp2-1.13.0/doc/nghttp2_stream_get_next_sibling.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_stream_get_next_sibling.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_stream_get_next_sibling -=============================== - -Synopsis --------- - -*#include * - -.. function:: nghttp2_stream * nghttp2_stream_get_next_sibling(nghttp2_stream *stream) - - - Returns the next sibling stream of *stream* in dependency tree. - Returns NULL if there is no such stream. diff -Nru nghttp2-1.13.0/doc/nghttp2_stream_get_parent.rst nghttp2-0.6.7/doc/nghttp2_stream_get_parent.rst --- nghttp2-1.13.0/doc/nghttp2_stream_get_parent.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_stream_get_parent.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_stream_get_parent -========================= - -Synopsis --------- - -*#include * - -.. function:: nghttp2_stream * nghttp2_stream_get_parent(nghttp2_stream *stream) - - - Returns the parent stream of *stream* in dependency tree. Returns - NULL if there is no such stream. diff -Nru nghttp2-1.13.0/doc/nghttp2_stream_get_previous_sibling.rst nghttp2-0.6.7/doc/nghttp2_stream_get_previous_sibling.rst --- nghttp2-1.13.0/doc/nghttp2_stream_get_previous_sibling.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_stream_get_previous_sibling.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_stream_get_previous_sibling -=================================== - -Synopsis --------- - -*#include * - -.. function:: nghttp2_stream * nghttp2_stream_get_previous_sibling(nghttp2_stream *stream) - - - Returns the previous sibling stream of *stream* in dependency tree. - Returns NULL if there is no such stream. diff -Nru nghttp2-1.13.0/doc/nghttp2_stream_get_state.rst nghttp2-0.6.7/doc/nghttp2_stream_get_state.rst --- nghttp2-1.13.0/doc/nghttp2_stream_get_state.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_stream_get_state.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - -nghttp2_stream_get_state -======================== - -Synopsis --------- - -*#include * - -.. function:: nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) - - - Returns state of *stream*. The root stream retrieved by - `nghttp2_session_get_root_stream()` will have stream state - :macro:`NGHTTP2_STREAM_STATE_IDLE`. diff -Nru nghttp2-1.13.0/doc/nghttp2_stream_get_sum_dependency_weight.rst nghttp2-0.6.7/doc/nghttp2_stream_get_sum_dependency_weight.rst --- nghttp2-1.13.0/doc/nghttp2_stream_get_sum_dependency_weight.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_stream_get_sum_dependency_weight.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_stream_get_sum_dependency_weight -======================================== - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream) - - - Returns the sum of the weight for *stream*'s children. diff -Nru nghttp2-1.13.0/doc/nghttp2_stream_get_weight.rst nghttp2-0.6.7/doc/nghttp2_stream_get_weight.rst --- nghttp2-1.13.0/doc/nghttp2_stream_get_weight.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_stream_get_weight.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - -nghttp2_stream_get_weight -========================= - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_stream_get_weight(nghttp2_stream *stream) - - - Returns dependency weight to the parent stream of *stream*. diff -Nru nghttp2-1.13.0/doc/nghttp2_strerror.rst nghttp2-0.6.7/doc/nghttp2_strerror.rst --- nghttp2-1.13.0/doc/nghttp2_strerror.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_strerror.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - -nghttp2_strerror -================ - -Synopsis --------- - -*#include * - -.. function:: const char *nghttp2_strerror(int lib_error_code) - - - Returns string describing the *lib_error_code*. The - *lib_error_code* must be one of the :macro:`nghttp2_error`. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_altsvc.rst nghttp2-0.6.7/doc/nghttp2_submit_altsvc.rst --- nghttp2-1.13.0/doc/nghttp2_submit_altsvc.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_altsvc.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ - -nghttp2_submit_altsvc -===================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags, int32_t stream_id, const uint8_t *origin, size_t origin_len, const uint8_t *field_value, size_t field_value_len) - - - Submits ALTSVC frame. - - ALTSVC frame is a non-critical extension to HTTP/2, and defined in - is defined in `RFC 7383 - `_. - - The *flags* is currently ignored and should be - :macro:`NGHTTP2_FLAG_NONE`. - - The *origin* points to the origin this alternative service is - associated with. The *origin_len* is the length of the origin. If - *stream_id* is 0, the origin must be specified. If *stream_id* is - not zero, the origin must be empty (in other words, *origin_len* - must be 0). - - The ALTSVC frame is only usable from server side. If this function - is invoked with client side session, this function returns - :macro:`NGHTTP2_ERR_INVALID_STATE`. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory - :macro:`NGHTTP2_ERR_INVALID_STATE` - The function is called from client side session - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The sum of *origin_len* and *field_value_len* is larger than - 16382; or *origin_len* is 0 while *stream_id* is 0; or - *origin_len* is not 0 while *stream_id* is not 0. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_data.rst nghttp2-0.6.7/doc/nghttp2_submit_data.rst --- nghttp2-1.13.0/doc/nghttp2_submit_data.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_data.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ - -nghttp2_submit_data -=================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_data_provider *data_prd) - - - Submits one or more DATA frames to the stream *stream_id*. The - data to be sent are provided by *data_prd*. If *flags* contains - :macro:`NGHTTP2_FLAG_END_STREAM`, the last DATA frame has END_STREAM - flag set. - - This function does not take ownership of the *data_prd*. The - function copies the members of the *data_prd*. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_DATA_EXIST` - DATA or HEADERS has been already submitted and not fully - processed yet. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *stream_id* is 0. - :macro:`NGHTTP2_ERR_STREAM_CLOSED` - The stream was already closed; or the *stream_id* is invalid. - - .. note:: - - Currently, only one DATA or HEADERS is allowed for a stream at a - time. Submitting these frames more than once before first DATA - or HEADERS is finished results in :macro:`NGHTTP2_ERR_DATA_EXIST` - error code. The earliest callback which tells that previous - frame is done is :type:`nghttp2_on_frame_send_callback`. In side - that callback, new data can be submitted using - `nghttp2_submit_data()`. Of course, all data except for last one - must not have :macro:`NGHTTP2_FLAG_END_STREAM` flag set in - *flags*. This sounds a bit complicated, and we recommend to use - `nghttp2_submit_request()` and `nghttp2_submit_response()` to - avoid this cascading issue. The experience shows that for HTTP - use, these two functions are enough to implement both client and - server. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_extension.rst nghttp2-0.6.7/doc/nghttp2_submit_extension.rst --- nghttp2-1.13.0/doc/nghttp2_submit_extension.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_extension.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ - -nghttp2_submit_extension -======================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_extension(nghttp2_session *session, uint8_t type, uint8_t flags, int32_t stream_id, void *payload) - - - Submits extension frame. - - Application can pass arbitrary frame flags and stream ID in *flags* - and *stream_id* respectively. The *payload* is opaque pointer, and - it can be accessible though ``frame->ext.payload`` in - :type:`nghttp2_pack_extension_callback`. The library will not own - passed *payload* pointer. - - The application must set :type:`nghttp2_pack_extension_callback` - using `nghttp2_session_callbacks_set_pack_extension_callback()`. - - The application should retain the memory pointed by *payload* until - the transmission of extension frame is done (which is indicated by - :type:`nghttp2_on_frame_send_callback`), or transmission fails - (which is indicated by :type:`nghttp2_on_frame_not_send_callback`). - If application does not touch this memory region after packing it - into a wire format, application can free it inside - :type:`nghttp2_pack_extension_callback`. - - The standard HTTP/2 frame cannot be sent with this function, so - *type* must be strictly grater than 0x9. Otherwise, this function - will fail with error code :macro:`NGHTTP2_ERR_INVALID_ARGUMENT`. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_INVALID_STATE` - If :type:`nghttp2_pack_extension_callback` is not set. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - If *type* specifies standard HTTP/2 frame type. The frame - types in the rage [0x0, 0x9], both inclusive, are standard - HTTP/2 frame type, and cannot be sent using this function. - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_goaway.rst nghttp2-0.6.7/doc/nghttp2_submit_goaway.rst --- nghttp2-1.13.0/doc/nghttp2_submit_goaway.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_goaway.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ - -nghttp2_submit_goaway -===================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags, int32_t last_stream_id, uint32_t error_code, const uint8_t *opaque_data, size_t opaque_data_len) - - - Submits GOAWAY frame with the last stream ID *last_stream_id* and - the error code *error_code*. - - The pre-defined error code is one of :macro:`nghttp2_error_code`. - - The *flags* is currently ignored and should be - :macro:`NGHTTP2_FLAG_NONE`. - - The *last_stream_id* is peer's stream ID or 0. So if *session* is - initialized as client, *last_stream_id* must be even or 0. If - *session* is initialized as server, *last_stream_id* must be odd or - 0. - - The HTTP/2 specification says last_stream_id must not be increased - from the value previously sent. So the actual value sent as - last_stream_id is the minimum value between the given - *last_stream_id* and the last_stream_id previously sent to the - peer. - - If the *opaque_data* is not ``NULL`` and *opaque_data_len* is not - zero, those data will be sent as additional debug data. The - library makes a copy of the memory region pointed by *opaque_data* - with the length *opaque_data_len*, so the caller does not need to - keep this memory after the return of this function. If the - *opaque_data_len* is 0, the *opaque_data* could be ``NULL``. - - After successful transmission of GOAWAY, following things happen. - All incoming streams having strictly more than *last_stream_id* are - closed. All incoming HEADERS which starts new stream are simply - ignored. After all active streams are handled, both - `nghttp2_session_want_read()` and `nghttp2_session_want_write()` - return 0 and the application can close session. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *opaque_data_len* is too large; the *last_stream_id* is - invalid. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_headers.rst nghttp2-0.6.7/doc/nghttp2_submit_headers.rst --- nghttp2-1.13.0/doc/nghttp2_submit_headers.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_headers.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ - -nghttp2_submit_headers -====================== - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, void *stream_user_data) - - - Submits HEADERS frame. The *flags* is bitwise OR of the - following values: - - * :macro:`NGHTTP2_FLAG_END_STREAM` - - If *flags* includes :macro:`NGHTTP2_FLAG_END_STREAM`, this frame has - END_STREAM flag set. - - The library handles the CONTINUATION frame internally and it - correctly sets END_HEADERS to the last sequence of the PUSH_PROMISE - or CONTINUATION frame. - - If the *stream_id* is -1, this frame is assumed as request (i.e., - request HEADERS frame which opens new stream). In this case, the - assigned stream ID will be returned. Otherwise, specify stream ID - in *stream_id*. - - The *pri_spec* is priority specification of this request. ``NULL`` - means the default priority (see - `nghttp2_priority_spec_default_init()`). To specify the priority, - use `nghttp2_priority_spec_init()`. If *pri_spec* is not ``NULL``, - this function will copy its data members. - - The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`, - :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is - strictly less than :macro:`NGHTTP2_MIN_WEIGHT`, it becomes - :macro:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than - :macro:`NGHTTP2_MAX_WEIGHT`, it becomes :macro:`NGHTTP2_MAX_WEIGHT`. - - The *nva* is an array of name/value pair :type:`nghttp2_nv` with - *nvlen* elements. The application is responsible to include - required pseudo-header fields (header field whose name starts with - ":") in *nva* and must place pseudo-headers before regular header - fields. - - This function creates copies of all name/value pairs in *nva*. It - also lower-cases all names in *nva*. The order of elements in - *nva* is preserved. For header fields with - :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and - :macro:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name - and value are not copied respectively. With - :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to - pass header field name in lowercase. The application should - maintain the references to them until - :type:`nghttp2_on_frame_send_callback` or - :type:`nghttp2_on_frame_not_send_callback` is called. - - The *stream_user_data* is a pointer to an arbitrary data which is - associated to the stream this frame will open. Therefore it is - only used if this frame opens streams, in other words, it changes - stream state from idle or reserved to open. - - This function is low-level in a sense that the application code can - specify flags directly. For usual HTTP request, - `nghttp2_submit_request()` is useful. Likewise, for HTTP response, - prefer `nghttp2_submit_response()`. - - This function returns newly assigned stream ID if it succeeds and - *stream_id* is -1. Otherwise, this function returns 0 if it - succeeds, or one of the following negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE` - No stream ID is available because maximum stream ID was - reached. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *stream_id* is 0; or trying to depend on itself (stream ID - equals ``pri_spec->stream_id``). - :macro:`NGHTTP2_ERR_DATA_EXIST` - DATA or HEADERS has been already submitted and not fully - processed yet. This happens if stream denoted by *stream_id* - is in reserved state. - :macro:`NGHTTP2_ERR_PROTO` - The *stream_id* is -1, and *session* is server session. - - .. warning:: - - This function returns assigned stream ID if it succeeds and - *stream_id* is -1. But that stream is not opened yet. The - application must not submit frame to that stream ID before - :type:`nghttp2_before_frame_send_callback` is called for this - frame. - diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_ping.rst nghttp2-0.6.7/doc/nghttp2_submit_ping.rst --- nghttp2-1.13.0/doc/nghttp2_submit_ping.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_ping.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ - -nghttp2_submit_ping -=================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags, const uint8_t *opaque_data) - - - Submits PING frame. You don't have to send PING back when you - received PING frame. The library automatically submits PING frame - in this case. - - The *flags* is bitwise OR of 0 or more of the following value. - - * :macro:`NGHTTP2_FLAG_ACK` - - Unless `nghttp2_option_set_no_auto_ping_ack()` is used, the *flags* - should be :macro:`NGHTTP2_FLAG_NONE`. - - If the *opaque_data* is non ``NULL``, then it should point to the 8 - bytes array of memory to specify opaque data to send with PING - frame. If the *opaque_data* is ``NULL``, zero-cleared 8 bytes will - be sent as opaque data. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_priority.rst nghttp2-0.6.7/doc/nghttp2_submit_priority.rst --- nghttp2-1.13.0/doc/nghttp2_submit_priority.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_priority.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ - -nghttp2_submit_priority -======================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_priority_spec *pri_spec) - - - Submits PRIORITY frame to change the priority of stream *stream_id* - to the priority specification *pri_spec*. - - The *flags* is currently ignored and should be - :macro:`NGHTTP2_FLAG_NONE`. - - The *pri_spec* is priority specification of this request. ``NULL`` - is not allowed for this function. To specify the priority, use - `nghttp2_priority_spec_init()`. This function will copy its data - members. - - The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`, - :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is - strictly less than :macro:`NGHTTP2_MIN_WEIGHT`, it becomes - :macro:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than - :macro:`NGHTTP2_MAX_WEIGHT`, it becomes :macro:`NGHTTP2_MAX_WEIGHT`. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *stream_id* is 0; or the *pri_spec* is NULL; or trying to - depend on itself. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_push_promise.rst nghttp2-0.6.7/doc/nghttp2_submit_push_promise.rst --- nghttp2-1.13.0/doc/nghttp2_submit_push_promise.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_push_promise.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ - -nghttp2_submit_push_promise -=========================== - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen, void *promised_stream_user_data) - - - Submits PUSH_PROMISE frame. - - The *flags* is currently ignored. The library handles the - CONTINUATION frame internally and it correctly sets END_HEADERS to - the last sequence of the PUSH_PROMISE or CONTINUATION frame. - - The *stream_id* must be client initiated stream ID. - - The *nva* is an array of name/value pair :type:`nghttp2_nv` with - *nvlen* elements. The application is responsible to include - required pseudo-header fields (header field whose name starts with - ":") in *nva* and must place pseudo-headers before regular header - fields. - - This function creates copies of all name/value pairs in *nva*. It - also lower-cases all names in *nva*. The order of elements in - *nva* is preserved. For header fields with - :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and - :macro:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name - and value are not copied respectively. With - :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to - pass header field name in lowercase. The application should - maintain the references to them until - :type:`nghttp2_on_frame_send_callback` or - :type:`nghttp2_on_frame_not_send_callback` is called. - - The *promised_stream_user_data* is a pointer to an arbitrary data - which is associated to the promised stream this frame will open and - make it in reserved state. It is available using - `nghttp2_session_get_stream_user_data()`. The application can - access it in :type:`nghttp2_before_frame_send_callback` and - :type:`nghttp2_on_frame_send_callback` of this frame. - - The client side is not allowed to use this function. - - To submit response headers and data, use - `nghttp2_submit_response()`. - - This function returns assigned promised stream ID if it succeeds, - or one of the following negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_PROTO` - This function was invoked when *session* is initialized as - client. - :macro:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE` - No stream ID is available because maximum stream ID was - reached. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *stream_id* is 0; The *stream_id* does not designate stream - that peer initiated. - :macro:`NGHTTP2_ERR_STREAM_CLOSED` - The stream was already closed; or the *stream_id* is invalid. - - .. warning:: - - This function returns assigned promised stream ID if it succeeds. - As of 1.16.0, stream object for pushed resource is created when - this function succeeds. In that case, the application can submit - push response for the promised frame. - - In 1.15.0 or prior versions, pushed stream is not opened yet when - this function succeeds. The application must not submit frame to - that stream ID before :type:`nghttp2_before_frame_send_callback` - is called for this frame. - diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_request.rst nghttp2-0.6.7/doc/nghttp2_submit_request.rst --- nghttp2-1.13.0/doc/nghttp2_submit_request.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_request.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ - -nghttp2_submit_request -====================== - -Synopsis --------- - -*#include * - -.. function:: int32_t nghttp2_submit_request(nghttp2_session *session, const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd, void *stream_user_data) - - - Submits HEADERS frame and optionally one or more DATA frames. - - The *pri_spec* is priority specification of this request. ``NULL`` - means the default priority (see - `nghttp2_priority_spec_default_init()`). To specify the priority, - use `nghttp2_priority_spec_init()`. If *pri_spec* is not ``NULL``, - this function will copy its data members. - - The ``pri_spec->weight`` must be in [:macro:`NGHTTP2_MIN_WEIGHT`, - :macro:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is - strictly less than :macro:`NGHTTP2_MIN_WEIGHT`, it becomes - :macro:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than - :macro:`NGHTTP2_MAX_WEIGHT`, it becomes :macro:`NGHTTP2_MAX_WEIGHT`. - - The *nva* is an array of name/value pair :type:`nghttp2_nv` with - *nvlen* elements. The application is responsible to include - required pseudo-header fields (header field whose name starts with - ":") in *nva* and must place pseudo-headers before regular header - fields. - - This function creates copies of all name/value pairs in *nva*. It - also lower-cases all names in *nva*. The order of elements in - *nva* is preserved. For header fields with - :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and - :macro:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name - and value are not copied respectively. With - :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to - pass header field name in lowercase. The application should - maintain the references to them until - :type:`nghttp2_on_frame_send_callback` or - :type:`nghttp2_on_frame_not_send_callback` is called. - - HTTP/2 specification has requirement about header fields in the - request HEADERS. See the specification for more details. - - If *data_prd* is not ``NULL``, it provides data which will be sent - in subsequent DATA frames. In this case, a method that allows - request message bodies - (https://tools.ietf.org/html/rfc7231#section-4) must be specified - with ``:method`` key in *nva* (e.g. ``POST``). This function does - not take ownership of the *data_prd*. The function copies the - members of the *data_prd*. If *data_prd* is ``NULL``, HEADERS have - END_STREAM set. The *stream_user_data* is data associated to the - stream opened by this request and can be an arbitrary pointer, - which can be retrieved later by - `nghttp2_session_get_stream_user_data()`. - - This function returns assigned stream ID if it succeeds, or one of - the following negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE` - No stream ID is available because maximum stream ID was - reached. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - Trying to depend on itself (new stream ID equals - ``pri_spec->stream_id``). - :macro:`NGHTTP2_ERR_PROTO` - The *session* is server session. - - .. warning:: - - This function returns assigned stream ID if it succeeds. But - that stream is not opened yet. The application must not submit - frame to that stream ID before - :type:`nghttp2_before_frame_send_callback` is called for this - frame. - diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_response.rst nghttp2-0.6.7/doc/nghttp2_submit_response.rst --- nghttp2-1.13.0/doc/nghttp2_submit_response.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_response.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ - -nghttp2_submit_response -======================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd) - - - Submits response HEADERS frame and optionally one or more DATA - frames against the stream *stream_id*. - - The *nva* is an array of name/value pair :type:`nghttp2_nv` with - *nvlen* elements. The application is responsible to include - required pseudo-header fields (header field whose name starts with - ":") in *nva* and must place pseudo-headers before regular header - fields. - - This function creates copies of all name/value pairs in *nva*. It - also lower-cases all names in *nva*. The order of elements in - *nva* is preserved. For header fields with - :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and - :macro:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name - and value are not copied respectively. With - :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to - pass header field name in lowercase. The application should - maintain the references to them until - :type:`nghttp2_on_frame_send_callback` or - :type:`nghttp2_on_frame_not_send_callback` is called. - - HTTP/2 specification has requirement about header fields in the - response HEADERS. See the specification for more details. - - If *data_prd* is not ``NULL``, it provides data which will be sent - in subsequent DATA frames. This function does not take ownership - of the *data_prd*. The function copies the members of the - *data_prd*. If *data_prd* is ``NULL``, HEADERS will have - END_STREAM flag set. - - This method can be used as normal HTTP response and push response. - When pushing a resource using this function, the *session* must be - configured using `nghttp2_session_server_new()` or its variants and - the target stream denoted by the *stream_id* must be reserved using - `nghttp2_submit_push_promise()`. - - To send non-final response headers (e.g., HTTP status 101), don't - use this function because this function half-closes the outbound - stream. Instead, use `nghttp2_submit_headers()` for this purpose. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *stream_id* is 0. - :macro:`NGHTTP2_ERR_DATA_EXIST` - DATA or HEADERS has been already submitted and not fully - processed yet. Normally, this does not happen, but when - application wrongly calls `nghttp2_submit_response()` twice, - this may happen. - :macro:`NGHTTP2_ERR_PROTO` - The *session* is client session. - - .. warning:: - - Calling this function twice for the same stream ID may lead to - program crash. It is generally considered to a programming error - to commit response twice. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_rst_stream.rst nghttp2-0.6.7/doc/nghttp2_submit_rst_stream.rst --- nghttp2-1.13.0/doc/nghttp2_submit_rst_stream.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_rst_stream.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ - -nghttp2_submit_rst_stream -========================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags, int32_t stream_id, uint32_t error_code) - - - Submits RST_STREAM frame to cancel/reject the stream *stream_id* - with the error code *error_code*. - - The pre-defined error code is one of :macro:`nghttp2_error_code`. - - The *flags* is currently ignored and should be - :macro:`NGHTTP2_FLAG_NONE`. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *stream_id* is 0. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_settings.rst nghttp2-0.6.7/doc/nghttp2_submit_settings.rst --- nghttp2-1.13.0/doc/nghttp2_submit_settings.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_settings.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ - -nghttp2_submit_settings -======================= - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags, const nghttp2_settings_entry *iv, size_t niv) - - - Stores local settings and submits SETTINGS frame. The *iv* is the - pointer to the array of :type:`nghttp2_settings_entry`. The *niv* - indicates the number of :type:`nghttp2_settings_entry`. - - The *flags* is currently ignored and should be - :macro:`NGHTTP2_FLAG_NONE`. - - This function does not take ownership of the *iv*. This function - copies all the elements in the *iv*. - - While updating individual stream's local window size, if the window - size becomes strictly larger than NGHTTP2_MAX_WINDOW_SIZE, - RST_STREAM is issued against such a stream. - - SETTINGS with :macro:`NGHTTP2_FLAG_ACK` is automatically submitted - by the library and application could not send it at its will. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *iv* contains invalid value (e.g., initial window size - strictly greater than (1 << 31) - 1. - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_shutdown_notice.rst nghttp2-0.6.7/doc/nghttp2_submit_shutdown_notice.rst --- nghttp2-1.13.0/doc/nghttp2_submit_shutdown_notice.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_shutdown_notice.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - -nghttp2_submit_shutdown_notice -============================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_shutdown_notice(nghttp2_session *session) - - - Signals to the client that the server started graceful shutdown - procedure. - - This function is only usable for server. If this function is - called with client side session, this function returns - :macro:`NGHTTP2_ERR_INVALID_STATE`. - - To gracefully shutdown HTTP/2 session, server should call this - function to send GOAWAY with last_stream_id (1u << 31) - 1. And - after some delay (e.g., 1 RTT), send another GOAWAY with the stream - ID that the server has some processing using - `nghttp2_submit_goaway()`. See also - `nghttp2_session_get_last_proc_stream_id()`. - - Unlike `nghttp2_submit_goaway()`, this function just sends GOAWAY - and does nothing more. This is a mere indication to the client - that session shutdown is imminent. The application should call - `nghttp2_submit_goaway()` with appropriate last_stream_id after - this call. - - If one or more GOAWAY frame have been already sent by either - `nghttp2_submit_goaway()` or `nghttp2_session_terminate_session()`, - this function has no effect. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_STATE` - The *session* is initialized as client. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_trailer.rst nghttp2-0.6.7/doc/nghttp2_submit_trailer.rst --- nghttp2-1.13.0/doc/nghttp2_submit_trailer.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_trailer.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ - -nghttp2_submit_trailer -====================== - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen) - - - Submits trailer fields HEADERS against the stream *stream_id*. - - The *nva* is an array of name/value pair :type:`nghttp2_nv` with - *nvlen* elements. The application is responsible not to include - pseudo-header fields (header field whose name starts with ":") in - *nva*. - - This function creates copies of all name/value pairs in *nva*. It - also lower-cases all names in *nva*. The order of elements in - *nva* is preserved. For header fields with - :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and - :macro:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name - and value are not copied respectively. With - :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to - pass header field name in lowercase. The application should - maintain the references to them until - :type:`nghttp2_on_frame_send_callback` or - :type:`nghttp2_on_frame_not_send_callback` is called. - - For server, trailer fields must follow response HEADERS or response - DATA without END_STREAM flat set. The library does not enforce - this requirement, and applications should do this for themselves. - If `nghttp2_submit_trailer()` is called before any response HEADERS - submission (usually by `nghttp2_submit_response()`), the content of - *nva* will be sent as response headers, which will result in error. - - This function has the same effect with `nghttp2_submit_headers()`, - with flags = :macro:`NGHTTP2_FLAG_END_STREAM` and both pri_spec and - stream_user_data to NULL. - - To submit trailer fields after `nghttp2_submit_response()` is - called, the application has to specify - :type:`nghttp2_data_provider` to `nghttp2_submit_response()`. - Inside of :type:`nghttp2_data_source_read_callback`, when setting - :macro:`NGHTTP2_DATA_FLAG_EOF`, also set - :macro:`NGHTTP2_DATA_FLAG_NO_END_STREAM`. After that, the - application can send trailer fields using - `nghttp2_submit_trailer()`. `nghttp2_submit_trailer()` can be used - inside :type:`nghttp2_data_source_read_callback`. - - This function returns 0 if it succeeds and *stream_id* is -1. - Otherwise, this function returns 0 if it succeeds, or one of the - following negative error codes: - - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. - :macro:`NGHTTP2_ERR_INVALID_ARGUMENT` - The *stream_id* is 0. diff -Nru nghttp2-1.13.0/doc/nghttp2_submit_window_update.rst nghttp2-0.6.7/doc/nghttp2_submit_window_update.rst --- nghttp2-1.13.0/doc/nghttp2_submit_window_update.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_submit_window_update.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ - -nghttp2_submit_window_update -============================ - -Synopsis --------- - -*#include * - -.. function:: int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags, int32_t stream_id, int32_t window_size_increment) - - - Submits WINDOW_UPDATE frame. - - The *flags* is currently ignored and should be - :macro:`NGHTTP2_FLAG_NONE`. - - The *stream_id* is the stream ID to send this WINDOW_UPDATE. To - send connection level WINDOW_UPDATE, specify 0 to *stream_id*. - - If the *window_size_increment* is positive, the WINDOW_UPDATE with - that value as window_size_increment is queued. If the - *window_size_increment* is larger than the received bytes from the - remote endpoint, the local window size is increased by that - difference. If the sole purpose is to increase the local window - size, consider to use `nghttp2_session_set_local_window_size()`. - - If the *window_size_increment* is negative, the local window size - is decreased by -*window_size_increment*. If automatic - WINDOW_UPDATE is enabled - (`nghttp2_option_set_no_auto_window_update()`), and the library - decided that the WINDOW_UPDATE should be submitted, then - WINDOW_UPDATE is queued with the current received bytes count. If - the sole purpose is to decrease the local window size, consider to - use `nghttp2_session_set_local_window_size()`. - - If the *window_size_increment* is 0, the function does nothing and - returns 0. - - This function returns 0 if it succeeds, or one of the following - negative error codes: - - :macro:`NGHTTP2_ERR_FLOW_CONTROL` - The local window size overflow or gets negative. - :macro:`NGHTTP2_ERR_NOMEM` - Out of memory. diff -Nru nghttp2-1.13.0/doc/nghttp2_version.rst nghttp2-0.6.7/doc/nghttp2_version.rst --- nghttp2-1.13.0/doc/nghttp2_version.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttp2_version.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ - -nghttp2_version -=============== - -Synopsis --------- - -*#include * - -.. function:: nghttp2_info *nghttp2_version(int least_version) - - - Returns a pointer to a nghttp2_info struct with version information - about the run-time library in use. The *least_version* argument - can be set to a 24 bit numerical value for the least accepted - version number and if the condition is not met, this function will - return a ``NULL``. Pass in 0 to skip the version checking. diff -Nru nghttp2-1.13.0/doc/nghttpd.1 nghttp2-0.6.7/doc/nghttpd.1 --- nghttp2-1.13.0/doc/nghttpd.1 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttpd.1 2014-11-30 14:15:07.000000000 +0000 @@ -1,218 +1,93 @@ -.\" Man page generated from reStructuredText. -. -.TH "NGHTTPD" "1" "Jul 21, 2016" "1.13.0" "nghttp2" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.4. +.TH NGHTTPD "1" "November 2014" "nghttpd nghttp2/0.6.7" "User Commands" .SH NAME -nghttpd \- HTTP/2 server -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. +nghttpd \- HTTP/2 experimental server .SH SYNOPSIS -.sp -\fBnghttpd\fP [OPTION]... [ ] +.B nghttpd +[\fI\,OPTION\/\fR]... \fI\, \/\fR +.br +.B nghttpd +\fI\,--no-tls \/\fR[\fI\,OPTION\/\fR]... \fI\,\/\fR .SH DESCRIPTION -.sp -HTTP/2 server -.INDENT 0.0 +HTTP/2 experimental server .TP -.B + Specify listening port number. -.UNINDENT -.INDENT 0.0 .TP -.B -Set path to server\(aqs private key. Required unless -\fI\%\-\-no\-tls\fP is specified. -.UNINDENT -.INDENT 0.0 -.TP -.B -Set path to server\(aqs certificate. Required unless -\fI\%\-\-no\-tls\fP is specified. -.UNINDENT + +Set path to server's private key. Required +unless \fB\-\-no\-tls\fR is specified. +.TP + +Set path to server's certificate. Required +unless \fB\-\-no\-tls\fR is specified. .SH OPTIONS -.INDENT 0.0 .TP -.B \-a, \-\-address= -The address to bind to. If not specified the default IP -address determined by getaddrinfo is used. -.UNINDENT -.INDENT 0.0 -.TP -.B \-D, \-\-daemon -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 -.INDENT 0.0 -.TP -.B \-V, \-\-verify\-client -The server sends a client certificate request. If the -client did not return a certificate, the handshake is -terminated. Currently, this option just requests a -client certificate and does not verify it. -.UNINDENT -.INDENT 0.0 -.TP -.B \-d, \-\-htdocs= -Specify document root. If this option is not specified, -the document root is the current working directory. -.UNINDENT -.INDENT 0.0 -.TP -.B \-v, \-\-verbose -Print debug information such as reception/ transmission -of frames and name/value pairs. -.UNINDENT -.INDENT 0.0 +\fB\-D\fR, \fB\-\-daemon\fR +Run in a background. If \fB\-D\fR is used, the current +working directory is changed to '/'. Therefore +if this option is used, \fB\-d\fR option must be +specified. +.TP +\fB\-V\fR, \fB\-\-verify\-client\fR +The server sends a client certificate request. +If the client did not return a certificate, the +handshake is terminated. Currently, this option +just requests a client certificate and does not +verify it. +.TP +\fB\-d\fR, \fB\-\-htdocs=\fR +Specify document root. If this option is not +specified, the document root is the current +working directory. +.TP +\fB\-v\fR, \fB\-\-verbose\fR +Print debug information such as reception/ +transmission of frames and name/value pairs. .TP -.B \-\-no\-tls +\fB\-\-no\-tls\fR Disable SSL/TLS. -.UNINDENT -.INDENT 0.0 .TP -.B \-c, \-\-header\-table\-size= +\fB\-c\fR, \fB\-\-header\-table\-size=\fR Specify decoder header table size. -.UNINDENT -.INDENT 0.0 .TP -.B \-\-color +\fB\-\-color\fR Force colored log output. -.UNINDENT -.INDENT 0.0 .TP -.B \-p, \-\-push== -Push resources s when is requested. -This option can be used repeatedly to specify multiple -push configurations. and s are -relative to document root. See \fI\%\-\-htdocs\fP option. -Example: \fI\%\-p\fP/=/foo.png \fI\%\-p\fP/doc=/bar.css -.UNINDENT -.INDENT 0.0 -.TP -.B \-b, \-\-padding= -Add at most bytes to a frame payload as padding. -Specify 0 to disable padding. -.UNINDENT -.INDENT 0.0 -.TP -.B \-m, \-\-max\-concurrent\-streams= -Set the maximum number of the concurrent streams in one -HTTP/2 session. -.sp -Default: \fB100\fP -.UNINDENT -.INDENT 0.0 +\fB\-p\fR, \fB\-\-push=\fR= +Push resources s when is +requested. This option can be used repeatedly to +specify multiple push configurations. and +s are relative to document root. See +\fB\-\-htdocs\fR option. Example: \fB\-p\fR/=/foo.png +\fB\-p\fR/doc=/bar.css +.TP +\fB\-b\fR, \fB\-\-padding=\fR +Add at most bytes to a frame payload as +padding. Specify 0 to disable padding. .TP -.B \-n, \-\-workers= +\fB\-n\fR, \fB\-\-workers=\fR Set the number of worker threads. -.sp -Default: \fB1\fP -.UNINDENT -.INDENT 0.0 +Default: 1 .TP -.B \-e, \-\-error\-gzip +\fB\-e\fR, \fB\-\-error\-gzip\fR Make error response gzipped. -.UNINDENT -.INDENT 0.0 .TP -.B \-w, \-\-window\-bits= -Sets the stream level initial window size to 2**\-1. -.UNINDENT -.INDENT 0.0 -.TP -.B \-W, \-\-connection\-window\-bits= -Sets the connection level initial window size to -2**\-1. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-dh\-param\-file= -Path to file that contains DH parameters in PEM format. -Without this option, DHE cipher suites are not -available. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-early\-response -Start sending response when request HEADERS is received, -rather than complete request is received. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-trailer=
-Add a trailer header to a response.
must not -include pseudo header field (header field name starting -with \(aq:\(aq). The trailer is sent only if a response has -body part. Example: \fI\%\-\-trailer\fP \(aqfoo: bar\(aq. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-hexdump -Display the incoming traffic in hexadecimal (Canonical -hex+ASCII display). If SSL/TLS is used, decrypted data -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 \-\-mime\-types\-file= -Path to file that contains MIME media types and the -extensions that represent them. -.sp -Default: \fB/etc/mime.types\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-no\-content\-length -Don\(aqt send content\-length header field. -.UNINDENT -.INDENT 0.0 +\fB\-\-dh\-param\-file=\fR +Path to file that contains DH parameters in PEM +format. Without this option, DHE cipher suites +are not available. +.TP +\fB\-\-early\-response\fR +Start sending response when request HEADERS is +received, rather than complete request is +received. .TP -.B \-\-version +\fB\-\-version\fR Display version information and exit. -.UNINDENT -.INDENT 0.0 .TP -.B \-h, \-\-help +\fB\-h\fR, \fB\-\-help\fR Display this help and exit. -.UNINDENT -.sp -The argument is an integer and an optional unit (e.g., 10K is -10 * 1024). Units are K, M and G (powers of 1024). -.SH SEE ALSO -.sp -\fBnghttp(1)\fP, \fBnghttpx(1)\fP, \fBh2load(1)\fP -.SH AUTHOR -Tatsuhiro Tsujikawa -.SH COPYRIGHT -2012, 2015, 2016, Tatsuhiro Tsujikawa -.\" Generated by docutils manpage writer. -. +.SH "SEE ALSO" + +nghttp(1), nghttpx(1), h2load(1) diff -Nru nghttp2-1.13.0/doc/nghttpd.1.rst nghttp2-0.6.7/doc/nghttpd.1.rst --- nghttp2-1.13.0/doc/nghttpd.1.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttpd.1.rst 2014-11-30 14:15:07.000000000 +0000 @@ -1,171 +1,138 @@ - -.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY. +.. DO NOT MODIFY THIS FILE! It was generated by man2rst.py .. program:: nghttpd nghttpd(1) ========== +NAME +---- +nghttpd - HTTP/2 experimental server + SYNOPSIS -------- +**nghttpd** [OPTION]... -**nghttpd** [OPTION]... [ ] +**nghttpd** --no-tls [OPTION]... DESCRIPTION ----------- +HTTP/2 experimental server -HTTP/2 server - -.. describe:: +.. option:: PORT Specify listening port number. -.. describe:: +.. option:: PRIVATE_KEY - - Set path to server's private key. Required unless - :option:`--no-tls` is specified. + Set path to server's private key. Required + unless :option:`--no-tls` is specified. -.. describe:: +.. option:: CERT - Set path to server's certificate. Required unless - :option:`--no-tls` is specified. + Set path to server's certificate. Required + unless :option:`--no-tls` is specified. OPTIONS ------- -.. option:: -a, --address= - - The address to bind to. If not specified the default IP - address determined by getaddrinfo is used. - .. option:: -D, --daemon - Run in a background. If :option:`-D` is used, the current working - directory is changed to '*/*'. Therefore if this option - is used, :option:`-d` option must be specified. + + Run in a background. If :option:`-D` is used, the current + working directory is changed to '/'. Therefore + if this option is used, :option:`-d` option must be + specified. .. option:: -V, --verify-client - The server sends a client certificate request. If the - client did not return a certificate, the handshake is - terminated. Currently, this option just requests a - client certificate and does not verify it. + + The server sends a client certificate request. + If the client did not return a certificate, the + handshake is terminated. Currently, this option + just requests a client certificate and does not + verify it. .. option:: -d, --htdocs= - Specify document root. If this option is not specified, - the document root is the current working directory. + + Specify document root. If this option is not + specified, the document root is the current + working directory. .. option:: -v, --verbose - Print debug information such as reception/ transmission - of frames and name/value pairs. + + Print debug information such as reception/ + transmission of frames and name/value pairs. .. option:: --no-tls + Disable SSL/TLS. -.. option:: -c, --header-table-size= +.. option:: -c, --header-table-size= + Specify decoder header table size. .. option:: --color + Force colored log output. .. option:: -p, --push== - Push resources s when is requested. - This option can be used repeatedly to specify multiple - push configurations. and s are - relative to document root. See :option:`--htdocs` option. - Example: :option:`-p`\/=/foo.png :option:`-p`\/doc=/bar.css + + Push resources s when is + requested. This option can be used repeatedly to + specify multiple push configurations. and + s are relative to document root. See + :option:`--htdocs` option. Example: -p/=/foo.png + -p/doc=/bar.css .. option:: -b, --padding= - Add at most bytes to a frame payload as padding. - Specify 0 to disable padding. - -.. option:: -m, --max-concurrent-streams= - - Set the maximum number of the concurrent streams in one - HTTP/2 session. - - Default: ``100`` + + Add at most bytes to a frame payload as + padding. Specify 0 to disable padding. -.. option:: -n, --workers= +.. option:: -n, --workers= + Set the number of worker threads. - - Default: ``1`` + Default: 1 .. option:: -e, --error-gzip + Make error response gzipped. -.. option:: -w, --window-bits= - - Sets the stream level initial window size to 2\*\*-1. - -.. option:: -W, --connection-window-bits= - - Sets the connection level initial window size to - 2\*\*-1. - .. option:: --dh-param-file= - Path to file that contains DH parameters in PEM format. - Without this option, DHE cipher suites are not - available. + + Path to file that contains DH parameters in PEM + format. Without this option, DHE cipher suites + are not available. .. option:: --early-response - Start sending response when request HEADERS is received, - rather than complete request is received. - -.. option:: --trailer=
- - Add a trailer header to a response.
must not - include pseudo header field (header field name starting - with ':'). The trailer is sent only if a response has - body part. Example: :option:`--trailer` 'foo: bar'. - -.. option:: --hexdump - - Display the incoming traffic in hexadecimal (Canonical - 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:: --mime-types-file= - - Path to file that contains MIME media types and the - extensions that represent them. - - Default: ``/etc/mime.types`` - -.. option:: --no-content-length - - Don't send content-length header field. + + Start sending response when request HEADERS is + received, rather than complete request is + received. .. option:: --version + Display version information and exit. .. option:: -h, --help + Display this help and exit. - - -The argument is an integer and an optional unit (e.g., 10K is -10 * 1024). Units are K, M and G (powers of 1024). - SEE ALSO -------- -:manpage:`nghttp(1)`, :manpage:`nghttpx(1)`, :manpage:`h2load(1)` +nghttp(1), nghttpx(1), h2load(1) diff -Nru nghttp2-1.13.0/doc/nghttpx.1 nghttp2-0.6.7/doc/nghttpx.1 --- nghttp2-1.13.0/doc/nghttpx.1 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttpx.1 2014-11-30 14:15:07.000000000 +0000 @@ -1,1801 +1,458 @@ -.\" Man page generated from reStructuredText. -. -.TH "NGHTTPX" "1" "Jul 21, 2016" "1.13.0" "nghttp2" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.4. +.TH NGHTTPX "1" "November 2014" "nghttpx nghttp2/0.6.7" "User Commands" .SH NAME -nghttpx \- HTTP/2 proxy -. -.nr rst2man-indent-level 0 -. -.de1 rstReportMargin -\\$1 \\n[an-margin] -level \\n[rst2man-indent-level] -level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] -- -\\n[rst2man-indent0] -\\n[rst2man-indent1] -\\n[rst2man-indent2] -.. -.de1 INDENT -.\" .rstReportMargin pre: -. RS \\$1 -. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] -. nr rst2man-indent-level +1 -.\" .rstReportMargin post: -.. -.de UNINDENT -. RE -.\" indent \\n[an-margin] -.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] -.nr rst2man-indent-level -1 -.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] -.in \\n[rst2man-indent\\n[rst2man-indent-level]]u -.. +nghttpx \- HTTP/2 experimental proxy .SH SYNOPSIS -.sp -\fBnghttpx\fP [OPTIONS]... [ ] +.B nghttpx +[\fI\,OPTIONS\/\fR]... [\fI\, \/\fR] .SH DESCRIPTION -.sp A reverse proxy for HTTP/2, HTTP/1 and SPDY. -.INDENT 0.0 .TP -.B -Set path to server\(aqs private key. Required unless -"no\-tls" parameter is used in \fI\%\-\-frontend\fP option. -.UNINDENT -.INDENT 0.0 -.TP -.B -Set path to server\(aqs certificate. Required unless -"no\-tls" parameter is used in \fI\%\-\-frontend\fP option. To -make OCSP stapling work, this must be an absolute path. -.UNINDENT + +Set path to server's private key. Required +unless \fB\-p\fR, \fB\-\-client\fR or \fB\-\-frontend\-no\-tls\fR are +given. +.TP + +Set path to server's certificate. Required +unless \fB\-p\fR, \fB\-\-client\fR or \fB\-\-frontend\-no\-tls\fR are +given. .SH OPTIONS -.sp +.IP The options are categorized into several groups. -.SS Connections -.INDENT 0.0 +.SS "Connections:" .TP -.B \-b, \-\-backend=(,|unix:)[;[[:...]][[;PARAM]...] -Set backend host and port. The multiple backend -addresses are accepted by repeating this option. UNIX -domain socket can be specified by prefixing path name -with "unix:" (e.g., unix:/var/run/backend.sock). -.sp -Optionally, if s are given, the backend address -is only used if request matches the pattern. If -\fI\%\-\-http2\-proxy\fP is used, s are ignored. The -pattern matching is closely designed to ServeMux in -net/http package of Go programming language. -consists of path, host + path or just host. The path -must start with "\fI/\fP". If it ends with "\fI/\fP", it matches -all request path in its subtree. To deal with the -request to the directory without trailing slash, the -path which ends with "\fI/\fP" also matches the request path -which only lacks trailing \(aq\fI/\fP\(aq (e.g., path "\fI/foo/\fP" -matches request path "\fI/foo\fP"). If it does not end with -"\fI/\fP", it performs exact match against the request path. -If host is given, it performs exact match against the -request host. If host alone is given, "\fI/\fP" is appended -to it, so that it matches all request paths under the -host (e.g., specifying "nghttp2.org" equals to -"nghttp2.org/"). -.sp -Patterns with host take precedence over patterns with -just path. Then, longer patterns take precedence over -shorter ones. -.sp -Host can include "*" in the left most position to -indicate wildcard match (only suffix match is done). -The "*" must match at least one character. For example, -host pattern "*.nghttp2.org" matches against -"www.nghttp2.org" and "git.ngttp2.org", but does not -match against "nghttp2.org". The exact hosts match -takes precedence over the wildcard hosts match. -.sp -If is omitted or empty string, "\fI/\fP" is used as -pattern, which matches all request paths (catch\-all -pattern). The catch\-all backend must be given. -.sp -When doing a match, nghttpx made some normalization to -pattern, request host and path. For host part, they are -converted to lower case. For path part, percent\-encoded -unreserved characters defined in RFC 3986 are decoded, -and any dot\-segments (".." and ".") are resolved and -removed. -.sp -For example, \fI\%\-b\fP\(aq127.0.0.1,8080;nghttp2.org/httpbin/\(aq -matches the request host "nghttp2.org" and the request -path "\fI/httpbin/get\fP", but does not match the request host -"nghttp2.org" and the request path "\fI/index.html\fP". -.sp -The multiple s can be specified, delimiting -them by ":". Specifying -\fI\%\-b\fP\(aq127.0.0.1,8080;nghttp2.org:www.nghttp2.org\(aq has the -same effect to specify \fI\%\-b\fP\(aq127.0.0.1,8080;nghttp2.org\(aq -and \fI\%\-b\fP\(aq127.0.0.1,8080;www.nghttp2.org\(aq. -.sp -The backend addresses sharing same are grouped -together forming load balancing group. -.sp -Several parameters are accepted after . -The parameters are delimited by ";". The available -parameters are: "proto=", "tls", -"sni=", "fall=", "rise=", and -"affinity=". The parameter consists of keyword, -and optionally followed by "=" and value. For example, -the parameter "proto=h2" consists of the keyword "proto" -and value "h2". The parameter "tls" consists of the -keyword "tls" without value. Each parameter is -described as follows. -.sp -The backend application protocol can be specified using -optional "proto" parameter, and in the form of -"proto=". should be one of the following -list without quotes: "h2", "http/1.1". The default -value of is "http/1.1". Note that usually "h2" -refers to HTTP/2 over TLS. But in this option, it may -mean HTTP/2 over cleartext TCP unless "tls" keyword is -used (see below). -.sp -TLS can be enabled by specifying optional "tls" -parameter. TLS is not enabled by default. -.sp -With "sni=" parameter, it can override the TLS -SNI field value with given . This will -default to the backend name -.sp -The feature to detect whether backend is online or -offline can be enabled using optional "fall" and "rise" -parameters. Using "fall=" parameter, if nghttpx -cannot connect to a this backend times in a row, -this backend is assumed to be offline, and it is -excluded from load balancing. If is 0, this backend -never be excluded from load balancing whatever times -nghttpx cannot connect to it, and this is the default. -There is also "rise=" parameter. After backend was -excluded from load balancing group, nghttpx periodically -attempts to make a connection to the failed backend, and -if the connection is made successfully times in a -row, the backend is assumed to be online, and it is now -eligible for load balancing target. If is 0, a -backend is permanently offline, once it goes in that -state, and this is the default behaviour. -.sp -The session affinity is enabled using -"affinity=" parameter. If "ip" is given in -, client IP based session affinity is enabled. -If "none" is given in , session affinity is -disabled, and this is the default. The session affinity -is enabled per . If at least one backend has -"affinity" parameter, and its is not "none", -session affinity is enabled for all backend servers -sharing the same . It is advised to set -"affinity" parameter to all backend explicitly if -session affinity is desired. The session affinity may -break if one of the backend gets unreachable, or backend -settings are reloaded or replaced by API. -.sp -Since ";" and ":" are used as delimiter, must -not contain these characters. Since ";" has special -meaning in shell, the option value must be quoted. -.sp -Default: \fB127.0.0.1,80\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-f, \-\-frontend=(,|unix:)[[;PARAM]...] -Set frontend host and port. If is \(aq*\(aq, it -assumes all addresses including both IPv4 and IPv6. -UNIX domain socket can be specified by prefixing path -name with "unix:" (e.g., unix:/var/run/nghttpx.sock). -This option can be used multiple times to listen to -multiple addresses. -.sp -This option can take 0 or more parameters, which are -described below. Note that "api" and "healthmon" -parameters are mutually exclusive. -.sp -Optionally, TLS can be disabled by specifying "no\-tls" -parameter. TLS is enabled by default. -.sp -To make this frontend as API endpoint, specify "api" -parameter. This is disabled by default. It is -important to limit the access to the API frontend. -Otherwise, someone may change the backend server, and -break your services, or expose confidential information -to the outside the world. -.sp -To make this frontend as health monitor endpoint, -specify "healthmon" parameter. This is disabled by -default. Any requests which come through this address -are replied with 200 HTTP status, without no body. -.sp -Default: \fB*,3000\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backlog= -Set listen backlog size. -.sp -Default: \fB512\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backend\-address\-family=(auto|IPv4|IPv6) -Specify address family of backend connections. If -"auto" is given, both IPv4 and IPv6 are considered. If -"IPv4" is given, only IPv4 address is considered. If -"IPv6" is given, only IPv6 address is considered. -.sp -Default: \fBauto\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backend\-http\-proxy\-uri= -Specify proxy URI in the form -\fI\%http:/\fP/[:@]:. If a proxy -requires authentication, specify and . -Note that they must be properly percent\-encoded. This -proxy is used when the backend connection is HTTP/2. -First, make a CONNECT request to the proxy and it -connects to the backend on behalf of nghttpx. This -forms tunnel. After that, nghttpx performs SSL/TLS -handshake with the downstream through the tunnel. The -timeouts when connecting and making CONNECT request can -be specified by \fI\%\-\-backend\-read\-timeout\fP and -\fI\%\-\-backend\-write\-timeout\fP options. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-accept\-proxy\-protocol -Accept PROXY protocol version 1 on frontend connection. -.UNINDENT -.SS Performance -.INDENT 0.0 +\fB\-b\fR, \fB\-\-backend=\fR +Set backend host and port. +Default: '127.0.0.1,80' +.TP +\fB\-f\fR, \fB\-\-frontend=\fR +Set frontend host and port. If is '*', it +assumes all addresses including both IPv4 and +IPv6. +Default: '*,3000' +.TP +\fB\-\-backlog=\fR +Set listen backlog size. If \fB\-1\fR is given, +libevent will choose suitable value. +Default: \fB\-1\fR +.TP +\fB\-\-backend\-ipv4\fR +Resolve backend hostname to IPv4 address only. +.TP +\fB\-\-backend\-ipv6\fR +Resolve backend hostname to IPv6 address only. +.TP +\fB\-\-backend\-http\-proxy\-uri=\fR +Specify proxy URI in the form +http://[:@]:. If a +proxy requires authentication, specify and +. Note that they must be properly +percent\-encoded. This proxy is used when the +backend connection is HTTP/2. First, make a +CONNECT request to the proxy and it connects to +the backend on behalf of nghttpx. This forms +tunnel. After that, nghttpx performs SSL/TLS +handshake with the downstream through the tunnel. +The timeouts when connecting and making CONNECT +request can be specified by +\fB\-\-backend\-read\-timeout\fR and +\fB\-\-backend\-write\-timeout\fR options. +.SS "Performance:" .TP -.B \-n, \-\-workers= +\fB\-n\fR, \fB\-\-workers=\fR Set the number of worker threads. -.sp -Default: \fB1\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-read\-rate= -Set maximum average read rate on frontend connection. -Setting 0 to this option means read rate is unlimited. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-read\-burst= -Set maximum read burst size on frontend connection. -Setting 0 to this option means read burst size is -unlimited. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-write\-rate= -Set maximum average write rate on frontend connection. -Setting 0 to this option means write rate is unlimited. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-write\-burst= -Set maximum write burst size on frontend connection. -Setting 0 to this option means write burst size is -unlimited. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-worker\-read\-rate= -Set maximum average read rate on frontend connection per -worker. Setting 0 to this option means read rate is -unlimited. Not implemented yet. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-worker\-read\-burst= -Set maximum read burst size on frontend connection per -worker. Setting 0 to this option means read burst size -is unlimited. Not implemented yet. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-worker\-write\-rate= -Set maximum average write rate on frontend connection -per worker. Setting 0 to this option means write rate -is unlimited. Not implemented yet. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-worker\-write\-burst= -Set maximum write burst size on frontend connection per -worker. Setting 0 to this option means write burst size -is unlimited. Not implemented yet. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-worker\-frontend\-connections= -Set maximum number of simultaneous connections frontend -accepts. Setting 0 means unlimited. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backend\-connections\-per\-host= -Set maximum number of backend concurrent connections -(and/or streams in case of HTTP/2) per origin host. -This option is meaningful when \fI\%\-\-http2\-proxy\fP option is -used. The origin host is determined by authority -portion of request URI (or :authority header field for -HTTP/2). To limit the number of connections per -frontend for default mode, use -\fI\%\-\-backend\-connections\-per\-frontend\fP\&. -.sp -Default: \fB8\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backend\-connections\-per\-frontend= -Set maximum number of backend concurrent connections -(and/or streams in case of HTTP/2) per frontend. This -option is only used for default mode. 0 means -unlimited. To limit the number of connections per host -with \fI\%\-\-http2\-proxy\fP option, use -\fI\%\-\-backend\-connections\-per\-host\fP\&. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-rlimit\-nofile= -Set maximum number of open files (RLIMIT_NOFILE) to . -If 0 is given, nghttpx does not set the limit. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backend\-request\-buffer= -Set buffer size used to store backend request. -.sp -Default: \fB16K\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backend\-response\-buffer= -Set buffer size used to store backend response. -.sp -Default: \fB128K\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-fastopen= -Enables "TCP Fast Open" for the listening socket and -limits the maximum length for the queue of connections -that have not yet completed the three\-way handshake. If -value is 0 then fast open is disabled. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-no\-kqueue -Don\(aqt use kqueue. This option is only applicable for -the platforms which have kqueue. For other platforms, -this option will be simply ignored. -.UNINDENT -.SS Timeout -.INDENT 0.0 +Default: 1 .TP -.B \-\-frontend\-http2\-read\-timeout= -Specify read timeout for HTTP/2 and SPDY frontend +\fB\-\-read\-rate=\fR +Set maximum average read rate on frontend +connection. Setting 0 to this option means read +rate is unlimited. +Default: 0 +.TP +\fB\-\-read\-burst=\fR +Set maximum read burst size on frontend +connection. Setting 0 does not work, but it is +not a problem because \fB\-\-read\-rate\fR=\fI\,0\/\fR will give +unlimited read rate regardless of this option +value. +Default: 1073741824 +.TP +\fB\-\-write\-rate=\fR +Set maximum average write rate on frontend +connection. Setting 0 to this option means write +rate is unlimited. +Default: 0 +.TP +\fB\-\-write\-burst=\fR +Set maximum write burst size on frontend +connection. Setting 0 to this option means write +burst size is unlimited. +Default: 0 +.TP +\fB\-\-worker\-read\-rate=\fR +Set maximum average read rate on frontend +connection per worker. Setting 0 to this option +means read rate is unlimited. +Default: 0 +.TP +\fB\-\-worker\-read\-burst=\fR +Set maximum read burst size on frontend +connection per worker. Setting 0 to this option +means read burst size is unlimited. +Default: 0 +.TP +\fB\-\-worker\-write\-rate=\fR +Set maximum average write rate on frontend +connection per worker. Setting 0 to this option +means write rate is unlimited. +Default: 0 +.TP +\fB\-\-worker\-write\-burst=\fR +Set maximum write burst size on frontend +connection per worker. Setting 0 to this option +means write burst size is unlimited. +Default: 0 +.TP +\fB\-\-worker\-frontend\-connections=\fR +Set maximum number of simultaneous connections +frontend accepts. Setting 0 means unlimited. +Default: 0 +.TP +\fB\-\-backend\-connections\-per\-frontend=\fR +Set maximum number of backend simultaneous +connections per frontend. This option is +meaningful when the combination of HTTP/2 or SPDY +frontend and HTTP/1 backend is used. +Default: 100 +.SS "Timeout:" +.TP +\fB\-\-frontend\-http2\-read\-timeout=\fR +Specify read timeout for HTTP/2 and SPDY frontend +connection. +Default: 180 +.TP +\fB\-\-frontend\-read\-timeout=\fR +Specify read timeout for HTTP/1.1 frontend connection. -.sp -Default: \fB3m\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-frontend\-read\-timeout= -Specify read timeout for HTTP/1.1 frontend connection. -.sp -Default: \fB1m\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-frontend\-write\-timeout= -Specify write timeout for all frontend connections. -.sp -Default: \fB30s\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-stream\-read\-timeout= -Specify read timeout for HTTP/2 and SPDY streams. 0 -means no timeout. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-stream\-write\-timeout= -Specify write timeout for HTTP/2 and SPDY streams. 0 -means no timeout. -.sp -Default: \fB0\fP -.UNINDENT -.INDENT 0.0 +Default: 30 .TP -.B \-\-backend\-read\-timeout= +\fB\-\-frontend\-write\-timeout=\fR +Specify write timeout for all frontend +connections. +Default: 30 +.TP +\fB\-\-stream\-read\-timeout=\fR +Specify read timeout for HTTP/2 and SPDY streams. +0 means no timeout. +Default: 0 +.TP +\fB\-\-stream\-write\-timeout=\fR +Specify write timeout for HTTP/2 and SPDY +streams. 0 means no timeout. +Default: 0 +.TP +\fB\-\-backend\-read\-timeout=\fR Specify read timeout for backend connection. -.sp -Default: \fB1m\fP -.UNINDENT -.INDENT 0.0 +Default: 30 .TP -.B \-\-backend\-write\-timeout= +\fB\-\-backend\-write\-timeout=\fR Specify write timeout for backend connection. -.sp -Default: \fB30s\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backend\-keep\-alive\-timeout= -Specify keep\-alive timeout for backend connection. -.sp -Default: \fB2s\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-listener\-disable\-timeout= -After accepting connection failed, connection listener -is disabled for a given amount of time. Specifying 0 -disables this feature. -.sp -Default: \fB30s\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-frontend\-http2\-setting\-timeout= -Specify timeout before SETTINGS ACK is received from -client. -.sp -Default: \fB10s\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backend\-http2\-settings\-timeout= -Specify timeout before SETTINGS ACK is received from -backend server. -.sp -Default: \fB10s\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backend\-max\-backoff= -Specify maximum backoff interval. This is used when -doing health check against offline backend (see "fail" -parameter in \fI\%\-\-backend\fP option). It is also used to -limit the maximum interval to temporarily disable -backend when nghttpx failed to connect to it. These -intervals are calculated using exponential backoff, and -consecutive failed attempts increase the interval. This -option caps its maximum value. -.sp -Default: \fB2m\fP -.UNINDENT -.SS SSL/TLS -.INDENT 0.0 -.TP -.B \-\-ciphers= -Set allowed cipher list. The format of the string is -described in OpenSSL ciphers(1). -.UNINDENT -.INDENT 0.0 -.TP -.B \-k, \-\-insecure -Don\(aqt verify backend server\(aqs certificate if TLS is -enabled for backend connections. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-cacert= -Set path to trusted CA certificate file used in backend -TLS connections. The file must be in PEM format. It -can contain multiple certificates. If the linked -OpenSSL is configured to load system wide certificates, -they are loaded at startup regardless of this option. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-private\-key\-passwd\-file= -Path to file that contains password for the server\(aqs -private key. If none is given and the private key is -password protected it\(aqll be requested interactively. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-subcert=: -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. To make OCSP -stapling work, must be absolute path. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-dh\-param\-file= -Path to file that contains DH parameters in PEM format. -Without this option, DHE cipher suites are not -available. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-npn\-list= -Comma delimited list of ALPN protocol identifier sorted -in the order of preference. That means most desirable -protocol comes first. This is used in both ALPN and -NPN. The parameter must be delimited by a single comma -only and any white spaces are treated as a part of -protocol string. -.sp -Default: \fBh2,h2\-16,h2\-14,spdy/3.1,http/1.1\fP -.UNINDENT -.INDENT 0.0 +Default: 30 +.TP +\fB\-\-backend\-keep\-alive\-timeout=\fR +Specify keep\-alive timeout for backend +connection. +Default: 60 .TP -.B \-\-verify\-client +\fB\-\-listener\-disable\-timeout=\fR +After accepting connection failed, connection +listener is disabled for a given time in seconds. +Specifying 0 disables this feature. +Default: 0 +.SS "SSL/TLS:" +.TP +\fB\-\-ciphers=\fR +Set allowed cipher list. The format of the +string is described in OpenSSL ciphers(1). +.TP +\fB\-k\fR, \fB\-\-insecure\fR +Don't verify backend server's certificate if \fB\-p\fR, +\fB\-\-client\fR or \fB\-\-http2\-bridge\fR are given and +\fB\-\-backend\-no\-tls\fR is not given. +.TP +\fB\-\-cacert=\fR +Set path to trusted CA certificate file if \fB\-p\fR, +\fB\-\-client\fR or \fB\-\-http2\-bridge\fR are given and +\fB\-\-backend\-no\-tls\fR is not given. The file must be +in PEM format. It can contain multiple +certificates. If the linked OpenSSL is +configured to load system wide certificates, they +are loaded at startup regardless of this option. +.TP +\fB\-\-private\-key\-passwd\-file=\fR +Path to file that contains password for the +server's private key. If none is given and the +private key is password protected it'll be +requested interactively. +.TP +\fB\-\-subcert=\fR: +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. +.TP +\fB\-\-backend\-tls\-sni\-field=\fR +Explicitly set the content of the TLS SNI +extension. This will default to the backend HOST +name. +.TP +\fB\-\-dh\-param\-file=\fR +Path to file that contains DH parameters in PEM +format. Without this option, DHE cipher suites +are not available. +.TP +\fB\-\-npn\-list=\fR +Comma delimited list of ALPN protocol identifier +sorted in the order of preference. That means +most desirable protocol comes first. This is +used in both ALPN and NPN. The parameter must be +delimited by a single comma only and any white +spaces are treated as a part of protocol string. +Default: h2\-14,spdy/3.1,http/1.1 +.TP +\fB\-\-verify\-client\fR Require and verify client certificate. -.UNINDENT -.INDENT 0.0 .TP -.B \-\-verify\-client\-cacert= -Path to file that contains CA certificates to verify -client certificate. The file must be in PEM format. It -can contain multiple certificates. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-client\-private\-key\-file= -Path to file that contains client private key used in -backend client authentication. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-client\-cert\-file= -Path to file that contains client certificate used in -backend client authentication. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-proto\-list= -Comma delimited list of SSL/TLS protocol to be enabled. -The following protocols are available: TLSv1.2, TLSv1.1 -and TLSv1.0. The name matching is done in -case\-insensitive manner. The parameter must be -delimited by a single comma only and any white spaces -are treated as a part of protocol string. If the -protocol list advertised by client does not overlap this -list, you will receive the error message "unknown -protocol". -.sp -Default: \fBTLSv1.2,TLSv1.1\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-ticket\-key\-file= -Path to file that contains random data to construct TLS -session ticket parameters. If aes\-128\-cbc is given in -\fI\%\-\-tls\-ticket\-key\-cipher\fP, the file must contain exactly -48 bytes. If aes\-256\-cbc is given in -\fI\%\-\-tls\-ticket\-key\-cipher\fP, the file must contain exactly -80 bytes. This options can be used repeatedly to -specify multiple ticket parameters. If several files -are given, only the first key is used to encrypt TLS -session tickets. Other keys are accepted but server -will issue new session ticket with first key. This -allows session key rotation. Please note that key -rotation does not occur automatically. User should -rearrange files or change options values and restart -nghttpx gracefully. If opening or reading given file -fails, all loaded keys are discarded and it is treated -as if none of this option is given. If this option is -not given or an error occurred while opening or reading -a file, key is generated every 1 hour internally and -they are valid for 12 hours. This is recommended if -ticket key sharing between nghttpx instances is not -required. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-ticket\-key\-memcached=,[;tls] -Specify address of memcached server to get TLS ticket -keys for session resumption. This enables shared TLS -ticket key between multiple nghttpx instances. nghttpx -does not set TLS ticket key to memcached. The external -ticket key generator is required. nghttpx just gets TLS -ticket keys from memcached, and use them, possibly -replacing current set of keys. It is up to extern TLS -ticket key generator to rotate keys frequently. See -"TLS SESSION TICKET RESUMPTION" section in manual page -to know the data format in memcached entry. Optionally, -memcached connection can be encrypted with TLS by -specifying "tls" parameter. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-ticket\-key\-memcached\-address\-family=(auto|IPv4|IPv6) -Specify address family of memcached connections to get -TLS ticket keys. If "auto" is given, both IPv4 and IPv6 -are considered. If "IPv4" is given, only IPv4 address -is considered. If "IPv6" is given, only IPv6 address is -considered. -.sp -Default: \fBauto\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-ticket\-key\-memcached\-interval= -Set interval to get TLS ticket keys from memcached. -.sp -Default: \fB10m\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-ticket\-key\-memcached\-max\-retry= -Set maximum number of consecutive retries before -abandoning TLS ticket key retrieval. If this number is -reached, the attempt is considered as failure, and -"failure" count is incremented by 1, which contributed -to the value controlled -\fI\%\-\-tls\-ticket\-key\-memcached\-max\-fail\fP option. -.sp -Default: \fB3\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-ticket\-key\-memcached\-max\-fail= -Set maximum number of consecutive failure before -disabling TLS ticket until next scheduled key retrieval. -.sp -Default: \fB2\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-ticket\-key\-cipher= -Specify cipher to encrypt TLS session ticket. Specify -either aes\-128\-cbc or aes\-256\-cbc. By default, -aes\-128\-cbc is used. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-ticket\-key\-memcached\-cert\-file= -Path to client certificate for memcached connections to -get TLS ticket keys. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-ticket\-key\-memcached\-private\-key\-file= -Path to client private key for memcached connections to -get TLS ticket keys. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-fetch\-ocsp\-response\-file= -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= -Set interval to update OCSP response cache. -.sp -Default: \fB4h\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-no\-ocsp -Disable OCSP stapling. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-session\-cache\-memcached=,[;tls] -Specify address of memcached server to store session -cache. This enables shared session cache between -multiple nghttpx instances. Optionally, memcached -connection can be encrypted with TLS by specifying "tls" -parameter. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-session\-cache\-memcached\-address\-family=(auto|IPv4|IPv6) -Specify address family of memcached connections to store -session cache. If "auto" is given, both IPv4 and IPv6 -are considered. If "IPv4" is given, only IPv4 address -is considered. If "IPv6" is given, only IPv6 address is -considered. -.sp -Default: \fBauto\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-session\-cache\-memcached\-cert\-file= -Path to client certificate for memcached connections to -store session cache. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-session\-cache\-memcached\-private\-key\-file= -Path to client private key for memcached connections to -store session cache. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-dyn\-rec\-warmup\-threshold= -Specify the threshold size for TLS dynamic record size -behaviour. During a TLS session, after the threshold -number of bytes have been written, the TLS record size -will be increased to the maximum allowed (16K). The max -record size will continue to be used on the active TLS -session. After \fI\%\-\-tls\-dyn\-rec\-idle\-timeout\fP has elapsed, -the record size is reduced to 1300 bytes. Specify 0 to -always use the maximum record size, regardless of idle -period. This behaviour applies to all TLS based -frontends, and TLS HTTP/2 backends. -.sp -Default: \fB1M\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-tls\-dyn\-rec\-idle\-timeout= -Specify TLS dynamic record size behaviour timeout. See -\fI\%\-\-tls\-dyn\-rec\-warmup\-threshold\fP for more information. -This behaviour applies to all TLS based frontends, and -TLS HTTP/2 backends. -.sp -Default: \fB1s\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-no\-http2\-cipher\-black\-list -Allow black listed cipher suite on HTTP/2 connection. -See \fI\%https://tools.ietf.org/html/rfc7540#appendix\-A\fP for -the complete HTTP/2 cipher suites black list. -.UNINDENT -.SS HTTP/2 and SPDY -.INDENT 0.0 -.TP -.B \-c, \-\-frontend\-http2\-max\-concurrent\-streams= -Set the maximum number of the concurrent streams in one -frontend HTTP/2 and SPDY session. -.sp -Default: \(ga\(ga 100\(ga\(ga -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-backend\-http2\-max\-concurrent\-streams= -Set the maximum number of the concurrent streams in one -backend HTTP/2 session. This sets maximum number of -concurrent opened pushed streams. The maximum number of -concurrent requests are set by a remote server. -.sp -Default: \fB100\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-frontend\-http2\-window\-bits= -Sets the per\-stream initial window size of HTTP/2 SPDY -frontend connection. For HTTP/2, the size is 2**\-1. -For SPDY, the size is 2**. -.sp -Default: \fB16\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-frontend\-http2\-connection\-window\-bits= -Sets the per\-connection window size of HTTP/2 and SPDY -frontend connection. For HTTP/2, the size is -2**\-1. For SPDY, the size is 2**. -.sp -Default: \fB16\fP -.UNINDENT -.INDENT 0.0 +\fB\-\-verify\-client\-cacert=\fR +Path to file that contains CA certificates to +verify client certificate. The file must be in +PEM format. It can contain multiple +certificates. +.TP +\fB\-\-client\-private\-key\-file=\fR +Path to file that contains client private key +used in backend client authentication. +.TP +\fB\-\-client\-cert\-file=\fR +Path to file that contains client certificate +used in backend client authentication. +.TP +\fB\-\-tls\-proto\-list=\fR +Comma delimited list of SSL/TLS protocol to be +enabled. The following protocols are available: +TLSv1.2, TLSv1.1 and TLSv1.0. The name matching +is done in case\-insensitive manner. The +parameter must be delimited by a single comma +only and any white spaces are treated as a part +of protocol string. +Default: TLSv1.2,TLSv1.1 +.SS "HTTP/2 and SPDY:" +.TP +\fB\-c\fR, \fB\-\-http2\-max\-concurrent\-streams=\fR +Set the maximum number of the concurrent streams +in one HTTP/2 and SPDY session. +Default: 100 +.TP +\fB\-\-frontend\-http2\-window\-bits=\fR +Sets the per\-stream initial window size of HTTP/2 +SPDY frontend connection. For HTTP/2, the size +is 2**\-1. For SPDY, the size is 2**. +Default: 16 +.TP +\fB\-\-frontend\-http2\-connection\-window\-bits=\fR +Sets the per\-connection window size of HTTP/2 and +SPDY frontend connection. For HTTP/2, the size +is 2**\-1. For SPDY, the size is 2**. +Default: 16 .TP -.B \-\-backend\-http2\-window\-bits= -Sets the initial window size of HTTP/2 backend -connection to 2**\-1. -.sp -Default: \fB16\fP -.UNINDENT -.INDENT 0.0 +\fB\-\-frontend\-no\-tls\fR +Disable SSL/TLS on frontend connections. .TP -.B \-\-backend\-http2\-connection\-window\-bits= -Sets the per\-connection window size of HTTP/2 backend +\fB\-\-backend\-http2\-window\-bits=\fR +Sets the initial window size of HTTP/2 backend connection to 2**\-1. -.sp -Default: \fB30\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-http2\-no\-cookie\-crumbling -Don\(aqt crumble cookie header field. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-padding= -Add at most bytes to a HTTP/2 frame payload as -padding. Specify 0 to disable padding. This option is -meant for debugging purpose and not intended to enhance -protocol security. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-no\-server\-push -Disable HTTP/2 server push. Server push is supported by -default mode and HTTP/2 frontend via Link header field. -It is also supported if both frontend and backend are -HTTP/2 in default mode. In this case, server push from -backend session is relayed to frontend, and server push -via Link header field is also supported. SPDY frontend -does not support server push. -.UNINDENT -.SS Mode -.INDENT 0.0 -.TP -.B (default mode) -Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS. "no\-tls" -parameter is used in \fI\%\-\-frontend\fP option, accept HTTP/2 -and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1 -connection can be upgraded to HTTP/2 through HTTP -Upgrade. -.UNINDENT -.INDENT 0.0 -.TP -.B \-s, \-\-http2\-proxy -Like default mode, but enable forward proxy. This is so -called HTTP/2 proxy mode. -.UNINDENT -.SS Logging -.INDENT 0.0 -.TP -.B \-L, \-\-log\-level= -Set the severity level of log output. must be -one of INFO, NOTICE, WARN, ERROR and FATAL. -.sp -Default: \fBNOTICE\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-accesslog\-file= -Set path to write access log. To reopen file, send USR1 -signal to nghttpx. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-accesslog\-syslog -Send access log to syslog. If this option is used, -\fI\%\-\-accesslog\-file\fP option is ignored. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-accesslog\-format= -Specify format string for access log. The default -format is combined format. The following variables are -available: -.INDENT 7.0 -.IP \(bu 2 +Default: 16 +.TP +\fB\-\-backend\-http2\-connection\-window\-bits=\fR +Sets the per\-connection window size of HTTP/2 +backend connection to 2**\-1. +Default: 16 +.TP +\fB\-\-backend\-no\-tls\fR +Disable SSL/TLS on backend connections. +.TP +\fB\-\-http2\-no\-cookie\-crumbling\fR +Don't crumble cookie header field. +.TP +\fB\-\-padding=\fR +Add at most bytes to a HTTP/2 frame payload +as padding. Specify 0 to disable padding. This +option is meant for debugging purpose and not +intended to enhance protocol security. +.SS "Mode:" +.TP +(default mode) +Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS. +If \fB\-\-frontend\-no\-tls\fR is used, accept HTTP/2 and +HTTP/1.1. The incoming HTTP/1.1 connection can +be upgraded to HTTP/2 through HTTP Upgrade. The +protocol to the backend is HTTP/1.1. +.TP +\fB\-s\fR, \fB\-\-http2\-proxy\fR +Like default mode, but enable secure proxy mode. +.TP +\fB\-\-http2\-bridge\fR +Like default mode, but communicate with the +backend in HTTP/2 over SSL/TLS. Thus the +incoming all connections are converted to HTTP/2 +connection and relayed to the backend. See +\fB\-\-backend\-http\-proxy\-uri\fR option if you are behind +the proxy and want to connect to the outside +HTTP/2 proxy. +.TP +\fB\-\-client\fR +Accept HTTP/2 and HTTP/1.1 without SSL/TLS. The +incoming HTTP/1.1 connection can be upgraded to +HTTP/2 connection through HTTP Upgrade. The +protocol to the backend is HTTP/2. To use +nghttpx as a forward proxy, use \fB\-p\fR option +instead. +.TP +\fB\-p\fR, \fB\-\-client\-proxy\fR +Like \fB\-\-client\fR option, but it also requires the +request path from frontend must be an absolute +URI, suitable for use as a forward proxy. +.SS "Logging:" +.TP +\fB\-L\fR, \fB\-\-log\-level=\fR +Set the severity level of log output. +must be one of INFO, NOTICE, WARN, ERROR and +FATAL. +Default: NOTICE +.TP +\fB\-\-accesslog\-file=\fR +Set path to write access log. To reopen file, +send USR1 signal to nghttpx. +.TP +\fB\-\-accesslog\-syslog\fR +Send access log to syslog. If this option is +used, \fB\-\-access\-file\fR option is ignored. +.TP +\fB\-\-accesslog\-format=\fR +Specify format string for access log. The +default format is combined format. The following +variables are available: $remote_addr: client IP address. -.IP \(bu 2 $time_local: local time in Common Log format. -.IP \(bu 2 $time_iso8601: local time in ISO 8601 format. -.IP \(bu 2 $request: HTTP request line. -.IP \(bu 2 $status: HTTP response status code. -.IP \(bu 2 -$body_bytes_sent: the number of bytes sent to client -as response body. -.IP \(bu 2 -$http_: value of HTTP request header where -\(aq_\(aq in is replaced with \(aq\-\(aq. -.IP \(bu 2 +$body_bytes_sent: the number of bytes sent to +client as response body. +$http_: value of HTTP request header +where '_' in is replaced with '\-'. $remote_port: client port. -.IP \(bu 2 $server_port: server port. -.IP \(bu 2 -$request_time: request processing time in seconds with -milliseconds resolution. -.IP \(bu 2 +$request_time: request processing time in +seconds with milliseconds resolution. $pid: PID of the running process. -.IP \(bu 2 -$alpn: ALPN identifier of the protocol which generates -the response. For HTTP/1, ALPN is always http/1.1, -regardless of minor version. -.IP \(bu 2 -$ssl_cipher: cipher used for SSL/TLS connection. -.IP \(bu 2 -$ssl_protocol: protocol for SSL/TLS connection. -.IP \(bu 2 -$ssl_session_id: session ID for SSL/TLS connection. -.IP \(bu 2 -$ssl_session_reused: "r" if SSL/TLS session was -reused. Otherwise, "." -.UNINDENT -.sp -The variable can be enclosed by "{" and "}" for -disambiguation (e.g., ${remote_addr}). -.sp -Default: \fB$remote_addr \- \- [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-errorlog\-file= -Set path to write error log. To reopen file, send USR1 -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 -.INDENT 0.0 -.TP -.B \-\-errorlog\-syslog -Send error log to syslog. If this option is used, -\fI\%\-\-errorlog\-file\fP option is ignored. -.UNINDENT -.INDENT 0.0 +$alpn: ALPN identifier of the protocol which +generates the response. For HTTP/1, ALPN is +always http/1.1, regardless of minor version. +Default: $remote_addr \- \- [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" +.TP +\fB\-\-errorlog\-file=\fR +Set path to write error log. To reopen file, +send USR1 signal to nghttpx. +Default: \fI\,/dev/stderr\/\fP +.TP +\fB\-\-errorlog\-syslog\fR +Send error log to syslog. If this option is +used, \fB\-\-errorlog\-file\fR option is ignored. .TP -.B \-\-syslog\-facility= +\fB\-\-syslog\-facility=\fR Set syslog facility to . -.sp -Default: \fBdaemon\fP -.UNINDENT -.SS HTTP -.INDENT 0.0 -.TP -.B \-\-add\-x\-forwarded\-for -Append X\-Forwarded\-For header field to the downstream -request. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-strip\-incoming\-x\-forwarded\-for -Strip X\-Forwarded\-For header field from inbound client -requests. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-add\-forwarded= -Append RFC 7239 Forwarded header field with parameters -specified in comma delimited list . The supported -parameters are "by", "for", "host", and "proto". By -default, the value of "by" and "for" parameters are -obfuscated string. See \fI\%\-\-forwarded\-by\fP and -\fI\%\-\-forwarded\-for\fP options respectively. Note that nghttpx -does not translate non\-standard X\-Forwarded\-* header -fields into Forwarded header field, and vice versa. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-strip\-incoming\-forwarded -Strip Forwarded header field from inbound client -requests. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-forwarded\-by=(obfuscated|ip|) -Specify the parameter value sent out with "by" parameter -of Forwarded header field. If "obfuscated" is given, -the string is randomly generated at startup. If "ip" is -given, the interface address of the connection, -including port number, is sent with "by" parameter. In -case of UNIX domain socket, "localhost" is used instead -of address and port. User can also specify the static -obfuscated string. The limitation is that it must start -with "_", and only consists of character set -[A\-Za\-z0\-9._\-], as described in RFC 7239. -.sp -Default: \fBobfuscated\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-forwarded\-for=(obfuscated|ip) -Specify the parameter value sent out with "for" -parameter of Forwarded header field. If "obfuscated" is -given, the string is randomly generated for each client -connection. If "ip" is given, the remote client address -of the connection, without port number, is sent with -"for" parameter. In case of UNIX domain socket, -"localhost" is used instead of address. -.sp -Default: \fBobfuscated\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-no\-via -Don\(aqt append to Via header field. If Via header field -is received, it is left unaltered. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-no\-location\-rewrite -Don\(aqt rewrite location header field in default mode. -When \fI\%\-\-http2\-proxy\fP is used, location header field will -not be altered regardless of this option. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-host\-rewrite -Rewrite host and :authority header fields in default -mode. When \fI\%\-\-http2\-proxy\fP is used, these headers will -not be altered regardless of this option. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-altsvc= -Specify protocol ID, port, host and origin of -alternative service. and are optional. -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 -.B \-\-add\-request\-header=
-Specify additional header field to add to request header -set. This option just appends header field and won\(aqt -replace anything already set. This option can be used -several times to specify multiple header fields. -Example: \fI\%\-\-add\-request\-header\fP="foo: bar" -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-add\-response\-header=
-Specify additional header field to add to response -header set. This option just appends header field and -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 \-\-request\-header\-field\-buffer= -Set maximum buffer size for incoming HTTP request header -field list. This is the sum of header name and value in -bytes. If trailer fields exist, they are counted -towards this number. -.sp -Default: \fB64K\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-max\-request\-header\-fields= -Set maximum number of incoming HTTP request header -fields. If trailer fields exist, they are counted -towards this number. -.sp -Default: \fB100\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-response\-header\-field\-buffer= -Set maximum buffer size for incoming HTTP response -header field list. This is the sum of header name and -value in bytes. If trailer fields exist, they are -counted towards this number. -.sp -Default: \fB64K\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-max\-response\-header\-fields= -Set maximum number of incoming HTTP response header -fields. If trailer fields exist, they are counted -towards this number. -.sp -Default: \fB500\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-error\-page=(|*)= -Set file path to custom error page served when nghttpx -originally generates HTTP error status code . - must be greater than or equal to 400, and at most -599. If "*" is used instead of , it matches all -HTTP status code. If error status code comes from -backend server, the custom error pages are not used. -.UNINDENT -.SS API -.INDENT 0.0 -.TP -.B \-\-api\-max\-request\-body= -Set the maximum size of request body for API request. -.sp -Default: \fB16K\fP -.UNINDENT -.SS Debug -.INDENT 0.0 -.TP -.B \-\-frontend\-http2\-dump\-request\-header= -Dumps request headers received by HTTP/2 frontend to the -file denoted in . The output is done in HTTP/1 -header field format and each header block is followed by -an empty line. This option is not thread safe and MUST -NOT be used with option \fI\%\-n\fP, where >= 2. -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-frontend\-http2\-dump\-response\-header= -Dumps response headers sent from HTTP/2 frontend to the -file denoted in . The output is done in HTTP/1 -header field format and each header block is followed by -an empty line. This option is not thread safe and MUST -NOT be used with option \fI\%\-n\fP, where >= 2. -.UNINDENT -.INDENT 0.0 -.TP -.B \-o, \-\-frontend\-frame\-debug -Print HTTP/2 frames in frontend to stderr. This option -is not thread safe and MUST NOT be used with option -\fI\%\-n\fP=N, where N >= 2. -.UNINDENT -.SS Process -.INDENT 0.0 -.TP -.B \-D, \-\-daemon -Run in a background. If \fI\%\-D\fP is used, the current working -directory is changed to \(aq\fI/\fP\(aq. -.UNINDENT -.INDENT 0.0 +Default: daemon +.SS "Misc:" .TP -.B \-\-pid\-file= +\fB\-\-add\-x\-forwarded\-for\fR +Append X\-Forwarded\-For header field to the +downstream request. +.TP +\fB\-\-strip\-incoming\-x\-forwarded\-for\fR +Strip X\-Forwarded\-For header field from inbound +client requests. +.TP +\fB\-\-no\-via\fR +Don't append to Via header field. If Via header +field is received, it is left unaltered. +.TP +\fB\-\-no\-location\-rewrite\fR +Don't rewrite location header field on +\fB\-\-http2\-bridge\fR, \fB\-\-client\fR and default mode. For +\fB\-\-http2\-proxy\fR and \fB\-\-client\-proxy\fR mode, location +header field will not be altered regardless of +this option. +.TP +\fB\-\-altsvc=\fR +Specify protocol ID, port, host and origin of +alternative service. and 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: \fB\-\-altsvc\fR=\fI\,h2\/\fR,443 +.TP +\fB\-\-add\-response\-header=\fR
+Specify additional header field to add to +response header set. This option just appends +header field and won't replace anything already +set. This option can be used several times to +specify multiple header fields. +Example: \fB\-\-add\-response\-header=\fR"foo: bar" +.TP +\fB\-\-frontend\-http2\-dump\-request\-header=\fR +Dumps request headers received by HTTP/2 frontend +to the file denoted in . The output is +done in HTTP/1 header field format and each +header block is followed by an empty line. This +option is not thread safe and MUST NOT be used +with option \fB\-n\fR, where >= 2. +.TP +\fB\-\-frontend\-http2\-dump\-response\-header=\fR +Dumps response headers sent from HTTP/2 frontend +to the file denoted in . The output is +done in HTTP/1 header field format and each +header block is followed by an empty line. This +option is not thread safe and MUST NOT be used +with option \fB\-n\fR, where >= 2. +.TP +\fB\-o\fR, \fB\-\-frontend\-frame\-debug\fR +Print HTTP/2 frames in frontend to stderr. This +option is not thread safe and MUST NOT be used +with option \fB\-n\fR=\fI\,N\/\fR, where N >= 2. +.TP +\fB\-D\fR, \fB\-\-daemon\fR +Run in a background. If \fB\-D\fR is used, the current +working directory is changed to '/'. +.TP +\fB\-\-pid\-file=\fR Set path to save PID of this program. -.UNINDENT -.INDENT 0.0 .TP -.B \-\-user= -Run this program as . This option is intended to -be used to drop root privileges. -.UNINDENT -.SS Scripting -.INDENT 0.0 -.TP -.B \-\-mruby\-file= -Set mruby script file -.UNINDENT -.SS Misc -.INDENT 0.0 +\fB\-\-user=\fR +Run this program as . This option is +intended to be used to drop root privileges. .TP -.B \-\-conf= +\fB\-\-conf=\fR Load configuration from . -.sp -Default: \fB/etc/nghttpx/nghttpx.conf\fP -.UNINDENT -.INDENT 0.0 -.TP -.B \-\-include= -Load additional configurations from . File -is read when configuration parser encountered this -option. This option can be used multiple times, or even -recursively. -.UNINDENT -.INDENT 0.0 +Default: \fI\,/etc/nghttpx/nghttpx.conf\/\fP .TP -.B \-v, \-\-version +\fB\-v\fR, \fB\-\-version\fR Print version and exit. -.UNINDENT -.INDENT 0.0 .TP -.B \-h, \-\-help +\fB\-h\fR, \fB\-\-help\fR Print this help and exit. -.UNINDENT -.sp -The 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 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 FILES -.INDENT 0.0 -.TP -.B \fI/etc/nghttpx/nghttpx.conf\fP -The default configuration file path nghttpx searches at startup. -The configuration file path can be changed using \fI\%\-\-conf\fP -option. -.sp -Those lines which are staring \fB#\fP are treated as comment. -.sp -The option name in the configuration file is the long command\-line -option name with leading \fB\-\-\fP stripped (e.g., \fBfrontend\fP). Put -\fB=\fP between option name and value. Don\(aqt put extra leading or -trailing spaces. -.sp -When specifying arguments including characters which have special -meaning to a shell, we usually use quotes so that shell does not -interpret them. When writing this configuration file, quotes for -this purpose must not be used. For example, specify additional -request header field, do this: -.INDENT 7.0 -.INDENT 3.5 -.sp -.nf -.ft C -add\-request\-header=foo: bar -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -instead of: -.INDENT 7.0 -.INDENT 3.5 -.sp -.nf -.ft C -add\-request\-header="foo: bar" -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -The options which do not take argument in the command\-line \fItake\fP -argument in the configuration file. Specify \fByes\fP as an argument -(e.g., \fBhttp2\-proxy=yes\fP). If other string is given, it is -ignored. -.sp -To specify private key and certificate file which are given as -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 -will be ignored if specified. -.UNINDENT -.SH SIGNALS -.INDENT 0.0 -.TP -.B SIGQUIT -Shutdown gracefully. First accept pending connections and stop -accepting connection. After all connections are handled, nghttpx -exits. -.TP -.B SIGUSR1 -Reopen log files. -.TP -.B SIGUSR2 -Fork and execute nghttpx. It will execute the binary in the same -path with same command\-line arguments and environment variables. -After new process comes up, sending SIGQUIT to the original process -to perform hot swapping. -.UNINDENT -.sp -\fBNOTE:\fP -.INDENT 0.0 -.INDENT 3.5 -nghttpx consists of multiple processes: one process for processing -these signals, and another one for processing requests. The former -spawns the latter. The former is called master process, and the -latter is called worker process. If neverbleed is enabled, the -worker process spawns neverbleed daemon process which does RSA key -processing. The above signal must be sent to the master process. -If the other processes received one of them, it is ignored. This -behaviour of these processes may change in the future release. In -other words, in the future release, the processes other than master -process may terminate upon the reception of these signals. -Therefore these signals should not be sent to the processes other -than master process. -.UNINDENT -.UNINDENT -.SH SERVER PUSH -.sp -nghttpx supports HTTP/2 server push in default mode with Link header -field. nghttpx looks for Link header field (\fI\%RFC 5988\fP) in response headers from -backend server and extracts URI\-reference with parameter -\fBrel=preload\fP (see \fI\%preload\fP) -and pushes those URIs to the frontend client. Here is a sample Link -header field to initiate server push: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -Link: ; rel=preload -Link: ; rel=preload -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -Currently, the following restriction is applied for server push: -.INDENT 0.0 -.IP 1. 3 -The associated stream must have method "GET" or "POST". The -associated stream\(aqs status code must be 200. -.UNINDENT -.sp -This limitation may be loosened in the future release. -.sp -nghttpx also supports server push if both frontend and backend are -HTTP/2 in default mode. In this case, in addition to server push via -Link header field, server push from backend is forwarded to frontend -HTTP/2 session. -.sp -HTTP/2 server push will be disabled if \fI\%\-\-http2\-proxy\fP is -used. -.SH UNIX DOMAIN SOCKET -.sp -nghttpx supports UNIX domain socket with a filename for both frontend -and backend connections. -.sp -Please note that current nghttpx implementation does not delete a -socket with a filename. And on start up, if nghttpx detects that the -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 Python script -\fBfetch\-ocsp\-response\fP, which has been originally developed in Perl -as part of h2o project (\fI\%https://github.com/h2o/h2o\fP), and was -translated into Python. -.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. -.sp -If OCSP query is failed, previous OCSP response, if any, is continued -to be used. -.SH TLS SESSION RESUMPTION -.sp -nghttpx supports TLS session resumption through both session ID and -session ticket. -.SS SESSION ID RESUMPTION -.sp -By default, session ID is shared by all worker threads. -.sp -If \fI\%\-\-tls\-session\-cache\-memcached\fP is given, nghttpx will -insert serialized session data to memcached with -\fBnghttpx:tls\-session\-cache:\fP + lowercased hex string of session ID -as a memcached entry key, with expiry time 12 hours. Session timeout -is set to 12 hours. -.sp -By default, connections to memcached server are not encrypted. To -enable encryption, use \fBtls\fP keyword in -\fI\%\-\-tls\-session\-cache\-memcached\fP option. -.SS TLS SESSION TICKET RESUMPTION -.sp -By default, session ticket is shared by all worker threads. The -automatic key rotation is also enabled by default. Every an hour, new -encryption key is generated, and previous encryption key becomes -decryption only key. We set session timeout to 12 hours, and thus we -keep at most 12 keys. -.sp -If \fI\%\-\-tls\-ticket\-key\-memcached\fP is given, encryption keys are -retrieved from memcached. nghttpx just reads keys from memcached; one -has to deploy key generator program to update keys frequently (e.g., -every 1 hour). The example key generator tlsticketupdate.go is -available under contrib directory in nghttp2 archive. The memcached -entry key is \fBnghttpx:tls\-ticket\-key\fP\&. The data format stored in -memcached is the binary format described below: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -+\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ -| VERSION (4) |LEN (2)|KEY(48 or 80) ... -+\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ - ^ | - | | - +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ - (LEN, KEY) pair can be repeated -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -All numbers in the above figure is bytes. All integer fields are -network byte order. -.sp -First 4 bytes integer VERSION field, which must be 1. The 2 bytes -integer LEN field gives the length of following KEY field, which -contains key. If \fI\%\-\-tls\-ticket\-key\-cipher\fP=aes\-128\-cbc is -used, LEN must be 48. If -\fI\%\-\-tls\-ticket\-key\-cipher\fP=aes\-256\-cbc is used, LEN must be -80. LEN and KEY pair can be repeated multiple times to store multiple -keys. The key appeared first is used as encryption key. All the -remaining keys are used as decryption only. -.sp -By default, connections to memcached server are not encrypted. To -enable encryption, use \fBtls\fP keyword in -\fI\%\-\-tls\-ticket\-key\-memcached\fP option. -.sp -If \fI\%\-\-tls\-ticket\-key\-file\fP is given, encryption key is read -from the given file. In this case, nghttpx does not rotate key -automatically. To rotate key, one has to restart nghttpx (see -SIGNALS). -.SH MRUBY SCRIPTING -.sp -\fBWARNING:\fP -.INDENT 0.0 -.INDENT 3.5 -The current mruby extension API is experimental and not frozen. The -API is subject to change in the future release. -.UNINDENT -.UNINDENT -.sp -nghttpx allows users to extend its capability using mruby scripts. -nghttpx has 2 hook points to execute mruby script: request phase and -response phase. The request phase hook is invoked after all request -header fields are received from client. The response phase hook is -invoked after all response header fields are received from backend -server. These hooks allows users to modify header fields, or common -HTTP variables, like authority or request path, and even return custom -response without forwarding request to backend servers. -.sp -To specify mruby script file, use \fI\%\-\-mruby\-file\fP option. The -script will be evaluated once per thread on startup, and it must -instantiate object and evaluate it as the return value (e.g., -\fBApp.new\fP). This object is called app object. If app object -defines \fBon_req\fP method, it is called with \fI\%Nghttpx::Env\fP -object on request hook. Similarly, if app object defines \fBon_resp\fP -method, it is called with \fI\%Nghttpx::Env\fP object on response -hook. For each method invocation, user can can access -\fI\%Nghttpx::Request\fP and \fI\%Nghttpx::Response\fP objects -via \fI\%Nghttpx::Env#req\fP and \fI\%Nghttpx::Env#resp\fP -respectively. -.INDENT 0.0 -.TP -.B Nghttpx::REQUEST_PHASE -Constant to represent request phase. -.UNINDENT -.INDENT 0.0 -.TP -.B Nghttpx::RESPONSE_PHASE -Constant to represent response phase. -.UNINDENT -.INDENT 0.0 -.TP -.B class Nghttpx::Env -Object to represent current request specific context. -.INDENT 7.0 -.TP -.B attribute [R] req -Return \fI\%Request\fP object. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] resp -Return \fI\%Response\fP object. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] ctx -Return Ruby hash object. It persists until request finishes. -So values set in request phase hoo can be retrieved in -response phase hook. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] phase -Return the current phase. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] remote_addr -Return IP address of a remote client. If connection is made -via UNIX domain socket, this returns the string "localhost". -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] server_addr -Return address of server that accepted the connection. This -is a string which specified in \fI\%\-\-frontend\fP option, -excluding port number, and not a resolved IP address. For -UNIX domain socket, this is a path to UNIX domain socket. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] server_port -Return port number of the server frontend which accepted the -connection from client. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] tls_used -Return true if TLS is used on the connection. -.UNINDENT -.UNINDENT -.INDENT 0.0 -.TP -.B class Nghttpx::Request -Object to represent request from client. The modification to -Request object is allowed only in request phase hook. -.INDENT 7.0 -.TP -.B attribute [R] http_version_major -Return HTTP major version. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] http_version_minor -Return HTTP minor version. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R/W] method -HTTP method. On assignment, copy of given value is assigned. -We don\(aqt accept arbitrary method name. We will document them -later, but well known methods, like GET, PUT and POST, are all -supported. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R/W] authority -Authority (i.e., example.org), including optional port -component . On assignment, copy of given value is assigned. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R/W] scheme -Scheme (i.e., http, https). On assignment, copy of given -value is assigned. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R/W] path -Request path, including query component (i.e., /index.html). -On assignment, copy of given value is assigned. The path does -not include authority component of URI. This may include -query component. nghttpx makes certain normalization for -path. It decodes percent\-encoding for unreserved characters -(see \fI\%https://tools.ietf.org/html/rfc3986#section\-2.3\fP), and -resolves ".." and ".". But it may leave characters which -should be percent\-encoded as is. So be careful when comparing -path against desired string. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] headers -Return Ruby hash containing copy of request header fields. -Changing values in returned hash does not change request -header fields actually used in request processing. Use -\fI\%Nghttpx::Request#add_header\fP or -\fI\%Nghttpx::Request#set_header\fP to change request -header fields. -.UNINDENT -.INDENT 7.0 -.TP -.B add_header(key, value) -Add header entry associated with key. The value can be single -string or array of string. It does not replace any existing -values associated with key. -.UNINDENT -.INDENT 7.0 -.TP -.B set_header(key, value) -Set header entry associated with key. The value can be single -string or array of string. It replaces any existing values -associated with key. -.UNINDENT -.INDENT 7.0 -.TP -.B clear_headers() -Clear all existing request header fields. -.UNINDENT -.INDENT 7.0 -.TP -.B push(uri) -Initiate to push resource identified by \fIuri\fP\&. Only HTTP/2 -protocol supports this feature. For the other protocols, this -method is noop. \fIuri\fP can be absolute URI, absolute path or -relative path to the current request. For absolute or -relative path, scheme and authority are inherited from the -current request. Currently, method is always GET. nghttpx -will issue request to backend servers to fulfill this request. -The request and response phase hooks will be called for pushed -resource as well. -.UNINDENT -.UNINDENT -.INDENT 0.0 -.TP -.B class Nghttpx::Response -Object to represent response from backend server. -.INDENT 7.0 -.TP -.B attribute [R] http_version_major -Return HTTP major version. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] http_version_minor -Return HTTP minor version. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R/W] status -HTTP status code. It must be in the range [200, 999], -inclusive. The non\-final status code is not supported in -mruby scripting at the moment. -.UNINDENT -.INDENT 7.0 -.TP -.B attribute [R] headers -Return Ruby hash containing copy of response header fields. -Changing values in returned hash does not change response -header fields actually used in response processing. Use -\fI\%Nghttpx::Response#add_header\fP or -\fI\%Nghttpx::Response#set_header\fP to change response -header fields. -.UNINDENT -.INDENT 7.0 -.TP -.B add_header(key, value) -Add header entry associated with key. The value can be single -string or array of string. It does not replace any existing -values associated with key. -.UNINDENT -.INDENT 7.0 -.TP -.B set_header(key, value) -Set header entry associated with key. The value can be single -string or array of string. It replaces any existing values -associated with key. -.UNINDENT -.INDENT 7.0 -.TP -.B clear_headers() -Clear all existing response header fields. -.UNINDENT -.INDENT 7.0 -.TP -.B return(body) -Return custom response \fIbody\fP to a client. When this method -is called in request phase hook, the request is not forwarded -to the backend, and response phase hook for this request will -not be invoked. When this method is called in response phase -hook, response from backend server is canceled and discarded. -The status code and response header fields should be set -before using this method. To set status code, use :rb:meth To -set response header fields, use -\fI\%Nghttpx::Response#status\fP\&. If status code is not -set, 200 is used. \fI\%Nghttpx::Response#add_header\fP and -\fI\%Nghttpx::Response#set_header\fP\&. When this method is -invoked in response phase hook, the response headers are -filled with the ones received from backend server. To send -completely custom header fields, first call -\fI\%Nghttpx::Response#clear_headers\fP to erase all -existing header fields, and then add required header fields. -It is an error to call this method twice for a given request. -.UNINDENT -.UNINDENT -.SS MRUBY EXAMPLES -.sp -Modify request path: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -class App - def on_req(env) - env.req.path = "/apps#{env.req.path}" - end -end - -App.new -.ft P -.fi -.UNINDENT -.UNINDENT -.sp -Don\(aqt forget to instantiate and evaluate object at the last line. -.sp -Restrict permission of viewing a content to a specific client -addresses: -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -class App - def on_req(env) - allowed_clients = ["127.0.0.1", "::1"] - - if env.req.path.start_with?("/log/") && - !allowed_clients.include?(env.remote_addr) then - env.resp.status = 404 - env.resp.return "permission denied" - end - end -end +.SH "SEE ALSO" -App.new -.ft P -.fi -.UNINDENT -.UNINDENT -.SH API ENDPOINTS -.sp -nghttpx exposes API endpoints to manipulate it via HTTP based API. By -default, API endpoint is disabled. To enable it, add a dedicated -frontend for API using \fI\%\-\-frontend\fP option with "api" -parameter. All requests which come from this frontend address, will -be treated as API request. -.sp -The response is normally JSON dictionary, and at least includes the -following keys: -.INDENT 0.0 -.TP -.B status -The status of the request processing. The following values are -defined: -.INDENT 7.0 -.TP -.B Success -The request was successful. -.TP -.B Failure -The request was failed. No change has been made. -.UNINDENT -.TP -.B code -HTTP status code -.UNINDENT -.sp -We wrote "normally", since nghttpx may return ordinal HTML response in -some cases where the error has occurred before reaching API endpoint -(e.g., header field is too large). -.sp -The following section describes available API endpoints. -.SS PUT /api/v1beta1/backendconfig -.sp -This API replaces the current backend server settings with the -requested ones. The request method should be PUT, but POST is also -acceptable. The request body must be nghttpx configuration file -format. For configuration file format, see \fI\%FILES\fP section. The -line separator inside the request body must be single LF (0x0A). -Currently, only \fI\%backend\fP option is parsed, the -others are simply ignored. The semantics of this API is replace the -current backend with the backend options in request body. Describe -the desired set of backend severs, and nghttpx makes it happen. If -there is no \fI\%backend\fP option is found in request -body, the current set of backend is replaced with the \fI\%backend\fP option\(aqs default value, which is \fB127.0.0.1,80\fP\&. -.sp -The replacement is done instantly without breaking existing -connections or requests. It also avoids any process creation as is -the case with hot swapping with signals. -.sp -The one limitation is that only numeric IP address is allowd in -\fI\%backend\fP in request body while non numeric -hostname is allowed in command\-line or configuration file is read -using \fI\%\-\-conf\fP\&. -.SH SEE ALSO -.sp -\fBnghttp(1)\fP, \fBnghttpd(1)\fP, \fBh2load(1)\fP -.SH AUTHOR -Tatsuhiro Tsujikawa -.SH COPYRIGHT -2012, 2015, 2016, Tatsuhiro Tsujikawa -.\" Generated by docutils manpage writer. -. +nghttp(1), nghttpd(1), h2load(1) diff -Nru nghttp2-1.13.0/doc/nghttpx.1.rst nghttp2-0.6.7/doc/nghttpx.1.rst --- nghttp2-1.13.0/doc/nghttpx.1.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/nghttpx.1.rst 2014-11-30 14:15:07.000000000 +0000 @@ -1,33 +1,33 @@ - -.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY. +.. DO NOT MODIFY THIS FILE! It was generated by man2rst.py .. program:: nghttpx nghttpx(1) ========== +NAME +---- +nghttpx - HTTP/2 experimental proxy + SYNOPSIS -------- - **nghttpx** [OPTIONS]... [ ] DESCRIPTION ----------- - A reverse proxy for HTTP/2, HTTP/1 and SPDY. -.. describe:: +.. option:: PRIVATE_KEY - - Set path to server's private key. Required unless - "no-tls" parameter is used in :option:`--frontend` option. - -.. describe:: + Set path to server's private key. Required + unless :option:`-p`, :option:`--client` or :option:`--frontend-no-tls` are + given. - Set path to server's certificate. Required unless - "no-tls" parameter is used in :option:`--frontend` option. To - make OCSP stapling work, this must be an absolute path. +.. option:: CERT + Set path to server's certificate. Required + unless :option:`-p`, :option:`--client` or :option:`--frontend-no-tls` are + given. OPTIONS ------- @@ -35,1604 +35,604 @@ The options are categorized into several groups. Connections -~~~~~~~~~~~ +^^^^^^^^^^^ -.. option:: -b, --backend=(,|unix:)[;[[:...]][[;PARAM]...] +.. option:: -b, --backend= + + Set backend host and port. + Default: '127.0.0.1,80' - Set backend host and port. The multiple backend - addresses are accepted by repeating this option. UNIX - domain socket can be specified by prefixing path name - with "unix:" (e.g., unix:/var/run/backend.sock). - - Optionally, if s are given, the backend address - is only used if request matches the pattern. If - :option:`--http2-proxy` is used, s are ignored. The - pattern matching is closely designed to ServeMux in - net/http package of Go programming language. - consists of path, host + path or just host. The path - must start with "*/*". If it ends with "*/*", it matches - all request path in its subtree. To deal with the - request to the directory without trailing slash, the - path which ends with "*/*" also matches the request path - which only lacks trailing '*/*' (e.g., path "*/foo/*" - matches request path "*/foo*"). If it does not end with - "*/*", it performs exact match against the request path. - If host is given, it performs exact match against the - request host. If host alone is given, "*/*" is appended - to it, so that it matches all request paths under the - host (e.g., specifying "nghttp2.org" equals to - "nghttp2.org/"). - - Patterns with host take precedence over patterns with - just path. Then, longer patterns take precedence over - shorter ones. - - Host can include "\*" in the left most position to - indicate wildcard match (only suffix match is done). - The "*" must match at least one character. For example, - host pattern "\*.nghttp2.org" matches against - "www.nghttp2.org" and "git.ngttp2.org", but does not - match against "nghttp2.org". The exact hosts match - takes precedence over the wildcard hosts match. - - If is omitted or empty string, "*/*" is used as - pattern, which matches all request paths (catch-all - pattern). The catch-all backend must be given. - - When doing a match, nghttpx made some normalization to - pattern, request host and path. For host part, they are - converted to lower case. For path part, percent-encoded - unreserved characters defined in RFC 3986 are decoded, - and any dot-segments (".." and ".") are resolved and - removed. - - For example, :option:`-b`\'127.0.0.1,8080;nghttp2.org/httpbin/' - matches the request host "nghttp2.org" and the request - path "*/httpbin/get*", but does not match the request host - "nghttp2.org" and the request path "*/index.html*". - - The multiple s can be specified, delimiting - them by ":". Specifying - :option:`-b`\'127.0.0.1,8080;nghttp2.org:www.nghttp2.org' has the - same effect to specify :option:`-b`\'127.0.0.1,8080;nghttp2.org' - and :option:`-b`\'127.0.0.1,8080;www.nghttp2.org'. - - The backend addresses sharing same are grouped - together forming load balancing group. - - Several parameters are accepted after . - The parameters are delimited by ";". The available - parameters are: "proto=", "tls", - "sni=", "fall=", "rise=", and - "affinity=". The parameter consists of keyword, - and optionally followed by "=" and value. For example, - the parameter "proto=h2" consists of the keyword "proto" - and value "h2". The parameter "tls" consists of the - keyword "tls" without value. Each parameter is - described as follows. - - The backend application protocol can be specified using - optional "proto" parameter, and in the form of - "proto=". should be one of the following - list without quotes: "h2", "http/1.1". The default - value of is "http/1.1". Note that usually "h2" - refers to HTTP/2 over TLS. But in this option, it may - mean HTTP/2 over cleartext TCP unless "tls" keyword is - used (see below). - - TLS can be enabled by specifying optional "tls" - parameter. TLS is not enabled by default. - - With "sni=" parameter, it can override the TLS - SNI field value with given . This will - default to the backend name - - The feature to detect whether backend is online or - offline can be enabled using optional "fall" and "rise" - parameters. Using "fall=" parameter, if nghttpx - cannot connect to a this backend times in a row, - this backend is assumed to be offline, and it is - excluded from load balancing. If is 0, this backend - never be excluded from load balancing whatever times - nghttpx cannot connect to it, and this is the default. - There is also "rise=" parameter. After backend was - excluded from load balancing group, nghttpx periodically - attempts to make a connection to the failed backend, and - if the connection is made successfully times in a - row, the backend is assumed to be online, and it is now - eligible for load balancing target. If is 0, a - backend is permanently offline, once it goes in that - state, and this is the default behaviour. - - The session affinity is enabled using - "affinity=" parameter. If "ip" is given in - , client IP based session affinity is enabled. - If "none" is given in , session affinity is - disabled, and this is the default. The session affinity - is enabled per . If at least one backend has - "affinity" parameter, and its is not "none", - session affinity is enabled for all backend servers - sharing the same . It is advised to set - "affinity" parameter to all backend explicitly if - session affinity is desired. The session affinity may - break if one of the backend gets unreachable, or backend - settings are reloaded or replaced by API. - - Since ";" and ":" are used as delimiter, must - not contain these characters. Since ";" has special - meaning in shell, the option value must be quoted. - - - Default: ``127.0.0.1,80`` - -.. option:: -f, --frontend=(,|unix:)[[;PARAM]...] - - Set frontend host and port. If is '\*', it - assumes all addresses including both IPv4 and IPv6. - UNIX domain socket can be specified by prefixing path - name with "unix:" (e.g., unix:/var/run/nghttpx.sock). - This option can be used multiple times to listen to - multiple addresses. - - This option can take 0 or more parameters, which are - described below. Note that "api" and "healthmon" - parameters are mutually exclusive. - - Optionally, TLS can be disabled by specifying "no-tls" - parameter. TLS is enabled by default. - - To make this frontend as API endpoint, specify "api" - parameter. This is disabled by default. It is - important to limit the access to the API frontend. - Otherwise, someone may change the backend server, and - break your services, or expose confidential information - to the outside the world. - - To make this frontend as health monitor endpoint, - specify "healthmon" parameter. This is disabled by - default. Any requests which come through this address - are replied with 200 HTTP status, without no body. - - - Default: ``*,3000`` - -.. option:: --backlog= - - Set listen backlog size. - - Default: ``512`` - -.. option:: --backend-address-family=(auto|IPv4|IPv6) - - Specify address family of backend connections. If - "auto" is given, both IPv4 and IPv6 are considered. If - "IPv4" is given, only IPv4 address is considered. If - "IPv6" is given, only IPv6 address is considered. +.. option:: -f, --frontend= - Default: ``auto`` + + Set frontend host and port. If is '\*', it + assumes all addresses including both IPv4 and + IPv6. + Default: '\*,3000' -.. option:: --backend-http-proxy-uri= +.. option:: --backlog= - Specify proxy URI in the form - http://[:@]:. If a proxy - requires authentication, specify and . - Note that they must be properly percent-encoded. This - proxy is used when the backend connection is HTTP/2. - First, make a CONNECT request to the proxy and it - connects to the backend on behalf of nghttpx. This - forms tunnel. After that, nghttpx performs SSL/TLS - handshake with the downstream through the tunnel. The - timeouts when connecting and making CONNECT request can - be specified by :option:`--backend-read-timeout` and - :option:`--backend-write-timeout` options. + + Set listen backlog size. If -1 is given, + libevent will choose suitable value. + Default: -1 -.. option:: --accept-proxy-protocol +.. option:: --backend-ipv4 - Accept PROXY protocol version 1 on frontend connection. + + Resolve backend hostname to IPv4 address only. +.. option:: --backend-ipv6 -Performance -~~~~~~~~~~~ - -.. option:: -n, --workers= + + Resolve backend hostname to IPv6 address only. - Set the number of worker threads. +.. option:: --backend-http-proxy-uri= - Default: ``1`` + + Specify proxy URI in the form + http://[:@]:. If a + proxy requires authentication, specify and + . Note that they must be properly + percent-encoded. This proxy is used when the + backend connection is HTTP/2. First, make a + CONNECT request to the proxy and it connects to + the backend on behalf of nghttpx. This forms + tunnel. After that, nghttpx performs SSL/TLS + handshake with the downstream through the tunnel. + The timeouts when connecting and making CONNECT + request can be specified by + :option:`--backend-read-timeout` and + :option:`--backend-write-timeout` options. -.. option:: --read-rate= +Performance +^^^^^^^^^^^ - Set maximum average read rate on frontend connection. - Setting 0 to this option means read rate is unlimited. +.. option:: -n, --workers= - Default: ``0`` + + Set the number of worker threads. + Default: 1 -.. option:: --read-burst= +.. option:: --read-rate= - Set maximum read burst size on frontend connection. - Setting 0 to this option means read burst size is - unlimited. + + Set maximum average read rate on frontend + connection. Setting 0 to this option means read + rate is unlimited. + Default: 0 - Default: ``0`` +.. option:: --read-burst= -.. option:: --write-rate= + + Set maximum read burst size on frontend + connection. Setting 0 does not work, but it is + not a problem because --read-rate=0 will give + unlimited read rate regardless of this option + value. + Default: 1073741824 - Set maximum average write rate on frontend connection. - Setting 0 to this option means write rate is unlimited. +.. option:: --write-rate= - Default: ``0`` + + Set maximum average write rate on frontend + connection. Setting 0 to this option means write + rate is unlimited. + Default: 0 .. option:: --write-burst= - Set maximum write burst size on frontend connection. - Setting 0 to this option means write burst size is - unlimited. - - Default: ``0`` - -.. option:: --worker-read-rate= + + Set maximum write burst size on frontend + connection. Setting 0 to this option means write + burst size is unlimited. + Default: 0 - Set maximum average read rate on frontend connection per - worker. Setting 0 to this option means read rate is - unlimited. Not implemented yet. +.. option:: --worker-read-rate= - Default: ``0`` + + Set maximum average read rate on frontend + connection per worker. Setting 0 to this option + means read rate is unlimited. + Default: 0 .. option:: --worker-read-burst= - Set maximum read burst size on frontend connection per - worker. Setting 0 to this option means read burst size - is unlimited. Not implemented yet. - - Default: ``0`` - -.. option:: --worker-write-rate= + + Set maximum read burst size on frontend + connection per worker. Setting 0 to this option + means read burst size is unlimited. + Default: 0 - Set maximum average write rate on frontend connection - per worker. Setting 0 to this option means write rate - is unlimited. Not implemented yet. +.. option:: --worker-write-rate= - Default: ``0`` + + Set maximum average write rate on frontend + connection per worker. Setting 0 to this option + means write rate is unlimited. + Default: 0 .. option:: --worker-write-burst= - Set maximum write burst size on frontend connection per - worker. Setting 0 to this option means write burst size - is unlimited. Not implemented yet. - - Default: ``0`` - -.. option:: --worker-frontend-connections= - - Set maximum number of simultaneous connections frontend - accepts. Setting 0 means unlimited. - - Default: ``0`` - -.. option:: --backend-connections-per-host= - - Set maximum number of backend concurrent connections - (and/or streams in case of HTTP/2) per origin host. - This option is meaningful when :option:`--http2-proxy` option is - used. The origin host is determined by authority - portion of request URI (or :authority header field for - HTTP/2). To limit the number of connections per - frontend for default mode, use - :option:`--backend-connections-per-frontend`\. - - Default: ``8`` - -.. option:: --backend-connections-per-frontend= - - Set maximum number of backend concurrent connections - (and/or streams in case of HTTP/2) per frontend. This - option is only used for default mode. 0 means - unlimited. To limit the number of connections per host - with :option:`--http2-proxy` option, use - :option:`--backend-connections-per-host`\. - - Default: ``0`` - -.. option:: --rlimit-nofile= - - Set maximum number of open files (RLIMIT_NOFILE) to . - If 0 is given, nghttpx does not set the limit. - - Default: ``0`` - -.. option:: --backend-request-buffer= - - Set buffer size used to store backend request. - - Default: ``16K`` - -.. option:: --backend-response-buffer= - - Set buffer size used to store backend response. - - Default: ``128K`` - -.. option:: --fastopen= - - Enables "TCP Fast Open" for the listening socket and - limits the maximum length for the queue of connections - that have not yet completed the three-way handshake. If - value is 0 then fast open is disabled. + + Set maximum write burst size on frontend + connection per worker. Setting 0 to this option + means write burst size is unlimited. + Default: 0 - Default: ``0`` +.. option:: --worker-frontend-connections= -.. option:: --no-kqueue + + Set maximum number of simultaneous connections + frontend accepts. Setting 0 means unlimited. + Default: 0 - Don't use kqueue. This option is only applicable for - the platforms which have kqueue. For other platforms, - this option will be simply ignored. +.. option:: --backend-connections-per-frontend= + + Set maximum number of backend simultaneous + connections per frontend. This option is + meaningful when the combination of HTTP/2 or SPDY + frontend and HTTP/1 backend is used. + Default: 100 Timeout -~~~~~~~ +^^^^^^^ -.. option:: --frontend-http2-read-timeout= +.. option:: --frontend-http2-read-timeout= - Specify read timeout for HTTP/2 and SPDY frontend + + Specify read timeout for HTTP/2 and SPDY frontend connection. + Default: 180 - Default: ``3m`` - -.. option:: --frontend-read-timeout= - - Specify read timeout for HTTP/1.1 frontend connection. - - Default: ``1m`` +.. option:: --frontend-read-timeout= -.. option:: --frontend-write-timeout= - - Specify write timeout for all frontend connections. - - Default: ``30s`` + + Specify read timeout for HTTP/1.1 frontend + connection. + Default: 30 -.. option:: --stream-read-timeout= +.. option:: --frontend-write-timeout= - Specify read timeout for HTTP/2 and SPDY streams. 0 - means no timeout. + + Specify write timeout for all frontend + connections. + Default: 30 - Default: ``0`` +.. option:: --stream-read-timeout= -.. option:: --stream-write-timeout= + + Specify read timeout for HTTP/2 and SPDY streams. + 0 means no timeout. + Default: 0 - Specify write timeout for HTTP/2 and SPDY streams. 0 - means no timeout. +.. option:: --stream-write-timeout= - Default: ``0`` + + Specify write timeout for HTTP/2 and SPDY + streams. 0 means no timeout. + Default: 0 -.. option:: --backend-read-timeout= +.. option:: --backend-read-timeout= + Specify read timeout for backend connection. + Default: 30 - Default: ``1m`` - -.. option:: --backend-write-timeout= +.. option:: --backend-write-timeout= + Specify write timeout for backend connection. + Default: 30 - Default: ``30s`` - -.. option:: --backend-keep-alive-timeout= - - Specify keep-alive timeout for backend connection. +.. option:: --backend-keep-alive-timeout= - Default: ``2s`` - -.. option:: --listener-disable-timeout= - - After accepting connection failed, connection listener - is disabled for a given amount of time. Specifying 0 - disables this feature. - - Default: ``30s`` - -.. option:: --frontend-http2-setting-timeout= - - Specify timeout before SETTINGS ACK is received from - client. - - Default: ``10s`` - -.. option:: --backend-http2-settings-timeout= - - Specify timeout before SETTINGS ACK is received from - backend server. - - Default: ``10s`` - -.. option:: --backend-max-backoff= - - Specify maximum backoff interval. This is used when - doing health check against offline backend (see "fail" - parameter in :option:`--backend` option). It is also used to - limit the maximum interval to temporarily disable - backend when nghttpx failed to connect to it. These - intervals are calculated using exponential backoff, and - consecutive failed attempts increase the interval. This - option caps its maximum value. + + Specify keep-alive timeout for backend + connection. + Default: 60 - Default: ``2m`` +.. option:: --listener-disable-timeout= + + After accepting connection failed, connection + listener is disabled for a given time in seconds. + Specifying 0 disables this feature. + Default: 0 SSL/TLS -~~~~~~~ +^^^^^^^ .. option:: --ciphers= - Set allowed cipher list. The format of the string is - described in OpenSSL ciphers(1). + + Set allowed cipher list. The format of the + string is described in OpenSSL ciphers(1). .. option:: -k, --insecure - Don't verify backend server's certificate if TLS is - enabled for backend connections. + + Don't verify backend server's certificate if :option:`-p`, + :option:`--client` or :option:`--http2-bridge` are given and + :option:`--backend-no-tls` is not given. .. option:: --cacert= - Set path to trusted CA certificate file used in backend - TLS connections. The file must be in PEM format. It - can contain multiple certificates. If the linked - OpenSSL is configured to load system wide certificates, - they are loaded at startup regardless of this option. - -.. option:: --private-key-passwd-file= - - Path to file that contains password for the server's - private key. If none is given and the private key is - password protected it'll be requested interactively. + + Set path to trusted CA certificate file if :option:`-p`, + :option:`--client` or :option:`--http2-bridge` are given and + :option:`--backend-no-tls` is not given. The file must be + in PEM format. It can contain multiple + certificates. If the linked OpenSSL is + configured to load system wide certificates, they + are loaded at startup regardless of this option. + +.. option:: --private-key-passwd-file= + + + Path to file that contains password for the + server's private key. If none is given and the + private key is password protected it'll be + requested interactively. .. option:: --subcert=: - 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. To make OCSP - stapling work, must be absolute path. + + 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:: --backend-tls-sni-field= + + + Explicitly set the content of the TLS SNI + extension. This will default to the backend HOST + name. .. option:: --dh-param-file= - Path to file that contains DH parameters in PEM format. - Without this option, DHE cipher suites are not - available. + + Path to file that contains DH parameters in PEM + format. Without this option, DHE cipher suites + are not available. .. option:: --npn-list= - Comma delimited list of ALPN protocol identifier sorted - in the order of preference. That means most desirable - protocol comes first. This is used in both ALPN and - NPN. The parameter must be delimited by a single comma - only and any white spaces are treated as a part of - protocol string. - - Default: ``h2,h2-16,h2-14,spdy/3.1,http/1.1`` + + Comma delimited list of ALPN protocol identifier + sorted in the order of preference. That means + most desirable protocol comes first. This is + used in both ALPN and NPN. The parameter must be + delimited by a single comma only and any white + spaces are treated as a part of protocol string. + Default: h2-14,spdy/3.1,http/1.1 .. option:: --verify-client + Require and verify client certificate. .. option:: --verify-client-cacert= - Path to file that contains CA certificates to verify - client certificate. The file must be in PEM format. It - can contain multiple certificates. + + Path to file that contains CA certificates to + verify client certificate. The file must be in + PEM format. It can contain multiple + certificates. .. option:: --client-private-key-file= - Path to file that contains client private key used in - backend client authentication. + + Path to file that contains client private key + used in backend client authentication. .. option:: --client-cert-file= - Path to file that contains client certificate used in - backend client authentication. + + Path to file that contains client certificate + used in backend client authentication. .. option:: --tls-proto-list= - Comma delimited list of SSL/TLS protocol to be enabled. - The following protocols are available: TLSv1.2, TLSv1.1 - and TLSv1.0. The name matching is done in - case-insensitive manner. The parameter must be - delimited by a single comma only and any white spaces - are treated as a part of protocol string. If the - protocol list advertised by client does not overlap this - list, you will receive the error message "unknown - protocol". - - Default: ``TLSv1.2,TLSv1.1`` - -.. option:: --tls-ticket-key-file= - - Path to file that contains random data to construct TLS - session ticket parameters. If aes-128-cbc is given in - :option:`--tls-ticket-key-cipher`\, the file must contain exactly - 48 bytes. If aes-256-cbc is given in - :option:`--tls-ticket-key-cipher`\, the file must contain exactly - 80 bytes. This options can be used repeatedly to - specify multiple ticket parameters. If several files - are given, only the first key is used to encrypt TLS - session tickets. Other keys are accepted but server - will issue new session ticket with first key. This - allows session key rotation. Please note that key - rotation does not occur automatically. User should - rearrange files or change options values and restart - nghttpx gracefully. If opening or reading given file - fails, all loaded keys are discarded and it is treated - as if none of this option is given. If this option is - not given or an error occurred while opening or reading - a file, key is generated every 1 hour internally and - they are valid for 12 hours. This is recommended if - ticket key sharing between nghttpx instances is not - required. - -.. option:: --tls-ticket-key-memcached=,[;tls] - - Specify address of memcached server to get TLS ticket - keys for session resumption. This enables shared TLS - ticket key between multiple nghttpx instances. nghttpx - does not set TLS ticket key to memcached. The external - ticket key generator is required. nghttpx just gets TLS - ticket keys from memcached, and use them, possibly - replacing current set of keys. It is up to extern TLS - ticket key generator to rotate keys frequently. See - "TLS SESSION TICKET RESUMPTION" section in manual page - to know the data format in memcached entry. Optionally, - memcached connection can be encrypted with TLS by - specifying "tls" parameter. - -.. option:: --tls-ticket-key-memcached-address-family=(auto|IPv4|IPv6) - - Specify address family of memcached connections to get - TLS ticket keys. If "auto" is given, both IPv4 and IPv6 - are considered. If "IPv4" is given, only IPv4 address - is considered. If "IPv6" is given, only IPv6 address is - considered. - - Default: ``auto`` - -.. option:: --tls-ticket-key-memcached-interval= - - Set interval to get TLS ticket keys from memcached. - - Default: ``10m`` - -.. option:: --tls-ticket-key-memcached-max-retry= - - Set maximum number of consecutive retries before - abandoning TLS ticket key retrieval. If this number is - reached, the attempt is considered as failure, and - "failure" count is incremented by 1, which contributed - to the value controlled - :option:`--tls-ticket-key-memcached-max-fail` option. - - Default: ``3`` - -.. option:: --tls-ticket-key-memcached-max-fail= - - Set maximum number of consecutive failure before - disabling TLS ticket until next scheduled key retrieval. - - Default: ``2`` - -.. option:: --tls-ticket-key-cipher= - - Specify cipher to encrypt TLS session ticket. Specify - either aes-128-cbc or aes-256-cbc. By default, - aes-128-cbc is used. - -.. option:: --tls-ticket-key-memcached-cert-file= - - Path to client certificate for memcached connections to - get TLS ticket keys. - -.. option:: --tls-ticket-key-memcached-private-key-file= - - Path to client private key for memcached connections to - get TLS ticket keys. - -.. option:: --fetch-ocsp-response-file= - - Path to fetch-ocsp-response script file. It should be - absolute path. - - Default: ``/usr/local/share/nghttp2/fetch-ocsp-response`` - -.. option:: --ocsp-update-interval= - - Set interval to update OCSP response cache. - - Default: ``4h`` - -.. option:: --no-ocsp - - Disable OCSP stapling. - -.. option:: --tls-session-cache-memcached=,[;tls] - - Specify address of memcached server to store session - cache. This enables shared session cache between - multiple nghttpx instances. Optionally, memcached - connection can be encrypted with TLS by specifying "tls" - parameter. - -.. option:: --tls-session-cache-memcached-address-family=(auto|IPv4|IPv6) - - Specify address family of memcached connections to store - session cache. If "auto" is given, both IPv4 and IPv6 - are considered. If "IPv4" is given, only IPv4 address - is considered. If "IPv6" is given, only IPv6 address is - considered. - - Default: ``auto`` - -.. option:: --tls-session-cache-memcached-cert-file= - - Path to client certificate for memcached connections to - store session cache. - -.. option:: --tls-session-cache-memcached-private-key-file= - - Path to client private key for memcached connections to - store session cache. - -.. option:: --tls-dyn-rec-warmup-threshold= - - Specify the threshold size for TLS dynamic record size - behaviour. During a TLS session, after the threshold - number of bytes have been written, the TLS record size - will be increased to the maximum allowed (16K). The max - record size will continue to be used on the active TLS - session. After :option:`--tls-dyn-rec-idle-timeout` has elapsed, - the record size is reduced to 1300 bytes. Specify 0 to - always use the maximum record size, regardless of idle - period. This behaviour applies to all TLS based - frontends, and TLS HTTP/2 backends. - - Default: ``1M`` - -.. option:: --tls-dyn-rec-idle-timeout= - - Specify TLS dynamic record size behaviour timeout. See - :option:`--tls-dyn-rec-warmup-threshold` for more information. - This behaviour applies to all TLS based frontends, and - TLS HTTP/2 backends. - - Default: ``1s`` - -.. option:: --no-http2-cipher-black-list - - Allow black listed cipher suite on HTTP/2 connection. - See https://tools.ietf.org/html/rfc7540#appendix-A for - the complete HTTP/2 cipher suites black list. - + + Comma delimited list of SSL/TLS protocol to be + enabled. The following protocols are available: + TLSv1.2, TLSv1.1 and TLSv1.0. The name matching + is done in case-insensitive manner. The + parameter must be delimited by a single comma + only and any white spaces are treated as a part + of protocol string. + Default: TLSv1.2,TLSv1.1 HTTP/2 and SPDY -~~~~~~~~~~~~~~~ - -.. option:: -c, --frontend-http2-max-concurrent-streams= +^^^^^^^^^^^^^^^ - Set the maximum number of the concurrent streams in one - frontend HTTP/2 and SPDY session. +.. option:: -c, --http2-max-concurrent-streams= - Default: `` 100`` - -.. option:: --backend-http2-max-concurrent-streams= - - Set the maximum number of the concurrent streams in one - backend HTTP/2 session. This sets maximum number of - concurrent opened pushed streams. The maximum number of - concurrent requests are set by a remote server. - - Default: ``100`` + + Set the maximum number of the concurrent streams + in one HTTP/2 and SPDY session. + Default: 100 .. option:: --frontend-http2-window-bits= - Sets the per-stream initial window size of HTTP/2 SPDY - frontend connection. For HTTP/2, the size is 2\*\*-1. - For SPDY, the size is 2\*\*. - - Default: ``16`` + + Sets the per-stream initial window size of HTTP/2 + SPDY frontend connection. For HTTP/2, the size + is 2\*\*-1. For SPDY, the size is 2\*\*. + Default: 16 .. option:: --frontend-http2-connection-window-bits= - Sets the per-connection window size of HTTP/2 and SPDY - frontend connection. For HTTP/2, the size is - 2**-1. For SPDY, the size is 2\*\*. + + Sets the per-connection window size of HTTP/2 and + SPDY frontend connection. For HTTP/2, the size + is 2\*\*-1. For SPDY, the size is 2\*\*. + Default: 16 + +.. option:: --frontend-no-tls - Default: ``16`` + + Disable SSL/TLS on frontend connections. .. option:: --backend-http2-window-bits= - Sets the initial window size of HTTP/2 backend + + Sets the initial window size of HTTP/2 backend connection to 2\*\*-1. - - Default: ``16`` + Default: 16 .. option:: --backend-http2-connection-window-bits= - Sets the per-connection window size of HTTP/2 backend - connection to 2\*\*-1. + + Sets the per-connection window size of HTTP/2 + backend connection to 2\*\*-1. + Default: 16 + +.. option:: --backend-no-tls - Default: ``30`` + + Disable SSL/TLS on backend connections. .. option:: --http2-no-cookie-crumbling + Don't crumble cookie header field. .. option:: --padding= - Add at most bytes to a HTTP/2 frame payload as - padding. Specify 0 to disable padding. This option is - meant for debugging purpose and not intended to enhance - protocol security. - -.. option:: --no-server-push - - Disable HTTP/2 server push. Server push is supported by - default mode and HTTP/2 frontend via Link header field. - It is also supported if both frontend and backend are - HTTP/2 in default mode. In this case, server push from - backend session is relayed to frontend, and server push - via Link header field is also supported. SPDY frontend - does not support server push. - + + Add at most bytes to a HTTP/2 frame payload + as padding. Specify 0 to disable padding. This + option is meant for debugging purpose and not + intended to enhance protocol security. Mode -~~~~ +^^^^ .. describe:: (default mode) - - Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS. "no-tls" - parameter is used in :option:`--frontend` option, accept HTTP/2 - and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1 - connection can be upgraded to HTTP/2 through HTTP - Upgrade. + Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS. + If :option:`--frontend-no-tls` is used, accept HTTP/2 and + HTTP/1.1. The incoming HTTP/1.1 connection can + be upgraded to HTTP/2 through HTTP Upgrade. The + protocol to the backend is HTTP/1.1. .. option:: -s, --http2-proxy - Like default mode, but enable forward proxy. This is so - called HTTP/2 proxy mode. + + Like default mode, but enable secure proxy mode. + +.. option:: --http2-bridge + + + Like default mode, but communicate with the + backend in HTTP/2 over SSL/TLS. Thus the + incoming all connections are converted to HTTP/2 + connection and relayed to the backend. See + :option:`--backend-http-proxy-uri` option if you are behind + the proxy and want to connect to the outside + HTTP/2 proxy. + +.. option:: --client + + Accept HTTP/2 and HTTP/1.1 without SSL/TLS. The + incoming HTTP/1.1 connection can be upgraded to + HTTP/2 connection through HTTP Upgrade. The + protocol to the backend is HTTP/2. To use + nghttpx as a forward proxy, use :option:`-p` option + instead. + +.. option:: -p, --client-proxy + + + Like :option:`--client` option, but it also requires the + request path from frontend must be an absolute + URI, suitable for use as a forward proxy. Logging -~~~~~~~ +^^^^^^^ .. option:: -L, --log-level= - Set the severity level of log output. must be - one of INFO, NOTICE, WARN, ERROR and FATAL. - - Default: ``NOTICE`` + + Set the severity level of log output. + must be one of INFO, NOTICE, WARN, ERROR and + FATAL. + Default: NOTICE .. option:: --accesslog-file= - Set path to write access log. To reopen file, send USR1 - signal to nghttpx. + + Set path to write access log. To reopen file, + send USR1 signal to nghttpx. .. option:: --accesslog-syslog - Send access log to syslog. If this option is used, - :option:`--accesslog-file` option is ignored. + + Send access log to syslog. If this option is + used, :option:`--access-file` option is ignored. .. option:: --accesslog-format= - Specify format string for access log. The default - format is combined format. The following variables are - available: - - * $remote_addr: client IP address. - * $time_local: local time in Common Log format. - * $time_iso8601: local time in ISO 8601 format. - * $request: HTTP request line. - * $status: HTTP response status code. - * $body_bytes_sent: the number of bytes sent to client - as response body. - * $http_: value of HTTP request header where - '_' in is replaced with '-'. - * $remote_port: client port. - * $server_port: server port. - * $request_time: request processing time in seconds with - milliseconds resolution. - * $pid: PID of the running process. - * $alpn: ALPN identifier of the protocol which generates - the response. For HTTP/1, ALPN is always http/1.1, - regardless of minor version. - * $ssl_cipher: cipher used for SSL/TLS connection. - * $ssl_protocol: protocol for SSL/TLS connection. - * $ssl_session_id: session ID for SSL/TLS connection. - * $ssl_session_reused: "r" if SSL/TLS session was - reused. Otherwise, "." - - The variable can be enclosed by "{" and "}" for - disambiguation (e.g., ${remote_addr}). - - - Default: ``$remote_addr - - [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"`` + + Specify format string for access log. The + default format is combined format. The following + variables are available: + $remote_addr: client IP address. + $time_local: local time in Common Log format. + $time_iso8601: local time in ISO 8601 format. + $request: HTTP request line. + $status: HTTP response status code. + $body_bytes_sent: the number of bytes sent to + client as response body. + $http_: value of HTTP request header + where '_' in is replaced with '-'. + $remote_port: client port. + $server_port: server port. + $request_time: request processing time in + seconds with milliseconds resolution. + $pid: PID of the running process. + $alpn: ALPN identifier of the protocol which + generates the response. For HTTP/1, ALPN is + always http/1.1, regardless of minor version. + Default: $remote_addr - - [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" .. option:: --errorlog-file= - Set path to write error log. To reopen file, send USR1 - signal to nghttpx. stderr will be redirected to the - error log file unless :option:`--errorlog-syslog` is used. - - Default: ``/dev/stderr`` + + Set path to write error log. To reopen file, + send USR1 signal to nghttpx. + Default: /dev/stderr .. option:: --errorlog-syslog - Send error log to syslog. If this option is used, - :option:`--errorlog-file` option is ignored. + + Send error log to syslog. If this option is + used, :option:`--errorlog-file` option is ignored. .. option:: --syslog-facility= + Set syslog facility to . + Default: daemon - Default: ``daemon`` - - -HTTP -~~~~ +Misc +^^^^ .. option:: --add-x-forwarded-for - Append X-Forwarded-For header field to the downstream - request. + + Append X-Forwarded-For header field to the + downstream request. .. option:: --strip-incoming-x-forwarded-for - Strip X-Forwarded-For header field from inbound client - requests. - -.. option:: --add-forwarded= - - Append RFC 7239 Forwarded header field with parameters - specified in comma delimited list . The supported - parameters are "by", "for", "host", and "proto". By - default, the value of "by" and "for" parameters are - obfuscated string. See :option:`--forwarded-by` and - :option:`--forwarded-for` options respectively. Note that nghttpx - does not translate non-standard X-Forwarded-\* header - fields into Forwarded header field, and vice versa. - -.. option:: --strip-incoming-forwarded - - Strip Forwarded header field from inbound client - requests. - -.. option:: --forwarded-by=(obfuscated|ip|) - - Specify the parameter value sent out with "by" parameter - of Forwarded header field. If "obfuscated" is given, - the string is randomly generated at startup. If "ip" is - given, the interface address of the connection, - including port number, is sent with "by" parameter. In - case of UNIX domain socket, "localhost" is used instead - of address and port. User can also specify the static - obfuscated string. The limitation is that it must start - with "_", and only consists of character set - [A-Za-z0-9._-], as described in RFC 7239. - - Default: ``obfuscated`` - -.. option:: --forwarded-for=(obfuscated|ip) - - Specify the parameter value sent out with "for" - parameter of Forwarded header field. If "obfuscated" is - given, the string is randomly generated for each client - connection. If "ip" is given, the remote client address - of the connection, without port number, is sent with - "for" parameter. In case of UNIX domain socket, - "localhost" is used instead of address. - - Default: ``obfuscated`` + + Strip X-Forwarded-For header field from inbound + client requests. .. option:: --no-via - Don't append to Via header field. If Via header field - is received, it is left unaltered. + + Don't append to Via header field. If Via header + field is received, it is left unaltered. .. option:: --no-location-rewrite - Don't rewrite location header field in default mode. - When :option:`--http2-proxy` is used, location header field will - not be altered regardless of this option. - -.. option:: --host-rewrite - - Rewrite host and :authority header fields in default - mode. When :option:`--http2-proxy` is used, these headers will - not be altered regardless of this option. + + Don't rewrite location header field on + :option:`--http2-bridge`, :option:`--client` and default mode. For + :option:`--http2-proxy` and :option:`--client-proxy` mode, location + header field will not be altered regardless of + this option. .. option:: --altsvc= - Specify protocol ID, port, host and origin of - alternative service. and are optional. - 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-request-header=
- - Specify additional header field to add to request header - set. This option just appends header field and won't - replace anything already set. This option can be used - several times to specify multiple header fields. - Example: :option:`--add-request-header`\="foo: bar" + + Specify protocol ID, port, host and origin of + alternative service. and 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: --altsvc=h2,443 .. option:: --add-response-header=
- Specify additional header field to add to response - header set. This option just appends header field and - won't replace anything already set. This option can be - used several times to specify multiple header fields. - Example: :option:`--add-response-header`\="foo: bar" - -.. option:: --request-header-field-buffer= - - Set maximum buffer size for incoming HTTP request header - field list. This is the sum of header name and value in - bytes. If trailer fields exist, they are counted - towards this number. - - Default: ``64K`` - -.. option:: --max-request-header-fields= - - Set maximum number of incoming HTTP request header - fields. If trailer fields exist, they are counted - towards this number. - - Default: ``100`` - -.. option:: --response-header-field-buffer= - - Set maximum buffer size for incoming HTTP response - header field list. This is the sum of header name and - value in bytes. If trailer fields exist, they are - counted towards this number. - - Default: ``64K`` - -.. option:: --max-response-header-fields= - - Set maximum number of incoming HTTP response header - fields. If trailer fields exist, they are counted - towards this number. - - Default: ``500`` - -.. option:: --error-page=(|*)= - - Set file path to custom error page served when nghttpx - originally generates HTTP error status code . - must be greater than or equal to 400, and at most - 599. If "*" is used instead of , it matches all - HTTP status code. If error status code comes from - backend server, the custom error pages are not used. - - -API -~~~ - -.. option:: --api-max-request-body= - - Set the maximum size of request body for API request. - - Default: ``16K`` - - -Debug -~~~~~ + + Specify additional header field to add to + response header set. This option just appends + header field and won't replace anything already + set. This option can be used several times to + specify multiple header fields. + Example: --add-response-header="foo: bar" .. option:: --frontend-http2-dump-request-header= - Dumps request headers received by HTTP/2 frontend to the - file denoted in . The output is done in HTTP/1 - header field format and each header block is followed by - an empty line. This option is not thread safe and MUST - NOT be used with option :option:`-n`\, where >= 2. + + Dumps request headers received by HTTP/2 frontend + to the file denoted in . The output is + done in HTTP/1 header field format and each + header block is followed by an empty line. This + option is not thread safe and MUST NOT be used + with option -n, where >= 2. .. option:: --frontend-http2-dump-response-header= - Dumps response headers sent from HTTP/2 frontend to the - file denoted in . The output is done in HTTP/1 - header field format and each header block is followed by - an empty line. This option is not thread safe and MUST - NOT be used with option :option:`-n`\, where >= 2. + + Dumps response headers sent from HTTP/2 frontend + to the file denoted in . The output is + done in HTTP/1 header field format and each + header block is followed by an empty line. This + option is not thread safe and MUST NOT be used + with option -n, where >= 2. .. option:: -o, --frontend-frame-debug - Print HTTP/2 frames in frontend to stderr. This option - is not thread safe and MUST NOT be used with option - :option:`-n`\=N, where N >= 2. - - -Process -~~~~~~~ + + Print HTTP/2 frames in frontend to stderr. This + option is not thread safe and MUST NOT be used + with option -n=N, where N >= 2. .. option:: -D, --daemon - Run in a background. If :option:`-D` is used, the current working - directory is changed to '*/*'. + + Run in a background. If :option:`-D` is used, the current + working directory is changed to '/'. .. option:: --pid-file= + Set path to save PID of this program. .. option:: --user= - Run this program as . This option is intended to - be used to drop root privileges. - - -Scripting -~~~~~~~~~ - -.. option:: --mruby-file= - - Set mruby script file - - -Misc -~~~~ + + Run this program as . This option is + intended to be used to drop root privileges. .. option:: --conf= + Load configuration from . - - Default: ``/etc/nghttpx/nghttpx.conf`` - -.. option:: --include= - - Load additional configurations from . File - is read when configuration parser encountered this - option. This option can be used multiple times, or even - recursively. + Default: /etc/nghttpx/nghttpx.conf .. option:: -v, --version + Print version and exit. .. option:: -h, --help + Print this help and exit. - - -The argument is an integer and an optional unit (e.g., 10K is -10 * 1024). Units are K, M and G (powers of 1024). - -The 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. - -FILES ------ - -*/etc/nghttpx/nghttpx.conf* - The default configuration file path nghttpx searches at startup. - The configuration file path can be changed using :option:`--conf` - option. - - Those lines which are staring ``#`` are treated as comment. - - The option name in the configuration file is the long command-line - option name with leading ``--`` stripped (e.g., ``frontend``). Put - ``=`` between option name and value. Don't put extra leading or - trailing spaces. - - When specifying arguments including characters which have special - meaning to a shell, we usually use quotes so that shell does not - interpret them. When writing this configuration file, quotes for - this purpose must not be used. For example, specify additional - request header field, do this: - - .. code-block:: text - - add-request-header=foo: bar - - instead of: - - .. code-block:: text - - add-request-header="foo: bar" - - The options which do not take argument in the command-line *take* - argument in the configuration file. Specify ``yes`` as an argument - (e.g., ``http2-proxy=yes``). If other string is given, it is - ignored. - - To specify private key and certificate file which are given as - positional arguments in command-line, use ``private-key-file`` and - ``certificate-file``. - - :option:`--conf` option cannot be used in the configuration file and - will be ignored if specified. - -SIGNALS -------- - -SIGQUIT - Shutdown gracefully. First accept pending connections and stop - accepting connection. After all connections are handled, nghttpx - exits. - -SIGUSR1 - Reopen log files. - -SIGUSR2 - Fork and execute nghttpx. It will execute the binary in the same - path with same command-line arguments and environment variables. - After new process comes up, sending SIGQUIT to the original process - to perform hot swapping. - -.. note:: - - nghttpx consists of multiple processes: one process for processing - these signals, and another one for processing requests. The former - spawns the latter. The former is called master process, and the - latter is called worker process. If neverbleed is enabled, the - worker process spawns neverbleed daemon process which does RSA key - processing. The above signal must be sent to the master process. - If the other processes received one of them, it is ignored. This - behaviour of these processes may change in the future release. In - other words, in the future release, the processes other than master - process may terminate upon the reception of these signals. - Therefore these signals should not be sent to the processes other - than master process. - -SERVER PUSH ------------ - -nghttpx supports HTTP/2 server push in default mode with Link header -field. nghttpx looks for Link header field (`RFC 5988 -`_) in response headers from -backend server and extracts URI-reference with parameter -``rel=preload`` (see `preload -`_) -and pushes those URIs to the frontend client. Here is a sample Link -header field to initiate server push: - -.. code-block:: text - - Link: ; rel=preload - Link: ; rel=preload - -Currently, the following restriction is applied for server push: - -1. The associated stream must have method "GET" or "POST". The - associated stream's status code must be 200. - -This limitation may be loosened in the future release. - -nghttpx also supports server push if both frontend and backend are -HTTP/2 in default mode. In this case, in addition to server push via -Link header field, server push from backend is forwarded to frontend -HTTP/2 session. - -HTTP/2 server push will be disabled if :option:`--http2-proxy` is -used. - -UNIX DOMAIN SOCKET ------------------- - -nghttpx supports UNIX domain socket with a filename for both frontend -and backend connections. - -Please note that current nghttpx implementation does not delete a -socket with a filename. And on start up, if nghttpx detects that the -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. - -OCSP STAPLING -------------- - -OCSP query is done using external Python script -``fetch-ocsp-response``, which has been originally developed in Perl -as part of h2o project (https://github.com/h2o/h2o), and was -translated into Python. - -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. - -If OCSP query is failed, previous OCSP response, if any, is continued -to be used. - -TLS SESSION RESUMPTION ----------------------- - -nghttpx supports TLS session resumption through both session ID and -session ticket. - -SESSION ID RESUMPTION -~~~~~~~~~~~~~~~~~~~~~ - -By default, session ID is shared by all worker threads. - -If :option:`--tls-session-cache-memcached` is given, nghttpx will -insert serialized session data to memcached with -``nghttpx:tls-session-cache:`` + lowercased hex string of session ID -as a memcached entry key, with expiry time 12 hours. Session timeout -is set to 12 hours. - -By default, connections to memcached server are not encrypted. To -enable encryption, use ``tls`` keyword in -:option:`--tls-session-cache-memcached` option. - -TLS SESSION TICKET RESUMPTION -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default, session ticket is shared by all worker threads. The -automatic key rotation is also enabled by default. Every an hour, new -encryption key is generated, and previous encryption key becomes -decryption only key. We set session timeout to 12 hours, and thus we -keep at most 12 keys. - -If :option:`--tls-ticket-key-memcached` is given, encryption keys are -retrieved from memcached. nghttpx just reads keys from memcached; one -has to deploy key generator program to update keys frequently (e.g., -every 1 hour). The example key generator tlsticketupdate.go is -available under contrib directory in nghttp2 archive. The memcached -entry key is ``nghttpx:tls-ticket-key``. The data format stored in -memcached is the binary format described below: - -.. code-block:: text - - +--------------+-------+----------------+ - | VERSION (4) |LEN (2)|KEY(48 or 80) ... - +--------------+-------+----------------+ - ^ | - | | - +------------------------+ - (LEN, KEY) pair can be repeated - -All numbers in the above figure is bytes. All integer fields are -network byte order. - -First 4 bytes integer VERSION field, which must be 1. The 2 bytes -integer LEN field gives the length of following KEY field, which -contains key. If :option:`--tls-ticket-key-cipher`\=aes-128-cbc is -used, LEN must be 48. If -:option:`--tls-ticket-key-cipher`\=aes-256-cbc is used, LEN must be -80. LEN and KEY pair can be repeated multiple times to store multiple -keys. The key appeared first is used as encryption key. All the -remaining keys are used as decryption only. - -By default, connections to memcached server are not encrypted. To -enable encryption, use ``tls`` keyword in -:option:`--tls-ticket-key-memcached` option. - -If :option:`--tls-ticket-key-file` is given, encryption key is read -from the given file. In this case, nghttpx does not rotate key -automatically. To rotate key, one has to restart nghttpx (see -SIGNALS). - -MRUBY SCRIPTING ---------------- - -.. warning:: - - The current mruby extension API is experimental and not frozen. The - API is subject to change in the future release. - -nghttpx allows users to extend its capability using mruby scripts. -nghttpx has 2 hook points to execute mruby script: request phase and -response phase. The request phase hook is invoked after all request -header fields are received from client. The response phase hook is -invoked after all response header fields are received from backend -server. These hooks allows users to modify header fields, or common -HTTP variables, like authority or request path, and even return custom -response without forwarding request to backend servers. - -To specify mruby script file, use :option:`--mruby-file` option. The -script will be evaluated once per thread on startup, and it must -instantiate object and evaluate it as the return value (e.g., -``App.new``). This object is called app object. If app object -defines ``on_req`` method, it is called with :rb:class:`Nghttpx::Env` -object on request hook. Similarly, if app object defines ``on_resp`` -method, it is called with :rb:class:`Nghttpx::Env` object on response -hook. For each method invocation, user can can access -:rb:class:`Nghttpx::Request` and :rb:class:`Nghttpx::Response` objects -via :rb:attr:`Nghttpx::Env#req` and :rb:attr:`Nghttpx::Env#resp` -respectively. - -.. rb:module:: Nghttpx - -.. rb:const:: REQUEST_PHASE - - Constant to represent request phase. - -.. rb:const:: RESPONSE_PHASE - - Constant to represent response phase. - -.. rb:class:: Env - - Object to represent current request specific context. - - .. rb:attr_reader:: req - - Return :rb:class:`Request` object. - - .. rb:attr_reader:: resp - - Return :rb:class:`Response` object. - - .. rb:attr_reader:: ctx - - Return Ruby hash object. It persists until request finishes. - So values set in request phase hoo can be retrieved in - response phase hook. - - .. rb:attr_reader:: phase - - Return the current phase. - - .. rb:attr_reader:: remote_addr - - Return IP address of a remote client. If connection is made - via UNIX domain socket, this returns the string "localhost". - - .. rb:attr_reader:: server_addr - - Return address of server that accepted the connection. This - is a string which specified in :option:`--frontend` option, - excluding port number, and not a resolved IP address. For - UNIX domain socket, this is a path to UNIX domain socket. - - .. rb:attr_reader:: server_port - - Return port number of the server frontend which accepted the - connection from client. - - .. rb:attr_reader:: tls_used - - Return true if TLS is used on the connection. - -.. rb:class:: Request - - Object to represent request from client. The modification to - Request object is allowed only in request phase hook. - - .. rb:attr_reader:: http_version_major - - Return HTTP major version. - - .. rb:attr_reader:: http_version_minor - - Return HTTP minor version. - - .. rb:attr_accessor:: method - - HTTP method. On assignment, copy of given value is assigned. - We don't accept arbitrary method name. We will document them - later, but well known methods, like GET, PUT and POST, are all - supported. - - .. rb:attr_accessor:: authority - - Authority (i.e., example.org), including optional port - component . On assignment, copy of given value is assigned. - - .. rb:attr_accessor:: scheme - - Scheme (i.e., http, https). On assignment, copy of given - value is assigned. - - .. rb:attr_accessor:: path - - Request path, including query component (i.e., /index.html). - On assignment, copy of given value is assigned. The path does - not include authority component of URI. This may include - query component. nghttpx makes certain normalization for - path. It decodes percent-encoding for unreserved characters - (see https://tools.ietf.org/html/rfc3986#section-2.3), and - resolves ".." and ".". But it may leave characters which - should be percent-encoded as is. So be careful when comparing - path against desired string. - - .. rb:attr_reader:: headers - - Return Ruby hash containing copy of request header fields. - Changing values in returned hash does not change request - header fields actually used in request processing. Use - :rb:meth:`Nghttpx::Request#add_header` or - :rb:meth:`Nghttpx::Request#set_header` to change request - header fields. - - .. rb:method:: add_header(key, value) - - Add header entry associated with key. The value can be single - string or array of string. It does not replace any existing - values associated with key. - - .. rb:method:: set_header(key, value) - - Set header entry associated with key. The value can be single - string or array of string. It replaces any existing values - associated with key. - - .. rb:method:: clear_headers - - Clear all existing request header fields. - - .. rb:method:: push(uri) - - Initiate to push resource identified by *uri*. Only HTTP/2 - protocol supports this feature. For the other protocols, this - method is noop. *uri* can be absolute URI, absolute path or - relative path to the current request. For absolute or - relative path, scheme and authority are inherited from the - current request. Currently, method is always GET. nghttpx - will issue request to backend servers to fulfill this request. - The request and response phase hooks will be called for pushed - resource as well. - -.. rb:class:: Response - - Object to represent response from backend server. - - .. rb:attr_reader:: http_version_major - - Return HTTP major version. - - .. rb:attr_reader:: http_version_minor - - Return HTTP minor version. - - .. rb:attr_accessor:: status - - HTTP status code. It must be in the range [200, 999], - inclusive. The non-final status code is not supported in - mruby scripting at the moment. - - .. rb:attr_reader:: headers - - Return Ruby hash containing copy of response header fields. - Changing values in returned hash does not change response - header fields actually used in response processing. Use - :rb:meth:`Nghttpx::Response#add_header` or - :rb:meth:`Nghttpx::Response#set_header` to change response - header fields. - - .. rb:method:: add_header(key, value) - - Add header entry associated with key. The value can be single - string or array of string. It does not replace any existing - values associated with key. - - .. rb:method:: set_header(key, value) - - Set header entry associated with key. The value can be single - string or array of string. It replaces any existing values - associated with key. - - .. rb:method:: clear_headers - - Clear all existing response header fields. - - .. rb:method:: return(body) - - Return custom response *body* to a client. When this method - is called in request phase hook, the request is not forwarded - to the backend, and response phase hook for this request will - not be invoked. When this method is called in response phase - hook, response from backend server is canceled and discarded. - The status code and response header fields should be set - before using this method. To set status code, use :rb:meth To - set response header fields, use - :rb:attr:`Nghttpx::Response#status`. If status code is not - set, 200 is used. :rb:meth:`Nghttpx::Response#add_header` and - :rb:meth:`Nghttpx::Response#set_header`. When this method is - invoked in response phase hook, the response headers are - filled with the ones received from backend server. To send - completely custom header fields, first call - :rb:meth:`Nghttpx::Response#clear_headers` to erase all - existing header fields, and then add required header fields. - It is an error to call this method twice for a given request. - -MRUBY EXAMPLES -~~~~~~~~~~~~~~ - -Modify request path: - -.. code-block:: ruby - - class App - def on_req(env) - env.req.path = "/apps#{env.req.path}" - end - end - - App.new - -Don't forget to instantiate and evaluate object at the last line. - -Restrict permission of viewing a content to a specific client -addresses: - -.. code-block:: ruby - - class App - def on_req(env) - allowed_clients = ["127.0.0.1", "::1"] - - if env.req.path.start_with?("/log/") && - !allowed_clients.include?(env.remote_addr) then - env.resp.status = 404 - env.resp.return "permission denied" - end - end - end - - App.new - -API ENDPOINTS -------------- - -nghttpx exposes API endpoints to manipulate it via HTTP based API. By -default, API endpoint is disabled. To enable it, add a dedicated -frontend for API using :option:`--frontend` option with "api" -parameter. All requests which come from this frontend address, will -be treated as API request. - -The response is normally JSON dictionary, and at least includes the -following keys: - -status - The status of the request processing. The following values are - defined: - - Success - The request was successful. - - Failure - The request was failed. No change has been made. - -code - HTTP status code - -We wrote "normally", since nghttpx may return ordinal HTML response in -some cases where the error has occurred before reaching API endpoint -(e.g., header field is too large). - -The following section describes available API endpoints. - -PUT /api/v1beta1/backendconfig -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This API replaces the current backend server settings with the -requested ones. The request method should be PUT, but POST is also -acceptable. The request body must be nghttpx configuration file -format. For configuration file format, see `FILES`_ section. The -line separator inside the request body must be single LF (0x0A). -Currently, only :option:`backend <--backend>` option is parsed, the -others are simply ignored. The semantics of this API is replace the -current backend with the backend options in request body. Describe -the desired set of backend severs, and nghttpx makes it happen. If -there is no :option:`backend <--backend>` option is found in request -body, the current set of backend is replaced with the :option:`backend -<--backend>` option's default value, which is ``127.0.0.1,80``. - -The replacement is done instantly without breaking existing -connections or requests. It also avoids any process creation as is -the case with hot swapping with signals. - -The one limitation is that only numeric IP address is allowd in -:option:`backend <--backend>` in request body while non numeric -hostname is allowed in command-line or configuration file is read -using :option:`--conf`. - SEE ALSO -------- -:manpage:`nghttp(1)`, :manpage:`nghttpd(1)`, :manpage:`h2load(1)` +nghttp(1), nghttpd(1), h2load(1) diff -Nru nghttp2-1.13.0/doc/programmers-guide.rst nghttp2-0.6.7/doc/programmers-guide.rst --- nghttp2-1.13.0/doc/programmers-guide.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/programmers-guide.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,426 +0,0 @@ -Programmers' Guide -================== - -Architecture ------------- - -The most notable point in nghttp2 library architecture is it does not -perform any I/O. nghttp2 only performs HTTP/2 protocol stuff based on -input byte strings. It will calls callback functions set by -applications while processing input. The output of nghttp2 is just -byte string. An application is responsible to send these output to -the remote peer. The callback functions may be called while producing -output. - -Not doing I/O makes embedding nghttp2 library in the existing code -base very easy. Usually, the existing applications have its own I/O -event loops. It is very hard to use nghttp2 in that situation if -nghttp2 does its own I/O. It also makes light weight language wrapper -for nghttp2 easy with the same reason. The down side is that an -application author has to write more code to write complete -application using nghttp2. This is especially true for simple "toy" -application. For the real applications, however, this is not the -case. This is because you probably want to support HTTP/1 which -nghttp2 does not provide, and to do that, you will need to write your -own HTTP/1 stack or use existing third-party library, and bind them -together with nghttp2 and I/O event loop. In this point, not -performing I/O in nghttp2 has more point than doing it. - -The primary object that an application uses is :type:`nghttp2_session` -object, which is opaque struct and its details are hidden in order to -ensure the upgrading its internal architecture without breaking the -backward compatibility. An application can set callbacks to -:type:`nghttp2_session` object through the dedicated object and -functions, and it also interacts with it via many API function calls. - -An application can create as many :type:`nghttp2_session` object as it -wants. But single :type:`nghttp2_session` object must be used by a -single thread at the same time. This is not so hard to enforce since -most event-based architecture applicatons use is single thread per -core, and handling one connection I/O is done by single thread. - -To feed input to :type:`nghttp2_session` object, one can use -`nghttp2_session_recv()` or `nghttp2_session_mem_recv()` functions. -They behave similarly, and the difference is that -`nghttp2_session_recv()` will use :type:`nghttp2_read_callback` to get -input. On the other hand, `nghttp2_session_mem_recv()` will take -input as its parameter. If in doubt, use `nghttp2_session_mem_recv()` -since it is simpler, and could be faster since it avoids calling -callback function. - -To get output from :type:`nghttp2_session` object, one can use -`nghttp2_session_send()` or `nghttp2_session_mem_send()`. The -difference between them is that the former uses -:type:`nghttp2_send_callback` to pass output to an application. On -the other hand, the latter returns the output to the caller. If in -doubt, use `nghttp2_session_mem_send()` since it is simpler. But -`nghttp2_session_send()` might be easier to use if the output buffer -an application has is fixed sized. - -In general, an application should call `nghttp2_session_mem_send()` -when it gets input from underlying connection. Since there is great -chance to get something pushed into transmission queue while the call -of `nghttp2_session_mem_send()`, it is recommended to call -`nghttp2_session_mem_recv()` after `nghttp2_session_mem_send()`. - -There is a question when we are safe to close HTTP/2 session without -waiting for the closure of underlying connection. We offer 2 API -calls for this: `nghttp2_session_want_read()` and -`nghttp2_session_want_write()`. If they both return 0, application -can destroy :type:`nghttp2_session`, and then close the underlying -connection. But make sure that the buffered output has been -transmitted to the peer before closing the connection when -`nghttp2_session_mem_send()` is used, since -`nghttp2_session_want_write()` does not take into account the -transmission of the buffered data outside of :type:`nghttp2_session`. - -Includes --------- - -To use the public APIs, include ``nghttp2/nghttp2.h``:: - - #include - -The header files are also available online: :doc:`nghttp2.h` and -:doc:`nghttp2ver.h`. - -Remarks -------- - -Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send()`, -`nghttp2_session_recv()` or `nghttp2_session_mem_recv()` from the -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. - -`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 --------------- - -By default, nghttp2 library checks HTTP messaging rules described in -`HTTP/2 specification, section 8 -`_. -Everything described in that section is not validated however. We -briefly describe what the library does in this area. In the following -description, without loss of generality we omit CONTINUATION frame -since they must follow HEADERS frame and are processed atomically. In -other words, they are just one big HEADERS frame. To disable these -validations, use `nghttp2_option_set_no_http_messaging()`. - -For HTTP request, including those carried by PUSH_PROMISE, HTTP -message starts with one HEADERS frame containing request headers. It -is followed by zero or more DATA frames containing request body, which -is followed by zero or one HEADERS containing trailer headers. The -request headers must include ":scheme", ":method" and ":path" pseudo -header fields unless ":method" is not "CONNECT". ":authority" is -optional, but nghttp2 requires either ":authority" or "Host" header -field must be present. If ":method" is "CONNECT", the request headers -must include ":method" and ":authority" and must omit ":scheme" and -":path". - -For HTTP response, HTTP message starts with zero or more HEADERS -frames containing non-final response (status code 1xx). They are -followed by one HEADERS frame containing final response headers -(non-1xx). It is followed by zero or more DATA frames containing -response body, which is followed by zero or one HEADERS containing -trailer headers. The non-final and final response headers must -contain ":status" pseudo header field containing 3 digits only. - -All request and response headers must include exactly one valid value -for each pseudo header field. Additionally nghttp2 requires all -request headers must not include more than one "Host" header field. - -HTTP/2 prohibits connection-specific header fields. The following -header fields must not appear: "Connection", "Keep-Alive", -"Proxy-Connection", "Transfer-Encoding" and "Upgrade". Additionally, -"TE" header field must not include any value other than "trailers". - -Each header field name and value must obey the field-name and -field-value production rules described in `RFC 7230, section -3.2. `_. -Additionally, all field name must be lower cased. While the pseudo -header fields must satisfy these rules, we just ignore illegal regular -headers (this means that these header fields are not passed to -application callback). This is because these illegal header fields -are floating around in existing internet and resetting stream just -because of this may break many web sites. This is especially true if -we forward to or translate from HTTP/1 traffic. - -For "http" or "https" URIs, ":path" pseudo header fields must start -with "/". The only exception is OPTIONS request, in that case, "*" is -allowed in ":path" pseudo header field to represent system-wide -OPTIONS request. - -With the above validations, nghttp2 library guarantees that header -field name passed to `nghttp2_on_header_callback()` is not empty. -Also required pseudo headers are all present and not empty. - -nghttp2 enforces "Content-Length" validation as well. All request or -response headers must not contain more than one "Content-Length" -header field. If "Content-Length" header field is present, it must be -parsed as 64 bit signed integer. The sum of data length in the -following DATA frames must match with the number in "Content-Length" -header field if it is present (this does not include padding bytes). - -Any deviation results in stream error of type PROTOCOL_ERROR. If -error is found in PUSH_PROMISE frame, stream error is raised against -promised stream. - -Implement user defined HTTP/2 non-critical extensions ------------------------------------------------------ - -As of nghttp2 v1.8.0, we have added HTTP/2 non-critical extension -framework, which lets application send and receive user defined custom -HTTP/2 non-critical extension frames. nghttp2 also offers built-in -functionality to send and receive official HTTP/2 extension frames -(e.g., ALTSVC frame). For these built-in handler, refer to the next -section. - -To send extension frame, use `nghttp2_submit_extension()`, and -implement :type:`nghttp2_pack_extension_callback`. The callback -implements how to encode data into wire format. The callback must be -set to :type:`nghttp2_session_callbacks` using -`nghttp2_session_callbacks_set_pack_extension_callback()`. - -For example, we will illustrate how to send `ALTSVC -`_ frame. - -.. code-block:: c - - typedef struct { - const char *origin; - const char *field; - } alt_svc; - - ssize_t pack_extension_callback(nghttp2_session *session, uint8_t *buf, - size_t len, const nghttp2_frame *frame, - void *user_data) { - const alt_svc *altsvc = (const alt_svc *)frame->ext.payload; - size_t originlen = strlen(altsvc->origin); - size_t fieldlen = strlen(altsvc->field); - - uint8_t *p; - - if (len < 2 + originlen + fieldlen || originlen > 0xffff) { - return NGHTTP2_ERR_CANCEL; - } - - p = buf; - *p++ = originlen >> 8; - *p++ = originlen & 0xff; - memcpy(p, altsvc->origin, originlen); - p += originlen; - memcpy(p, altsvc->field, fieldlen); - p += fieldlen; - - return p - buf; - } - -This implements :type:`nghttp2_pack_extension_callback`. We have to -set this callback to :type:`nghttp2_session_callbacks`: - -.. code-block:: c - - nghttp2_session_callbacks_set_pack_extension_callback( - callbacks, pack_extension_callback); - -To send ALTSVC frame, call `nghttp2_submit_extension()`: - -.. code-block:: c - - static const alt_svc altsvc = {"example.com", "h2=\":8000\""}; - - nghttp2_submit_extension(session, 0xa, NGHTTP2_FLAG_NONE, 0, - (void *)&altsvc); - -Notice that ALTSVC is use frame type ``0xa``. - -To receive extension frames, implement 2 callbacks: -:type:`nghttp2_unpack_extension_callback` and -:type:`nghttp2_on_extension_chunk_recv_callback`. -:type:`nghttp2_unpack_extension_callback` implements the way how to -decode wire format. :type:`nghttp2_on_extension_chunk_recv_callback` -implements how to buffer the incoming extension payload. These -callbacks must be set using -`nghttp2_session_callbacks_set_unpack_extension_callback()` and -`nghttp2_session_callbacks_set_on_extension_chunk_recv_callback()` -respectively. The application also must tell the library which -extension frame type it is willing to receive using -`nghttp2_option_set_user_recv_extension_type()`. Note that the -application has to create :type:`nghttp2_option` object for that -purpose, and initialize session with it. - -We use ALTSVC again to illustrate how to receive extension frames. We -use different ``alt_svc`` struct than the previous one. - -First implement 2 callbacks. We store incoming ALTSVC payload to -global variable ``altsvc_buffer``. Don't do this in production code -since this is not thread safe: - -.. code-block:: c - - typedef struct { - const uint8_t *origin; - size_t originlen; - const uint8_t *field; - size_t fieldlen; - } alt_svc; - - /* buffers incoming ALTSVC payload */ - uint8_t altsvc_buffer[4096]; - /* The length of byte written to altsvc_buffer */ - size_t altsvc_bufferlen = 0; - - int on_extension_chunk_recv_callback(nghttp2_session *session, - const nghttp2_frame_hd *hd, - const uint8_t *data, size_t len, - void *user_data) { - if (sizeof(altsvc_buffer) < altsvc_bufferlen + len) { - altsvc_bufferlen = 0; - return NGHTTP2_ERR_CANCEL; - } - - memcpy(altsvc_buffer + altsvc_bufferlen, data, len); - altsvc_bufferlen += len; - - return 0; - } - - int unpack_extension_callback(nghttp2_session *session, void **payload, - const nghttp2_frame_hd *hd, void *user_data) { - uint8_t *origin, *field; - size_t originlen, fieldlen; - uint8_t *p, *end; - alt_svc *altsvc; - - if (altsvc_bufferlen < 2) { - altsvc_bufferlen = 0; - return NGHTTP2_ERR_CANCEL; - } - - p = altsvc_buffer; - end = altsvc_buffer + altsvc_bufferlen; - - originlen = ((*p) << 8) + *(p + 1); - p += 2; - - if (p + originlen > end) { - altsvc_bufferlen = 0; - return NGHTTP2_ERR_CANCEL; - } - - origin = p; - field = p + originlen; - fieldlen = end - field; - - altsvc = (alt_svc *)malloc(sizeof(alt_svc)); - altsvc->origin = origin; - altsvc->originlen = originlen; - altsvc->field = field; - altsvc->fieldlen = fieldlen; - - *payload = altsvc; - - altsvc_bufferlen = 0; - - return 0; - } - -Set these callbacks to :type:`nghttp2_session_callbacks`: - -.. code-block:: c - - nghttp2_session_callbacks_set_on_extension_chunk_recv_callback( - callbacks, on_extension_chunk_recv_callback); - - nghttp2_session_callbacks_set_unpack_extension_callback( - callbacks, unpack_extension_callback); - - -In ``unpack_extension_callback`` above, we set unpacked ``alt_svc`` -object to ``*payload``. nghttp2 library then, calls -:type:`nghttp2_on_frame_recv_callback`, and ``*payload`` will be -available as ``frame->ext.payload``: - -.. code-block:: c - - int on_frame_recv_callback(nghttp2_session *session, - const nghttp2_frame *frame, void *user_data) { - - switch (frame->hd.type) { - ... - case 0xa: { - alt_svc *altsvc = (alt_svc *)frame->ext.payload; - fprintf(stderr, "ALTSVC frame received\n"); - fprintf(stderr, " origin: %.*s\n", (int)altsvc->originlen, altsvc->origin); - fprintf(stderr, " field : %.*s\n", (int)altsvc->fieldlen, altsvc->field); - free(altsvc); - break; - } - } - - return 0; - } - -Finally, application should set the extension frame types it is -willing to receive: - -.. code-block:: c - - nghttp2_option_set_user_recv_extension_type(option, 0xa); - -The :type:`nghttp2_option` must be set to :type:`nghttp2_session` on -its creation: - -.. code-block:: c - - nghttp2_session_client_new2(&session, callbacks, user_data, option); - -How to use built-in HTTP/2 extension frame handlers ---------------------------------------------------- - -In the previous section, we talked about the user defined HTTP/2 -extension frames. In this section, we talk about HTTP/2 extension -frame support built into nghttp2 library. - -As of this writing, nghttp2 supports ALTSVC extension frame. To send -ALTSVC frame, use `nghttp2_submit_altsvc()` function. - -To receive ALTSVC frame through built-in functionality, application -has to use `nghttp2_option_set_builtin_recv_extension_type()` to -indicate the willingness of receiving ALTSVC frame: - -.. code-block:: c - - nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC); - -This is very similar to the case when we used to receive user defined -frames. - -If the same frame type is set using -`nghttp2_option_set_builtin_recv_extension_type()` and -`nghttp2_option_set_user_recv_extension_type()`, the latter takes -precedence. Application can implement its own frame handler rather -than using built-in handler. - -The :type:`nghttp2_option` must be set to :type:`nghttp2_session` on -its creation, like so: - -.. code-block:: c - - nghttp2_session_client_new2(&session, callbacks, user_data, option); - -When ALTSVC is received, :type:`nghttp2_on_frame_recv_callback` will -be called as usual. - diff -Nru nghttp2-1.13.0/doc/README.rst nghttp2-0.6.7/doc/README.rst --- nghttp2-1.13.0/doc/README.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/README.rst 2014-11-30 14:15:07.000000000 +0000 @@ -22,7 +22,7 @@ block starting ``/**``. The comment block must end with ``*/``. The ``mkapiref.py`` requires that which type of the object this comment block refers to. To specify the type of the object, the next line -must contain the so-called action keyword. Currently, the following +must contain the so-caled action keyword. Currently, the following action keywords are supported: ``@function``, ``@functypedef``, ``@enum``, ``@struct`` and ``@union``. The following sections describes each action keyword. diff -Nru nghttp2-1.13.0/doc/sources/building-android-binary.rst nghttp2-0.6.7/doc/sources/building-android-binary.rst --- nghttp2-1.13.0/doc/sources/building-android-binary.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/sources/building-android-binary.rst 2014-11-30 14:15:07.000000000 +0000 @@ -17,40 +17,36 @@ under ``$ANDROID_HOME/toolchain``. An user can freely choose the path for ``ANDROID_HOME``. For example, to install toolchain under ``$ANDROID_HOME/toolchain``, do this in the the directory where NDK is -unpacked: +unpacked:: -.. code-block:: text + $ build/tools/make-standalone-toolchain.sh \ + --install-dir=$ANDROID_HOME/toolchain \ + --toolchain=arm-linux-androideabi-4.8 - $ build/tools/make_standalone_toolchain.py \ - --arch arm --api 16 --stl gnustl - --install-dir $ANDROID_HOME/toolchain +The additional flag ``--system=linux-x86_64`` may be required if you +are using x86_64 system. -The API level (``--api``) is not important here because we don't use -Android specific C/C++ API. +The platform level is not important here because we don't use Android +specific C/C++ API. -The dependent libraries, such as OpenSSL and libev should be built +The dependent libraries, such as OpenSSL and libevent should be built with the toolchain and installed under ``$ANDROID_HOME/usr/local``. We recommend to build these libraries as static library to make the deployment easier. libxml2 support is currently disabled. -Although zlib comes with Android NDK, it seems not to be a part of -public API, so we have to built it for our own. That also provides us -proper .pc file as a bonus. +We use zlib which comes with Android NDK, so we don't have to build it +by ourselves. If SPDY support is required for nghttpx and h2load, build and install spdylay as well. Before running ``android-config`` and ``android-make``, ``ANDROID_HOME`` environment variable must be set to point to the -correct path. Also add ``$ANDROID_HOME/toolchain/bin`` to ``PATH``: - -.. code-block:: text +correct path. Also add ``$ANDROID_HOME/toolchain/bin`` to ``PATH``:: $ export PATH=$PATH:$ANDROID_HOME/toolchain/bin -To configure OpenSSL, use the following script: - -.. code-block:: sh +To configure OpenSSL, use the following script:: #!/bin/sh @@ -65,15 +61,9 @@ export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi- ./Configure --prefix=$PREFIX android -And run ``make install_sw`` to build and install without -documentation. - -We cannot compile libev without modification. Apply `this patch -`_ before -configuring libev. This patch is for libev-4.19. After applying the -patch, to configure libev, use the following script: +And run ``make install`` to build and install. -.. code-block:: sh +To configure libevent, use the following script:: #!/bin/sh @@ -96,70 +86,39 @@ And run ``make install`` to build and install. -To configure zlib, use the following script: - -.. code-block:: sh - - #!/bin/sh -e +To configure spdylay, use the following script:: if [ -z "$ANDROID_HOME" ]; then - echo 'No $ANDROID_HOME specified.' - exit 1 + echo 'No $ANDROID_HOME specified.' + exit 1 fi PREFIX=$ANDROID_HOME/usr/local TOOLCHAIN=$ANDROID_HOME/toolchain PATH=$TOOLCHAIN/bin:$PATH - HOST=arm-linux-androideabi - - CC=$HOST-gcc \ - AR=$HOST-ar \ - LD=$HOST-ld \ - RANLIB=$HOST-ranlib \ - STRIP=$HOST-strip \ ./configure \ - --prefix=$PREFIX \ - --libdir=$PREFIX/lib \ - --includedir=$PREFIX/include \ - --static - -And run ``make install`` to build and install. + --disable-shared \ + --host=arm-linux-androideabi \ + --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \ + --prefix=$PREFIX \ + --without-libxml2 \ + --disable-src \ + --disable-examples \ + CPPFLAGS="-I$PREFIX/include" \ + PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \ + LDFLAGS="-L$PREFIX/lib" + +And run ``make install`` to build and install. After spdylay +installation, edit $ANDROID_HOME/usr/local/lib/pkgconfig/libspdylay.pc +and remove the following line:: -To configure spdylay, use the following script: - -.. code-block:: sh - - #!/bin/sh -e - - if [ -z "$ANDROID_HOME" ]; then - echo 'No $ANDROID_HOME specified.' - exit 1 - fi - PREFIX=$ANDROID_HOME/usr/local - TOOLCHAIN=$ANDROID_HOME/toolchain - PATH=$TOOLCHAIN/bin:$PATH - - ./configure \ - --disable-shared \ - --host=arm-linux-androideabi \ - --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \ - --prefix=$PREFIX \ - --without-libxml2 \ - --disable-src \ - --disable-examples \ - CPPFLAGS="-I$PREFIX/include" \ - PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \ - LDFLAGS="-L$PREFIX/lib" - -And run ``make install`` to build and install. + Requires.private: zlib After prerequisite libraries are prepared, run ``android-config`` and then ``android-make`` to compile nghttp2 source files. If all went well, application binaries, such as nghttpx, are created under src directory. Strip debugging information from the binary -using the following command: - -.. code-block:: text +using the following command:: $ arm-linux-androideabi-strip src/nghttpx diff -Nru nghttp2-1.13.0/doc/sources/contribute.rst nghttp2-0.6.7/doc/sources/contribute.rst --- nghttp2-1.13.0/doc/sources/contribute.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/sources/contribute.rst 2014-11-30 14:15:07.000000000 +0000 @@ -27,7 +27,7 @@ clang-format configuration file .clang-format is located at the root directory. Since clang-format produces slightly different results between versions, we currently use clang-format which comes with -clang-3.6. +clang-3.5. To detect any violation to the coding style, we recommend to setup git pre-commit hook to check coding style of the changes you introduced. @@ -35,7 +35,7 @@ .git/hooks and make sure that it is executable. The pre-commit script uses clang-format-diff.py to detect any style errors. If it is not in your PATH or it exists under different name (e.g., -clang-format-diff-3.6 in debian), either add it to PATH variable or +clang-format-diff-3.5 in debian), either add it to PATH variable or add git option ``clangformatdiff.binary`` to point to the script. For emacs users, integrating clang-format to emacs is very easy. diff -Nru nghttp2-1.13.0/doc/sources/h2load-howto.rst nghttp2-0.6.7/doc/sources/h2load-howto.rst --- nghttp2-1.13.0/doc/sources/h2load-howto.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/sources/h2load-howto.rst 2014-11-30 14:15:07.000000000 +0000 @@ -1,82 +1,63 @@ -.. program:: h2load - h2load - HTTP/2 benchmarking tool - HOW-TO ========================================== -:doc:`h2load.1` is benchmarking tool for HTTP/2 and HTTP/1.1. If -built with spdylay (http://tatsuhiro-t.github.io/spdylay/) library, it -also supports SPDY protocol. It supports SSL/TLS and clear text for -all supported protocols. - -Compiling from source ---------------------- - -h2load is compiled alongside nghttp2 and requires that the -``--enable-apps`` flag is passed to ``./configure`` and `required -dependencies `_ are -available during compilation. For details on compiling, see `nghttp2: -Building from Git -`_. +h2load is benchmarking tool for HTTP/2. If built with +spdylay (http://tatsuhiro-t.github.io/spdylay/) library, it also +supports SPDY protocol. It supports SSL/TLS and clear text for both +HTTP/2 and SPDY. Basic Usage ----------- In order to set benchmark settings, specify following 3 options. -:option:`-n` +``-n`` The number of total requests. Default: 1 -:option:`-c` +``-c`` The number of concurrent clients. Default: 1 -:option:`-m` - The max concurrent streams to issue per client. Default: 1 - -For SSL/TLS connection, the protocol will be negotiated via ALPN/NPN. -You can set specific protocols in :option:`--npn-list` option. For -cleartext connection, the default protocol is HTTP/2. To change the -protocol in cleartext connection, use :option:`--no-tls-proto` option. -For convenience, :option:`--h1` option forces HTTP/1.1 for both -cleartext and SSL/TLS connections. +``-m`` + The max concurrent streams to issue per client. + If ``auto`` is given, the number of given URIs is used. + Default: ``auto`` Here is a command-line to perform benchmark to URI \https://localhost using total 100000 requests, 100 concurrent clients and 10 max -concurrent streams: - -.. code-block:: text +concurrent streams:: $ h2load -n100000 -c100 -m10 https://localhost -The benchmarking result looks like this: - -.. code-block:: text +The benchmarking result looks like this:: - finished in 7.08s, 141164.80 req/s, 555.33MB/s - requests: 1000000 total, 1000000 started, 1000000 done, 1000000 succeeded, 0 failed, 0 errored, 0 timeout - status codes: 1000000 2xx, 0 3xx, 0 4xx, 0 5xx - traffic: 4125025824 bytes total, 11023424 bytes headers (space savings 93.07%), 4096000000 bytes data - min max mean sd +/- sd - time for request: 15.31ms 146.85ms 69.78ms 9.26ms 92.43% - time for connect: 1.08ms 25.04ms 10.71ms 9.80ms 64.00% - time to 1st byte: 25.36ms 184.96ms 79.11ms 53.97ms 78.00% - req/s (client) : 1412.04 1447.84 1426.52 10.57 63.00% - -See the h2load manual page :ref:`h2load-1-output` section for the -explanation of the above numbers. + finished in 0 sec, 385 millisec and 851 microsec, 2591 req/s, 1689 kbytes/s + requests: 1000 total, 1000 started, 1000 done, 1000 succeeded, 0 failed, 0 errored + status codes: 1000 2xx, 0 3xx, 0 4xx, 0 5xx + traffic: 667500 bytes total, 28700 bytes headers, 612000 bytes data + +The number of ``failed`` is the number of requests returned with non +2xx status. The number of ``error`` is the number of ``failed`` plus +the number of requests which failed with connection error. + +The number of ``total`` in ``traffic`` is the received application +data. If SSL/TLS is used, this number is calculated after decryption. +The number of ``headers`` is the sum of payload size of response +HEADERS (or SYN_REPLY for SPDY). This number comes before +decompressing header block. The number of ``data`` is the sum of +response body. Flow Control ------------ HTTP/2 and SPDY/3 or later employ flow control and it may affect -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: +benchmarking results. To adjust receiver flow control window size, +there is following options: -:option:`-w` +``-w`` Sets the stream level initial window size to (2**)-1. For SPDY, 2** is used instead. -:option:`-W` +``-W`` Sets the connection level initial window size to (2**)-1. For SPDY, if is strictly less than 16, this option is ignored. Otherwise @@ -86,17 +67,17 @@ --------------- Sometimes benchmarking client itself becomes a bottleneck. To remedy -this situation, use :option:`-t` option to specify the number of native +this situation, use ``-t`` option to specify the number of native thread to use. -:option:`-t` +``-t`` The number of native threads. Default: 1 Selecting protocol for clear text --------------------------------- By default, if \http:// URI is given, HTTP/2 protocol is used. To -change the protocol to use for clear text, use :option:`-p` option. +change the protocol to use for clear text, use ``-p`` option. Multiple URIs ------------- @@ -105,14 +86,5 @@ .. note:: - Please note that h2load uses scheme, host and port in the first URI + Please note that h2load uses sheme, host and port in the first URI and ignores those parts in the rest of the URIs. - -UNIX domain socket ------------------- - -To request against UNIX domain socket, use :option:`--base-uri`, and -specify ``unix:`` followed by the path to UNIX domain socket. For -example, if UNIX domain socket is ``/tmp/nghttpx.sock``, use -``--base-uri=unix:/tmp/nghttpx.sock``. h2load uses scheme, host and -port in the first URI in command-line or input file. diff -Nru nghttp2-1.13.0/doc/sources/index.rst nghttp2-0.6.7/doc/sources/index.rst --- nghttp2-1.13.0/doc/sources/index.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/sources/index.rst 2014-11-30 14:15:07.000000000 +0000 @@ -6,10 +6,10 @@ nghttp2 - HTTP/2 C Library ============================ -This is an implementation of Hypertext Transfer Protocol version 2. +This is an experimental implementation of Hypertext Transfer Protocol +version 2. -The project is hosted at `github.com/nghttp2/nghttp2 -`_. +The project is hosted at `github.com/tatsuhiro-t/nghttp2 `_. Contents: @@ -28,27 +28,23 @@ h2load.1 nghttpx-howto h2load-howto - programmers-guide apiref libnghttp2_asio python-apiref nghttp2.h nghttp2ver.h - asio_http2_server.h - asio_http2_client.h asio_http2.h - Source - Issues - nghttp2.org + Source + Issues Released Versions ================= -https://github.com/nghttp2/nghttp2/releases +https://github.com/tatsuhiro-t/nghttp2/releases Resources --------- -* HTTP/2 https://tools.ietf.org/html/rfc7540 -* HPACK https://tools.ietf.org/html/rfc7541 -* HTTP Alternative Services https://tools.ietf.org/html/rfc7838 +* http://tools.ietf.org/html/draft-ietf-httpbis-http2-14 +* http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09 +* http://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-04 diff -Nru nghttp2-1.13.0/doc/sources/libnghttp2_asio.rst nghttp2-0.6.7/doc/sources/libnghttp2_asio.rst --- nghttp2-1.13.0/doc/sources/libnghttp2_asio.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/sources/libnghttp2_asio.rst 2014-11-30 14:15:07.000000000 +0000 @@ -4,7 +4,7 @@ libnghttp2_asio is C++ library built on top of libnghttp2 and provides high level abstraction API to build HTTP/2 applications. It depends on Boost::ASIO library and OpenSSL. Currently libnghttp2_asio -provides server and client side API. +provides server side API. libnghttp2_asio is not built by default. Use ``--enable-asio-lib`` configure flag to build libnghttp2_asio. The required Boost libraries @@ -14,64 +14,42 @@ * Boost::System * Boost::Thread -We have 3 header files for this library: +To use libnghttp2_asio, first include following header file: -* :doc:`asio_http2_server.h` -* :doc:`asio_http2_client.h` -* :doc:`asio_http2.h` - -asio_http2.h is included from the other two files. - -To build a program with libnghttp2_asio, link to the following -libraries:: - - -lnghttp2_asio -lboost_system +.. code-block:: cpp -If ``boost::asio::ssl`` is used in application code, OpenSSL is also -required in link line:: + #include - -lnghttp2_asio -lboost_system -lssl -lcrypto +Also take a look at that header file :doc:`asio_http2.h`. Server API ---------- -To use server API, first include following header file: - -.. code-block:: cpp - - #include - -Also take a look at that header file :doc:`asio_http2_server.h`. - Server API is designed to build HTTP/2 server very easily to utilize C++11 anonymous function and closure. The bare minimum example of HTTP/2 server looks like this: .. code-block:: cpp + #include + using namespace nghttp2::asio_http2; using namespace nghttp2::asio_http2::server; int main(int argc, char *argv[]) { - boost::system::error_code ec; http2 server; - server.handle("/", [](const request &req, const response &res) { - res.write_head(200); - res.end("hello, world\n"); + server.listen("*", 3000, [](const std::shared_ptr &req, + const std::shared_ptr &res) { + res->write_head(200); + res->end("hello, world"); }); - - if (server.listen_and_serve(ec, "localhost", "3000")) { - std::cerr << "error: " << ec.message() << std::endl; - } } First we instantiate ``nghttp2::asio_http2::server::http2`` object. -``nghttp2::asio_http2::server::http2::handle`` function registers -pattern and its handler function. In this example, we register "/" as -pattern, which matches all requests. Then call -``nghttp2::asio_http2::server::http2::listen_and_serve`` function with -address and port to listen to. +Then call ``nghttp2::asio_http2::server::http2::listen`` function with +address and port to listen to and callback function, namely "request +callback", invoked when request arrives. The ``req`` and ``res`` represent HTTP request and response respectively. ``nghttp2::asio_http2_::server::response::write_head`` @@ -80,13 +58,9 @@ which is omitted in the above example, is additional header fields to send. -``nghttp2::asio_http2::server::response::end`` sends response body. +``nghttp2::asio_http2::server::response::end`` sends responde body. In the above example, we send string "hello, world". -The life time of req and res object ends after the callback set by -``nghttp2::asio_http2::server::response::on_close`` function. -Application must not use those objects after this call. - Serving static files and enabling SSL/TLS +++++++++++++++++++++++++++++++++++++++++ @@ -95,47 +69,40 @@ .. code-block:: cpp - #include + #include using namespace nghttp2::asio_http2; using namespace nghttp2::asio_http2::server; int main(int argc, char *argv[]) { - boost::system::error_code ec; - boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23); - - tls.use_private_key_file("server.key", boost::asio::ssl::context::pem); - tls.use_certificate_chain_file("server.crt"); - - configure_tls_context_easy(ec, tls); - http2 server; - server.handle("/index.html", [](const request &req, const response &res) { - res.write_head(200); - res.end(file_generator("index.html")); - }); + server.tls("server.key", "server.crt"); - if (server.listen_and_serve(ec, tls, "localhost", "3000")) { - std::cerr << "error: " << ec.message() << std::endl; - } + server.listen("*", 3000, [](const std::shared_ptr &req, + const std::shared_ptr &res) { + if (req->path() == "/" || req->path() == "/index.html") { + res->write_head(200); + res->end(file_reader("index.html")); + } else { + res->write_head(404); + res->end("404" + "404 Not Found"); + } + }); } -We first create ``boost::asio::ssl::context`` object and set path to -private key file and certificate file. -``nghttp2::asio_http2::server::configure_tls_context_easy`` function -configures SSL/TLS context object for HTTP/2 server use, including NPN -callbacks. +Specifying path to private key file and certificate file in +``nghttp2::asio_http2::server::http2::tls`` will enable SSL/TLS. Both +files must be in PEM format. -In the above example, if request path is "/index.html", we serve -index.html file in the current working directory. +In the above example, if request path is either "/" or "/index.html", +we serve index.html file in the current working directory. ``nghttp2::asio_http2::server::response::end`` has overload to take -function of type ``nghttp2::asio_http2::generator_cb`` and application -pass its implementation to generate response body. For the -convenience, libnghttp2_asio library provides -``nghttp2::asio_http2::file_generator`` function to generate function -to server static file. If other resource is requested, server -automatically responds with 404 status code. +function of type ``nghttp2::asio_http2::read_cb`` and application pass +its implementation to generate response body. For the convenience, +libnghttp2_asio library provides ``nghttp2::asio_http2::file_reader`` +function to generate function to server static file. Server push +++++++++++ @@ -144,56 +111,44 @@ .. code-block:: cpp - #include + #include using namespace nghttp2::asio_http2; using namespace nghttp2::asio_http2::server; int main(int argc, char *argv[]) { - boost::system::error_code ec; - boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23); + http2 server; - tls.use_private_key_file("server.key", boost::asio::ssl::context::pem); - tls.use_certificate_chain_file("server.crt"); + server.tls("server.key", "server.crt"); - configure_tls_context_easy(ec, tls); + server.listen("*", 3000, [](const std::shared_ptr &req, + const std::shared_ptr &res) { + if (req->path() == "/") { + req->push("GET", "/my.css"); - http2 server; + res->write_head(200); + res->end(file_reader("index.html")); - std::string style_css = "h1 { color: green; }"; + return; + } - server.handle("/", [&style_css](const request &req, const response &res) { - boost::system::error_code ec; - auto push = res.push(ec, "GET", "/style.css"); - push->write_head(200); - push->end(style_css); - - res.write_head(200); - res.end(R"( - - HTTP/2 FTW - -

This should be green

- - )"); - }); + if (req->path() == "/my.css") { + res->write_head(200); + res->end(file_reader("my.css")); - server.handle("/style.css", - [&style_css](const request &req, const response &res) { - res.write_head(200); - res.end(style_css); - }); + return; + } - if (server.listen_and_serve(ec, tls, "localhost", "3000")) { - std::cerr << "error: " << ec.message() << std::endl; - } + res->write_head(404); + res->end("404" + "404 Not Found"); + }); } -When client requested any resource other than "/style.css", we push -"/style.css". To push resource, call -``nghttp2::asio_http2::server::response::push`` function with desired -method and path. It returns another response object and use its -functions to send push response. +When client requested "/", we push "/my.css". To push resource, call +``nghttp2::asio_http2::server::request::push`` function with desired +method and path. Later, the callback will be called with the pushed +resource "/my.css". Enable multi-threading ++++++++++++++++++++++ @@ -209,225 +164,65 @@ // Use 4 native threads server.num_threads(4); -Client API ----------- - -To use client API, first include following header file: - -.. code-block:: cpp - - #include +Run blocking tasks in background thread ++++++++++++++++++++++++++++++++++++++++ -Also take a look at that header file :doc:`asio_http2_client.h`. +The request callback is called in the same thread where HTTP request +is handled. And many connections shares the same thread, we cannot +directly run blocking tasks in request callback. -Here is the sample client code to access HTTP/2 server and print out -response header fields and response body to the console screen: +To run blocking tasks, use +``nghttp2::asio_http2::server::request::run_task``. The passed +callback will be executed in the different thread from the thread +where request callback was executed. So application can perform +blocking task there. The example follows: .. code-block:: cpp - #include - - #include - - using boost::asio::ip::tcp; + #include + #include using namespace nghttp2::asio_http2; - using namespace nghttp2::asio_http2::client; - - int main(int argc, char *argv[]) { - boost::system::error_code ec; - boost::asio::io_service io_service; - - // connect to localhost:3000 - session sess(io_service, "localhost", "3000"); - - sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) { - boost::system::error_code ec; - - 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; - - res.on_data([](const uint8_t *data, std::size_t len) { - std::cerr.write(reinterpret_cast(data), len); - std::cerr << std::endl; - }); - }); - - 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; - }); - - io_service.run(); - } - -``nghttp2::asio_http2::client::session`` object takes -``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 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. - -The life time of req and res object ends after the callback set by -``nghttp2::asio_http2::server::request::on_close`` function. -Application must not use those objects after this call. - -Normally, client does not stop even after all requests are done unless -connection is lost. To stop client, call -``nghttp2::asio_http2::server::session::shutdown()``. - -Recieve server push and enable SSL/TLS -++++++++++++++++++++++++++++++++++++++ - -.. code-block:: cpp - - #include - - #include - - using boost::asio::ip::tcp; - - using namespace nghttp2::asio_http2; - using namespace nghttp2::asio_http2::client; - - int main(int argc, char *argv[]) { - boost::system::error_code ec; - boost::asio::io_service io_service; - - boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23); - tls.set_default_verify_paths(); - // disabled to make development easier... - // tls_ctx.set_verify_mode(boost::asio::ssl::verify_peer); - configure_tls_context(ec, tls); - - // connect to localhost:3000 - session sess(io_service, tls, "localhost", "3000"); - - sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) { - boost::system::error_code ec; - - auto req = sess.submit(ec, "GET", "http://localhost:3000/"); - - req->on_response([&sess](const response &res) { - std::cerr << "response received!" << std::endl; - res.on_data([&sess](const uint8_t *data, std::size_t len) { - std::cerr.write(reinterpret_cast(data), len); - std::cerr << std::endl; - }); - }); - - req->on_push([](const request &push) { - std::cerr << "push request received!" << std::endl; - push.on_response([](const response &res) { - std::cerr << "push response received!" << std::endl; - res.on_data([](const uint8_t *data, std::size_t len) { - std::cerr.write(reinterpret_cast(data), len); - std::cerr << std::endl; - }); - }); - }); - }); - - sess.on_error([](const boost::system::error_code &ec) { - std::cerr << "error: " << ec.message() << std::endl; - }); - - io_service.run(); - } - -The above sample code demonstrates how to enable SSL/TLS and receive -server push. Currently, -``nghttp2::asio_http2::client::configure_tls_context`` function setups -NPN callbacks for SSL/TLS context for HTTP/2 use. - -To receive server push, use -``nghttp2::asio_http2::client::request::on_push`` function to set -callback function which is invoked when server push request is -arrived. The callback function takes -``nghttp2::asio_http2::client::request`` object, which contains the -pushed request. To get server push response, set callback using -``nghttp2::asio_http2::client::request::on_response``. - -As stated in the previous section, client does not stop automatically -as long as HTTP/2 session is fine and connection is alive. We don't -call ``nghttp2::asio_http2::client::session::shutdown`` in this -example, so the program does not terminate after all responses are -received. Hit Ctrl-C to terminate the program. - -Multiple concurrent requests -++++++++++++++++++++++++++++ - -.. code-block:: cpp - - #include - - #include - - using boost::asio::ip::tcp; - - using namespace nghttp2::asio_http2; - using namespace nghttp2::asio_http2::client; + using namespace nghttp2::asio_http2::server; int main(int argc, char *argv[]) { - boost::system::error_code ec; - boost::asio::io_service io_service; - - // connect to localhost:3000 - session sess(io_service, "localhost", "3000"); - - sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) { - boost::system::error_code ec; + http2 server; - auto printer = [](const response &res) { - res.on_data([](const uint8_t *data, std::size_t len) { - std::cerr.write(reinterpret_cast(data), len); - std::cerr << std::endl; - }); - }; - - std::size_t num = 3; - auto count = std::make_shared(num); - - for (std::size_t i = 0; i < num; ++i) { - auto req = sess.submit(ec, "GET", - "http://localhost:3000/" + std::to_string(i + 1)); - - req->on_response(printer); - req->on_close([&sess, count](uint32_t error_code) { - if (--*count == 0) { - // shutdown session after |num| requests were done. - sess.shutdown(); - } - }); - } - }); + server.num_concurrent_tasks(16); - sess.on_error([](const boost::system::error_code &ec) { - std::cerr << "error: " << ec.message() << std::endl; + server.listen("*", 3000, [](const std::shared_ptr &req, + const std::shared_ptr &res) { + req->run_task([res](channel &channel) { + // executed in different thread than the thread where + // request callback was executed. + + // using res directly here is not safe. Capturing it by + // value is safe because it is std::shared_ptr. + + sleep(1); + + channel.post([res]() { + // executed in the same thread where request callback + // was executed. + res->write_head(200); + res->end("hello, world"); + }); + }); }); - - io_service.run(); } -Here is the sample to send 3 requests at once. Depending on the -server settings, these requests are processed out-of-order. In this -example, we have a trick to shutdown session after all requests were -done. We made ``count`` object which is shared pointer to int and is -initialized to 3. On each request closure (the invocation of the -callback set by ``nghttp2::asio_http2::client::request::on_close``), -we decrement the count. If count becomes 0, we are sure that all -requests have been done and initiate shutdown. +First we set the number of background threads which run tasks. By +default it is set to 1. In this example, we set it to 16, so at most +16 tasks can be executed concurrently without blocking handling new +requests. + +We call ``req->run_task()`` to execute task in background thread. In +the passed callback, we just simply sleeps 1 second. After sleep is +over, we schedule another callback to send response to the client. +Since the callback passed to ``req->run_task()`` is executed in the +different thread from the thread where request callback is called, +using ``req`` or ``res`` object directly there may cause undefined +behaviour. To avoid this issue, we can use +``nghttp2::asio_http2::channel::post`` by supplying a callback which +in turn get called in the same thread where request callback was +called. diff -Nru nghttp2-1.13.0/doc/sources/nghttpx-howto.rst nghttp2-0.6.7/doc/sources/nghttpx-howto.rst --- nghttp2-1.13.0/doc/sources/nghttpx-howto.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/sources/nghttpx-howto.rst 2014-11-30 14:15:07.000000000 +0000 @@ -1,109 +1,83 @@ -.. program:: nghttpx - nghttpx - HTTP/2 proxy - HOW-TO =============================== -:doc:`nghttpx.1` is a proxy translating protocols between HTTP/2 and -other protocols (e.g., HTTP/1, SPDY). It operates in several modes -and each mode may require additional programs to work with. This -article describes each operation mode and explains the intended -use-cases. It also covers some useful options later. +nghttpx is a proxy translating protocols between HTTP/2 and other +protocols (e.g., HTTP/1, SPDY). It operates in several modes and each +mode may require additional programs to work with. This article +describes each operation mode and explains the intended use-cases. It +also covers some useful options later. Default mode ------------ -If nghttpx is invoked without :option:`--http2-proxy`, it operates in -default mode. In this mode, it works as reverse proxy (gateway) for -both HTTP/2 and HTTP/1 clients to backend servers. This is also known -as "HTTP/2 router". If nghttpx is linked with spdylay library and -frontend connection is SSL/TLS, the frontend also supports SPDY -protocol. - -By default, 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 frontend -protocol selection will be done via ALPN or NPN. - -To turn off encryption on frontend connection, use ``no-tls`` keyword -in :option:`--frontend` option. In this case, SPDY protocol is not -available even if spdylay library is liked to nghttpx. HTTP/2 and -HTTP/1 are available on the frontend, and an HTTP/1 connection can be -upgraded to HTTP/2 using HTTP Upgrade. Starting HTTP/2 connection by -sending HTTP/2 connection preface is also supported. - -nghttpx can listen on multiple frontend addresses. This is achieved -by using multiple :option:`--frontend` options. For each frontend -address, TLS can be enabled or disabled. - -By default, backend connections are not encrypted. To enable TLS -encryption on backend connections, use ``tls`` keyword in -:option:`--backend` option. Using patterns and ``proto`` keyword in -:option:`--backend` option, backend application protocol can be -specified per host/request path pattern. It means that you can use -both HTTP/2 and HTTP/1 in backend connections at the same time. Note -that default backend protocol is HTTP/1.1. To use HTTP/2 in backend, -you have to specify ``h2`` in ``proto`` keyword in :option:`--backend` -explicitly. +If nghttpx is invoked without any ``-s``, ``-p`` and ``--client``, it +operates in default mode. In this mode, nghttpx frontend listens for +HTTP/2 requests and translates them to HTTP/1 requests. Thus it works +as reverse proxy (gateway) for HTTP/2 clients to HTTP/1 web server. +HTTP/1 requests are also supported in frontend as a fallback. If +nghttpx is linked with spdylay library and frontend connection is +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. + +With ``--frontend-no-tls`` option, user can turn off SSL/TLS in +frontend connection. In this case, SPDY protocol is not available +even if spdylay library is liked to nghttpx. HTTP/2 and HTTP/1 are +available on the frontend and a HTTP/1 connection can be upgraded to +HTTP/2 using HTTP Upgrade. Starting HTTP/2 connection by sending +HTTP/2 connection preface is also supported. -The backend is supposed to be Web server. For example, to make +The backend is supposed to be HTTP/1 Web server. For example, to make nghttpx listen to encrypted HTTP/2 requests at port 8443, and a -backend Web server is configured to listen to HTTP request at port -8080 in the same host, run nghttpx command-line like this: - -.. code-block:: text +backend HTTP/1 web server is configured to listen to HTTP/1 request at +port 8080 in the same host, run nghttpx command-line like this:: $ nghttpx -f0.0.0.0,8443 -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt Then HTTP/2 enabled client can access to the nghttpx in HTTP/2. For -example, you can send GET request to the server using nghttp: - -.. code-block:: text +example, you can send GET request to the server using nghttp:: $ nghttp -nv https://localhost:8443/ HTTP/2 proxy mode ----------------- -If nghttpx is invoked with :option:`--http2-proxy` (or its shorthand -:option:`-s`) option, it operates in HTTP/2 proxy mode. The supported -protocols in frontend and backend connections are the same in `default -mode`_. The difference is that this mode acts like forward proxy and -assumes the backend is HTTP proxy server (e.g., Squid, Apache Traffic -Server). HTTP/1 request must include absolute URI in request line. - -By default, frontend connection is encrypted. So this mode is also -called secure proxy. If nghttpx is linked with spdylay, it supports -SPDY protocols and it works as so called SPDY proxy. +If nghttpx is invoked with ``-s`` option, it operates in HTTP/2 proxy +mode. The supported protocols in frontend and backend connections are +the same in `default mode`_. The difference is that this mode acts +like forward proxy and assumes the backend is HTTP/1 proxy server +(e.g., squid, traffic server). So HTTP/1 request must include +absolute URI in request line. + +By default, frontend connection is encrypted, this mode is also called +secure proxy. If nghttpx is linked with spdylay, it supports SPDY +protocols and it works as so called SPDY proxy. -To turn off encryption on frontend connection, use ``no-tls`` keyword -in :option:`--frontend` option. +With ``--frontend-no-tls`` option, SSL/TLS is turned off in frontend +connection, so the connection gets insecure. -The backend must be HTTP proxy server. nghttpx supports multiple -backend server addresses. It translates incoming requests to HTTP +The backend must be HTTP/1 proxy server. nghttpx only supports 1 +backend server address. It translates incoming requests to HTTP/1 request to backend server. The backend server performs real proxy work for each request, for example, dispatching requests to the origin server and caching contents. -The backend connection is not encrypted by default. To enable -encryption, use ``tls`` keyword in :option:`--backend` option. The -default backend protocol is HTTP/1.1. To use HTTP/2 in backend -connection, use :option:`--backend` option, and specify ``h2`` in -``proto`` keyword explicitly. - For example, to make nghttpx listen to encrypted HTTP/2 requests at -port 8443, and a backend HTTP proxy server is configured to listen to -HTTP/1 request at port 8080 in the same host, run nghttpx command-line -like this: - -.. code-block:: text +port 8443, and a backend HTTP/1 proxy server is configured to listen +to HTTP/1 request at port 8080 in the same host, run nghttpx +command-line like this:: $ nghttpx -s -f'*,8443' -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt -At the time of this writing, Firefox 41 and Chromium v46 can use -nghttpx as HTTP/2 proxy. +At the time of this writing, Firefox nightly supports HTTP/2 proxy. +Chromium can use nghttpx as secure (SPDY) proxy and will support +HTTP/2 proxy in the near future. -To make Firefox or Chromium use nghttpx as HTTP/2 or SPDY proxy, user -has to create proxy.pac script file like this: +To make Firefox nightly or Chromium use nghttpx as HTTP/2 or SPDY +proxy, user has to create proxy.pac script file like this: .. code-block:: javascript @@ -112,90 +86,161 @@ } ``SERVERADDR`` and ``PORT`` is the hostname/address and port of the -machine nghttpx is running. Please note that both Firefox and -Chromium require valid certificate for secure proxy. +machine nghttpx is running. Please note that both Firefox nightly and +Chromium requires valid certificate for secure proxy. -For Firefox, open Preference window and select Advanced then click -Network tab. Clicking Connection Settings button will show the +For Firefox nightly, open Preference window and select Advanced then +click Network tab. Clicking Connection Settings button will show the dialog. Select "Automatic proxy configuration URL" and enter the path -to proxy.pac file, something like this: - -.. code-block:: text +to proxy.pac file, something like this:: file:///path/to/proxy.pac -For Chromium, use following command-line: - -.. code-block:: text +For Chromium, use following command-line:: $ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn -As HTTP/1 proxy server, Squid may work as out-of-box. Traffic server -requires to be configured as forward proxy. Here is the minimum -configuration items to edit: - -.. code-block:: text +Squid may work as out-of-box. Traffic server requires to be +configured as forward proxy. Here is the minimum configuration items +to edit:: CONFIG proxy.config.reverse_proxy.enabled INT 0 CONFIG proxy.config.url_remap.remap_required INT 0 Consult Traffic server `documentation -`_ +`_ to know how to configure traffic server as forward proxy and its security implications. -Disable frontend SSL/TLS ------------------------- +Client mode +----------- + +If nghttpx is invoked with ``--client`` option, it operates in client +mode. In this mode, nghttpx listens for plain, unencrypted HTTP/2 and +HTTP/1 requests and translates them to encrypted HTTP/2 requests to +the backend. User cannot enable SSL/TLS in frontend connection. + +HTTP/1 frontend connection can be upgraded to HTTP/2 using HTTP +Upgrade. To disable SSL/TLS in backend connection, use +``--backend-no-tls`` option. + +The backend connection is created one per worker (thread). + +The backend server is supporsed to be a HTTP/2 web server (e.g., +nghttpd). The one use-case of this mode is utilize existing HTTP/1 +clients to test HTTP/2 deployment. Suppose that HTTP/2 web server +listens to port 80 without encryption. Then run nghttpx as client +mode to access to that web server:: + + $ nghttpx --client -f127.0.0.1,8080 -b127.0.0.1,80 --backend-no-tls + +.. note:: + + You may need ``-k`` option if HTTP/2 server enables SSL/TLS and + its certificate is self-signed. But please note that it is + insecure. + +Then you can use curl to access HTTP/2 server via nghttpx:: + + $ curl http://localhost:8080/ + +Client proxy mode +----------------- + +If nghttpx is invoked with ``-p`` option, it operates in client proxy +mode. This mode behaves like `client mode`_, but it works like +forward proxy. So HTTP/1 request must include absolute URI in request +line. + +HTTP/1 frontend connection can be upgraded to HTTP/2 using HTTP +Upgrade. To disable SSL/TLS in backend connection, use +``--backend-no-tls`` option. -The frontend connections are encrypted with SSL/TLS by default. To -turn off SSL/TLS, use ``no-tls`` keyword in :option:`--frontend` -option. If this option is used, the private key and certificate are -not required to run nghttpx. +The backend connection is created one per worker (thread). -Enable backend SSL/TLS ----------------------- +The backend server must be a HTTP/2 proxy. You can use nghttpx in +`HTTP/2 proxy mode`_ as backend server. The one use-case of this mode +is utilize existing HTTP/1 clients to test HTTP/2 connections between +2 proxies. The another use-case is use this mode to aggregate local +HTTP/1 connections to one HTTP/2 backend encrypted connection. This +makes HTTP/1 clients which does not support secure proxy can use +secure HTTP/2 proxy via nghttpx client mode. -The backend connections are not encrypted by default. To enable -SSL/TLS encryption, use ``tls`` keyword in :option:`--backend` option. +Suppose that HTTP/2 proxy listens to port 8443, just like we saw in +`HTTP/2 proxy mode`_. To run nghttpx in client proxy mode to access +that server, invoke nghttpx like this:: -Enable SSL/TLS on memcached connection --------------------------------------- + $ nghttpx -p -f127.0.0.1,8080 -b127.0.0.1,8443 -By default, memcached connection is not encrypted. To enable -encryption, use ``tls`` keyword in -:option:`--tls-ticket-key-memcached` for TLS ticket key, and -:option:`--tls-session-cache-memcached` for TLS session cache. +.. note:: -Specifying additional server certificates ------------------------------------------ + You may need ``-k`` option if HTTP/2 server's certificate is + self-signed. But please note that it is insecure. -nghttpx accepts additional server private key and certificate pairs -using :option:`--subcert` option. It can be used multiple times. +Then you can use curl to issue HTTP request via HTTP/2 proxy:: + + $ curl --http-proxy=http://localhost:8080 http://www.google.com/ + +You can configure web browser to use localhost:8080 as forward +proxy. + +HTTP/2 bridge mode +------------------ + +If nghttpx is invoked with ``--http2-bridge`` option, it operates in +HTTP/2 bridge mode. The supported protocols in frontend connections +are the same in `default mode`_. The protocol in backend is HTTP/2 +only. + +With ``--frontend-no-tls`` option, SSL/TLS is turned off in frontend +connection, so the connection gets insecure. To disable SSL/TLS in +backend connection, use ``--backend-no-tls`` option. + +The backend server is supporsed to be a HTTP/2 web server or HTTP/2 +proxy. If backend server is HTTP/2 proxy, use +``--no-location-rewrite`` option to disable rewriting location header +field. + +The use-case of this mode is aggregate the incoming connections to one +HTTP/2 connection. One backend HTTP/2 connection is created per +worker (thread). + +Disable SSL/TLS +--------------- + +In `default mode`_, `HTTP/2 proxy mode`_ and `HTTP/2 bridge mode`_, +frontend connections are encrypted with SSL/TLS by default. To turn +off SSL/TLS, use ``--frontend-no-tls`` option. If this option is +used, the private key and certificate are not required to run nghttpx. + +In `client mode`_, `client proxy mode`_ and `HTTP/2 bridge mode`_, +backend connections are encrypted with SSL/TLS by default. To turn +off SSL/TLS, use ``--backend-no-tls`` option. Specifying additional CA certificate ------------------------------------ By default, nghttpx tries to read CA certificate from system. But depending on the system you use, this may fail or is not supported. -To specify CA certificate manually, use :option:`--cacert` option. -The specified file must be PEM format and can contain multiple +To specify CA certificate manually, use ``--cacert`` option. The +specified file must be PEM format and can contain multiple certificates. By default, nghttpx validates server's certificate. If you want to turn off this validation, knowing this is really insecure and what you -are doing, you can use :option:`--insecure` option to disable -certificate validation. +are doing, you can use ``-k`` option to disable certificate +validation. Read/write rate limit --------------------- nghttpx supports transfer rate limiting on frontend connections. You -can do rate limit per frontend connection for reading and writing +can do rate limit per worker (thread) for reading and writeing individually. -To perform rate limit for reading, use :option:`--read-rate` and -:option:`--read-burst` options. For writing, use -:option:`--write-rate` and :option:`--write-burst`. +To rate limit per worker (thread), use ``--worker-read-rate`` and +``--worker-read-burst`` options. For writing, use +``--worker-write-rate`` and ``--worker-write-burst``. Please note that rate limit is performed on top of TCP and nothing to do with HTTP/2 flow control. @@ -218,10 +263,10 @@ in :authority header field, rewrite is retried with the value in host header field. -Hot swapping ------------- +Hot deploy +---------- -nghttpx supports hot swapping using signals. The hot swapping in +nghttpx supports hot deploy feature using signals. The hot deploy in nghttpx is multi step process. First send USR2 signal to nghttpx process. It will do fork and execute new executable, using same command-line arguments and environment variables. At this point, both @@ -237,168 +282,5 @@ When rotating log files, it is desirable to re-open log files after log rotation daemon renamed existing log files. To tell nghttpx to re-open log files, send USR1 signal to nghttpx process. It will -re-open files specified by :option:`--accesslog-file` and -:option:`--errorlog-file` options. - -Multiple frontend addresses ---------------------------- - -nghttpx can listen on multiple frontend addresses. To specify them, -just use :option:`--frontend` (or its shorthand :option:`-f`) option -repeatedly. TLS can be enabled or disabled per frontend address -basis. For example, to listen on port 443 with TLS enabled, and on -port 80 without TLS: - -.. code-block:: text - - frontend=*,443 - frontend=*,80;no-tls - - -Multiple backend addresses --------------------------- - -nghttpx supports multiple backend addresses. To specify them, just -use :option:`--backend` (or its shorthand :option:`-b`) option -repeatedly. For example, to use ``192.168.0.10:8080`` and -``192.168.0.11:8080``, use command-line like this: -``-b192.168.0.10,8080 -b192.168.0.11,8080``. In configuration file, -this looks like: - -.. code-block:: text - - backend=192.168.0.10,8080 - backend=192.168.0.11,8008 - -nghttpx can route request to different backend according to request -host and path. For example, to route request destined to host -``doc.example.com`` to backend server ``docserv:3000``, you can write -like so: - -.. code-block:: text - - backend=docserv,3000;doc.example.com/ - -When you write this option in command-line, you should enclose -argument with single or double quotes, since the character ``;`` has a -special meaning in shell. - -To route, request to request path whose prefix is ``/foo`` to backend -server ``[::1]:8080``, you can write like so: - -.. code-block:: text - - backend=::1,8080;/foo - -Of course, you can specify both host and request path at the same -time: - -.. code-block:: text - - backend=192.168.0.10,8080;example.com/foo - -We can use ``*`` in the left most position of host to achieve wildcard -suffix match. If ``*`` is the left most character, then the remaining -string should match the request host suffix. ``*`` must match at -least one character. For example, ``*.example.com`` matches -``www.example.com`` and ``dev.example.com``, and does not match -``example.com`` and ``nghttp2.org``. The exact match (without ``*``) -always takes precedence over wildcard match. - -One important thing you have to remember is that we have to specify -default routing pattern for so called "catch all" pattern. To write -"catch all" pattern, just specify backend server address, without -pattern. - -Usually, host is the value of ``Host`` header field. In HTTP/2, the -value of ``:authority`` pseudo header field is used. - -When you write multiple backend addresses sharing the same routing -pattern, they are used as load balancing. For example, to use 2 -servers ``serv1:3000`` and ``serv2:3000`` for request host -``example.com`` and path ``/myservice``, you can write like so: - -.. code-block:: text - - backend=serv1,3000;example.com/myservice - backend=serv2,3000;example.com/myservice - -You can also specify backend application protocol in -:option:`--backend` option using ``proto`` keyword after pattern. -Utilizing this allows ngttpx to route certain request to HTTP/2, other -requests to HTTP/1. For example, to route requests to ``/ws/`` in -backend HTTP/1.1 connection, and use backend HTTP/2 for other -requests, do this: - -.. code-block:: text - - backend=serv1,3000;/;proto=h2 - backend=serv1,3000;/ws/;proto=http/1.1 - -Note that the backends share the same pattern must have the same -backend protocol. The default backend protocol is HTTP/1.1. - -TLS can be enabed per pattern basis: - -.. code-block:: text - - backend=serv1,8443;/;proto=h2;tls - backend=serv2,8080;/ws/;proto=http/1.1 - -In the above case, connection to serv1 will be encrypted by TLS. On -the other hand, connection to serv2 will not be encrypted by TLS. - -Migration from nghttpx v1.8.0 or earlier ----------------------------------------- - -As of nghttpx 1.9.0, ``--frontend-no-tls`` and ``--backend-no-tls`` -have been removed. - -To disable encryption on frontend connection, use ``no-tls`` keyword -in :option:`--frontend` potion: - -.. code-block:: text - - frontend=*,3000;no-tls - -The TLS encryption is now disabled on backend connection in all modes -by default. To enable encryption on backend connection, use ``tls`` -keyword in :option:`--backend` option: - -.. code-block:: text - - backend=127.0.0.1,8080;tls - -As of nghttpx 1.9.0, ``--http2-bridge``, ``--client`` and -``--client-proxy`` options have been removed. These functionality can -be used using combinations of options. - -Use following option instead of ``--http2-bridge``: - -.. code-block:: text - - backend=,;;proto=h2;tls - -Use following options instead of ``--client``: - -.. code-block:: text - - frontend=,;no-tls - backend=,;;proto=h2;tls - -Use following options instead of ``--client-proxy``: - -.. code-block:: text - - http2-proxy=yes - frontend=,;no-tls - backend=,;;proto=h2;tls - -We also removed ``--backend-http2-connections-per-worker`` option. It -was present because previously the number of backend h2 connection was -statically configured, and defaulted to 1. Now the number of backend -h2 connection is increased on demand. We know the maximum number of -concurrent streams per connection. When we push as many request as -the maximum concurrency to the one connection, we create another new -connection so that we can distribute load and avoid delay the request -processing. This is done automatically without any configuration. +re-open files specified by ``--accesslog-file`` and +``--errorlog-file`` options. diff -Nru nghttp2-1.13.0/doc/sources/python-apiref.rst nghttp2-0.6.7/doc/sources/python-apiref.rst --- nghttp2-1.13.0/doc/sources/python-apiref.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/sources/python-apiref.rst 2014-11-30 14:15:07.000000000 +0000 @@ -140,9 +140,7 @@ Python 3.4 or later is required to use these objects. To explicitly configure nghttp2 build to use Python 3.4, specify the ``PYTHON`` variable to the path to Python 3.4 executable when - invoking configure script like this: - - .. code-block:: text + invoking configure script like this:: $ ./configure PYTHON=/usr/bin/python3.4 @@ -222,10 +220,6 @@ 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() @@ -255,28 +249,10 @@ 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``, :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. + 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. The *headers* is a list of tuple of the form ``(name, value)``. The ``name`` and ``value`` can be either byte string @@ -297,8 +273,10 @@ 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 has the same - semantics of *body* parameter of :py:meth:`send_response()`. + 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 headers and request_headers are a list of tuple of the form ``(name, value)``. The ``name`` and ``value`` can be either byte @@ -310,27 +288,6 @@ 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: @@ -339,7 +296,6 @@ #!/usr/bin/env python import io, ssl - import nghttp2 class Handler(nghttp2.BaseRequestHandler): @@ -355,85 +311,9 @@ body=io.BytesIO(b'nghttp2-python FTW')) ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 + ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 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() diff -Nru nghttp2-1.13.0/doc/sources/tutorial-client.rst nghttp2-0.6.7/doc/sources/tutorial-client.rst --- nghttp2-1.13.0/doc/sources/tutorial-client.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/sources/tutorial-client.rst 2014-11-30 14:15:07.000000000 +0000 @@ -1,27 +1,25 @@ Tutorial: HTTP/2 client ========================= -In this tutorial, we are going to write a very primitive HTTP/2 +In this tutorial, we are going to write very primitive HTTP/2 client. The complete source code, `libevent-client.c`_, is attached at -the end of this page. It also resides in the examples directory in -the archive or repository. +the end of this page. It also resides in examples directory in the +archive or repository. -This simple client takes a single HTTPS URI and retrieves the resource -at the URI. The synopsis is: - -.. code-block:: text +This simple client takes 1 argument, HTTPS URI, and retrieves the +resource denoted by the URI. Its synopsis is like this:: $ libevent-client HTTPS_URI We use libevent in this tutorial to handle networking I/O. Please note that nghttp2 itself does not depend on libevent. -The client starts with some libevent and OpenSSL setup in the -``main()`` and ``run()`` functions. This setup isn't specific to -nghttp2, but one thing you should look at is setup of the NPN -callback. The NPN callback is used by the client to select the next -application protocol over TLS. In this tutorial, we use the -`nghttp2_select_next_protocol()` helper function to select the HTTP/2 +First we do some setup routine for libevent and OpenSSL library in +function ``main()`` and ``run()``, which is not so relevant to nghttp2 +library use. The one thing you should look at is setup NPN callback. +The NPN callback is used for the client to select the next application +protocol over the SSL/TLS transport. In this tutorial, we use +`nghttp2_select_next_protocol()` function to select the HTTP/2 protocol the library supports:: static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out, @@ -33,19 +31,8 @@ return SSL_TLSEXT_ERR_OK; } -If you are following TLS related RFC, you know that NPN is not the -standardized way to negotiate HTTP/2. NPN itself is not event -published as RFC. The standard way to negotiate HTTP/2 is ALPN, -Application-Layer Protocol Negotiation Extension, defined in `RFC 7301 -`_. The one caveat of ALPN is -that OpenSSL >= 1.0.2 is required. We use macro to enable/disable -ALPN support depending on OpenSSL version. OpenSSL's ALPN -implementation does not require callback function like the above. But -we have to instruct OpenSSL SSL_CTX to use ALPN, which we'll talk -about soon. - -The callback is added to the SSL_CTX object using -``SSL_CTX_set_next_proto_select_cb()``:: +The callback is set to the SSL_CTX object using +``SSL_CTX_set_next_proto_select_cb()`` function:: static SSL_CTX *create_ssl_ctx(void) { SSL_CTX *ssl_ctx; @@ -59,22 +46,11 @@ SSL_OP_NO_COMPRESSION | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL); - - #if OPENSSL_VERSION_NUMBER >= 0x10002000L - SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3); - #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - return ssl_ctx; } -Here we see ``SSL_CTX_get_alpn_protos()`` function call. We instructs -OpenSSL to notify the server that we support h2, ALPN identifier for -HTTP/2. - -The example client defines a couple of structs: - -We define and use a ``http2_session_data`` structure to store data -related to the HTTP/2 session:: +We use ``http2_session_data`` structure to store the data related to +the HTTP/2 session:: typedef struct { nghttp2_session *session; @@ -83,17 +59,17 @@ http2_stream_data *stream_data; } http2_session_data; -Since this program only handles one URI, it uses only one stream. We -store the single stream's data in a ``http2_stream_data`` structure -and the ``stream_data`` points to it. The ``http2_stream_data`` -structure is defined as follows:: +Since this program only handles 1 URI, it uses only 1 stream. We store +its stream specific data in ``http2_stream_data`` structure and the +``stream_data`` points to it. The ``struct http2_stream_data`` is +defined as follows:: typedef struct { - /* The NULL-terminated URI string to retrieve. */ + /* The NULL-terminated URI string to retreive. */ const char *uri; /* Parsed result of the |uri| */ struct http_parser_url *u; - /* The authority portion of the |uri|, not NULL-terminated */ + /* The authroity portion of the |uri|, not NULL-terminated */ char *authority; /* The path portion of the |uri|, including query, not NULL-terminated */ @@ -106,12 +82,12 @@ int32_t stream_id; } http2_stream_data; -We create and initialize these structures in +We creates and initializes these structures in ``create_http2_session_data()`` and ``create_http2_stream_data()`` respectively. -``initiate_connection()`` is called to start the connection to the -remote server. It's defined as:: +Then we call function ``initiate_connection()`` to start connecting to +the remote server:: static void initiate_connection(struct event_base *evbase, SSL_CTX *ssl_ctx, const char *host, uint16_t port, @@ -134,11 +110,11 @@ session_data->bev = bev; } -``initiate_connection()`` creates a bufferevent for the connection and -sets up three callbacks: ``readcb``, ``writecb``, and ``eventcb``. +We set 3 callbacks for the bufferevent: ``reacb``, ``writecb`` and +``eventcb``. -The ``eventcb()`` is invoked by the libevent event loop when an event -(e.g. connection has been established, timeout, etc.) occurs on the +The ``eventcb()`` is invoked by libevent event loop when an event +(e.g., connection has been established, timeout, etc) happens on the underlying network socket:: static void eventcb(struct bufferevent *bev, short events, void *ptr) { @@ -146,27 +122,7 @@ if (events & BEV_EVENT_CONNECTED) { int fd = bufferevent_getfd(bev); int val = 1; - const unsigned char *alpn = NULL; - unsigned int alpnlen = 0; - SSL *ssl; - fprintf(stderr, "Connected\n"); - - ssl = bufferevent_openssl_get_ssl(session_data->bev); - - SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen); - #if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (alpn == NULL) { - SSL_get0_alpn_selected(ssl, &alpn, &alpnlen); - } - #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) { - fprintf(stderr, "h2 is not negotiated\n"); - delete_http2_session_data(session_data); - return; - } - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); initialize_nghttp2_session(session_data); send_client_connection_header(session_data); @@ -186,18 +142,11 @@ delete_http2_session_data(session_data); } -Here we validate that HTTP/2 is negotiated, and if not, drop -connection. - -For ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR``, and ``BEV_EVENT_TIMEOUT`` -events, we just simply tear down the connection. - -The ``BEV_EVENT_CONNECTED`` event is invoked when the SSL/TLS -handshake has completed successfully. After this we're ready to begin -communicating via HTTP/2. - -The ``initialize_nghttp2_session()`` function initializes the nghttp2 -session object and several callbacks:: +For ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR`` and ``BEV_EVENT_TIMEOUT`` +event, we just simply tear down the connection. The +``BEV_EVENT_CONNECTED`` event is invoked when SSL/TLS handshake is +finished successfully. We first initialize nghttp2 session object in +``initialize_nghttp2_session()`` function:: static void initialize_nghttp2_session(http2_session_data *session_data) { nghttp2_session_callbacks *callbacks; @@ -226,19 +175,18 @@ nghttp2_session_callbacks_del(callbacks); } -Since we are creating a client, we use `nghttp2_session_client_new()` -to initialize the nghttp2 session object. The callbacks setup are -explained later. - -The `delete_http2_session_data()` function destroys ``session_data`` -and frees its bufferevent, so the underlying connection is closed. It -also calls `nghttp2_session_del()` to delete the nghttp2 session -object. - -A HTTP/2 connection begins by sending the client connection preface, -which is a 24 byte magic byte string (:macro:`NGHTTP2_CLIENT_MAGIC`), -followed by a SETTINGS frame. The 24 byte magic string is sent -automatically by nghttp2. We send the SETTINGS frame in +Since we are creating client, we use `nghttp2_session_client_new()` to +initialize nghttp2 session object. We setup 7 callbacks for the +nghttp2 session. We'll explain these callbacks later. + +The `delete_http2_session_data()` destroys ``session_data`` and frees +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 ``send_client_connection_header()``:: static void send_client_connection_header(http2_session_data *session_data) { @@ -246,7 +194,8 @@ {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}}; int rv; - /* client 24 bytes magic string will be sent by nghttp2 library */ + bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE, + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv, ARRLEN(iv)); if (rv != 0) { @@ -254,17 +203,17 @@ } } -Here we specify SETTINGS_MAX_CONCURRENT_STREAMS as 100. This is not -needed for this tiny example program, it just demonstrates use of the -SETTINGS frame. To queue the SETTINGS frame for transmission, we call -`nghttp2_submit_settings()`. Note that `nghttp2_submit_settings()` -only queues the frame for transmission, and doesn't actually send it. -All ``nghttp2_submit_*()`` family functions have this property. To -actually send the frame, `nghttp2_session_send()` has to be called, -which is described (and called) later. +Here we specify SETTINGS_MAX_CONCURRENT_STREAMS to 100, which is +really not needed for this tiny example progoram, 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 +actually send it. All ``nghttp2_submit_*()`` family functions have +this property. To actually send the frame, `nghttp2_session_send()` is +used, which is described about later. -After the transmission of the client connection header, we enqueue the -HTTP request in the ``submit_request()`` function:: +After the transmission of client connection header, we enqueue HTTP +request in ``submit_request()`` function:: static void submit_request(http2_session_data *session_data) { int32_t stream_id; @@ -288,18 +237,17 @@ stream_data->stream_id = stream_id; } -We build the HTTP request header fields in ``hdrs``, which is an array -of :type:`nghttp2_nv`. There are four header fields to be sent: -``:method``, ``:scheme``, ``:authority``, and ``:path``. To queue the -HTTP request, we call `nghttp2_submit_request()`. The ``stream_data`` -is passed via the *stream_user_data* parameter, which is helpfully -later passed back to callback functions. - +We build HTTP request header fields in ``hdrs`` which is an array of +:type:`nghttp2_nv`. There are 4 header fields to be sent: ``:method``, +``:scheme``, ``:authority`` and ``:path``. To queue this HTTP request, +we use `nghttp2_submit_request()` function. The `stream_data` is +passed in *stream_user_data* parameter. It is used in nghttp2 +callbacks which we'll describe about later. `nghttp2_submit_request()` returns the newly assigned stream ID for -the request. +this request. The next bufferevent callback is ``readcb()``, which is invoked when -data is available to read from the bufferevent input buffer:: +data is available to read in the bufferevent input buffer:: static void readcb(struct bufferevent *bev, void *ptr) { http2_session_data *session_data = (http2_session_data *)ptr; @@ -314,7 +262,7 @@ delete_http2_session_data(session_data); return; } - if (evbuffer_drain(input, (size_t)readlen) != 0) { + if (evbuffer_drain(input, readlen) != 0) { warnx("Fatal error: evbuffer_drain failed"); delete_http2_session_data(session_data); return; @@ -325,13 +273,12 @@ } } -In this function we feed all unprocessed, received data to the nghttp2 -session object using the `nghttp2_session_mem_recv()` function. +In this function, we feed all unprocessed, received data to nghttp2 +session object using `nghttp2_session_mem_recv()` function. The `nghttp2_session_mem_recv()` processes the received data and may -invoke nghttp2 callbacks and queue frames for transmission. Since -there may be pending frames for transmission, we call immediately -``session_send()`` to send them. ``session_send()`` is defined as -follows:: +invoke nghttp2 callbacks and also queue frames. Since there may be +pending frames, we call ``session_send()`` function to send those +frames. The ``session_send()`` function is defined as follows:: static int session_send(http2_session_data *session_data) { int rv; @@ -344,34 +291,34 @@ return 0; } -The `nghttp2_session_send()` function serializes pending frames into -wire format and calls the ``send_callback()`` function to send them. -``send_callback()`` has type :type:`nghttp2_send_callback` and is -defined as:: +The `nghttp2_session_send()` function serializes the frame into wire +format and call ``send_callback()`` function of type +:type:`nghttp2_send_callback`. The ``send_callback()`` is defined as +follows:: static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data, size_t length, int flags _U_, void *user_data) { http2_session_data *session_data = (http2_session_data *)user_data; struct bufferevent *bev = session_data->bev; bufferevent_write(bev, data, length); - return (ssize_t)length; + return length; } Since we use bufferevent to abstract network I/O, we just write the data to the bufferevent object. Note that `nghttp2_session_send()` continues to write all frames queued so far. If we were writing the -data to the non-blocking socket directly using the ``write()`` system -call, we'd soon receive an ``EAGAIN`` or ``EWOULDBLOCK`` error, since -sockets have a limited send buffer. If that happens, it's possible to -return :macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the nghttp2 library -to stop sending further data. When writing to a bufferevent, you -should regulate the amount of data written, to avoid possible huge -memory consumption. In this example client however we don't implement -a limit. To see how to regulate the amount of buffered data, see the -``send_callback()`` in the server tutorial. +data to the non-blocking socket directly using ``write()`` system call +in the ``send_callback()``, we will surely get ``EAGAIN`` or +``EWOULDBLOCK`` since the socket has limited send buffer. If that +happens, we can return :macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the +nghttp2 library to stop sending further data. But writing to the +bufferevent, we have to regulate the amount data to be buffered by +ourselves to avoid possible huge memory consumption. In this example +client, we do not limit anything. To see how to regulate the amount of +buffered data, see the ``send_callback()`` in the server tutorial. The third bufferevent callback is ``writecb()``, which is invoked when -all data written in the bufferevent output buffer has been sent:: +all data written in the bufferevent output buffer have been sent:: static void writecb(struct bufferevent *bev _U_, void *ptr) { http2_session_data *session_data = (http2_session_data *)ptr; @@ -383,25 +330,25 @@ } As described earlier, we just write off all data in `send_callback()`, -so there is no data to write in this function. All we have to do is -check if the connection should be dropped or not. The nghttp2 session -object keeps track of reception and transmission of GOAWAY frames and -other error conditions. Using this information, the nghttp2 session -object can state whether the connection should be dropped or not. -More specifically, when both `nghttp2_session_want_read()` and -`nghttp2_session_want_write()` return 0, the connection is no-longer -required and can be closed. Since we're using bufferevent and its -deferred callback option, the bufferevent output buffer may still -contain pending data when the ``writecb()`` is called. To handle this -situation, we also check whether the output buffer is empty or not. If -all of these conditions are met, then we drop the connection. +we have no data to write in this function. All we have to do is check +we have to drop connection or not. The nghttp2 session object keeps +track of reception and transmission of GOAWAY frame and other error +conditions as well. Using these information, nghttp2 session object +will tell whether the connection should be dropped or not. More +specifically, both `nghttp2_session_want_read()` and +`nghttp2_session_want_write()` return 0, we have no business in the +connection. But since we are using bufferevent and its deferred +callback option, the bufferevent output buffer may contain the pending +data when the ``writecb()`` is called. To handle this situation, we +also check whether the output buffer is empty or not. If these +conditions are met, we drop connection. -Now let's look at the remaining nghttp2 callbacks setup in the +We have already described about nghttp2 callback ``send_callback()``. +Let's describe remaining nghttp2 callbacks we setup in ``initialize_nghttp2_setup()`` function. -A server responds to the request by first sending a HEADERS frame. -The HEADERS frame consists of response header name/value pairs, and -the ``on_header_callback()`` is called for each name/value pair:: +Each request header name/value pair is emitted via +``on_header_callback`` function:: static int on_header_callback(nghttp2_session *session _U_, const nghttp2_frame *frame, const uint8_t *name, @@ -421,11 +368,10 @@ return 0; } -In this tutorial, we just print the name/value pairs on stdout. +In this tutorial, we just print the name/value pair. -After the HEADERS frame has been fully received (and thus all response -header name/value pairs have been received), the -``on_frame_recv_callback()`` function is called:: +After all name/value pairs are emitted for a frame, +``on_frame_recv_callback`` function is called:: static int on_frame_recv_callback(nghttp2_session *session _U_, const nghttp2_frame *frame, void *user_data) { @@ -441,16 +387,13 @@ return 0; } -``on_frame_recv_callback()`` is called for other frame types too. +In this tutorial, we are just interested in the HTTP response +HEADERS. We check te frame type and its category (it should be +:macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). Also check +its stream ID. -In this tutorial, we are just interested in the HTTP response HEADERS -frame. We check the frame type and its category (it should be -:macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). We also -check its stream ID. - -Next, zero or more DATA frames can be received. The -``on_data_chunk_recv_callback()`` function is invoked when a chunk of -data is received from the remote peer:: +The ``on_data_chunk_recv_callback()`` function is invoked when a chunk +of data is received from the remote peer:: static int on_data_chunk_recv_callback(nghttp2_session *session _U_, uint8_t flags _U_, int32_t stream_id, @@ -463,10 +406,10 @@ return 0; } -In our case, a chunk of data is HTTP response body. After checking the -stream ID, we just write the received data to stdout. Note the output -in the terminal may be corrupted if the response body contains some -binary data. +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 +output in the terminal may be corrupted if the response body contains +some binary data. The ``on_stream_close_callback()`` function is invoked when the stream is about to close:: @@ -489,9 +432,9 @@ } If the stream ID matches the one we initiated, it means that its -stream is going to be closed. Since we have finished receiving -resource we wanted (or the stream was reset by RST_STREAM from the +stream is going to be closed. Since we have finished to get the +resource we want (or the stream was reset by RST_STREAM from the remote peer), we call `nghttp2_session_terminate_session()` to -commence closure of the HTTP/2 session gracefully. If you have +commencing the closure of the HTTP/2 session gracefully. If you have some data associated for the stream to be closed, you may delete it here. diff -Nru nghttp2-1.13.0/doc/sources/tutorial-hpack.rst nghttp2-0.6.7/doc/sources/tutorial-hpack.rst --- nghttp2-1.13.0/doc/sources/tutorial-hpack.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/sources/tutorial-hpack.rst 2014-11-30 14:15:07.000000000 +0000 @@ -1,129 +1,118 @@ Tutorial: HPACK API =================== -In this tutorial, we describe basic use of nghttp2's HPACK API. We -briefly describe the APIs for deflating and inflating header fields. -The full example of using these APIs, `deflate.c`_, is attached at the -end of this page. It also resides in the examples directory in the -archive or repository. +In this tutorial, we describe basic use of HPACK API in nghttp2 +library. We briefly describe APIs for deflating and inflating header +fields. The example of using these APIs are presented as complete +source code `deflate.c`_. Deflating (encoding) headers ---------------------------- -First we need to initialize a :type:`nghttp2_hd_deflater` object using -the `nghttp2_hd_deflate_new()` function:: +First we need to initialize :type:`nghttp2_hd_deflater` object using +`nghttp2_hd_deflate_new()` function:: int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, size_t deflate_hd_table_bufsize_max); -This function allocates a :type:`nghttp2_hd_deflater` object, -initializes it, and assigns its pointer to ``*deflater_ptr``. The -*deflate_hd_table_bufsize_max* is the upper bound of header table size -the deflater will use. This will limit the memory usage by the -deflater object for the dynamic header table. If in doubt, just +This function allocates :type:`nghttp2_hd_deflater` object and +initializes it and assigns its pointer to ``*deflater_ptr`` passed by +parameter. The *deflate_hd_table_bufsize_max* is the upper bound of +header table size the deflater will use. This will limit the memory +usage in deflater object for dynamic header table. If you doubt, just specify 4096 here, which is the default upper bound of dynamic header table buffer size. -To encode header fields, use the `nghttp2_hd_deflate_hd()` function:: +To encode header fields, `nghttp2_hd_deflate_hd()` function:: ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, size_t buflen, const nghttp2_nv *nva, size_t nvlen); The *deflater* is the deflater object initialized by -`nghttp2_hd_deflate_new()` described above. The encoded byte string is -written to the buffer *buf*, which has length *buflen*. The *nva* is -a pointer to an array of headers fields, each of type -:type:`nghttp2_nv`. *nvlen* is the number of header fields which -*nva* contains. +`nghttp2_hd_deflate_new()` function described above. The *buf* is a +pointer to buffer to store encoded byte string. The *buflen* is +capacity of *buf*. The *nva* is a pointer to :type:`nghttp2_nv`, +which is an array of header fields to deflate. The *nvlen* is the +number of header fields which *nva* contains. It is important to initialize and assign all members of -:type:`nghttp2_nv`. For security sensitive header fields (such as -cookies), set the :macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in -:member:`nghttp2_nv.flags`. Setting this flag prevents recovery of -sensitive header fields by compression based attacks: This is achieved -by not inserting the header field into the dynamic header table. +:type:`nghttp2_nv`. If a header field should not be inserted in +dynamic header table for a security reason, set +:macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in :member:`nghttp2_nv.flags`. `nghttp2_hd_deflate_hd()` processes all headers given in *nva*. The *nva* must include all request or response header fields to be sent in one HEADERS (or optionally following (multiple) CONTINUATION frame(s)). The *buf* must have enough space to store the encoded -result, otherwise the function will fail. To estimate the upper bound -of the encoded result length, use `nghttp2_hd_deflate_bound()`:: +result. Otherwise, the function will fail. To estimate the upper +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 the same parameters (*deflater*, *nva*, and -*nvlen*) which will be passed to `nghttp2_hd_deflate_hd()`. +Pass this function with the same paramters *deflater*, *nva* and +*nvlen* which will be passed to `nghttp2_hd_deflate_hd()`. -Subsequent calls to `nghttp2_hd_deflate_hd()` will use the current -encoder state and perform differential encoding, which yields HPAC's -fundamental compression gain. - -If `nghttp2_hd_deflate_hd()` fails, the failure is fatal and any -further calls with the same deflater object will fail. Thus it's very -important to use `nghttp2_hd_deflate_bound()` to determine the -required size of the output buffer. +The subsequent call of `nghttp2_hd_deflate_hd()` will use current +encoder state and perform differential encoding which is the +fundamental compression gain for HPACK. + +Once `nghttp2_hd_deflate_hd()` fails, it cannot be undone and its +further call with the same deflater object shall fail. So it is very +important to use `nghttp2_hd_deflate_bound()` to know the required +size of buffer. -To delete a :type:`nghttp2_hd_deflater` object, use the -`nghttp2_hd_deflate_del()` function. +To delete :type:`nghttp2_hd_deflater` object, use `nghttp2_hd_deflate_del()` +function. Inflating (decoding) headers ---------------------------- -A :type:`nghttp2_hd_inflater` object is used to inflate compressed -header data. To initialize the object, use -`nghttp2_hd_inflate_new()`:: +We use :type:`nghttp2_hd_inflater` object to inflate compressed header +data. To initialize the object, use `nghttp2_hd_inflate_new()`:: int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr); -To inflate header data, use `nghttp2_hd_inflate_hd()`:: +To inflate header data, use `nghttp2_hd_inflate_hd()` function:: ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, int *inflate_flags, uint8_t *in, size_t inlen, int in_final); -`nghttp2_hd_inflate_hd()` reads a stream of bytes and outputs a single -header field at a time. Multiple calls are normally required to read a -full stream of bytes and output all of the header fields. - The *inflater* is the inflater object initialized above. The *nv_out* -is a pointer to a :type:`nghttp2_nv` into which one header field may -be stored. The *in* is a pointer to input data, and *inlen* is its -length. The caller is not required to specify the whole deflated -header data via *in* at once: Instead it can call this function -multiple times as additional data bytes become available. If -*in_final* is nonzero, it tells the function that the passed data is -the final sequence of deflated header data. - -The *inflate_flags* is an output parameter; on success the function -sets it to a bitset of flags. It will be described later. +is a pointer to :type:`nghttp2_nv` to store the result. The *in* is a +pointer to input data and *inlen* is its length. The caller is not +required to specify whole deflated header data to *in* at once. It +can call this function multiple times for portion of the data in +streaming way. If *in_final* is nonzero, it tells the function that +the passed data is the final sequence of deflated header data. The +*inflate_flags* is output parameter and successful call of this +function stores a set of flags in it. It will be described later. This function returns when each header field is inflated. When this -happens, the function sets the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag -in *inflate_flags*, and a header field is stored in *nv_out*. The -return value indicates the number of bytes read from *in* processed so -far, which may be less than *inlen*. The caller should call the -function repeatedly until all bytes are processed. Processed bytes -should be removed from *in*, and *inlen* should be adjusted -appropriately. +happens, the function sets :macro:`NGHTTP2_HD_INFLATE_EMIT` flag to +*inflate_flag* parameter and header field is stored in *nv_out*. The +return value indicates the number of data read from *in* to processed +so far. It may be less than *inlen*. The caller should call the +function repeatedly until all data are processed by adjusting *in* and +*inlen* with the processed bytes. If *in_final* is nonzero and all given data was processed, the -function sets the :macro:`NGHTTP2_HD_INFLATE_FINAL` flag in -*inflate_flags*. When you see this flag set, call the +function sets :macro:`NGHTTP2_HD_INFLATE_FINAL` flag to +*inflate_flag*. If the caller sees this flag set, call `nghttp2_hd_inflate_end_headers()` function. -If *in_final* is zero and the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is -not set, it indicates that all given data was processed. The caller -is required to pass additional data. +If *in_final* is zero and :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is not +set, it indicates that all given data was processed. The caller is +required to pass subsequent data. It is important to note that the function may produce one or more header fields even if *inlen* is 0 when *in_final* is nonzero, due to differential encoding. -Example usage of `nghttp2_hd_inflate_hd()` is shown in the +The example use of `nghttp2_hd_inflate_hd()` is shown in `inflate_header_block()` function in `deflate.c`_. -Finally, to delete a :type:`nghttp2_hd_inflater` object, use -`nghttp2_hd_inflate_del()`. +To delete :type:`nghttp2_hd_inflater` object, use `nghttp2_hd_inflate_del()` +function. diff -Nru nghttp2-1.13.0/doc/sources/tutorial-server.rst nghttp2-0.6.7/doc/sources/tutorial-server.rst --- nghttp2-1.13.0/doc/sources/tutorial-server.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/sources/tutorial-server.rst 2014-11-30 14:15:07.000000000 +0000 @@ -1,43 +1,30 @@ Tutorial: HTTP/2 server ========================= -In this tutorial, we are going to write a single-threaded, event-based -HTTP/2 web server, which supports HTTPS only. It can handle concurrent -multiple requests, but only the GET method is supported. The complete -source code, `libevent-server.c`_, is attached at the end of this -page. The source also resides in the examples directory in the -archive or repository. - -This simple server takes 3 arguments: The port number to listen on, -the path to your SSL/TLS private key file, and the path to your -certificate file. The synopsis is: - -.. code-block:: text +In this tutorial, we are going to write single-threaded, event-based +HTTP/2 web server, which supports HTTPS only. It can handle +concurrent multiple requests, but only the GET method is supported. The +complete source code, `libevent-server.c`_, is attached at the end of +this page. It also resides in examples directory in the archive or +repository. + +This simple server takes 3 arguments, a port number to listen to, a path to +your SSL/TLS private key file and a path to your certificate file. Its +synopsis is like this:: $ libevent-server PORT /path/to/server.key /path/to/server.crt We use libevent in this tutorial to handle networking I/O. Please note that nghttp2 itself does not depend on libevent. -The server starts with some libevent and OpenSSL setup in the -``main()`` and ``run()`` functions. This setup isn't specific to -nghttp2, but one thing you should look at is setup of the NPN -callback. The NPN callback is used by the server to advertise which -application protocols the server supports to a client. In this -example program, when creating the ``SSL_CTX`` object, we store the -application protocol name in the wire format of NPN in a statically -allocated buffer. This is safe because we only create one ``SSL_CTX`` -object in the program's entire lifetime. - -If you are following TLS related RFC, you know that NPN is not the -standardized way to negotiate HTTP/2. NPN itself is not even -published as RFC. The standard way to negotiate HTTP/2 is ALPN, -Application-Layer Protocol Negotiation Extension, defined in `RFC 7301 -`_. The one caveat of ALPN is -that OpenSSL >= 1.0.2 is required. We use macro to enable/disable -ALPN support depending on OpenSSL version. In ALPN, client sends the -list of supported application protocols, and server selects one of -them. We provide the callback for it:: +First we create a setup routine for libevent and OpenSSL in the functions +``main()`` and ``run()``. One thing in there you should look at, is the setup +of the NPN callback. The NPN callback is used for the server to advertise +which application protocols the server supports to a client. In this example +program, when creating ``SSL_CTX`` object, we store the application protocol +name in the wire format of NPN in a statically allocated buffer. This is safe +because we only create one ``SSL_CTX`` object in the program's entire life +time:: static unsigned char next_proto_list[256]; static size_t next_proto_list_len; @@ -49,22 +36,6 @@ return SSL_TLSEXT_ERR_OK; } - #if OPENSSL_VERSION_NUMBER >= 0x10002000L - static int alpn_select_proto_cb(SSL *ssl _U_, const unsigned char **out, - unsigned char *outlen, const unsigned char *in, - unsigned int inlen, void *arg _U_) { - int rv; - - rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen); - - if (rv != 1) { - return SSL_TLSEXT_ERR_NOACK; - } - - return SSL_TLSEXT_ERR_OK; - } - #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) { SSL_CTX *ssl_ctx; EC_KEY *ecdh; @@ -79,33 +50,20 @@ next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN; SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL); - - #if OPENSSL_VERSION_NUMBER >= 0x10002000L - SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL); - #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - return ssl_ctx; } -The wire format of NPN is a sequence of length prefixed strings, with -exactly one byte used to specify the length of each protocol -identifier. In this tutorial, we advertise the specific HTTP/2 -protocol version the current nghttp2 library supports, which is -exported in the identifier :macro:`NGHTTP2_PROTO_VERSION_ID`. The -``next_proto_cb()`` function is the server-side NPN callback. In the -OpenSSL implementation, we just assign the pointer to the NPN buffers -we filled in earlier. The NPN callback function is set to the -``SSL_CTX`` object using ``SSL_CTX_set_next_protos_advertised_cb()``. - -In ``alpn_select_proto_cb()``, we use `nghttp2_select_next_protocol()` -to select application protocol. The `nghttp2_select_next_protocol()` -returns 1 only if it selected h2 (ALPN identifier for HTTP/2), and out -parameters were assigned accordingly. - -Next, let's take a look at the main structures used by the example -application: +The wire format of NPN is a sequence of length prefixed string. Exactly one +byte is used to specify the length of each protocol identifier. In this +tutorial, we advertise the specific HTTP/2 protocol version the current +nghttp2 library supports. The nghttp2 library exports its identifier in +:macro:`NGHTTP2_PROTO_VERSION_ID`. The ``next_proto_cb()`` function is the +server-side NPN callback. In the OpenSSL implementation, we just assign the +pointer to the NPN buffers we filled in earlier. The NPN callback function is +set to the ``SSL_CTX`` object using +``SSL_CTX_set_next_protos_advertised_cb()``. -We use the ``app_context`` structure to store application-wide data:: +We use the ``app_content`` structure to store application-wide data:: struct app_context { SSL_CTX *ssl_ctx; @@ -132,21 +90,18 @@ int fd; } http2_stream_data; -A single HTTP/2 session can have multiple streams. To manage them, we -use a doubly linked list: The first element of this list is pointed -to by the ``root->next`` in ``http2_session_data``. Initially, -``root->next`` is ``NULL``. - -libevent's bufferevent structure is used to perform network I/O, with -the pointer to the bufferevent stored in the ``http2_session_data`` -structure. Note that the bufferevent object is kept in -``http2_session_data`` and not in ``http2_stream_data``. This is -because ``http2_stream_data`` is just a logical stream multiplexed -over the single connection managed by the bufferevent in +A single HTTP/2 session can have multiple streams. We manage these +multiple streams with a doubly linked list. The first element of this +list is pointed to by the ``root->next`` in ``http2_session_data``. +Initially, ``root->next`` is ``NULL``. We use libevent's bufferevent +structure to perform network I/O. Note that the bufferevent object is +kept in ``http2_session_data`` and not in ``http2_stream_data``. This +is because ``http2_stream_data`` is just a logical stream multiplexed +over the single connection managed by bufferevent in ``http2_session_data``. -We first create a listener object to accept incoming connections. -libevent's ``struct evconnlistener`` is used for this purpose:: +We first create a listener object to accept incoming connections. We use +libevent's ``struct evconnlistener`` for this purpose:: static void start_listen(struct event_base *evbase, const char *service, app_context *app_ctx) { @@ -170,7 +125,7 @@ struct evconnlistener *listener; listener = evconnlistener_new_bind( evbase, acceptcb, app_ctx, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, - 16, rp->ai_addr, (int)rp->ai_addrlen); + 16, rp->ai_addr, rp->ai_addrlen); if (listener) { freeaddrinfo(res); @@ -180,7 +135,7 @@ errx(1, "Could not start listener"); } -We specify the ``acceptcb`` callback, which is called when a new connection is +We specify the ``acceptcb`` callback which is called when a new connection is accepted:: static void acceptcb(struct evconnlistener *listener _U_, int fd, @@ -193,43 +148,23 @@ bufferevent_setcb(session_data->bev, readcb, writecb, eventcb, session_data); } -Here we create the ``http2_session_data`` object. The connection's -bufferevent is initialized at the same time. We specify three -callbacks for the bufferevent: ``readcb``, ``writecb``, and +Here we create the ``http2_session_data`` object. The bufferevent for +this connection is also initialized at this time. We specify three +callbacks for the bufferevent: ``readcb``, ``writecb`` and ``eventcb``. The ``eventcb()`` callback is invoked by the libevent event loop when an event -(e.g. connection has been established, timeout, etc.) occurs on the +(e.g., connection has been established, timeout, etc) happens on the underlying network socket:: static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) { http2_session_data *session_data = (http2_session_data *)ptr; if (events & BEV_EVENT_CONNECTED) { - const unsigned char *alpn = NULL; - unsigned int alpnlen = 0; - SSL *ssl; - fprintf(stderr, "%s connected\n", session_data->client_addr); - ssl = bufferevent_openssl_get_ssl(session_data->bev); - - SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen); - #if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (alpn == NULL) { - SSL_get0_alpn_selected(ssl, &alpn, &alpnlen); - } - #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) { - fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr); - delete_http2_session_data(session_data); - return; - } - initialize_nghttp2_session(session_data); - if (send_server_connection_header(session_data) != 0 || - session_send(session_data) != 0) { + if (send_server_connection_header(session_data) != 0) { delete_http2_session_data(session_data); return; } @@ -246,26 +181,28 @@ delete_http2_session_data(session_data); } -Here we validate that HTTP/2 is negotiated, and if not, drop -connection. - -For the ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR``, and +For the ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR`` and ``BEV_EVENT_TIMEOUT`` events, we just simply tear down the connection. The ``delete_http2_session_data()`` function destroys the -``http2_session_data`` object and its associated bufferevent member. -As a result, the underlying connection is closed. - -The -``BEV_EVENT_CONNECTED`` event is invoked when SSL/TLS handshake has -completed successfully. After this we are ready to begin communicating -via HTTP/2. +``http2_session_data`` object and thus also its bufferevent member. +As a result, the underlying connection is closed. The +``BEV_EVENT_CONNECTED`` event is invoked when SSL/TLS handshake is +finished successfully. Now we are ready to start the HTTP/2 +communication. -The ``initialize_nghttp2_session()`` function initializes the nghttp2 -session object and several callbacks:: +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); @@ -282,18 +219,23 @@ nghttp2_session_callbacks_set_on_begin_headers_callback( callbacks, on_begin_headers_callback); - nghttp2_session_server_new(&session_data->session, callbacks, session_data); + nghttp2_session_server_new2(&session_data->session, callbacks, session_data, + option); nghttp2_session_callbacks_del(callbacks); + nghttp2_option_del(option); } -Since we are creating a server, we use `nghttp2_session_server_new()` -to initialize the nghttp2 session object. We also setup 5 callbacks -for the nghttp2 session, these are explained later. - -The server now begins by sending the server connection preface, which -always consists of a SETTINGS frame. -``send_server_connection_header()`` configures and submits it:: +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. + +After initialization of the nghttp2 session object, we are going to send +a server connection header in ``send_server_connection_header()``:: static int send_server_connection_header(http2_session_data *session_data) { nghttp2_settings_entry iv[1] = { @@ -309,10 +251,11 @@ return 0; } -In the example SETTINGS frame we've set -SETTINGS_MAX_CONCURRENT_STREAMS to 100. `nghttp2_submit_settings()` -is used to queue the frame for transmission, but note it only queues -the frame for transmission, and doesn't actually send it. All +The server connection header is a SETTINGS frame. We specify +SETTINGS_MAX_CONCURRENT_STREAMS to 100 in the 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 it does not actually send it. All functions in the ``nghttp2_submit_*()`` family have this property. To actually send the frame, `nghttp2_session_send()` should be used, as described later. @@ -333,7 +276,7 @@ warnx("Fatal error: %s", nghttp2_strerror((int)readlen)); return -1; } - if (evbuffer_drain(input, (size_t)readlen) != 0) { + if (evbuffer_drain(input, readlen) != 0) { warnx("Fatal error: evbuffer_drain failed"); return -1; } @@ -343,14 +286,12 @@ return 0; } -In this function, we feed all unprocessed but already received data to -the nghttp2 session object using the `nghttp2_session_mem_recv()` -function. The `nghttp2_session_mem_recv()` function processes the data -and may both invoke the previously setup callbacks and also queue -outgoing frames. To send any pending outgoing frames, we immediately -call ``session_send()``. - -The ``session_send()`` function is defined as follows:: +In this function, we feed all unprocessed but already received data to the +nghttp2 session object using the `nghttp2_session_mem_recv()` function. The +`nghttp2_session_mem_recv()` function processes the data and may invoke the +nghttp2 callbacks and also queue outgoing frames. Since there may be pending +outgoing frames, we call ``session_send()`` function to send off those +frames. The ``session_send()`` function is defined as follows:: static int session_send(http2_session_data *session_data) { int rv; @@ -363,7 +304,7 @@ } The `nghttp2_session_send()` function serializes the frame into wire -format and calls the ``send_callback()``, which is of type +format and calls ``send_callback()`` of type :type:`nghttp2_send_callback`. The ``send_callback()`` is defined as follows:: @@ -377,22 +318,23 @@ return NGHTTP2_ERR_WOULDBLOCK; } bufferevent_write(bev, data, length); - return (ssize_t)length; + return length; } Since we use bufferevent to abstract network I/O, we just write the data to the bufferevent object. Note that `nghttp2_session_send()` continues to write all frames queued so far. If we were writing the -data to a non-blocking socket directly using the ``write()`` system -call in the ``send_callback()``, we'd soon receive an ``EAGAIN`` or -``EWOULDBLOCK`` error since sockets have a limited send buffer. If -that happens, it's possible to return :macro:`NGHTTP2_ERR_WOULDBLOCK` -to signal the nghttp2 library to stop sending further data. But here, -when writing to the bufferevent, we have to regulate the amount data -to buffered ourselves to avoid using huge amounts of memory. To -achieve this, we check the size of the output buffer and if it reaches -more than or equal to ``OUTPUT_WOULDBLOCK_THRESHOLD`` bytes, we stop -writing data and return :macro:`NGHTTP2_ERR_WOULDBLOCK`. +data to a non-blocking socket directly using ``write()`` system call +in the ``send_callback()``, we would surely get ``EAGAIN`` or +``EWOULDBLOCK`` back since the socket has limited send buffer. If that +happens, we can return :macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the +nghttp2 library to stop sending further data. But when writing to the +bufferevent, we have to regulate the amount data to get buffered +ourselves to avoid using huge amounts of memory. To achieve this, we +check the size of the output buffer and if it reaches more than or +equal to ``OUTPUT_WOULDBLOCK_THRESHOLD`` bytes, we stop writing data +and return :macro:`NGHTTP2_ERR_WOULDBLOCK` to tell the library to stop +calling send_callback. The next bufferevent callback is ``readcb()``, which is invoked when data is available to read in the bufferevent input buffer:: @@ -427,18 +369,16 @@ } } -First we check whether we should drop the connection or not. The -nghttp2 session object keeps track of reception and transmission of -GOAWAY frames and other error conditions as well. Using this -information, the nghttp2 session object can state whether the -connection should be dropped or not. More specifically, if both -`nghttp2_session_want_read()` and `nghttp2_session_want_write()` -return 0, the connection is no-longer required and can be closed. -Since we are using bufferevent and its deferred callback option, the -bufferevent output buffer may still contain pending data when the -``writecb()`` is called. To handle this, we check whether the output -buffer is empty or not. If all of these conditions are met, we drop -connection. +First we check whether we should drop the connection or not. The nghttp2 +session object keeps track of reception and transmission of GOAWAY frames and +other error conditions as well. Using this information, the nghttp2 session +object will tell whether the connection should be dropped or not. More +specifically, if both `nghttp2_session_want_read()` and +`nghttp2_session_want_write()` return 0, we have no business left in the +connection. But since we are using bufferevent and its deferred callback +option, the bufferevent output buffer may contain pending data when the +``writecb()`` is called. To handle this, we check whether the output buffer is +empty or not. If all these conditions are met, we drop connection. Otherwise, we call ``session_send()`` to process the pending output data. Remember that in ``send_callback()``, we must not write all data to @@ -446,7 +386,7 @@ when the output buffer becomes empty. We have already described the nghttp2 callback ``send_callback()``. Let's -learn about the remaining nghttp2 callbacks setup in +learn about the remaining nghttp2 callbacks we setup in ``initialize_nghttp2_setup()`` function. The ``on_begin_headers_callback()`` function is invoked when the reception of @@ -468,15 +408,13 @@ return 0; } -We are only interested in the HEADERS frame in this function. Since -the HEADERS frame has several roles in the HTTP/2 protocol, we check -that it is a request HEADERS, which opens new stream. If the frame is -a request HEADERS, we create a ``http2_stream_data`` object to store -the stream related data. We associate the created -``http2_stream_data`` object with the stream in the nghttp2 session -object using `nghttp2_set_stream_user_data()`. The -``http2_stream_data`` object can later be easily retrieved from the -stream, without searching through the doubly linked list. +We are only interested in the HEADERS frame in this function. Since the +HEADERS frame has several roles in the HTTP/2 protocol, we check that it is a +request HEADERS, which opens new stream. If the frame is a request HEADERS, we +create a ``http2_stream_data`` object to store the stream related data. We +associate the created ``http2_stream_data`` object with the stream in the +nghttp2 session object using `nghttp2_set_stream_user_data()` to get the +object without searching through the doubly linked list. In this example server, we want to serve files relative to the current working directory in which the program was invoked. Each header name/value pair is @@ -511,10 +449,10 @@ return 0; } -We search for the ``:path`` header field among the request headers and -store the requested path in the ``http2_stream_data`` object. In this -example program, we ignore the ``:method`` header field and always -treat the request as a GET request. +We search for the ``:path`` header field among the request headers and store +the requested path in the ``http2_stream_data`` object. In this example +program, we ignore ``:method`` header field and always treat the request as a +GET request. The ``on_frame_recv_callback()`` function is invoked when a frame is fully received:: @@ -544,15 +482,15 @@ return 0; } -First we retrieve the ``http2_stream_data`` object associated with the -stream in ``on_begin_headers_callback()`` using -`nghttp2_session_get_stream_user_data()`. If the requested path -cannot be served for some reason (e.g. file is not found), we send a -404 response using ``error_reply()``. Otherwise, we open -the requested file and send its content. We send the header field -``:status`` as a single response header. +First we retrieve the ``http2_stream_data`` object associated with the stream +in ``on_begin_headers_callback()``. It is done using +`nghttp2_session_get_stream_user_data()`. If the requested path cannot be +served for some reason (e.g., file is not found), we send a 404 response, +which is done in ``error_reply()``. Otherwise, we open the requested file and +send its content. We send the header field ``:status`` as a single response +header. -Sending the file content is performed by the ``send_response()`` function:: +Sending the content of the file is done in ``send_response()`` function:: static int send_response(nghttp2_session *session, int32_t stream_id, nghttp2_nv *nva, size_t nvlen, int fd) { @@ -569,13 +507,12 @@ return 0; } -nghttp2 uses the :type:`nghttp2_data_provider` structure to send the -entity body to the remote peer. The ``source`` member of this -structure is a union, which can be either a void pointer or an int -(which is intended to be used as file descriptor). In this example -server, we use it as a file descriptor. We also set the -``file_read_callback()`` callback function to read the contents of the -file:: +The nghttp2 library uses the :type:`nghttp2_data_provider` structure to +send entity body to the remote peer. The ``source`` member of this +structure is a union and it can be either void pointer or int which is +intended to be used as file descriptor. In this example server, we use +the file descriptor. We also set the ``file_read_callback()`` callback +function to read the contents of the file:: static ssize_t file_read_callback(nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf, @@ -595,11 +532,11 @@ return r; } -If an error occurs while reading the file, we return +If an error happens while reading the file, we return :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. This tells the -library to send RST_STREAM to the stream. When all data has been -read, the :macro:`NGHTTP2_DATA_FLAG_EOF` flag is set to signal nghttp2 -that we have finished reading the file. +library to send RST_STREAM to the stream. When all data has been read, set +the :macro:`NGHTTP2_DATA_FLAG_EOF` flag to ``*data_flags`` to tell the +nghttp2 library that we have finished reading the file. The `nghttp2_submit_response()` function is used to send the response to the remote peer. @@ -621,5 +558,5 @@ return 0; } -Lastly, we destroy the ``http2_stream_data`` object in this function, -since the stream is about to close and we no longer need the object. +We destroy the ``http2_stream_data`` object in this function since the stream +is about to close and we no longer use that object. diff -Nru nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/breadcrumbs.html nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/breadcrumbs.html --- nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/breadcrumbs.html 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/breadcrumbs.html 2014-11-30 14:15:07.000000000 +0000 @@ -1,31 +1,19 @@ -{# Support for Sphinx 1.3+ page_source_suffix, but don't break old builds. #} - -{% if page_source_suffix %} -{% set suffix = page_source_suffix %} -{% else %} -{% set suffix = source_suffix %} -{% endif %} -

diff -Nru nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/footer.html nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/footer.html --- nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/footer.html 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/footer.html 2014-11-30 14:15:07.000000000 +0000 @@ -2,10 +2,10 @@ {% if next or prev %} {% endif %} @@ -22,31 +22,11 @@ {%- endif %} {%- endif %} - {%- if build_id and build_url %} - {% trans build_url=build_url, build_id=build_id %} - - Build - {{ build_id }}. - - {% endtrans %} - {%- elif commit %} - {% trans commit=commit %} - - Revision {{ commit }}. - - {% endtrans %} - {%- elif last_updated %} + {%- if last_updated %} {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %} {%- endif %} -

- {%- if show_sphinx %} - {% trans %}Built with Sphinx using a theme provided by Read the Docs{% endtrans %}. - {%- endif %} - - {%- block extrafooter %} {% endblock %} - + {% trans %}Sphinx theme provided by Read the Docs{% endtrans %} - diff -Nru nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/__init__.py nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/__init__.py --- nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/__init__.py 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/__init__.py 2014-11-30 14:15:07.000000000 +0000 @@ -5,7 +5,7 @@ """ import os -VERSION = (0, 1, 9) +VERSION = (0, 1, 5) __version__ = ".".join(str(v) for v in VERSION) __version_full__ = __version__ diff -Nru nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/layout.html nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/layout.html --- nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/layout.html 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/layout.html 2014-11-30 14:15:07.000000000 +0000 @@ -12,7 +12,6 @@ - {{ metatags }} {% block htmltitle %} {{ title|striptags|e }}{{ titlesuffix }} @@ -24,6 +23,7 @@ {% endif %} {# CSS #} + {# OPENSEARCH #} {% if not embedded %} @@ -42,10 +42,6 @@ {% endfor %} - {% for cssfile in extra_css_files %} - - {% endfor %} - {%- block linktags %} {%- if hasdoc('about') %} + - {% block extrabody %} {% endblock %}
{# SIDE NAV, TOGGLES ON MOBILE #}
@@ -146,10 +113,8 @@
{% include "breadcrumbs.html" %} -
-
+
{% block body %}{% endblock %} -
{% include "footer.html" %}
diff -Nru nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/searchbox.html nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/searchbox.html --- nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/searchbox.html 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/searchbox.html 2014-11-30 14:15:07.000000000 +0000 @@ -1,9 +1,7 @@ -{%- if builder != 'singlehtml' %}
-
+
-{%- endif %} diff -Nru nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/static/css/theme.css nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/static/css/theme.css --- nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/static/css/theme.css 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/static/css/theme.css 2014-11-30 14:15:07.000000000 +0000 @@ -1,5 +1,5 @@ -*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,.rst-content tt,.rst-content code,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,.rst-content .toctree-wrapper p.caption,h3{orphans:3;widows:3}h2,.rst-content .toctree-wrapper p.caption,h3{page-break-after:avoid}}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}/*! - * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome +*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,.rst-content tt,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.fa:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url("../fonts/fontawesome-webfont.eot?v=4.2.0");src:url("../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff?v=4.2.0") format("woff"),url("../fonts/fontawesome-webfont.ttf?v=4.2.0") format("truetype"),url("../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:0.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:0.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.wy-menu-vertical li span.pull-left.toctree-expand,.wy-menu-vertical li.on a span.pull-left.toctree-expand,.wy-menu-vertical li.current>a span.pull-left.toctree-expand,.rst-content .pull-left.admonition-title,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content dl dt .pull-left.headerlink,.rst-content p.caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.rst-content code.download span.pull-left:first-child,.pull-left.icon{margin-right:.3em}.fa.pull-right,.wy-menu-vertical li span.pull-right.toctree-expand,.wy-menu-vertical li.on a span.pull-right.toctree-expand,.wy-menu-vertical li.current>a span.pull-right.toctree-expand,.rst-content .pull-right.admonition-title,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content dl dt .pull-right.headerlink,.rst-content p.caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.rst-content code.download span.pull-right:first-child,.pull-right.icon{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-remove:before,.fa-close:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.wy-dropdown .caret:before,.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li span.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:""}.fa-meanpath:before{content:""}.fa,.wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink,.rst-content tt.download span:first-child,.rst-content code.download span:first-child,.icon,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context{font-family:inherit}.fa:before,.wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before{font-family:"FontAwesome";display:inline-block;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa,a .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand,a .rst-content .admonition-title,.rst-content a .admonition-title,a .rst-content h1 .headerlink,.rst-content h1 a .headerlink,a .rst-content h2 .headerlink,.rst-content h2 a .headerlink,a .rst-content h3 .headerlink,.rst-content h3 a .headerlink,a .rst-content h4 .headerlink,.rst-content h4 a .headerlink,a .rst-content h5 .headerlink,.rst-content h5 a .headerlink,a .rst-content h6 .headerlink,.rst-content h6 a .headerlink,a .rst-content dl dt .headerlink,.rst-content dl dt a .headerlink,a .rst-content p.caption .headerlink,.rst-content p.caption a .headerlink,a .rst-content tt.download span:first-child,.rst-content tt.download a span:first-child,a .rst-content code.download span:first-child,.rst-content code.download a span:first-child,a .icon{display:inline-block;text-decoration:inherit}.btn .fa,.btn .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .btn span.toctree-expand,.btn .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .btn span.toctree-expand,.btn .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .btn span.toctree-expand,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.btn .rst-content p.caption .headerlink,.rst-content p.caption .btn .headerlink,.btn .rst-content tt.download span:first-child,.rst-content tt.download .btn span:first-child,.btn .rst-content code.download span:first-child,.rst-content code.download .btn span:first-child,.btn .icon,.nav .fa,.nav .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .nav span.toctree-expand,.nav .wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.on a .nav span.toctree-expand,.nav .wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.current>a .nav span.toctree-expand,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink,.nav .rst-content p.caption .headerlink,.rst-content p.caption .nav .headerlink,.nav .rst-content tt.download span:first-child,.rst-content tt.download .nav span:first-child,.nav .rst-content code.download span:first-child,.rst-content code.download .nav span:first-child,.nav .icon{display:inline}.btn .fa.fa-large,.btn .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .btn span.fa-large.toctree-expand,.btn .rst-content .fa-large.admonition-title,.rst-content .btn .fa-large.admonition-title,.btn .rst-content h1 .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.btn .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .btn .fa-large.headerlink,.btn .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .btn .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .btn span.fa-large:first-child,.btn .rst-content code.download span.fa-large:first-child,.rst-content code.download .btn span.fa-large:first-child,.btn .fa-large.icon,.nav .fa.fa-large,.nav .wy-menu-vertical li span.fa-large.toctree-expand,.wy-menu-vertical li .nav span.fa-large.toctree-expand,.nav .rst-content .fa-large.admonition-title,.rst-content .nav .fa-large.admonition-title,.nav .rst-content h1 .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.nav .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.nav .rst-content p.caption .fa-large.headerlink,.rst-content p.caption .nav .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.nav .rst-content code.download span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.nav .fa-large.icon{line-height:0.9em}.btn .fa.fa-spin,.btn .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .btn span.fa-spin.toctree-expand,.btn .rst-content .fa-spin.admonition-title,.rst-content .btn .fa-spin.admonition-title,.btn .rst-content h1 .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.btn .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .btn .fa-spin.headerlink,.btn .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .btn .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .btn span.fa-spin:first-child,.btn .rst-content code.download span.fa-spin:first-child,.rst-content code.download .btn span.fa-spin:first-child,.btn .fa-spin.icon,.nav .fa.fa-spin,.nav .wy-menu-vertical li span.fa-spin.toctree-expand,.wy-menu-vertical li .nav span.fa-spin.toctree-expand,.nav .rst-content .fa-spin.admonition-title,.rst-content .nav .fa-spin.admonition-title,.nav .rst-content h1 .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.nav .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.nav .rst-content p.caption .fa-spin.headerlink,.rst-content p.caption .nav .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.nav .rst-content code.download span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.nav .fa-spin.icon{display:inline-block}.btn.fa:before,.wy-menu-vertical li span.btn.toctree-expand:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before,.rst-content p.caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.rst-content code.download span.btn:first-child:before,.btn.icon:before{opacity:0.5;-webkit-transition:opacity 0.05s ease-in;-moz-transition:opacity 0.05s ease-in;transition:opacity 0.05s ease-in}.btn.fa:hover:before,.wy-menu-vertical li span.btn.toctree-expand:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content p.caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.rst-content code.download span.btn:first-child:hover:before,.btn.icon:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .wy-menu-vertical li span.toctree-expand:before,.wy-menu-vertical li .btn-mini span.toctree-expand:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before,.btn-mini .rst-content p.caption .headerlink:before,.rst-content p.caption .btn-mini .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.rst-content tt.download .btn-mini span:first-child:before,.btn-mini .rst-content code.download span:first-child:before,.rst-content code.download .btn-mini span:first-child:before,.btn-mini .icon:before{font-size:14px;vertical-align:-15%}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:#6ab0de;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.admonition-todo{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso,.rst-content .admonition-todo{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .admonition-todo .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .admonition-todo .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso,.rst-content .wy-alert-info.admonition-todo{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title,.rst-content .wy-alert-info.admonition-todo .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.admonition-todo{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.admonition-todo .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.admonition-todo{background:#f3f6f6}.wy-alert.wy-alert-neutral .wy-alert-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .admonition-title{color:#404040;background:#e1e4e5}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.admonition-todo a{color:#2980B9}.wy-alert p:last-child,.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition-todo p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0px;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all 0.3s ease-in;-moz-transition:all 0.3s ease-in;transition:all 0.3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27AE60}.wy-tray-container li.wy-tray-item-info{background:#2980B9}.wy-tray-container li.wy-tray-item-warning{background:#E67E22}.wy-tray-container li.wy-tray-item-danger{background:#E74C3C}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width: 768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);background-color:#27AE60;text-decoration:none;font-weight:normal;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset,0px -2px 0px 0px rgba(0,0,0,0.1) inset;outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all 0.1s linear;-moz-transition:all 0.1s linear;transition:all 0.1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:0px -1px 0px 0px rgba(0,0,0,0.05) inset,0px 2px 0px 0px rgba(0,0,0,0.1) inset;padding:8px 12px 6px 12px}.btn:visited{color:#fff}.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980B9 !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-neutral:visited{color:#404040 !important}.btn-success{background-color:#27AE60 !important}.btn-success:hover{background-color:#295 !important}.btn-danger{background-color:#E74C3C !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#E67E22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f !important}.btn-link{background-color:transparent !important;color:#2980B9;box-shadow:none;border-color:transparent !important}.btn-link:hover{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:active{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:visited{color:#9B59B6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980B9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980B9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 0.3125em 0;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#E74C3C}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full input[type="text"],.wy-control-group .wy-form-full input[type="password"],.wy-control-group .wy-form-full input[type="email"],.wy-control-group .wy-form-full input[type="url"],.wy-control-group .wy-form-full input[type="date"],.wy-control-group .wy-form-full input[type="month"],.wy-control-group .wy-form-full input[type="time"],.wy-control-group .wy-form-full input[type="datetime"],.wy-control-group .wy-form-full input[type="datetime-local"],.wy-control-group .wy-form-full input[type="week"],.wy-control-group .wy-form-full input[type="number"],.wy-control-group .wy-form-full input[type="search"],.wy-control-group .wy-form-full input[type="tel"],.wy-control-group .wy-form-full input[type="color"],.wy-control-group .wy-form-halves input[type="text"],.wy-control-group .wy-form-halves input[type="password"],.wy-control-group .wy-form-halves input[type="email"],.wy-control-group .wy-form-halves input[type="url"],.wy-control-group .wy-form-halves input[type="date"],.wy-control-group .wy-form-halves input[type="month"],.wy-control-group .wy-form-halves input[type="time"],.wy-control-group .wy-form-halves input[type="datetime"],.wy-control-group .wy-form-halves input[type="datetime-local"],.wy-control-group .wy-form-halves input[type="week"],.wy-control-group .wy-form-halves input[type="number"],.wy-control-group .wy-form-halves input[type="search"],.wy-control-group .wy-form-halves input[type="tel"],.wy-control-group .wy-form-halves input[type="color"],.wy-control-group .wy-form-thirds input[type="text"],.wy-control-group .wy-form-thirds input[type="password"],.wy-control-group .wy-form-thirds input[type="email"],.wy-control-group .wy-form-thirds input[type="url"],.wy-control-group .wy-form-thirds input[type="date"],.wy-control-group .wy-form-thirds input[type="month"],.wy-control-group .wy-form-thirds input[type="time"],.wy-control-group .wy-form-thirds input[type="datetime"],.wy-control-group .wy-form-thirds input[type="datetime-local"],.wy-control-group .wy-form-thirds input[type="week"],.wy-control-group .wy-form-thirds input[type="number"],.wy-control-group .wy-form-thirds input[type="search"],.wy-control-group .wy-form-thirds input[type="tel"],.wy-control-group .wy-form-thirds input[type="color"]{width:100%}.wy-control-group .wy-form-full{float:left;display:block;margin-right:2.35765%;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child{margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n+1){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child{margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control{margin:6px 0 0 0;font-size:90%}.wy-control-no-input{display:inline-block;margin:6px 0 0 0;font-size:90%}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:0.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:0.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}input[type="datetime-local"]{padding:0.34375em 0.625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:0.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#333}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129FEA}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#E74C3C;border:1px solid #E74C3C}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#E74C3C}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#E74C3C}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif}select,textarea{padding:0.5em 0.625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type="radio"][disabled],input[type="checkbox"][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{width:36px;height:12px;margin:12px 0;position:relative;border-radius:4px;background:#ccc;cursor:pointer;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.wy-switch:before{position:absolute;content:"";display:block;width:18px;height:18px;border-radius:4px;background:#999;left:-3px;top:-3px;-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out}.wy-switch:after{content:"false";position:absolute;left:48px;display:block;font-size:12px;color:#ccc}.wy-switch.active{background:#1e8449}.wy-switch.active:before{left:24px;background:#27AE60}.wy-switch.active:after{content:"true"}.wy-switch.disabled,.wy-switch.active.disabled{cursor:not-allowed}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#E74C3C}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 1px #E74C3C}.wy-control-group.wy-control-group-error textarea{border:solid 1px #E74C3C}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:0.5em 0.625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27AE60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#E74C3C}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#E67E22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980B9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:0.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0.3em;display:block}.wy-form label{margin-bottom:0.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:0.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px}.wy-table td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980B9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9B59B6}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#E67E22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980B9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27AE60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#E74C3C !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}h1,h2,.rst-content .toctree-wrapper p.caption,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2,.rst-content .toctree-wrapper p.caption{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}code,.rst-content tt,.rst-content code{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;color:#E74C3C;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li,article ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li p:last-child,.rst-content .section ul li p:last-child,.rst-content .toctree-wrapper ul li p:last-child,article ul li p:last-child{margin-bottom:0}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul,article ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,article ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,article ul li li li{list-style:square}.wy-plain-list-disc li ol li,.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,article ul li ol li{list-style:decimal}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li,article ol li{list-style:decimal;margin-left:24px}.wy-plain-list-decimal li p:last-child,.rst-content .section ol li p:last-child,.rst-content ol.arabic li p:last-child,article ol li p:last-child{margin-bottom:0}.wy-plain-list-decimal li ul,.rst-content .section ol li ul,.rst-content ol.arabic li ul,article ol li ul{margin-bottom:0}.wy-plain-list-decimal li ul li,.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,article ol li ul li{list-style:disc}.codeblock-example{border:1px solid #e1e4e5;border-bottom:none;padding:24px;padding-top:48px;font-weight:500;background:#fff;position:relative}.codeblock-example:after{content:"Example";position:absolute;top:0px;left:0px;background:#9B59B6;color:#fff;padding:6px 12px}.codeblock-example.prettyprint-example-only{border:1px solid #e1e4e5;margin-bottom:24px}.codeblock,pre.literal-block,.rst-content .literal-block,.rst-content pre.literal-block,div[class^='highlight']{border:1px solid #e1e4e5;padding:0px;overflow-x:auto;background:#fff;margin:1px 0 24px 0}.codeblock div[class^='highlight'],pre.literal-block div[class^='highlight'],.rst-content .literal-block div[class^='highlight'],div[class^='highlight'] div[class^='highlight']{border:none;background:none;margin:0}div[class^='highlight'] td.code{width:100%}.linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:12px;line-height:1.5;color:#d9d9d9}div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:12px;line-height:1.5;display:block;overflow:auto;color:#404040}@media print{.codeblock,pre.literal-block,.rst-content .literal-block,.rst-content pre.literal-block,div[class^='highlight'],div[class^='highlight'] pre{white-space:pre-wrap}}.hll{background-color:#ffc;margin:0 -12px;padding:0 12px;display:block}.c{color:#998;font-style:italic}.err{color:#a61717;background-color:#e3d2d2}.k{font-weight:bold}.o{font-weight:bold}.cm{color:#998;font-style:italic}.cp{color:#999;font-weight:bold}.c1{color:#998;font-style:italic}.cs{color:#999;font-weight:bold;font-style:italic}.gd{color:#000;background-color:#fdd}.gd .x{color:#000;background-color:#faa}.ge{font-style:italic}.gr{color:#a00}.gh{color:#999}.gi{color:#000;background-color:#dfd}.gi .x{color:#000;background-color:#afa}.go{color:#888}.gp{color:#555}.gs{font-weight:bold}.gu{color:purple;font-weight:bold}.gt{color:#a00}.kc{font-weight:bold}.kd{font-weight:bold}.kn{font-weight:bold}.kp{font-weight:bold}.kr{font-weight:bold}.kt{color:#458;font-weight:bold}.m{color:#099}.s{color:#d14}.n{color:#333}.na{color:teal}.nb{color:#0086b3}.nc{color:#458;font-weight:bold}.no{color:teal}.ni{color:purple}.ne{color:#900;font-weight:bold}.nf{color:#900;font-weight:bold}.nn{color:#555}.nt{color:navy}.nv{color:teal}.ow{font-weight:bold}.w{color:#bbb}.mf{color:#099}.mh{color:#099}.mi{color:#099}.mo{color:#099}.sb{color:#d14}.sc{color:#d14}.sd{color:#d14}.s2{color:#d14}.se{color:#d14}.sh{color:#d14}.si{color:#d14}.sx{color:#d14}.sr{color:#009926}.s1{color:#d14}.ss{color:#990073}.bp{color:#999}.vc{color:teal}.vg{color:teal}.vi{color:teal}.il{color:#099}.gc{color:#999;background-color:#EAF2F5}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs li code,.wy-breadcrumbs li .rst-content tt,.rst-content .wy-breadcrumbs li tt{padding:5px;border:none;background:none}.wy-breadcrumbs li code.literal,.wy-breadcrumbs li .rst-content tt.literal,.rst-content .wy-breadcrumbs li tt.literal{color:#404040}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{height:32px;display:inline-block;line-height:32px;padding:0 1.618em;margin-bottom:0;display:block;font-weight:bold;text-transform:uppercase;font-size:80%;color:#555;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li code,.wy-menu-vertical li .rst-content tt,.rst-content .wy-menu-vertical li tt{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li span.toctree-expand{display:block;float:left;margin-left:-1.2em;font-size:0.8em;line-height:1.6em;color:#4d4d4d}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:0.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.on a:hover span.toctree-expand,.wy-menu-vertical li.current>a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li.current>a span.toctree-expand{display:block;font-size:0.8em;line-height:1.6em;color:#333}.wy-menu-vertical li.toctree-l1.current li.toctree-l2>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>ul{display:none}.wy-menu-vertical li.toctree-l1.current li.toctree-l2.current>ul,.wy-menu-vertical li.toctree-l2.current li.toctree-l3.current>ul{display:block}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{display:block;background:#c9c9c9;padding:0.4045em 4.045em}.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l2 span.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3{font-size:0.9em}.wy-menu-vertical li.toctree-l3.current>a{background:#bdbdbd;padding:0.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{display:block;background:#bdbdbd;padding:0.4045em 5.663em;border-top:none;border-bottom:none}.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand{color:gray}.wy-menu-vertical li.toctree-l3 span.toctree-expand{color:#969696}.wy-menu-vertical li.toctree-l4{font-size:0.9em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical .local-toc li ul{display:block}.wy-menu-vertical li ul li a{margin-bottom:0;color:#b3b3b3;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:0.4045em 1.618em;display:block;position:relative;font-size:90%;color:#b3b3b3}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover span.toctree-expand{color:#b3b3b3}.wy-menu-vertical a:active{background-color:#2980B9;cursor:pointer;color:#fff}.wy-menu-vertical a:active span.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:0.809em;margin-bottom:0.809em;z-index:200;background-color:#2980B9;text-align:center;padding:0.809em;display:block;color:#fcfcfc;margin-bottom:0.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto 0.809em auto;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:0.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-side-nav-search>a img.logo,.wy-side-nav-search .wy-dropdown>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search>a.icon img.logo,.wy-side-nav-search .wy-dropdown>a.icon img.logo{margin-top:0.85em}.wy-side-nav-search>div.version{margin-top:-0.4045em;margin-bottom:0.809em;font-weight:normal;color:rgba(255,255,255,0.3)}.wy-nav .wy-menu-vertical header{color:#2980B9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980B9;color:#fff}[data-menu-wrap]{-webkit-transition:all 0.2s ease-in;-moz-transition:all 0.2s ease-in;transition:all 0.2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:left repeat-y #fcfcfc;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC);background-size:300px 1px}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980B9;color:#fff;padding:0.4045em 0.809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:#999}footer p{margin-bottom:12px}footer span.commit code,footer span.commit .rst-content tt,.rst-content footer span.commit tt{padding:0px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:1em;background:none;border:none;color:#999}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-side-scroll{width:auto}.wy-side-nav-search{width:auto}.wy-menu.wy-menu-vertical{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1400px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,footer,.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content p.caption .headerlink,.rst-content p.caption .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .icon{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}}.rst-content img{max-width:100%;height:auto !important}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img,.rst-content .section>a>img{margin-bottom:24px}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last,.rst-content .admonition-todo .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .line-block{margin-left:24px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto;display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content .toctree-wrapper p.caption .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.rst-content p.caption .headerlink{display:none;visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content .toctree-wrapper p.caption .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content p.caption .headerlink:after{visibility:visible;content:"";font-family:FontAwesome;display:inline-block}.rst-content h1:hover .headerlink,.rst-content h2:hover .headerlink,.rst-content .toctree-wrapper p.caption:hover .headerlink,.rst-content h3:hover .headerlink,.rst-content h4:hover .headerlink,.rst-content h5:hover .headerlink,.rst-content h6:hover .headerlink,.rst-content dl dt:hover .headerlink,.rst-content p.caption:hover .headerlink{display:inline-block}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#F1C40F;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:super;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:#999}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.docutils.citation tt,.rst-content table.docutils.citation code,.rst-content table.docutils.footnote tt,.rst-content table.docutils.footnote code{color:#555}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none;padding-top:5px}.rst-content table.field-list td>strong{display:inline-block;margin-top:3px}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left;padding-left:0}.rst-content tt,.rst-content tt,.rst-content code{color:#000;padding:2px 5px}.rst-content tt big,.rst-content tt em,.rst-content tt big,.rst-content code big,.rst-content tt em,.rst-content code em{font-size:100% !important;line-height:normal}.rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal{color:#E74C3C}.rst-content tt.xref,a .rst-content tt,.rst-content tt.xref,.rst-content code.xref,a .rst-content tt,a .rst-content code{font-weight:bold;color:#404040}.rst-content a tt,.rst-content a tt,.rst-content a code{color:#2980B9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:inline-block;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980B9;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:#555}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) tt,.rst-content dl:not(.docutils) code{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname,.rst-content dl:not(.docutils) tt.descclassname,.rst-content dl:not(.docutils) code.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) code.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27AE60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:bold}.rst-content tt.download,.rst-content code.download{background:inherit;padding:inherit;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content tt.download span:first-child:before,.rst-content code.download span:first-child:before{margin-right:4px}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040}.math{text-align:center}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:400;src:local("Inconsolata"),local("Inconsolata-Regular"),url(../fonts/Inconsolata-Regular.ttf) format("truetype")}@font-face{font-family:"Inconsolata";font-style:normal;font-weight:700;src:local("Inconsolata Bold"),local("Inconsolata-Bold"),url(../fonts/Inconsolata-Bold.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:400;src:local("Lato Regular"),local("Lato-Regular"),url(../fonts/Lato-Regular.ttf) format("truetype")}@font-face{font-family:"Lato";font-style:normal;font-weight:700;src:local("Lato Bold"),local("Lato-Bold"),url(../fonts/Lato-Bold.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:400;src:local("Roboto Slab Regular"),local("RobotoSlab-Regular"),url(../fonts/RobotoSlab-Regular.ttf) format("truetype")}@font-face{font-family:"Roboto Slab";font-style:normal;font-weight:700;src:local("Roboto Slab Bold"),local("RobotoSlab-Bold"),url(../fonts/RobotoSlab-Bold.ttf) format("truetype")} + */@font-face{font-family:'FontAwesome';src:url("../fonts/fontawesome-webfont.eot?v=4.1.0");src:url("../fonts/fontawesome-webfont.eot?#iefix&v=4.1.0") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff?v=4.1.0") format("woff"),url("../fonts/fontawesome-webfont.ttf?v=4.1.0") format("truetype"),url("../fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular") format("svg");font-weight:normal;font-style:normal}.fa,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.icon{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:0.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:0.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:solid 0.08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.rst-content .pull-left.admonition-title,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content dl dt .pull-left.headerlink,.pull-left.icon{margin-right:.3em}.fa.pull-right,.rst-content .pull-right.admonition-title,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content dl dt .pull-right.headerlink,.pull-right.icon{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-gear:before,.fa-cog:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-rotate-right:before,.fa-repeat:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.rst-content .admonition-title:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-warning:before,.fa-exclamation-triangle:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-gears:before,.fa-cogs:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-save:before,.fa-floppy-o:before{content:""}.fa-square:before{content:""}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.wy-dropdown .caret:before,.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-unsorted:before,.fa-sort:before{content:""}.fa-sort-down:before,.fa-sort-desc:before{content:""}.fa-sort-up:before,.fa-sort-asc:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-legal:before,.fa-gavel:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-flash:before,.fa-bolt:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-paste:before,.fa-clipboard:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-unlink:before,.fa-chain-broken:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:""}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:""}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:""}.fa-euro:before,.fa-eur:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-rupee:before,.fa-inr:before{content:""}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:""}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:""}.fa-won:before,.fa-krw:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-turkish-lira:before,.fa-try:before{content:""}.fa-plus-square-o:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-institution:before,.fa-bank:before,.fa-university:before{content:""}.fa-mortar-board:before,.fa-graduation-cap:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-square:before,.fa-pied-piper:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:""}.fa-file-zip-o:before,.fa-file-archive-o:before{content:""}.fa-file-sound-o:before,.fa-file-audio-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before{content:""}.fa-ge:before,.fa-empire:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-send:before,.fa-paper-plane:before{content:""}.fa-send-o:before,.fa-paper-plane-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa,.rst-content .admonition-title,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink,.icon,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context{font-family:inherit}.fa:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before{font-family:"FontAwesome";display:inline-block;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa,a .rst-content .admonition-title,.rst-content a .admonition-title,a .rst-content h1 .headerlink,.rst-content h1 a .headerlink,a .rst-content h2 .headerlink,.rst-content h2 a .headerlink,a .rst-content h3 .headerlink,.rst-content h3 a .headerlink,a .rst-content h4 .headerlink,.rst-content h4 a .headerlink,a .rst-content h5 .headerlink,.rst-content h5 a .headerlink,a .rst-content h6 .headerlink,.rst-content h6 a .headerlink,a .rst-content dl dt .headerlink,.rst-content dl dt a .headerlink,a .icon{display:inline-block;text-decoration:inherit}.btn .fa,.btn .rst-content .admonition-title,.rst-content .btn .admonition-title,.btn .rst-content h1 .headerlink,.rst-content h1 .btn .headerlink,.btn .rst-content h2 .headerlink,.rst-content h2 .btn .headerlink,.btn .rst-content h3 .headerlink,.rst-content h3 .btn .headerlink,.btn .rst-content h4 .headerlink,.rst-content h4 .btn .headerlink,.btn .rst-content h5 .headerlink,.rst-content h5 .btn .headerlink,.btn .rst-content h6 .headerlink,.rst-content h6 .btn .headerlink,.btn .rst-content dl dt .headerlink,.rst-content dl dt .btn .headerlink,.btn .icon,.nav .fa,.nav .rst-content .admonition-title,.rst-content .nav .admonition-title,.nav .rst-content h1 .headerlink,.rst-content h1 .nav .headerlink,.nav .rst-content h2 .headerlink,.rst-content h2 .nav .headerlink,.nav .rst-content h3 .headerlink,.rst-content h3 .nav .headerlink,.nav .rst-content h4 .headerlink,.rst-content h4 .nav .headerlink,.nav .rst-content h5 .headerlink,.rst-content h5 .nav .headerlink,.nav .rst-content h6 .headerlink,.rst-content h6 .nav .headerlink,.nav .rst-content dl dt .headerlink,.rst-content dl dt .nav .headerlink,.nav .icon{display:inline}.btn .fa.fa-large,.btn .rst-content .fa-large.admonition-title,.rst-content .btn .fa-large.admonition-title,.btn .rst-content h1 .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.btn .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .btn .fa-large.headerlink,.btn .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .fa-large.admonition-title,.rst-content .nav .fa-large.admonition-title,.nav .rst-content h1 .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.nav .rst-content dl dt .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.nav .fa-large.icon{line-height:0.9em}.btn .fa.fa-spin,.btn .rst-content .fa-spin.admonition-title,.rst-content .btn .fa-spin.admonition-title,.btn .rst-content h1 .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.btn .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .btn .fa-spin.headerlink,.btn .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .fa-spin.admonition-title,.rst-content .nav .fa-spin.admonition-title,.nav .rst-content h1 .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.nav .rst-content dl dt .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.nav .fa-spin.icon{display:inline-block}.btn.fa:before,.rst-content .btn.admonition-title:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content dl dt .btn.headerlink:before,.btn.icon:before{opacity:0.5;-webkit-transition:opacity 0.05s ease-in;-moz-transition:opacity 0.05s ease-in;transition:opacity 0.05s ease-in}.btn.fa:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.btn.icon:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .rst-content .admonition-title:before,.rst-content .btn-mini .admonition-title:before,.btn-mini .rst-content h1 .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.btn-mini .rst-content dl dt .headerlink:before,.rst-content dl dt .btn-mini .headerlink:before,.btn-mini .icon:before{font-size:14px;vertical-align:-15%}.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.rst-content .admonition-todo{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.wy-alert-title,.rst-content .admonition-title{color:#fff;font-weight:bold;display:block;color:#fff;background:#6ab0de;margin:-12px;padding:6px 12px;margin-bottom:12px}.wy-alert.wy-alert-danger,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.admonition-todo{background:#fdf3f2}.wy-alert.wy-alert-danger .wy-alert-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .danger .wy-alert-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .danger .admonition-title,.rst-content .error .admonition-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title{background:#f29f97}.wy-alert.wy-alert-warning,.rst-content .wy-alert-warning.note,.rst-content .attention,.rst-content .caution,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.tip,.rst-content .warning,.rst-content .wy-alert-warning.seealso,.rst-content .admonition-todo{background:#ffedcc}.wy-alert.wy-alert-warning .wy-alert-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .attention .wy-alert-title,.rst-content .caution .wy-alert-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .admonition-todo .wy-alert-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .attention .admonition-title,.rst-content .caution .admonition-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .warning .admonition-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .admonition-todo .admonition-title{background:#f0b37e}.wy-alert.wy-alert-info,.rst-content .note,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.rst-content .seealso,.rst-content .wy-alert-info.admonition-todo{background:#e7f2fa}.wy-alert.wy-alert-info .wy-alert-title,.rst-content .note .wy-alert-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.rst-content .note .admonition-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .seealso .admonition-title,.rst-content .wy-alert-info.admonition-todo .admonition-title{background:#6ab0de}.wy-alert.wy-alert-success,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.warning,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.admonition-todo{background:#dbfaf4}.wy-alert.wy-alert-success .wy-alert-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .hint .wy-alert-title,.rst-content .important .wy-alert-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .hint .admonition-title,.rst-content .important .admonition-title,.rst-content .tip .admonition-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.admonition-todo .admonition-title{background:#1abc9c}.wy-alert.wy-alert-neutral,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.admonition-todo{background:#f3f6f6}.wy-alert.wy-alert-neutral .wy-alert-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .admonition-title{color:#404040;background:#e1e4e5}.wy-alert.wy-alert-neutral a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.admonition-todo a{color:#2980B9}.wy-alert p:last-child,.rst-content .note p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.rst-content .seealso p:last-child,.rst-content .admonition-todo p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0px;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,0.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all 0.3s ease-in;-moz-transition:all 0.3s ease-in;transition:all 0.3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27AE60}.wy-tray-container li.wy-tray-item-info{background:#2980B9}.wy-tray-container li.wy-tray-item-warning{background:#E67E22}.wy-tray-container li.wy-tray-item-danger{background:#E74C3C}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width: 768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px 12px;color:#fff;border:1px solid rgba(0,0,0,0.1);background-color:#27AE60;text-decoration:none;font-weight:normal;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:0px 1px 2px -1px rgba(255,255,255,0.5) inset,0px -2px 0px 0px rgba(0,0,0,0.1) inset;outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all 0.1s linear;-moz-transition:all 0.1s linear;transition:all 0.1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:0px -1px 0px 0px rgba(0,0,0,0.05) inset,0px 2px 0px 0px rgba(0,0,0,0.1) inset;padding:8px 12px 6px 12px}.btn:visited{color:#fff}.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn-disabled:hover,.btn-disabled:focus,.btn-disabled:active{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:0.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980B9 !important}.btn-info:hover{background-color:#2e8ece !important}.btn-neutral{background-color:#f3f6f6 !important;color:#404040 !important}.btn-neutral:hover{background-color:#e5ebeb !important;color:#404040}.btn-neutral:visited{color:#404040 !important}.btn-success{background-color:#27AE60 !important}.btn-success:hover{background-color:#295 !important}.btn-danger{background-color:#E74C3C !important}.btn-danger:hover{background-color:#ea6153 !important}.btn-warning{background-color:#E67E22 !important}.btn-warning:hover{background-color:#e98b39 !important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f !important}.btn-link{background-color:transparent !important;color:#2980B9;box-shadow:none;border-color:transparent !important}.btn-link:hover{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:active{background-color:transparent !important;color:#409ad5 !important;box-shadow:none}.btn-link:visited{color:#9B59B6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:before,.wy-btn-group:after{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:solid 1px #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,0.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980B9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:solid 1px #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type="search"]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980B9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned input,.wy-form-aligned textarea,.wy-form-aligned select,.wy-form-aligned .wy-help-inline,.wy-form-aligned label{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{border:0;margin:0;padding:0}legend{display:block;width:100%;border:0;padding:0;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label{display:block;margin:0 0 0.3125em 0;color:#999;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;*zoom:1;max-width:68em;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group:before,.wy-control-group:after{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#E74C3C}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full input[type="text"],.wy-control-group .wy-form-full input[type="password"],.wy-control-group .wy-form-full input[type="email"],.wy-control-group .wy-form-full input[type="url"],.wy-control-group .wy-form-full input[type="date"],.wy-control-group .wy-form-full input[type="month"],.wy-control-group .wy-form-full input[type="time"],.wy-control-group .wy-form-full input[type="datetime"],.wy-control-group .wy-form-full input[type="datetime-local"],.wy-control-group .wy-form-full input[type="week"],.wy-control-group .wy-form-full input[type="number"],.wy-control-group .wy-form-full input[type="search"],.wy-control-group .wy-form-full input[type="tel"],.wy-control-group .wy-form-full input[type="color"],.wy-control-group .wy-form-halves input[type="text"],.wy-control-group .wy-form-halves input[type="password"],.wy-control-group .wy-form-halves input[type="email"],.wy-control-group .wy-form-halves input[type="url"],.wy-control-group .wy-form-halves input[type="date"],.wy-control-group .wy-form-halves input[type="month"],.wy-control-group .wy-form-halves input[type="time"],.wy-control-group .wy-form-halves input[type="datetime"],.wy-control-group .wy-form-halves input[type="datetime-local"],.wy-control-group .wy-form-halves input[type="week"],.wy-control-group .wy-form-halves input[type="number"],.wy-control-group .wy-form-halves input[type="search"],.wy-control-group .wy-form-halves input[type="tel"],.wy-control-group .wy-form-halves input[type="color"],.wy-control-group .wy-form-thirds input[type="text"],.wy-control-group .wy-form-thirds input[type="password"],.wy-control-group .wy-form-thirds input[type="email"],.wy-control-group .wy-form-thirds input[type="url"],.wy-control-group .wy-form-thirds input[type="date"],.wy-control-group .wy-form-thirds input[type="month"],.wy-control-group .wy-form-thirds input[type="time"],.wy-control-group .wy-form-thirds input[type="datetime"],.wy-control-group .wy-form-thirds input[type="datetime-local"],.wy-control-group .wy-form-thirds input[type="week"],.wy-control-group .wy-form-thirds input[type="number"],.wy-control-group .wy-form-thirds input[type="search"],.wy-control-group .wy-form-thirds input[type="tel"],.wy-control-group .wy-form-thirds input[type="color"]{width:100%}.wy-control-group .wy-form-full{float:left;display:block;margin-right:2.35765%;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child{margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(2n+1){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child{margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control{margin:6px 0 0 0;font-size:90%}.wy-control-no-input{display:inline-block;margin:6px 0 0 0;font-size:90%}.wy-control-group.fluid-input input[type="text"],.wy-control-group.fluid-input input[type="password"],.wy-control-group.fluid-input input[type="email"],.wy-control-group.fluid-input input[type="url"],.wy-control-group.fluid-input input[type="date"],.wy-control-group.fluid-input input[type="month"],.wy-control-group.fluid-input input[type="time"],.wy-control-group.fluid-input input[type="datetime"],.wy-control-group.fluid-input input[type="datetime-local"],.wy-control-group.fluid-input input[type="week"],.wy-control-group.fluid-input input[type="number"],.wy-control-group.fluid-input input[type="search"],.wy-control-group.fluid-input input[type="tel"],.wy-control-group.fluid-input input[type="color"]{width:100%}.wy-form-message-inline{display:inline-block;padding-left:0.3em;color:#666;vertical-align:middle;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:0.3125em;font-style:italic}input{line-height:normal}input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;*overflow:visible}input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}input[type="datetime-local"]{padding:0.34375em 0.625em}input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;margin-right:0.3125em;*height:13px;*width:13px}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input[type="text"]:focus,input[type="password"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus{outline:0;outline:thin dotted \9;border-color:#333}input.no-focus:focus{border-color:#ccc !important}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129FEA}input[type="text"][disabled],input[type="password"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="search"][disabled],input[type="tel"][disabled],input[type="color"][disabled]{cursor:not-allowed;background-color:#f3f6f6;color:#cad2d3}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#E74C3C;border:1px solid #E74C3C}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#E74C3C}input[type="file"]:focus:invalid:focus,input[type="radio"]:focus:invalid:focus,input[type="checkbox"]:focus:invalid:focus{outline-color:#E74C3C}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif}select,textarea{padding:0.5em 0.625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border 0.3s linear;-moz-transition:border 0.3s linear;transition:border 0.3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#fff;color:#cad2d3;border-color:transparent}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{padding:6px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:solid 1px #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#E74C3C}.wy-control-group.wy-control-group-error input[type="text"],.wy-control-group.wy-control-group-error input[type="password"],.wy-control-group.wy-control-group-error input[type="email"],.wy-control-group.wy-control-group-error input[type="url"],.wy-control-group.wy-control-group-error input[type="date"],.wy-control-group.wy-control-group-error input[type="month"],.wy-control-group.wy-control-group-error input[type="time"],.wy-control-group.wy-control-group-error input[type="datetime"],.wy-control-group.wy-control-group-error input[type="datetime-local"],.wy-control-group.wy-control-group-error input[type="week"],.wy-control-group.wy-control-group-error input[type="number"],.wy-control-group.wy-control-group-error input[type="search"],.wy-control-group.wy-control-group-error input[type="tel"],.wy-control-group.wy-control-group-error input[type="color"]{border:solid 1px #E74C3C}.wy-control-group.wy-control-group-error textarea{border:solid 1px #E74C3C}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:0.5em 0.625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27AE60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#E74C3C}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#E67E22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980B9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width: 480px){.wy-form button[type="submit"]{margin:0.7em 0 0}.wy-form input[type="text"],.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0.3em;display:block}.wy-form label{margin-bottom:0.3em;display:block}.wy-form input[type="password"],.wy-form input[type="email"],.wy-form input[type="url"],.wy-form input[type="date"],.wy-form input[type="month"],.wy-form input[type="time"],.wy-form input[type="datetime"],.wy-form input[type="datetime-local"],.wy-form input[type="week"],.wy-form input[type="number"],.wy-form input[type="search"],.wy-form input[type="tel"],.wy-form input[type="color"]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:0.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0 0}.wy-form .wy-help-inline,.wy-form-message-inline,.wy-form-message{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width: 768px){.tablet-hide{display:none}}@media screen and (max-width: 480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.wy-table,.rst-content table.docutils,.rst-content table.field-list{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.wy-table caption,.rst-content table.docutils caption,.rst-content table.field-list caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td,.wy-table th,.rst-content table.docutils th,.rst-content table.field-list th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.wy-table td:first-child,.rst-content table.docutils td:first-child,.rst-content table.field-list td:first-child,.wy-table th:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list th:first-child{border-left-width:0}.wy-table thead,.rst-content table.docutils thead,.rst-content table.field-list thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.wy-table thead th,.rst-content table.docutils thead th,.rst-content table.field-list thead th{font-weight:bold;border-bottom:solid 2px #e1e4e5}.wy-table td,.rst-content table.docutils td,.rst-content table.field-list td{background-color:transparent;vertical-align:middle}.wy-table td p,.rst-content table.docutils td p,.rst-content table.field-list td p{line-height:18px}.wy-table td p:last-child,.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child{margin-bottom:0}.wy-table .wy-table-cell-min,.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min{width:1%;padding-right:0}.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox],.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:gray;font-size:90%}.wy-table-tertiary{color:gray;font-size:80%}.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td,.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td{background-color:#f3f6f6}.wy-table-backed{background-color:#f3f6f6}.wy-table-bordered-all,.rst-content table.docutils{border:1px solid #e1e4e5}.wy-table-bordered-all td,.rst-content table.docutils td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.wy-table-bordered-all tbody>tr:last-child td,.rst-content table.docutils tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0 !important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980B9;text-decoration:none}a:hover{color:#3091d1}a:visited{color:#9B59B6}html{height:100%;overflow-x:hidden}body{font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;font-weight:normal;color:#404040;min-height:100%;overflow-x:hidden;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#E67E22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980B9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27AE60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#E74C3C !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}code,.rst-content tt{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;color:#E74C3C;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li,article ul li{list-style:disc;margin-left:24px}.wy-plain-list-disc li p:last-child,.rst-content .section ul li p:last-child,.rst-content .toctree-wrapper ul li p:last-child,article ul li p:last-child{margin-bottom:0}.wy-plain-list-disc li ul,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li ul,article ul li ul{margin-bottom:0}.wy-plain-list-disc li li,.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,article ul li li{list-style:circle}.wy-plain-list-disc li li li,.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,article ul li li li{list-style:square}.wy-plain-list-disc li ol li,.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,article ul li ol li{list-style:decimal}.wy-plain-list-decimal,.rst-content .section ol,.rst-content ol.arabic,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.wy-plain-list-decimal li,.rst-content .section ol li,.rst-content ol.arabic li,article ol li{list-style:decimal;margin-left:24px}.wy-plain-list-decimal li p:last-child,.rst-content .section ol li p:last-child,.rst-content ol.arabic li p:last-child,article ol li p:last-child{margin-bottom:0}.wy-plain-list-decimal li ul,.rst-content .section ol li ul,.rst-content ol.arabic li ul,article ol li ul{margin-bottom:0}.wy-plain-list-decimal li ul li,.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,article ol li ul li{list-style:disc}.codeblock-example{border:1px solid #e1e4e5;border-bottom:none;padding:24px;padding-top:48px;font-weight:500;background:#fff;position:relative}.codeblock-example:after{content:"Example";position:absolute;top:0px;left:0px;background:#9B59B6;color:#fff;padding:6px 12px}.codeblock-example.prettyprint-example-only{border:1px solid #e1e4e5;margin-bottom:24px}.codeblock,pre.literal-block,.rst-content .literal-block,.rst-content pre.literal-block,div[class^='highlight']{border:1px solid #e1e4e5;padding:0px;overflow-x:auto;background:#fff;margin:1px 0 24px 0}.codeblock div[class^='highlight'],pre.literal-block div[class^='highlight'],.rst-content .literal-block div[class^='highlight'],div[class^='highlight'] div[class^='highlight']{border:none;background:none;margin:0}div[class^='highlight'] td.code{width:100%}.linenodiv pre{border-right:solid 1px #e6e9ea;margin:0;padding:12px 12px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:12px;line-height:1.5;color:#d9d9d9}div[class^='highlight'] pre{white-space:pre;margin:0;padding:12px 12px;font-family:Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;font-size:12px;line-height:1.5;display:block;overflow:auto;color:#404040}@media print{.codeblock,pre.literal-block,.rst-content .literal-block,.rst-content pre.literal-block,div[class^='highlight'],div[class^='highlight'] pre{white-space:pre-wrap}}.hll{background-color:#ffc;margin:0 -12px;padding:0 12px;display:block}.c{color:#998;font-style:italic}.err{color:#a61717;background-color:#e3d2d2}.k{font-weight:bold}.o{font-weight:bold}.cm{color:#998;font-style:italic}.cp{color:#999;font-weight:bold}.c1{color:#998;font-style:italic}.cs{color:#999;font-weight:bold;font-style:italic}.gd{color:#000;background-color:#fdd}.gd .x{color:#000;background-color:#faa}.ge{font-style:italic}.gr{color:#a00}.gh{color:#999}.gi{color:#000;background-color:#dfd}.gi .x{color:#000;background-color:#afa}.go{color:#888}.gp{color:#555}.gs{font-weight:bold}.gu{color:purple;font-weight:bold}.gt{color:#a00}.kc{font-weight:bold}.kd{font-weight:bold}.kn{font-weight:bold}.kp{font-weight:bold}.kr{font-weight:bold}.kt{color:#458;font-weight:bold}.m{color:#099}.s{color:#d14}.n{color:#333}.na{color:teal}.nb{color:#0086b3}.nc{color:#458;font-weight:bold}.no{color:teal}.ni{color:purple}.ne{color:#900;font-weight:bold}.nf{color:#900;font-weight:bold}.nn{color:#555}.nt{color:navy}.nv{color:teal}.ow{font-weight:bold}.w{color:#bbb}.mf{color:#099}.mh{color:#099}.mi{color:#099}.mo{color:#099}.sb{color:#d14}.sc{color:#d14}.sd{color:#d14}.s2{color:#d14}.se{color:#d14}.sh{color:#d14}.si{color:#d14}.sx{color:#d14}.sr{color:#009926}.s1{color:#d14}.ss{color:#990073}.bp{color:#999}.vc{color:teal}.vg{color:teal}.vi{color:teal}.il{color:#099}.gc{color:#999;background-color:#EAF2F5}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width: 480px){.wy-breadcrumbs-extra{display:none}.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:before,.wy-menu-horiz:after{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz ul,.wy-menu-horiz li{display:inline-block}.wy-menu-horiz li:hover{background:rgba(255,255,255,0.1)}.wy-menu-horiz li.divide-left{border-left:solid 1px #404040}.wy-menu-horiz li.divide-right{border-right:solid 1px #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical header{height:32px;display:inline-block;line-height:32px;padding:0 1.618em;display:block;font-weight:bold;text-transform:uppercase;font-size:80%;color:#2980B9;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:solid 1px #404040}.wy-menu-vertical li.divide-bottom{border-bottom:solid 1px #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:gray;border-right:solid 1px #c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a{color:#404040;padding:0.4045em 1.618em;font-weight:bold;position:relative;background:#fcfcfc;border:none;border-bottom:solid 1px #c9c9c9;border-top:solid 1px #c9c9c9;padding-left:1.618em -4px}.wy-menu-vertical li.on a:hover,.wy-menu-vertical li.current>a:hover{background:#fcfcfc}.wy-menu-vertical li.toctree-l2.current>a{background:#c9c9c9;padding:0.4045em 2.427em}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical .local-toc li ul{display:block}.wy-menu-vertical li ul li a{margin-bottom:0;color:#b3b3b3;font-weight:normal}.wy-menu-vertical a{display:inline-block;line-height:18px;padding:0.4045em 1.618em;display:block;position:relative;font-size:90%;color:#b3b3b3}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:active{background-color:#2980B9;cursor:pointer;color:#fff}.wy-side-nav-search{z-index:200;background-color:#2980B9;text-align:center;padding:0.809em;display:block;color:#fcfcfc;margin-bottom:0.809em}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto 0.809em auto;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a{color:#fcfcfc;font-size:100%;font-weight:bold;display:inline-block;padding:4px 6px;margin-bottom:0.809em}.wy-side-nav-search>a:hover,.wy-side-nav-search .wy-dropdown>a:hover{background:rgba(255,255,255,0.1)}.wy-nav .wy-menu-vertical header{color:#2980B9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980B9;color:#fff}[data-menu-wrap]{-webkit-transition:all 0.2s ease-in;-moz-transition:all 0.2s ease-in;transition:all 0.2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:left repeat-y #fcfcfc;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC);background-size:300px 1px}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:absolute;top:0;left:0;width:300px;overflow:hidden;min-height:100%;background:#343131;z-index:200}.wy-nav-top{display:none;background:#2980B9;color:#fff;padding:0.4045em 0.809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:before,.wy-nav-top:after{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:bold}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980B9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,0.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:#999}footer p{margin-bottom:12px}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:before,.rst-footer-buttons:after{display:table;content:""}.rst-footer-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:solid 1px #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:solid 1px #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:gray;font-size:90%}@media screen and (max-width: 768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width: 1400px){.wy-nav-content-wrap{background:rgba(0,0,0,0.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,footer,.wy-nav-side{display:none}.wy-nav-content-wrap{margin-left:0}}nav.stickynav{position:fixed;top:0}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-versions .rst-current-version .icon{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}}.rst-content img{max-width:100%;height:auto !important}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure.align-center{text-align:center}.rst-content .section>img{margin-bottom:24px}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content .note .last,.rst-content .attention .last,.rst-content .caution .last,.rst-content .danger .last,.rst-content .error .last,.rst-content .hint .last,.rst-content .important .last,.rst-content .tip .last,.rst-content .warning .last,.rst-content .seealso .last,.rst-content .admonition-todo .last{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,0.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent !important;border-color:rgba(0,0,0,0.1) !important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha li{list-style:upper-alpha}.rst-content .section ol p,.rst-content .section ul p{margin-bottom:12px}.rst-content .line-block{margin-left:24px}.rst-content .topic-title{font-weight:bold;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0px 0px 24px 24px}.rst-content .align-left{float:left;margin:0px 24px 24px 0px}.rst-content .align-center{margin:auto;display:block}.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content dl dt .headerlink{display:none;visibility:hidden;font-size:14px}.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content dl dt .headerlink:after{visibility:visible;content:"";font-family:FontAwesome;display:inline-block}.rst-content h1:hover .headerlink,.rst-content h2:hover .headerlink,.rst-content h3:hover .headerlink,.rst-content h4:hover .headerlink,.rst-content h5:hover .headerlink,.rst-content h6:hover .headerlink,.rst-content dl dt:hover .headerlink{display:inline-block}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:solid 1px #e1e4e5}.rst-content .sidebar p,.rst-content .sidebar ul,.rst-content .sidebar dl{font-size:90%}.rst-content .sidebar .last{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif;font-weight:bold;background:#e1e4e5;padding:6px 12px;margin:-24px;margin-bottom:24px;font-size:100%}.rst-content .highlighted{background:#F1C40F;display:inline-block;font-weight:bold;padding:0 6px}.rst-content .footnote-reference,.rst-content .citation-reference{vertical-align:super;font-size:90%}.rst-content table.docutils.citation,.rst-content table.docutils.footnote{background:none;border:none;color:#999}.rst-content table.docutils.citation td,.rst-content table.docutils.citation tr,.rst-content table.docutils.footnote td,.rst-content table.docutils.footnote tr{border:none;background-color:transparent !important;white-space:normal}.rst-content table.docutils.citation td.label,.rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}.rst-content table.field-list{border:none}.rst-content table.field-list td{border:none;padding-top:5px}.rst-content table.field-list td>strong{display:inline-block;margin-top:3px}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left;padding-left:0}.rst-content tt{color:#000}.rst-content tt big,.rst-content tt em{font-size:100% !important;line-height:normal}.rst-content tt .xref,a .rst-content tt{font-weight:bold}.rst-content a tt{color:#2980B9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:bold}.rst-content dl p,.rst-content dl table,.rst-content dl ul,.rst-content dl ol{margin-bottom:12px !important}.rst-content dl dd{margin:0 0 12px 24px}.rst-content dl:not(.docutils){margin-bottom:24px}.rst-content dl:not(.docutils) dt{display:inline-block;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980B9;border-top:solid 3px #6ab0de;padding:6px;position:relative}.rst-content dl:not(.docutils) dt:before{color:#6ab0de}.rst-content dl:not(.docutils) dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dl dt{margin-bottom:6px;border:none;border-left:solid 3px #ccc;background:#f0f0f0;color:gray}.rst-content dl:not(.docutils) dl dt .headerlink{color:#404040;font-size:100% !important}.rst-content dl:not(.docutils) dt:first-child{margin-top:0}.rst-content dl:not(.docutils) tt{font-weight:bold}.rst-content dl:not(.docutils) tt.descname,.rst-content dl:not(.docutils) tt.descclassname{background-color:transparent;border:none;padding:0;font-size:100% !important}.rst-content dl:not(.docutils) tt.descname{font-weight:bold}.rst-content dl:not(.docutils) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:bold}.rst-content dl:not(.docutils) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-link,.rst-content .viewcode-back{display:inline-block;color:#27AE60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:bold}@media screen and (max-width: 480px){.rst-content .sidebar{width:100%}}span[id*='MathJax-Span']{color:#404040}.math{text-align:center} /*# sourceMappingURL=theme.css.map */ Binary files /tmp/tmpkTH3yG/hwMAGyxAK0/nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf and /tmp/tmpkTH3yG/E1uvhshvV0/nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf differ Binary files /tmp/tmpkTH3yG/hwMAGyxAK0/nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot and /tmp/tmpkTH3yG/E1uvhshvV0/nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot differ diff -Nru nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg --- nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg 2014-11-30 14:15:07.000000000 +0000 @@ -14,11 +14,10 @@ - - + - + @@ -31,7 +30,7 @@ - + @@ -53,7 +52,7 @@ - + @@ -78,11 +77,11 @@ - - - - - + + + + + @@ -110,8 +109,8 @@ - - + + @@ -144,17 +143,17 @@ - - + + - + - + @@ -177,14 +176,14 @@ - + - + @@ -219,8 +218,8 @@ - - + + @@ -248,10 +247,10 @@ - + - + @@ -346,8 +345,8 @@ - - + + @@ -368,8 +367,8 @@ - - + + @@ -380,7 +379,7 @@ - + @@ -402,119 +401,14 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + \ No newline at end of file Binary files /tmp/tmpkTH3yG/hwMAGyxAK0/nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf and /tmp/tmpkTH3yG/E1uvhshvV0/nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf differ Binary files /tmp/tmpkTH3yG/hwMAGyxAK0/nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff and /tmp/tmpkTH3yG/E1uvhshvV0/nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff differ diff -Nru nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/static/js/theme.js nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/static/js/theme.js --- nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/static/js/theme.js 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/static/js/theme.js 2014-11-30 14:15:07.000000000 +0000 @@ -1,156 +1,47 @@ -require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o
"); +}); + +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); + } + }, + enable = function () { + applyStickNav(); + win.on('resize', applyStickNav); + }, + init = function () { + navBar = jquery('nav.wy-nav-side:first'); + win = jquery(window); + }; + jquery(init); + return { + enable : enable }; + }()); + return { + StickyNav : stickyNav }; - - nav.init = function ($) { - var doc = $(document), - self = this; - - this.navBar = $('div.wy-side-scroll:first'); - this.win = $(window); - - // Set up javascript UX bits - $(document) - // Shift nav in mobile when clicking the menu. - .on('click', "[data-toggle='wy-nav-top']", function() { - $("[data-toggle='wy-nav-shift']").toggleClass("shift"); - $("[data-toggle='rst-versions']").toggleClass("shift"); - }) - - // Nav menu link click operations - .on('click', ".wy-menu-vertical .current ul li a", function() { - 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 - self.toggleCurrent(target); - self.hashChange(); - }) - .on('click', "[data-toggle='rst-current-version']", function() { - $("[data-toggle='rst-versions']").toggleClass("shift-up"); - }) - - // Make tables responsive - $("table.docutils:not(.field-list)") - .wrap("
"); - - // Add expand links to all parents of nested ul - $('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () { - var link = $(this); - expand = $(''); - expand.on('click', function (ev) { - self.toggleCurrent(link); - ev.stopPropagation(); - return false; - }); - link.prepend(expand); - }); - }; - - nav.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); - } - } - }; - - nav.onScroll = function () { - this.winScroll = false; - var newWinPosition = this.win.scrollTop(), - winBottom = newWinPosition + this.winHeight, - navPosition = this.navBar.scrollTop(), - newNavPosition = navPosition + (newWinPosition - this.winPosition); - if (newWinPosition < 0 || winBottom > this.docHeight) { - return; - } - this.navBar.scrollTop(newNavPosition); - this.winPosition = newWinPosition; - }; - - nav.onResize = function () { - this.winResize = false; - this.winHeight = this.win.height(); - this.docHeight = $(document).height(); - }; - - nav.hashChange = function () { - this.linkScroll = true; - this.win.one('hashchange', function () { - this.linkScroll = false; - }); - }; - - nav.toggleCurrent = function (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'); - } - - return nav; -}; - -module.exports.ThemeNav = ThemeNav(); - -if (typeof(window) != 'undefined') { - window.SphinxRtdTheme = { StickyNav: module.exports.ThemeNav }; -} - -},{"jquery":"jquery"}]},{},["sphinx-rtd-theme"]); +}($)); diff -Nru nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/theme.conf nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/theme.conf --- nghttp2-1.13.0/doc/_themes/sphinx_rtd_theme/theme.conf 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/doc/_themes/sphinx_rtd_theme/theme.conf 2014-11-30 14:15:07.000000000 +0000 @@ -6,6 +6,3 @@ typekit_id = hiw1hhg analytics_id = sticky_navigation = False -logo_only = -collapse_navigation = False -display_version = True diff -Nru nghttp2-1.13.0/doc/types.rst nghttp2-0.6.7/doc/types.rst --- nghttp2-1.13.0/doc/types.rst 2016-07-21 13:48:08.000000000 +0000 +++ nghttp2-0.6.7/doc/types.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,1124 +0,0 @@ - -Types (structs, unions and typedefs) -==================================== -.. type:: nghttp2_session - - - The primary structure to hold the resources needed for a HTTP/2 - session. The details of this structure are intentionally hidden - from the public API. - - -.. type:: nghttp2_info - - - This struct is what `nghttp2_version()` returns. It holds - information about the particular nghttp2 version. - - .. member:: int age - - Age of this struct. This instance of nghttp2 sets it to - :macro:`NGHTTP2_VERSION_AGE` but a future version may bump it and - add more struct fields at the bottom - .. member:: int version_num - - the :macro:`NGHTTP2_VERSION_NUM` number (since age ==1) - .. member:: const char *version_str - - points to the :macro:`NGHTTP2_VERSION` string (since age ==1) - .. member:: const char *proto_str - - points to the :macro:`NGHTTP2_PROTO_VERSION_ID` string this - instance implements (since age ==1) - -.. type:: nghttp2_vec - - - The object representing single contiguous buffer. - - .. member:: uint8_t *base - - The pointer to the buffer. - .. member:: size_t len - - The length of the buffer. - -.. type:: nghttp2_rcbuf - - - The object representing reference counted buffer. The details of - this structure are intentionally hidden from the public API. - - -.. type:: nghttp2_nv - - - The name/value pair, which mainly used to represent header fields. - - .. member:: uint8_t *name - - The *name* byte string. If this struct is presented from library - (e.g., :type:`nghttp2_on_frame_recv_callback`), *name* is - guaranteed to be NULL-terminated. For some callbacks - (:type:`nghttp2_before_frame_send_callback`, - :type:`nghttp2_on_frame_send_callback`, and - :type:`nghttp2_on_frame_not_send_callback`), it may not be - NULL-terminated if header field is passed from application with - the flag :macro:`NGHTTP2_NV_FLAG_NO_COPY_NAME`). When application - is constructing this struct, *name* is not required to be - NULL-terminated. - .. member:: uint8_t *value - - The *value* byte string. If this struct is presented from - library (e.g., :type:`nghttp2_on_frame_recv_callback`), *value* - is guaranteed to be NULL-terminated. For some callbacks - (:type:`nghttp2_before_frame_send_callback`, - :type:`nghttp2_on_frame_send_callback`, and - :type:`nghttp2_on_frame_not_send_callback`), it may not be - NULL-terminated if header field is passed from application with - the flag :macro:`NGHTTP2_NV_FLAG_NO_COPY_VALUE`). When - application is constructing this struct, *value* is not required - to be NULL-terminated. - .. member:: size_t namelen - - The length of the *name*, excluding terminating NULL. - .. member:: size_t valuelen - - The length of the *value*, excluding terminating NULL. - .. member:: uint8_t flags - - Bitwise OR of one or more of :type:`nghttp2_nv_flag`. - -.. type:: nghttp2_frame_hd - - The frame header. - - .. member:: size_t length - - The length field of this frame, excluding frame header. - .. member:: int32_t stream_id - - The stream identifier (aka, stream ID) - .. member:: uint8_t type - - The type of this frame. See `nghttp2_frame_type`. - .. member:: uint8_t flags - - The flags. - .. member:: uint8_t reserved - - Reserved bit in frame header. Currently, this is always set to 0 - and application should not expect something useful in here. - -.. type:: nghttp2_data_source - - - This union represents the some kind of data source passed to - :type:`nghttp2_data_source_read_callback`. - - .. member:: int fd - - The integer field, suitable for a file descriptor. - .. member:: void *ptr - - The pointer to an arbitrary object. - -.. type:: typedef ssize_t (*nghttp2_data_source_read_callback)( nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) - - - Callback function invoked when the library wants to read data from - the *source*. The read data is sent in the stream *stream_id*. - The implementation of this function must read at most *length* - bytes of data from *source* (or possibly other places) and store - them in *buf* and return number of data stored in *buf*. If EOF is - reached, set :macro:`NGHTTP2_DATA_FLAG_EOF` flag in *\*data_flags*. - - Sometime it is desirable to avoid copying data into *buf* and let - application to send data directly. To achieve this, set - :macro:`NGHTTP2_DATA_FLAG_NO_COPY` to *\*data_flags* (and possibly - other flags, just like when we do copy), and return the number of - bytes to send without copying data into *buf*. The library, seeing - :macro:`NGHTTP2_DATA_FLAG_NO_COPY`, will invoke - :type:`nghttp2_send_data_callback`. The application must send - complete DATA frame in that callback. - - If this callback is set by `nghttp2_submit_request()`, - `nghttp2_submit_response()` or `nghttp2_submit_headers()` and - `nghttp2_submit_data()` with flag parameter - :macro:`NGHTTP2_FLAG_END_STREAM` set, and - :macro:`NGHTTP2_DATA_FLAG_EOF` flag is set to *\*data_flags*, DATA - frame will have END_STREAM flag set. Usually, this is expected - behaviour and all are fine. One exception is send trailer fields. - You cannot send trailer fields after sending frame with END_STREAM - set. To avoid this problem, one can set - :macro:`NGHTTP2_DATA_FLAG_NO_END_STREAM` along with - :macro:`NGHTTP2_DATA_FLAG_EOF` to signal the library not to set - END_STREAM in DATA frame. Then application can use - `nghttp2_submit_trailer()` to send trailer fields. - `nghttp2_submit_trailer()` can be called inside this callback. - - If the application wants to postpone DATA frames (e.g., - asynchronous I/O, or reading data blocks for long time), it is - achieved by returning :macro:`NGHTTP2_ERR_DEFERRED` without reading - any data in this invocation. The library removes DATA frame from - the outgoing queue temporarily. To move back deferred DATA frame - to outgoing queue, call `nghttp2_session_resume_data()`. In case - of error, there are 2 choices. Returning - :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close the stream - by issuing RST_STREAM with :macro:`NGHTTP2_INTERNAL_ERROR`. If a - different error code is desirable, use - `nghttp2_submit_rst_stream()` with a desired error code and then - return :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Returning - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the entire session - failure. -.. type:: nghttp2_data_provider - - - This struct represents the data source and the way to read a chunk - of data from it. - - .. member:: nghttp2_data_source source - - The data source. - .. member:: nghttp2_data_source_read_callback read_callback - - The callback function to read a chunk of data from the *source*. - -.. type:: nghttp2_data - - - The DATA frame. The received data is delivered via - :type:`nghttp2_on_data_chunk_recv_callback`. - - .. member:: size_t padlen - - The length of the padding in this frame. This includes PAD_HIGH - and PAD_LOW. - -.. type:: nghttp2_priority_spec - - - The structure to specify stream dependency. - - .. member:: int32_t stream_id - - The stream ID of the stream to depend on. Specifying 0 makes - stream not depend any other stream. - .. member:: int32_t weight - - The weight of this dependency. - .. member:: uint8_t exclusive - - nonzero means exclusive dependency - -.. type:: nghttp2_headers - - - The HEADERS frame. It has the following members: - - .. member:: nghttp2_frame_hd hd - - The frame header. - .. member:: size_t padlen - - The length of the padding in this frame. This includes PAD_HIGH - and PAD_LOW. - .. member:: nghttp2_priority_spec pri_spec - - The priority specification - .. member:: nghttp2_nv *nva - - The name/value pairs. - .. member:: size_t nvlen - - The number of name/value pairs in *nva*. - .. member:: nghttp2_headers_category cat - - The category of this HEADERS frame. - -.. type:: nghttp2_priority - - - The PRIORITY frame. It has the following members: - - .. member:: nghttp2_frame_hd hd - - The frame header. - .. member:: nghttp2_priority_spec pri_spec - - The priority specification. - -.. type:: nghttp2_rst_stream - - - The RST_STREAM frame. It has the following members: - - .. member:: nghttp2_frame_hd hd - - The frame header. - .. member:: uint32_t error_code - - The error code. See :type:`nghttp2_error_code`. - -.. type:: nghttp2_settings_entry - - - The SETTINGS ID/Value pair. It has the following members: - - .. member:: int32_t settings_id - - The SETTINGS ID. See :type:`nghttp2_settings_id`. - .. member:: uint32_t value - - The value of this entry. - -.. type:: nghttp2_settings - - - The SETTINGS frame. It has the following members: - - .. member:: nghttp2_frame_hd hd - - The frame header. - .. member:: size_t niv - - The number of SETTINGS ID/Value pairs in *iv*. - .. member:: nghttp2_settings_entry *iv - - The pointer to the array of SETTINGS ID/Value pair. - -.. type:: nghttp2_push_promise - - - The PUSH_PROMISE frame. It has the following members: - - .. member:: nghttp2_frame_hd hd - - The frame header. - .. member:: size_t padlen - - The length of the padding in this frame. This includes PAD_HIGH - and PAD_LOW. - .. member:: nghttp2_nv *nva - - The name/value pairs. - .. member:: size_t nvlen - - The number of name/value pairs in *nva*. - .. member:: int32_t promised_stream_id - - The promised stream ID - .. member:: uint8_t reserved - - Reserved bit. Currently this is always set to 0 and application - should not expect something useful in here. - -.. type:: nghttp2_ping - - - The PING frame. It has the following members: - - .. member:: nghttp2_frame_hd hd - - The frame header. - .. member:: uint8_t opaque_data[8] - - The opaque data - -.. type:: nghttp2_goaway - - - The GOAWAY frame. It has the following members: - - .. member:: nghttp2_frame_hd hd - - The frame header. - .. member:: int32_t last_stream_id - - The last stream stream ID. - .. member:: uint32_t error_code - - The error code. See :type:`nghttp2_error_code`. - .. member:: uint8_t *opaque_data - - The additional debug data - .. member:: size_t opaque_data_len - - The length of *opaque_data* member. - .. member:: uint8_t reserved - - Reserved bit. Currently this is always set to 0 and application - should not expect something useful in here. - -.. type:: nghttp2_window_update - - - The WINDOW_UPDATE frame. It has the following members: - - .. member:: nghttp2_frame_hd hd - - The frame header. - .. member:: int32_t window_size_increment - - The window size increment. - .. member:: uint8_t reserved - - Reserved bit. Currently this is always set to 0 and application - should not expect something useful in here. - -.. type:: nghttp2_extension - - - The extension frame. It has following members: - - .. member:: nghttp2_frame_hd hd - - The frame header. - .. member:: void *payload - - The pointer to extension payload. The exact pointer type is - determined by hd.type. - - Currently, no extension is supported. This is a place holder for - the future extensions. - -.. type:: nghttp2_frame - - - This union includes all frames to pass them to various function - calls as nghttp2_frame type. The CONTINUATION frame is omitted - from here because the library deals with it internally. - - .. member:: nghttp2_frame_hd hd - - The frame header, which is convenient to inspect frame header. - .. member:: nghttp2_data data - - The DATA frame. - .. member:: nghttp2_headers headers - - The HEADERS frame. - .. member:: nghttp2_priority priority - - The PRIORITY frame. - .. member:: nghttp2_rst_stream rst_stream - - The RST_STREAM frame. - .. member:: nghttp2_settings settings - - The SETTINGS frame. - .. member:: nghttp2_push_promise push_promise - - The PUSH_PROMISE frame. - .. member:: nghttp2_ping ping - - The PING frame. - .. member:: nghttp2_goaway goaway - - The GOAWAY frame. - .. member:: nghttp2_window_update window_update - - The WINDOW_UPDATE frame. - .. member:: nghttp2_extension ext - - The extension frame. - -.. type:: typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session, const uint8_t *data, size_t length, int flags, void *user_data) - - - Callback function invoked when *session* wants to send data to the - remote peer. The implementation of this function must send at most - *length* bytes of data stored in *data*. The *flags* is currently - not used and always 0. It must return the number of bytes sent if - it succeeds. If it cannot send any single byte without blocking, - it must return :macro:`NGHTTP2_ERR_WOULDBLOCK`. For other errors, - it must return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. The - *user_data* pointer is the third argument passed in to the call to - `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. - - This callback is required if the application uses - `nghttp2_session_send()` to send data to the remote endpoint. If - the application uses solely `nghttp2_session_mem_send()` instead, - this callback function is unnecessary. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_send_callback()`. - - .. note:: - - The *length* may be very small. If that is the case, and - application disables Nagle algorithm (``TCP_NODELAY``), then just - writing *data* to the network stack leads to very small packet, - and it is very inefficient. An application should be responsible - to buffer up small chunks of data as necessary to avoid this - situation. -.. type:: typedef int (*nghttp2_send_data_callback)(nghttp2_session *session, nghttp2_frame *frame, const uint8_t *framehd, size_t length, nghttp2_data_source *source, void *user_data) - - - Callback function invoked when :macro:`NGHTTP2_DATA_FLAG_NO_COPY` is - used in :type:`nghttp2_data_source_read_callback` to send complete - DATA frame. - - The *frame* is a DATA frame to send. The *framehd* is the - serialized frame header (9 bytes). The *length* is the length of - application data to send (this does not include padding). The - *source* is the same pointer passed to - :type:`nghttp2_data_source_read_callback`. - - The application first must send frame header *framehd* of length 9 - bytes. If ``frame->data.padlen > 0``, send 1 byte of value - ``frame->data.padlen - 1``. Then send exactly *length* bytes of - application data. Finally, if ``frame->data.padlen > 1``, send - ``frame->data.padlen - 1`` bytes of zero as padding. - - The application has to send complete DATA frame in this callback. - If all data were written successfully, return 0. - - If it cannot send any data at all, just return - :macro:`NGHTTP2_ERR_WOULDBLOCK`; the library will call this callback - with the same parameters later (It is recommended to send complete - DATA frame at once in this function to deal with error; if partial - frame data has already sent, it is impossible to send another data - in that state, and all we can do is tear down connection). When - data is fully processed, but application wants to make - `nghttp2_session_mem_send()` or `nghttp2_session_send()` return - immediately without processing next frames, return - :macro:`NGHTTP2_ERR_PAUSE`. If application decided to reset this - stream, return :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`, then - the library will send RST_STREAM with INTERNAL_ERROR as error code. - The application can also return - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`, which will result in - connection closure. Returning any other value is treated as - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. -.. type:: typedef ssize_t (*nghttp2_recv_callback)(nghttp2_session *session, uint8_t *buf, size_t length, int flags, void *user_data) - - - Callback function invoked when *session* wants to receive data from - the remote peer. The implementation of this function must read at - most *length* bytes of data and store it in *buf*. The *flags* is - currently not used and always 0. It must return the number of - bytes written in *buf* if it succeeds. If it cannot read any - single byte without blocking, it must return - :macro:`NGHTTP2_ERR_WOULDBLOCK`. If it gets EOF before it reads any - single byte, it must return :macro:`NGHTTP2_ERR_EOF`. For other - errors, it must return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - Returning 0 is treated as :macro:`NGHTTP2_ERR_WOULDBLOCK`. The - *user_data* pointer is the third argument passed in to the call to - `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. - - This callback is required if the application uses - `nghttp2_session_recv()` to receive data from the remote endpoint. - If the application uses solely `nghttp2_session_mem_recv()` - instead, this callback function is unnecessary. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_recv_callback()`. -.. type:: typedef int (*nghttp2_on_frame_recv_callback)(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) - - - Callback function invoked by `nghttp2_session_recv()` and - `nghttp2_session_mem_recv()` when a frame is received. The - *user_data* pointer is the third argument passed in to the call to - `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. - - If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen`` - member of their data structure are always ``NULL`` and 0 - respectively. The header name/value pairs are emitted via - :type:`nghttp2_on_header_callback`. - - For HEADERS, PUSH_PROMISE and DATA frames, this callback may be - called after stream is closed (see - :type:`nghttp2_on_stream_close_callback`). The application should - check that stream is still alive using its own stream management or - :func:`nghttp2_session_get_stream_user_data()`. - - Only HEADERS and DATA frame can signal the end of incoming data. - If ``frame->hd.flags & NGHTTP2_FLAG_END_STREAM`` is nonzero, the - *frame* is the last frame from the remote peer in this stream. - - This callback won't be called for CONTINUATION frames. - HEADERS/PUSH_PROMISE + CONTINUATIONs are treated as single frame. - - The implementation of this function must return 0 if it succeeds. - If nonzero value is returned, it is treated as fatal error and - `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_on_frame_recv_callback()`. -.. type:: typedef int (*nghttp2_on_invalid_frame_recv_callback)( nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code, void *user_data) - - - Callback function invoked by `nghttp2_session_recv()` and - `nghttp2_session_mem_recv()` when an invalid non-DATA frame is - received. The error is indicated by the *lib_error_code*, which is - one of the values defined in :type:`nghttp2_error`. When this - callback function is invoked, the library automatically submits - either RST_STREAM or GOAWAY frame. The *user_data* pointer is the - third argument passed in to the call to - `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. - - If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen`` - member of their data structure are always ``NULL`` and 0 - respectively. - - The implementation of this function must return 0 if it succeeds. - If nonzero is returned, it is treated as fatal error and - `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_on_invalid_frame_recv_callback()`. -.. type:: typedef int (*nghttp2_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) - - - Callback function invoked when a chunk of data in DATA frame is - received. The *stream_id* is the stream ID this DATA frame belongs - to. The *flags* is the flags of DATA frame which this data chunk - is contained. ``(flags & NGHTTP2_FLAG_END_STREAM) != 0`` does not - necessarily mean this chunk of data is the last one in the stream. - You should use :type:`nghttp2_on_frame_recv_callback` to know all - data frames are received. The *user_data* pointer is the third - argument passed in to the call to `nghttp2_session_client_new()` or - `nghttp2_session_server_new()`. - - If the application uses `nghttp2_session_mem_recv()`, it can return - :macro:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()` - return without processing further input bytes. The memory by - pointed by the *data* is retained until - `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is called. - The application must retain the input bytes which was used to - produce the *data* parameter, because it may refer to the memory - region included in the input bytes. - - The implementation of this function must return 0 if it succeeds. - If nonzero is returned, it is treated as fatal error, and - `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_on_data_chunk_recv_callback()`. -.. type:: typedef int (*nghttp2_before_frame_send_callback)(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) - - - Callback function invoked just before the non-DATA frame *frame* is - sent. The *user_data* pointer is the third argument passed in to - the call to `nghttp2_session_client_new()` or - `nghttp2_session_server_new()`. - - The implementation of this function must return 0 if it succeeds. - It can also return :macro:`NGHTTP2_ERR_CANCEL` to cancel the - transmission of the given frame. - - If there is a fatal error while executing this callback, the - implementation should return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`, - which makes `nghttp2_session_send()` and - `nghttp2_session_mem_send()` functions immediately return - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - If the other value is returned, it is treated as if - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. But the - implementation should not rely on this since the library may define - new return value to extend its capability. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_before_frame_send_callback()`. -.. type:: typedef int (*nghttp2_on_frame_send_callback)(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) - - - Callback function invoked after the frame *frame* is sent. The - *user_data* pointer is the third argument passed in to the call to - `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. - - The implementation of this function must return 0 if it succeeds. - If nonzero is returned, it is treated as fatal error and - `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_on_frame_send_callback()`. -.. type:: typedef int (*nghttp2_on_frame_not_send_callback)(nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code, void *user_data) - - - Callback function invoked after the non-DATA frame *frame* is not - sent because of the error. The error is indicated by the - *lib_error_code*, which is one of the values defined in - :type:`nghttp2_error`. The *user_data* pointer is the third - argument passed in to the call to `nghttp2_session_client_new()` or - `nghttp2_session_server_new()`. - - The implementation of this function must return 0 if it succeeds. - If nonzero is returned, it is treated as fatal error and - `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - `nghttp2_session_get_stream_user_data()` can be used to get - associated data. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_on_frame_not_send_callback()`. -.. type:: typedef int (*nghttp2_on_stream_close_callback)(nghttp2_session *session, int32_t stream_id, uint32_t error_code, void *user_data) - - - Callback function invoked when the stream *stream_id* is closed. - The reason of closure is indicated by the *error_code*. The - *error_code* is usually one of :macro:`nghttp2_error_code`, but that - is not guaranteed. The stream_user_data, which was specified in - `nghttp2_submit_request()` or `nghttp2_submit_headers()`, is still - available in this function. The *user_data* pointer is the third - argument passed in to the call to `nghttp2_session_client_new()` or - `nghttp2_session_server_new()`. - - This function is also called for a stream in reserved state. - - The implementation of this function must return 0 if it succeeds. - If nonzero is returned, it is treated as fatal error and - `nghttp2_session_recv()`, `nghttp2_session_mem_recv()`, - `nghttp2_session_send()`, and `nghttp2_session_mem_send()` - functions immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_on_stream_close_callback()`. -.. type:: typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) - - - Callback function invoked when the reception of header block in - HEADERS or PUSH_PROMISE is started. Each header name/value pair - will be emitted by :type:`nghttp2_on_header_callback`. - - The ``frame->hd.flags`` may not have - :macro:`NGHTTP2_FLAG_END_HEADERS` flag set, which indicates that one - or more CONTINUATION frames are involved. But the application does - not need to care about that because the header name/value pairs are - emitted transparently regardless of CONTINUATION frames. - - The server applications probably create an object to store - information about new stream if ``frame->hd.type == - NGHTTP2_HEADERS`` and ``frame->headers.cat == - NGHTTP2_HCAT_REQUEST``. If *session* is configured as server side, - ``frame->headers.cat`` is either ``NGHTTP2_HCAT_REQUEST`` - containing request headers or ``NGHTTP2_HCAT_HEADERS`` containing - trailer fields and never get PUSH_PROMISE in this callback. - - For the client applications, ``frame->hd.type`` is either - ``NGHTTP2_HEADERS`` or ``NGHTTP2_PUSH_PROMISE``. In case of - ``NGHTTP2_HEADERS``, ``frame->headers.cat == - NGHTTP2_HCAT_RESPONSE`` means that it is the first response - headers, but it may be non-final response which is indicated by 1xx - status code. In this case, there may be zero or more HEADERS frame - with ``frame->headers.cat == NGHTTP2_HCAT_HEADERS`` which has - non-final response code and finally client gets exactly one HEADERS - frame with ``frame->headers.cat == NGHTTP2_HCAT_HEADERS`` - containing final response headers (non-1xx status code). The - trailer fields also has ``frame->headers.cat == - NGHTTP2_HCAT_HEADERS`` which does not contain any status code. - - Returning :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close - the stream (promised stream if frame is PUSH_PROMISE) by issuing - RST_STREAM with :macro:`NGHTTP2_INTERNAL_ERROR`. In this case, - :type:`nghttp2_on_header_callback` and - :type:`nghttp2_on_frame_recv_callback` will not be invoked. If a - different error code is desirable, use - `nghttp2_submit_rst_stream()` with a desired error code and then - return :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Again, use - ``frame->push_promise.promised_stream_id`` as stream_id parameter - in `nghttp2_submit_rst_stream()` if frame is PUSH_PROMISE. - - The implementation of this function must return 0 if it succeeds. - It can return :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` to - reset the stream (promised stream if frame is PUSH_PROMISE). For - critical errors, it must return - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the other value is - returned, it is treated as if :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` - is returned. If :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, - `nghttp2_session_mem_recv()` function will immediately return - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_on_begin_headers_callback()`. -.. type:: typedef int (*nghttp2_on_header_callback)(nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags, void *user_data) - - - Callback function invoked when a header name/value pair is received - for the *frame*. The *name* of length *namelen* is header name. - The *value* of length *valuelen* is header value. The *flags* is - bitwise OR of one or more of :type:`nghttp2_nv_flag`. - - If :macro:`NGHTTP2_NV_FLAG_NO_INDEX` is set in *flags*, the receiver - must not index this name/value pair when forwarding it to the next - hop. More specifically, "Literal Header Field never Indexed" - representation must be used in HPACK encoding. - - When this callback is invoked, ``frame->hd.type`` is either - :macro:`NGHTTP2_HEADERS` or :macro:`NGHTTP2_PUSH_PROMISE`. After all - header name/value pairs are processed with this callback, and no - error has been detected, :type:`nghttp2_on_frame_recv_callback` - will be invoked. If there is an error in decompression, - :type:`nghttp2_on_frame_recv_callback` for the *frame* will not be - invoked. - - Both *name* and *value* are guaranteed to be NULL-terminated. The - *namelen* and *valuelen* do not include terminal NULL. If - `nghttp2_option_set_no_http_messaging()` is used with nonzero - value, NULL character may be included in *name* or *value* before - terminating NULL. - - Please note that unless `nghttp2_option_set_no_http_messaging()` is - used, nghttp2 library does perform validation against the *name* - and the *value* using `nghttp2_check_header_name()` and - `nghttp2_check_header_value()`. In addition to this, nghttp2 - performs validation based on HTTP Messaging rule, which is briefly - explained in :ref:`http-messaging` section. - - If the application uses `nghttp2_session_mem_recv()`, it can return - :macro:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()` - return without processing further input bytes. The memory pointed - by *frame*, *name* and *value* parameters are retained until - `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is called. - The application must retain the input bytes which was used to - produce these parameters, because it may refer to the memory region - included in the input bytes. - - Returning :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close - the stream (promised stream if frame is PUSH_PROMISE) by issuing - RST_STREAM with :macro:`NGHTTP2_INTERNAL_ERROR`. In this case, - :type:`nghttp2_on_header_callback` and - :type:`nghttp2_on_frame_recv_callback` will not be invoked. If a - different error code is desirable, use - `nghttp2_submit_rst_stream()` with a desired error code and then - return :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Again, use - ``frame->push_promise.promised_stream_id`` as stream_id parameter - in `nghttp2_submit_rst_stream()` if frame is PUSH_PROMISE. - - The implementation of this function must return 0 if it succeeds. - It may return :macro:`NGHTTP2_ERR_PAUSE` or - :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. For other critical - failures, it must return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. If - the other nonzero value is returned, it is treated as - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. If - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, - `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_on_header_callback()`. - - .. warning:: - - Application should properly limit the total buffer size to store - incoming header fields. Without it, peer may send large number - of header fields or large header fields to cause out of memory in - local endpoint. Due to how HPACK works, peer can do this - effectively without using much memory on their own. -.. type:: typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session, const nghttp2_frame *frame, nghttp2_rcbuf *name, nghttp2_rcbuf *value, uint8_t flags, void *user_data) - - - Callback function invoked when a header name/value pair is received - for the *frame*. The *name* is header name. The *value* is header - value. The *flags* is bitwise OR of one or more of - :type:`nghttp2_nv_flag`. - - This callback behaves like :type:`nghttp2_on_header_callback`, - except that *name* and *value* are stored in reference counted - buffer. If application wishes to keep these references without - copying them, use `nghttp2_rcbuf_incref()` to increment their - reference count. It is the application's responsibility to call - `nghttp2_rcbuf_decref()` if they called `nghttp2_rcbuf_incref()` so - as not to leak memory. If the *session* is created by - `nghttp2_session_server_new3()` or `nghttp2_session_client_new3()`, - the function to free memory is the one belongs to the mem - parameter. As long as this free function alives, *name* and - *value* can live after *session* was destroyed. -.. type:: typedef ssize_t (*nghttp2_select_padding_callback)(nghttp2_session *session, const nghttp2_frame *frame, size_t max_payloadlen, void *user_data) - - - Callback function invoked when the library asks application how - many padding bytes are required for the transmission of the - *frame*. The application must choose the total length of payload - including padded bytes in range [frame->hd.length, max_payloadlen], - inclusive. Choosing number not in this range will be treated as - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. Returning - ``frame->hd.length`` means no padding is added. Returning - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` will make - `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_select_padding_callback()`. -.. type:: typedef ssize_t (*nghttp2_data_source_read_length_callback)( nghttp2_session *session, uint8_t frame_type, int32_t stream_id, int32_t session_remote_window_size, int32_t stream_remote_window_size, uint32_t remote_max_frame_size, void *user_data) - - - Callback function invoked when library wants to get max length of - data to send data to the remote peer. The implementation of this - function should return a value in the following range. [1, - min(*session_remote_window_size*, *stream_remote_window_size*, - *remote_max_frame_size*)]. If a value greater than this range is - returned than the max allow value will be used. Returning a value - smaller than this range is treated as - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. The *frame_type* is provided - for future extensibility and identifies the type of frame (see - :type:`nghttp2_frame_type`) for which to get the length for. - Currently supported frame types are: :macro:`NGHTTP2_DATA`. - - This callback can be used to control the length in bytes for which - :type:`nghttp2_data_source_read_callback` is allowed to send to the - remote endpoint. This callback is optional. Returning - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the entire session - failure. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_data_source_read_length_callback()`. -.. type:: typedef int (*nghttp2_on_begin_frame_callback)(nghttp2_session *session, const nghttp2_frame_hd *hd, void *user_data) - - - Callback function invoked when a frame header is received. The - *hd* points to received frame header. - - Unlike :type:`nghttp2_on_frame_recv_callback`, this callback will - also be called when frame header of CONTINUATION frame is received. - - If both :type:`nghttp2_on_begin_frame_callback` and - :type:`nghttp2_on_begin_headers_callback` are set and HEADERS or - PUSH_PROMISE is received, :type:`nghttp2_on_begin_frame_callback` - will be called first. - - The implementation of this function must return 0 if it succeeds. - If nonzero value is returned, it is treated as fatal error and - `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. - - To set this callback to :type:`nghttp2_session_callbacks`, use - `nghttp2_session_callbacks_set_on_begin_frame_callback()`. -.. type:: typedef int (*nghttp2_on_extension_chunk_recv_callback)( nghttp2_session *session, const nghttp2_frame_hd *hd, const uint8_t *data, size_t len, void *user_data) - - - Callback function invoked when chunk of extension frame payload is - received. The *hd* points to frame header. The received - chunk is *data* of length *len*. - - The implementation of this function must return 0 if it succeeds. - - To abort processing this extension frame, return - :macro:`NGHTTP2_ERR_CANCEL`. - - If fatal error occurred, application should return - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the - other values are returned, currently they are treated as - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. -.. type:: typedef int (*nghttp2_unpack_extension_callback)(nghttp2_session *session, void **payload, const nghttp2_frame_hd *hd, void *user_data) - - - Callback function invoked when library asks the application to - unpack extension payload from its wire format. The extension - payload has been passed to the application using - :type:`nghttp2_on_extension_chunk_recv_callback`. The frame header - is already unpacked by the library and provided as *hd*. - - To receive extension frames, the application must tell desired - extension frame type to the library using - `nghttp2_option_set_user_recv_extension_type()`. - - The implementation of this function may store the pointer to the - created object as a result of unpacking in *\*payload*, and returns - 0. The pointer stored in *\*payload* is opaque to the library, and - the library does not own its pointer. *\*payload* is initialized as - ``NULL``. The *\*payload* is available as ``frame->ext.payload`` in - :type:`nghttp2_on_frame_recv_callback`. Therefore if application - can free that memory inside :type:`nghttp2_on_frame_recv_callback` - callback. Of course, application has a liberty not ot use - *\*payload*, and do its own mechanism to process extension frames. - - To abort processing this extension frame, return - :macro:`NGHTTP2_ERR_CANCEL`. - - If fatal error occurred, application should return - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the - other values are returned, currently they are treated as - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. -.. type:: typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session, uint8_t *buf, size_t len, const nghttp2_frame *frame, void *user_data) - - - Callback function invoked when library asks the application to pack - extension payload in its wire format. The frame header will be - packed by library. Application must pack payload only. - ``frame->ext.payload`` is the object passed to - `nghttp2_submit_extension()` as payload parameter. Application - must pack extension payload to the *buf* of its capacity *len* - bytes. The *len* is at least 16KiB. - - The implementation of this function should return the number of - bytes written into *buf* when it succeeds. - - To abort processing this extension frame, return - :macro:`NGHTTP2_ERR_CANCEL`, and - :type:`nghttp2_on_frame_not_send_callback` will be invoked. - - If fatal error occurred, application should return - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the - other values are returned, currently they are treated as - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the return value is - strictly larger than *len*, it is treated as - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. -.. type:: typedef int (*nghttp2_error_callback)(nghttp2_session *session, const char *msg, size_t len, void *user_data) - - - Callback function invoked when library provides the error message - intended for human consumption. This callback is solely for - debugging purpose. The *msg* is typically NULL-terminated string - of length *len*. *len* does not include the sentinel NULL - character. - - The format of error message may change between nghttp2 library - versions. The application should not depend on the particular - format. - - Normally, application should return 0 from this callback. If fatal - error occurred while doing something in this callback, application - should return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - library will return immediately with return value - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. Currently, if nonzero value - is returned from this callback, they are treated as - :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`, but application should not - rely on this details. -.. type:: nghttp2_session_callbacks - - - Callback functions for :type:`nghttp2_session`. The details of - this structure are intentionally hidden from the public API. - - -.. type:: typedef void *(*nghttp2_malloc)(size_t size, void *mem_user_data) - - - Custom memory allocator to replace malloc(). The *mem_user_data* - is the mem_user_data member of :type:`nghttp2_mem` structure. -.. type:: typedef void (*nghttp2_free)(void *ptr, void *mem_user_data) - - - Custom memory allocator to replace free(). The *mem_user_data* is - the mem_user_data member of :type:`nghttp2_mem` structure. -.. type:: typedef void *(*nghttp2_calloc)(size_t nmemb, size_t size, void *mem_user_data) - - - Custom memory allocator to replace calloc(). The *mem_user_data* - is the mem_user_data member of :type:`nghttp2_mem` structure. -.. type:: typedef void *(*nghttp2_realloc)(void *ptr, size_t size, void *mem_user_data) - - - Custom memory allocator to replace realloc(). The *mem_user_data* - is the mem_user_data member of :type:`nghttp2_mem` structure. -.. type:: nghttp2_mem - - - Custom memory allocator functions and user defined pointer. The - *mem_user_data* member is passed to each allocator function. This - can be used, for example, to achieve per-session memory pool. - - In the following example code, ``my_malloc``, ``my_free``, - ``my_calloc`` and ``my_realloc`` are the replacement of the - standard allocators ``malloc``, ``free``, ``calloc`` and - ``realloc`` respectively:: - - void *my_malloc_cb(size_t size, void *mem_user_data) { - return my_malloc(size); - } - - void my_free_cb(void *ptr, void *mem_user_data) { my_free(ptr); } - - void *my_calloc_cb(size_t nmemb, size_t size, void *mem_user_data) { - return my_calloc(nmemb, size); - } - - void *my_realloc_cb(void *ptr, size_t size, void *mem_user_data) { - return my_realloc(ptr, size); - } - - void session_new() { - nghttp2_session *session; - nghttp2_session_callbacks *callbacks; - nghttp2_mem mem = {NULL, my_malloc_cb, my_free_cb, my_calloc_cb, - my_realloc_cb}; - - ... - - nghttp2_session_client_new3(&session, callbacks, NULL, NULL, &mem); - - ... - } - - .. member:: void *mem_user_data - - An arbitrary user supplied data. This is passed to each - allocator function. - .. member:: nghttp2_malloc malloc - - Custom allocator function to replace malloc(). - .. member:: nghttp2_free free - - Custom allocator function to replace free(). - .. member:: nghttp2_calloc calloc - - Custom allocator function to replace calloc(). - .. member:: nghttp2_realloc realloc - - Custom allocator function to replace realloc(). - -.. type:: nghttp2_option - - - Configuration options for :type:`nghttp2_session`. The details of - this structure are intentionally hidden from the public API. - - -.. type:: nghttp2_ext_altsvc - - - The payload of ALTSVC frame. ALTSVC frame is a non-critical - extension to HTTP/2. If this frame is received, and - `nghttp2_option_set_user_recv_extension_type()` is not set, and - `nghttp2_option_set_builtin_recv_extension_type()` is set for - :macro:`NGHTTP2_ALTSVC`, ``nghttp2_extension.payload`` will point to - this struct. - - It has the following members: - - .. member:: uint8_t *origin - - The pointer to origin which this alternative service is - associated with. This is not necessarily NULL-terminated. - .. member:: size_t origin_len - - The length of the *origin*. - .. member:: uint8_t *field_value - - The pointer to Alt-Svc field value contained in ALTSVC frame. - This is not necessarily NULL-terminated. - .. member:: size_t field_value_len - - The length of the *field_value*. - -.. type:: nghttp2_hd_deflater - - - HPACK deflater object. - - -.. type:: nghttp2_hd_inflater - - - HPACK inflater object. - - -.. type:: nghttp2_stream - - - The structure to represent HTTP/2 stream. The details of this - structure are intentionally hidden from the public API. - - diff -Nru nghttp2-1.13.0/Dockerfile.android nghttp2-0.6.7/Dockerfile.android --- nghttp2-1.13.0/Dockerfile.android 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/Dockerfile.android 2014-11-30 14:15:07.000000000 +0000 @@ -1,4 +1,3 @@ -# vim: ft=dockerfile: # Dockerfile to build nghttp2 android binary # # $ sudo docker build -t nghttp2-android - < Dockerfile.android @@ -10,7 +9,7 @@ # # $ sudo docker run -v /path/to/dest:/out nghttp2-android cp /root/build/nghttp2/src/nghttpx /out -FROM ubuntu:vivid +FROM ubuntu MAINTAINER Tatsuhiro Tsujikawa @@ -30,12 +29,11 @@ genisoimage libc6-i386 lib32stdc++6 WORKDIR /root/build -RUN curl -L -O http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin && \ - chmod a+x android-ndk-r10d-linux-x86_64.bin && \ - ./android-ndk-r10d-linux-x86_64.bin && \ - rm android-ndk-r10d-linux-x86_64.bin +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 -WORKDIR /root/build/android-ndk-r10d +WORKDIR /root/build/android-ndk-r10c RUN /bin/bash build/tools/make-standalone-toolchain.sh \ --install-dir=$ANDROID_HOME/toolchain \ --toolchain=arm-linux-androideabi-4.9 --llvm-version=3.5 \ @@ -59,24 +57,18 @@ make install WORKDIR /root/build -RUN curl -L -O https://www.openssl.org/source/openssl-1.0.2d.tar.gz && \ - tar xf openssl-1.0.2d.tar.gz && \ - rm openssl-1.0.2d.tar.gz - -WORKDIR /root/build/openssl-1.0.2d +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 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 && \ - 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 && \ - ./configure \ +RUN curl -L -O https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz +RUN tar xf libevent-2.0.21-stable.tar.gz +WORKDIR /root/build/libevent-2.0.21-stable +RUN ./configure \ --host=arm-linux-androideabi \ --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \ --prefix=$PREFIX \ @@ -87,26 +79,7 @@ make install WORKDIR /root/build -RUN curl -L -O http://zlib.net/zlib-1.2.8.tar.gz && \ - tar xf zlib-1.2.8.tar.gz && \ - rm zlib-1.2.8.tar.gz - -WORKDIR /root/build/zlib-1.2.8 -RUN HOST=arm-linux-androideabi \ - CC=$HOST-gcc \ - AR=$HOST-ar \ - LD=$HOST-ld \ - RANLIB=$HOST-ranlib \ - STRIP=$HOST-strip \ - ./configure \ - --prefix=$PREFIX \ - --libdir=$PREFIX/lib \ - --includedir=$PREFIX/include \ - --static && \ - make install - -WORKDIR /root/build -RUN git clone https://github.com/nghttp2/nghttp2 +RUN git clone https://github.com/tatsuhiro-t/nghttp2 WORKDIR /root/build/nghttp2 RUN autoreconf -i && \ ./configure \ @@ -120,9 +93,8 @@ --disable-threads \ LIBSPDYLAY_CFLAGS=-I$PREFIX/usr/local/include \ LIBSPDYLAY_LIBS="-L$PREFIX/usr/local/lib -lspdylay" \ - CPPFLAGS="-fPIE -I$PREFIX/include" \ - CXXFLAGS="-fno-strict-aliasing" \ + CPPFLAGS="-I$PREFIX/include" \ PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \ - LDFLAGS="-fPIE -pie -L$PREFIX/lib" && \ + LDFLAGS="-L$PREFIX/lib" && \ make && \ arm-linux-androideabi-strip src/nghttpx src/nghttpd src/nghttp diff -Nru nghttp2-1.13.0/examples/asio-cl2.cc nghttp2-0.6.7/examples/asio-cl2.cc --- nghttp2-1.13.0/examples/asio-cl2.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/asio-cl2.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ - -#include -#include - -#include - -using boost::asio::ip::tcp; - -using namespace nghttp2::asio_http2; -using namespace nghttp2::asio_http2::client; - -void print_header(const header_map &h) { - for (auto &kv : h) { - std::cerr << kv.first << ": " << kv.second.value << "\n"; - } - std::cerr << std::endl; -} - -void print_header(const response &res) { - std::cerr << "HTTP/2 " << res.status_code() << "\n"; - print_header(res.header()); -} - -void print_header(const request &req) { - auto &uri = req.uri(); - std::cerr << req.method() << " " << uri.scheme << "://" << uri.host - << uri.path; - if (!uri.raw_query.empty()) { - std::cerr << "?" << uri.raw_query; - } - std::cerr << " HTTP/2\n"; - print_header(req.header()); -} - -int main(int argc, char *argv[]) { - try { - if (argc < 2) { - std::cerr << "Usage: asio-cl URI" << std::endl; - return 1; - } - boost::system::error_code ec; - boost::asio::io_service io_service; - - std::string uri = argv[1]; - std::string scheme, host, service; - - if (host_service_from_uri(ec, scheme, host, service, uri)) { - std::cerr << "error: bad URI: " << ec.message() << std::endl; - return 1; - } - - boost::asio::ssl::context tls_ctx(boost::asio::ssl::context::sslv23); - tls_ctx.set_default_verify_paths(); - // disabled to make development easier... - // tls_ctx.set_verify_mode(boost::asio::ssl::verify_peer); - configure_tls_context(ec, tls_ctx); - - auto sess = scheme == "https" ? session(io_service, tls_ctx, host, service) - : session(io_service, host, service); - - sess.on_connect([&sess, &uri](tcp::resolver::iterator endpoint_it) { - std::cerr << "connected to " << (*endpoint_it).endpoint() << std::endl; - boost::system::error_code ec; - auto req = sess.submit(ec, "GET", uri, {{"cookie", {"foo=bar", true}}}); - if (ec) { - std::cerr << "error: " << ec.message() << std::endl; - return; - } - - req->on_response([&sess, req](const response &res) { - std::cerr << "response header was received" << std::endl; - print_header(res); - - res.on_data([&sess](const uint8_t *data, std::size_t len) { - std::cerr.write(reinterpret_cast(data), len); - std::cerr << std::endl; - }); - }); - - req->on_close([&sess](uint32_t error_code) { - std::cerr << "request done with error_code=" << error_code << std::endl; - }); - - req->on_push([](const request &push_req) { - std::cerr << "push request was received" << std::endl; - - print_header(push_req); - - push_req.on_response([](const response &res) { - std::cerr << "push response header was received" << std::endl; - - res.on_data([](const uint8_t *data, std::size_t len) { - std::cerr.write(reinterpret_cast(data), len); - std::cerr << std::endl; - }); - }); - }); - }); - - sess.on_error([](const boost::system::error_code &ec) { - std::cerr << "error: " << ec.message() << std::endl; - }); - - io_service.run(); - } catch (std::exception &e) { - std::cerr << "exception: " << e.what() << "\n"; - } - - return 0; -} diff -Nru nghttp2-1.13.0/examples/asio-cl.cc nghttp2-0.6.7/examples/asio-cl.cc --- nghttp2-1.13.0/examples/asio-cl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/asio-cl.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ - -#include - -#include - -using boost::asio::ip::tcp; - -using namespace nghttp2::asio_http2; -using namespace nghttp2::asio_http2::client; - -int main(int argc, char *argv[]) { - try { - if (argc < 2) { - std::cerr << "Usage: asio-cl URI" << std::endl; - return 1; - } - boost::system::error_code ec; - boost::asio::io_service io_service; - - std::string uri = argv[1]; - std::string scheme, host, service; - - if (host_service_from_uri(ec, scheme, host, service, uri)) { - std::cerr << "error: bad URI: " << ec.message() << std::endl; - return 1; - } - - boost::asio::ssl::context tls_ctx(boost::asio::ssl::context::sslv23); - tls_ctx.set_default_verify_paths(); - // disabled to make development easier... - // tls_ctx.set_verify_mode(boost::asio::ssl::verify_peer); - configure_tls_context(ec, tls_ctx); - - auto sess = scheme == "https" ? session(io_service, tls_ctx, host, service) - : session(io_service, host, service); - - sess.on_connect([&sess, &uri](tcp::resolver::iterator endpoint_it) { - boost::system::error_code ec; - auto req = sess.submit(ec, "GET", uri); - - if (ec) { - std::cerr << "error: " << ec.message() << std::endl; - return; - } - - req->on_response([&sess](const response &res) { - 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([&sess](const uint8_t *data, std::size_t len) { - std::cerr.write(reinterpret_cast(data), len); - std::cerr << std::endl; - }); - }); - - req->on_close([&sess](uint32_t error_code) { sess.shutdown(); }); - }); - - sess.on_error([](const boost::system::error_code &ec) { - std::cerr << "error: " << ec.message() << std::endl; - }); - - io_service.run(); - } catch (std::exception &e) { - std::cerr << "exception: " << e.what() << "\n"; - } - - return 0; -} diff -Nru nghttp2-1.13.0/examples/asio-sv2.cc nghttp2-0.6.7/examples/asio-sv2.cc --- nghttp2-1.13.0/examples/asio-sv2.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/asio-sv2.cc 2014-11-30 14:15:07.000000000 +0000 @@ -35,16 +35,12 @@ // #include #include -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H -#ifdef HAVE_FCNTL_H #include -#endif // HAVE_FCNTL_H #include #include -#include +#include using namespace nghttp2::asio_http2; using namespace nghttp2::asio_http2::server; @@ -52,28 +48,30 @@ int main(int argc, char *argv[]) { try { // Check command line arguments. - if (argc < 5) { - std::cerr << "Usage: asio-sv2
" - << "[ ]\n"; + if (argc < 4) { + std::cerr << "Usage: asio-sv2 " + << " \n"; return 1; } - boost::system::error_code ec; - - std::string addr = argv[1]; - std::string port = argv[2]; - std::size_t num_threads = std::stoi(argv[3]); - std::string docroot = argv[4]; + uint16_t port = std::stoi(argv[1]); + std::size_t num_threads = std::stoi(argv[2]); + std::string docroot = argv[3]; http2 server; server.num_threads(num_threads); - server.handle("/", [&docroot](const request &req, const response &res) { - auto path = percent_decode(req.uri().path); + if (argc >= 6) { + server.tls(argv[4], argv[5]); + } + + server.listen("*", port, [&docroot](const std::shared_ptr &req, + const std::shared_ptr &res) { + auto path = percent_decode(req->path()); if (!check_path(path)) { - res.write_head(404); - res.end(); + res->write_head(404); + res->end(); return; } @@ -84,39 +82,23 @@ path = docroot + path; auto fd = open(path.c_str(), O_RDONLY); if (fd == -1) { - res.write_head(404); - res.end(); + res->write_head(404); + res->end(); return; } - auto header = header_map(); + auto headers = std::vector
(); struct stat stbuf; if (stat(path.c_str(), &stbuf) == 0) { - header.emplace("content-length", - header_value{std::to_string(stbuf.st_size)}); - header.emplace("last-modified", - header_value{http_date(stbuf.st_mtime)}); + headers.push_back( + header{"content-length", std::to_string(stbuf.st_size)}); + headers.push_back( + header{"last-modified", http_date(stbuf.st_mtim.tv_sec)}); } - res.write_head(200, std::move(header)); - res.end(file_generator_from_fd(fd)); + res->write_head(200, std::move(headers)); + res->end(file_reader_from_fd(fd)); }); - - if (argc >= 7) { - boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23); - tls.use_private_key_file(argv[5], boost::asio::ssl::context::pem); - tls.use_certificate_chain_file(argv[6]); - - configure_tls_context_easy(ec, tls); - - if (server.listen_and_serve(ec, tls, addr, port)) { - std::cerr << "error: " << ec.message() << std::endl; - } - } else { - if (server.listen_and_serve(ec, addr, port)) { - std::cerr << "error: " << ec.message() << std::endl; - } - } } catch (std::exception &e) { std::cerr << "exception: " << e.what() << "\n"; } diff -Nru nghttp2-1.13.0/examples/asio-sv3.cc nghttp2-0.6.7/examples/asio-sv3.cc --- nghttp2-1.13.0/examples/asio-sv3.cc 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/examples/asio-sv3.cc 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 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. + */ +// We wrote this code based on the original code which has the +// following license: +// +// main.cpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include +#include +#include +#include + +#include + +using namespace nghttp2::asio_http2; +using namespace nghttp2::asio_http2::server; + +int main(int argc, char *argv[]) { + try { + // Check command line arguments. + if (argc < 4) { + std::cerr << "Usage: asio-sv3 " + << " \n"; + return 1; + } + + uint16_t port = std::stoi(argv[1]); + std::size_t num_threads = std::stoi(argv[2]); + std::size_t num_concurrent_tasks = std::stoi(argv[3]); + + http2 server; + + server.num_threads(num_threads); + + if (argc >= 5) { + server.tls(argv[4], argv[5]); + } + + server.num_concurrent_tasks(num_concurrent_tasks); + + server.listen("*", port, [](const std::shared_ptr &req, + const std::shared_ptr &res) { + res->write_head(200); + + auto msgq = std::make_shared>(); + + res->end([msgq](uint8_t * buf, std::size_t len) + -> std::pair { + if (msgq->empty()) { + // if msgq is empty, tells the library that don't call + // this callback until we call res->resume(). This is + // done by returing std::make_pair(0, false). + return std::make_pair(0, false); + } + auto msg = std::move(msgq->front()); + msgq->pop_front(); + + if (msg.empty()) { + // The empty message signals the end of response in + // this simple protocol. + return std::make_pair(0, true); + } + + auto nwrite = std::min(len, msg.size()); + std::copy(std::begin(msg), std::begin(msg) + nwrite, buf); + if (msg.size() > nwrite) { + msgq->push_front(msg.substr(nwrite)); + } + return std::make_pair(nwrite, false); + }); + + req->run_task([res, msgq](channel &channel) { + // executed in different thread from request callback + // was called. + + // Using res and msgq is not safe inside this callback. + // But using them in callback passed to channel::post is + // safe. + + // We just emit simple message "message N\n" in every 1 + // second and 3 times in total. + for (std::size_t i = 0; i < 3; ++i) { + msgq->push_back("message " + std::to_string(i + 1) + "\n"); + + channel.post([res]() { + // executed in same thread where + // request callback was called. + + // Tells library we have new message. + res->resume(); + }); + + sleep(1); + } + + // Send empty message to signal the end of response + // body. + msgq->push_back(""); + + channel.post([res]() { + // executed in same thread where request + // callback was called. + res->resume(); + }); + + }); + + }); + } catch (std::exception &e) { + std::cerr << "exception: " << e.what() << "\n"; + } + + return 0; +} diff -Nru nghttp2-1.13.0/examples/asio-sv.cc nghttp2-0.6.7/examples/asio-sv.cc --- nghttp2-1.13.0/examples/asio-sv.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/asio-sv.cc 2014-11-30 14:15:07.000000000 +0000 @@ -37,7 +37,7 @@ #include #include -#include +#include using namespace nghttp2::asio_http2; using namespace nghttp2::asio_http2::server; @@ -45,102 +45,28 @@ int main(int argc, char *argv[]) { try { // Check command line arguments. - if (argc < 4) { - std::cerr - << "Usage: asio-sv
[ " - << "]\n"; + if (argc < 3) { + std::cerr << "Usage: asio-sv " + << "\n"; return 1; } - boost::system::error_code ec; - - std::string addr = argv[1]; - std::string port = argv[2]; - std::size_t num_threads = std::stoi(argv[3]); + uint16_t port = std::stoi(argv[1]); + std::size_t num_threads = std::stoi(argv[2]); http2 server; server.num_threads(num_threads); - server.handle("/", [](const request &req, const response &res) { - res.write_head(200, {{"foo", {"bar"}}}); - res.end("hello, world\n"); - }); - server.handle("/secret/", [](const request &req, const response &res) { - res.write_head(200); - res.end("under construction!\n"); - }); - server.handle("/push", [](const request &req, const response &res) { - boost::system::error_code ec; - auto push = res.push(ec, "GET", "/push/1"); - if (!ec) { - push->write_head(200); - push->end("server push FTW!\n"); - } - - res.write_head(200); - res.end("you'll receive server push!\n"); - }); - server.handle("/delay", [](const request &req, const response &res) { - res.write_head(200); - - auto timer = std::make_shared( - res.io_service(), boost::posix_time::seconds(3)); - auto closed = std::make_shared(); - - res.on_close([timer, closed](uint32_t error_code) { - timer->cancel(); - *closed = true; - }); - - timer->async_wait([&res, closed](const boost::system::error_code &ec) { - if (ec || *closed) { - return; - } + if (argc >= 5) { + server.tls(argv[3], argv[4]); + } - res.end("finally!\n"); - }); - }); - server.handle("/trailer", [](const request &req, const response &res) { - // send trailer part. - res.write_head(200, {{"trailers", {"digest"}}}); - - std::string body = "nghttp2 FTW!\n"; - auto left = std::make_shared(body.size()); - - res.end([&res, body, left](uint8_t *dst, std::size_t len, - uint32_t *data_flags) { - auto n = std::min(len, *left); - std::copy_n(body.c_str() + (body.size() - *left), n, dst); - *left -= n; - if (*left == 0) { - *data_flags |= - NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM; - // RFC 3230 Instance Digests in HTTP. The digest value is - // SHA-256 message digest of body. - res.write_trailer( - {{"digest", - {"SHA-256=qqXqskW7F3ueBSvmZRCiSwl2ym4HRO0M/pvQCBlSDis="}}}); - } - return n; - }); + server.listen("*", port, [](const std::shared_ptr &req, + const std::shared_ptr &res) { + res->write_head(200, {header{"foo", "bar"}}); + res->end("hello, world"); }); - - if (argc >= 6) { - boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23); - tls.use_private_key_file(argv[4], boost::asio::ssl::context::pem); - tls.use_certificate_chain_file(argv[5]); - - configure_tls_context_easy(ec, tls); - - if (server.listen_and_serve(ec, tls, addr, port)) { - std::cerr << "error: " << ec.message() << std::endl; - } - } else { - if (server.listen_and_serve(ec, addr, port)) { - std::cerr << "error: " << ec.message() << std::endl; - } - } } catch (std::exception &e) { std::cerr << "exception: " << e.what() << "\n"; } diff -Nru nghttp2-1.13.0/examples/client.c nghttp2-0.6.7/examples/client.c --- nghttp2-1.13.0/examples/client.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/client.c 2014-11-30 14:15:07.000000000 +0000 @@ -28,33 +28,21 @@ */ #ifdef HAVE_CONFIG_H #include -#endif /* HAVE_CONFIG_H */ +#endif /* !HAVE_CONFIG_H */ -#include +#include #include -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ -#ifdef HAVE_FCNTL_H #include -#endif /* HAVE_FCNTL_H */ #include -#ifdef HAVE_SYS_SOCKET_H #include -#endif /* HAVE_SYS_SOCKET_H */ -#ifdef HAVE_NETDB_H #include -#endif /* HAVE_NETDB_H */ -#ifdef HAVE_NETINET_IN_H #include -#endif /* HAVE_NETINET_IN_H */ #include #include #include #include #include -#include -#include #include @@ -126,7 +114,6 @@ /* * Prints error message |msg| and exit. */ -NGHTTP2_NORETURN static void die(const char *msg) { fprintf(stderr, "FATAL: %s\n", msg); exit(EXIT_FAILURE); @@ -136,7 +123,6 @@ * Prints error containing the function name |func| and message |msg| * and exit. */ -NGHTTP2_NORETURN static void dief(const char *func, const char *msg) { fprintf(stderr, "FATAL: %s: %s\n", func, msg); exit(EXIT_FAILURE); @@ -146,7 +132,6 @@ * Prints error containing the function name |func| and error code * |error_code| and exit. */ -NGHTTP2_NORETURN static void diec(const char *func, int error_code) { fprintf(stderr, "FATAL: %s: error_code=%d, msg=%s\n", func, error_code, nghttp2_strerror(error_code)); @@ -167,7 +152,7 @@ connection->want_io = IO_NONE; ERR_clear_error(); rv = SSL_write(connection->ssl, data, (int)length); - if (rv <= 0) { + if (rv < 0) { int err = SSL_get_error(connection->ssl, rv); if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) { connection->want_io = @@ -219,9 +204,9 @@ const nghttp2_nv *nva = frame->headers.nva; printf("[INFO] C ----------------------------> S (HEADERS)\n"); for (i = 0; i < frame->headers.nvlen; ++i) { - fwrite(nva[i].name, 1, nva[i].namelen, stdout); + fwrite(nva[i].name, nva[i].namelen, 1, stdout); printf(": "); - fwrite(nva[i].value, 1, nva[i].valuelen, stdout); + fwrite(nva[i].value, nva[i].valuelen, 1, stdout); printf("\n"); } } @@ -249,9 +234,9 @@ if (req) { printf("[INFO] C <---------------------------- S (HEADERS)\n"); for (i = 0; i < frame->headers.nvlen; ++i) { - fwrite(nva[i].name, 1, nva[i].namelen, stdout); + fwrite(nva[i].name, nva[i].namelen, 1, stdout); printf(": "); - fwrite(nva[i].value, 1, nva[i].valuelen, stdout); + fwrite(nva[i].value, nva[i].valuelen, 1, stdout); printf("\n"); } } @@ -289,6 +274,8 @@ return 0; } +#define MAX_OUTLEN 4096 + /* * The implementation of nghttp2_on_data_chunk_recv_callback type. We * use this function to print the received response body. @@ -457,11 +444,12 @@ static void submit_request(struct Connection *connection, struct Request *req) { int32_t stream_id; /* Make sure that the last item is NULL */ - const nghttp2_nv nva[] = { - MAKE_NV(":method", "GET"), MAKE_NV_CS(":path", req->path), - MAKE_NV(":scheme", "https"), MAKE_NV_CS(":authority", req->hostport), - MAKE_NV("accept", "*/*"), - MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)}; + const nghttp2_nv nva[] = {MAKE_NV(":method", "GET"), + MAKE_NV_CS(":path", req->path), + MAKE_NV(":scheme", "https"), + MAKE_NV_CS(":authority", req->hostport), + MAKE_NV("accept", "*/*"), + MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)}; stream_id = nghttp2_submit_request(connection->session, NULL, nva, sizeof(nva) / sizeof(nva[0]), NULL, req); @@ -540,6 +528,10 @@ connection.ssl = ssl; connection.want_io = IO_NONE; + /* Send connection header in blocking I/O mode */ + SSL_write(ssl, NGHTTP2_CLIENT_CONNECTION_PREFACE, + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); + /* Here make file descriptor non-block */ make_non_block(fd); set_tcp_nodelay(fd); @@ -562,12 +554,6 @@ diec("nghttp2_session_client_new", rv); } - rv = nghttp2_submit_settings(connection.session, NGHTTP2_FLAG_NONE, NULL, 0); - - if (rv != 0) { - diec("nghttp2_submit_settings", rv); - } - /* Submit the HTTP request to the outbound queue. */ submit_request(&connection, &req); @@ -663,10 +649,10 @@ return -1; } offset = i; - res->port = (uint16_t)port; + res->port = port; } } - res->hostportlen = (size_t)(uri + offset + ipv6addr - res->host); + res->hostportlen = uri + offset + ipv6addr - res->host; for (i = offset; i < len; ++i) { if (uri[i] == '#') { break; @@ -695,6 +681,8 @@ act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, 0); + OPENSSL_config(NULL); + OpenSSL_add_all_algorithms(); SSL_load_error_strings(); SSL_library_init(); diff -Nru nghttp2-1.13.0/examples/CMakeLists.txt nghttp2-0.6.7/examples/CMakeLists.txt --- nghttp2-1.13.0/examples/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -if(ENABLE_EXAMPLES) - file(GLOB c_sources *.c) - set_source_files_properties(${c_sources} PROPERTIES - COMPILE_FLAGS "${WARNCFLAGS}") - file(GLOB cxx_sources *.cc) - set_source_files_properties(${cxx_sources} PROPERTIES - COMPILE_FLAGS "${WARNCXXFLAGS} ${CXX1XCXXFLAGS}") - - include_directories( - ${CMAKE_SOURCE_DIR} - ${CMAKE_SOURCE_DIR}/lib/includes - ${CMAKE_BINARY_DIR}/lib/includes - ${CMAKE_SOURCE_DIR}/src/includes - ${CMAKE_SOURCE_DIR}/third-party - - ${LIBEVENT_INCLUDE_DIRS} - ${OPENSSL_INCLUDE_DIRS} - ) - - link_libraries( - nghttp2 - ${LIBEVENT_OPENSSL_LIBRARIES} - ${OPENSSL_LIBRARIES} - ${APP_LIBRARIES} - ) - - add_executable(client client.c $) - add_executable(libevent-client libevent-client.c $) - add_executable(libevent-server libevent-server.c $) - add_executable(deflate deflate.c $) - - if(ENABLE_TINY_NGHTTPD) - add_executable(tiny-nghttpd tiny-nghttpd.c $) - endif() - - if(ENABLE_ASIO_LIB) - foreach(name asio-sv asio-sv2 asio-cl asio-cl2) - add_executable(${name} ${name}.cc $) - target_include_directories(${name} PRIVATE - ${OPENSSL_INCLUDE_DIRS} - ${Boost_INCLUDE_DIRS} - ) - target_link_libraries(${name} - nghttp2 - nghttp2_asio - ${JEMALLOC_LIBRARIES} - ${OPENSSL_LIBRARIES} - ${Boost_LIBRARIES} - ${APP_LIBRARIES} - ) - endforeach() - endif() -endif() diff -Nru nghttp2-1.13.0/examples/deflate.c nghttp2-0.6.7/examples/deflate.c --- nghttp2-1.13.0/examples/deflate.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/deflate.c 2014-11-30 14:15:07.000000000 +0000 @@ -109,9 +109,9 @@ printf("Input (%zu byte(s)):\n\n", sum); for (i = 0; i < nvlen; ++i) { - fwrite(nva[i].name, 1, nva[i].namelen, stdout); + fwrite(nva[i].name, nva[i].namelen, 1, stdout); printf(": "); - fwrite(nva[i].value, 1, nva[i].valuelen, stdout); + fwrite(nva[i].value, nva[i].valuelen, 1, stdout); printf("\n"); } @@ -129,10 +129,10 @@ exit(EXIT_FAILURE); } - outlen = (size_t)rv; + outlen = rv; printf("\nDeflate (%zu byte(s), ratio %.02f):\n\n", outlen, - sum == 0 ? 0 : (double)outlen / (double)sum); + sum == 0 ? 0 : (double)outlen / sum); for (i = 0; i < outlen; ++i) { if ((i & 0x0fu) == 0) { @@ -180,15 +180,15 @@ return -1; } - proclen = (size_t)rv; + proclen = rv; in += proclen; inlen -= proclen; if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { - fwrite(nv.name, 1, nv.namelen, stderr); + fwrite(nv.name, nv.namelen, 1, stderr); fprintf(stderr, ": "); - fwrite(nv.value, 1, nv.valuelen, stderr); + fwrite(nv.value, nv.valuelen, 1, stderr); fprintf(stderr, "\n"); } diff -Nru nghttp2-1.13.0/examples/libevent-client.c nghttp2-0.6.7/examples/libevent-client.c --- nghttp2-1.13.0/examples/libevent-client.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/libevent-client.c 2014-11-30 14:15:07.000000000 +0000 @@ -22,37 +22,17 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef __sgi -#include -#define errx(exitcode, format, args...) \ - { \ - warnx(format, ##args); \ - exit(exitcode); \ - } -#define warnx(format, args...) fprintf(stderr, format "\n", ##args) -char *strndup(const char *s, size_t size); -#endif - #ifdef HAVE_CONFIG_H #include -#endif /* HAVE_CONFIG_H */ +#endif /* !HAVE_CONFIG_H */ #include -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ -#ifdef HAVE_SYS_SOCKET_H #include -#endif /* HAVE_SYS_SOCKET_H */ -#ifdef HAVE_NETINET_IN_H #include -#endif /* HAVE_NETINET_IN_H */ #include -#ifndef __sgi #include -#endif #include -#include #include #include @@ -70,11 +50,11 @@ #define ARRLEN(x) (sizeof(x) / sizeof(x[0])) typedef struct { - /* The NULL-terminated URI string to retrieve. */ + /* The NULL-terminated URI string to retreive. */ const char *uri; /* Parsed result of the |uri| */ struct http_parser_url *u; - /* The authority portion of the |uri|, not NULL-terminated */ + /* The authroity portion of the |uri|, not NULL-terminated */ char *authority; /* The path portion of the |uri|, including query, not NULL-terminated */ @@ -110,35 +90,31 @@ u->field_data[UF_HOST].len); if (u->field_set & (1 << UF_PORT)) { stream_data->authoritylen += - (size_t)snprintf(stream_data->authority + u->field_data[UF_HOST].len, - extra, ":%u", u->port); + snprintf(stream_data->authority + u->field_data[UF_HOST].len, extra, + ":%u", u->port); } - /* If we don't have path in URI, we use "/" as path. */ - stream_data->pathlen = 1; + stream_data->pathlen = 0; if (u->field_set & (1 << UF_PATH)) { stream_data->pathlen = u->field_data[UF_PATH].len; } if (u->field_set & (1 << UF_QUERY)) { /* +1 for '?' character */ - stream_data->pathlen += (size_t)(u->field_data[UF_QUERY].len + 1); + stream_data->pathlen += u->field_data[UF_QUERY].len + 1; } - - stream_data->path = malloc(stream_data->pathlen); - if (u->field_set & (1 << UF_PATH)) { - memcpy(stream_data->path, &uri[u->field_data[UF_PATH].off], - u->field_data[UF_PATH].len); + if (stream_data->pathlen > 0) { + stream_data->path = malloc(stream_data->pathlen); + if (u->field_set & (1 << UF_PATH)) { + memcpy(stream_data->path, &uri[u->field_data[UF_PATH].off], + u->field_data[UF_PATH].len); + } + if (u->field_set & (1 << UF_QUERY)) { + memcpy(stream_data->path + u->field_data[UF_PATH].len + 1, + &uri[u->field_data[UF_QUERY].off], u->field_data[UF_QUERY].len); + } } else { - stream_data->path[0] = '/'; + stream_data->path = NULL; } - if (u->field_set & (1 << UF_QUERY)) { - stream_data->path[stream_data->pathlen - u->field_data[UF_QUERY].len - 1] = - '?'; - memcpy(stream_data->path + stream_data->pathlen - - u->field_data[UF_QUERY].len, - &uri[u->field_data[UF_QUERY].off], u->field_data[UF_QUERY].len); - } - return stream_data; } @@ -179,9 +155,9 @@ static void print_header(FILE *f, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen) { - fwrite(name, 1, namelen, f); + fwrite(name, namelen, 1, f); fprintf(f, ": "); - fwrite(value, 1, valuelen, f); + fwrite(value, valuelen, 1, f); fprintf(f, "\n"); } @@ -204,7 +180,7 @@ http2_session_data *session_data = (http2_session_data *)user_data; struct bufferevent *bev = session_data->bev; bufferevent_write(bev, data, length); - return (ssize_t)length; + return length; } /* nghttp2_on_header_callback: Called when nghttp2 library emits @@ -272,7 +248,7 @@ void *user_data) { http2_session_data *session_data = (http2_session_data *)user_data; if (session_data->stream_data->stream_id == stream_id) { - fwrite(data, 1, len, stdout); + fwrite(data, len, 1, stdout); } return 0; } @@ -282,7 +258,8 @@ 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) { + nghttp2_error_code error_code, + void *user_data) { http2_session_data *session_data = (http2_session_data *)user_data; int rv; @@ -322,11 +299,6 @@ SSL_OP_NO_COMPRESSION | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL); - -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3); -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - return ssl_ctx; } @@ -373,7 +345,8 @@ {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}}; int rv; - /* client 24 bytes magic string will be sent by nghttp2 library */ + bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE, + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv, ARRLEN(iv)); if (rv != 0) { @@ -446,7 +419,7 @@ delete_http2_session_data(session_data); return; } - if (evbuffer_drain(input, (size_t)readlen) != 0) { + if (evbuffer_drain(input, readlen) != 0) { warnx("Fatal error: evbuffer_drain failed"); delete_http2_session_data(session_data); return; @@ -480,27 +453,7 @@ if (events & BEV_EVENT_CONNECTED) { int fd = bufferevent_getfd(bev); int val = 1; - const unsigned char *alpn = NULL; - unsigned int alpnlen = 0; - SSL *ssl; - fprintf(stderr, "Connected\n"); - - ssl = bufferevent_openssl_get_ssl(session_data->bev); - - SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (alpn == NULL) { - SSL_get0_alpn_selected(ssl, &alpn, &alpnlen); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) { - fprintf(stderr, "h2 is not negotiated\n"); - delete_http2_session_data(session_data); - return; - } - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); initialize_nghttp2_session(session_data); send_client_connection_header(session_data); @@ -594,6 +547,8 @@ act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, NULL); + OPENSSL_config(NULL); + OpenSSL_add_all_algorithms(); SSL_load_error_strings(); SSL_library_init(); diff -Nru nghttp2-1.13.0/examples/libevent-server.c nghttp2-0.6.7/examples/libevent-server.c --- nghttp2-1.13.0/examples/libevent-server.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/libevent-server.c 2014-11-30 14:15:07.000000000 +0000 @@ -22,45 +22,21 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef __sgi -#define errx(exitcode, format, args...) \ - { \ - warnx(format, ##args); \ - exit(exitcode); \ - } -#define warn(format, args...) warnx(format ": %s", ##args, strerror(errno)) -#define warnx(format, args...) fprintf(stderr, format "\n", ##args) -#endif - #ifdef HAVE_CONFIG_H #include -#endif /* HAVE_CONFIG_H */ +#endif /* !HAVE_CONFIG_H */ #include -#ifdef HAVE_SYS_SOCKET_H #include -#endif /* HAVE_SYS_SOCKET_H */ -#ifdef HAVE_NETDB_H #include -#endif /* HAVE_NETDB_H */ #include -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ #include -#ifdef HAVE_FCNTL_H #include -#endif /* HAVE_FCNTL_H */ #include -#ifdef HAVE_NETINET_IN_H #include -#endif /* HAVE_NETINET_IN_H */ #include -#ifndef __sgi #include -#endif -#include -#include #include #include @@ -116,22 +92,6 @@ return SSL_TLSEXT_ERR_OK; } -#if OPENSSL_VERSION_NUMBER >= 0x10002000L -static int alpn_select_proto_cb(SSL *ssl _U_, const unsigned char **out, - unsigned char *outlen, const unsigned char *in, - unsigned int inlen, void *arg _U_) { - int rv; - - rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen); - - if (rv != 1) { - return SSL_TLSEXT_ERR_NOACK; - } - - return SSL_TLSEXT_ERR_OK; -} -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - /* Create SSL_CTX. */ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) { SSL_CTX *ssl_ctx; @@ -168,11 +128,6 @@ next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN; SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL); - -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL); -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - return ssl_ctx; } @@ -243,8 +198,7 @@ session_data->bev = bufferevent_openssl_socket_new( app_ctx->evbase, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); - rv = getnameinfo(addr, (socklen_t)addrlen, host, sizeof(host), NULL, 0, - NI_NUMERICHOST); + rv = getnameinfo(addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST); if (rv != 0) { session_data->client_addr = strdup("(unknown)"); } else { @@ -299,7 +253,7 @@ warnx("Fatal error: %s", nghttp2_strerror((int)readlen)); return -1; } - if (evbuffer_drain(input, (size_t)readlen) != 0) { + if (evbuffer_drain(input, readlen) != 0) { warnx("Fatal error: evbuffer_drain failed"); return -1; } @@ -319,7 +273,7 @@ return NGHTTP2_ERR_WOULDBLOCK; } bufferevent_write(bev, data, length); - return (ssize_t)length; + return length; } /* Returns nonzero if the string |s| ends with the substring |sub| */ @@ -335,13 +289,13 @@ /* Returns int value of hex string character |c| */ static uint8_t hex_to_uint(uint8_t c) { if ('0' <= c && c <= '9') { - return (uint8_t)(c - '0'); + return c - '0'; } if ('A' <= c && c <= 'F') { - return (uint8_t)(c - 'A' + 10); + return c - 'A' + 10; } if ('a' <= c && c <= 'f') { - return (uint8_t)(c - 'a' + 10); + return c - 'a' + 10; } return 0; } @@ -359,11 +313,10 @@ for (i = 0, j = 0; i < valuelen - 2;) { if (value[i] != '%' || !isxdigit(value[i + 1]) || !isxdigit(value[i + 2])) { - res[j++] = (char)value[i++]; + res[j++] = value[i++]; continue; } - res[j++] = - (char)((hex_to_uint(value[i + 1]) << 4) + hex_to_uint(value[i + 2])); + res[j++] = (hex_to_uint(value[i + 1]) << 4) + hex_to_uint(value[i + 2]); i += 3; } memcpy(&res[j], &value[i], 2); @@ -408,8 +361,8 @@ return 0; } -static const char ERROR_HTML[] = "404" - "

404 Not Found

"; +const char ERROR_HTML[] = "404" + "

404 Not Found

"; static int error_reply(nghttp2_session *session, http2_stream_data *stream_data) { @@ -584,8 +537,15 @@ } 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); @@ -602,9 +562,11 @@ nghttp2_session_callbacks_set_on_begin_headers_callback( callbacks, on_begin_headers_callback); - nghttp2_session_server_new(&session_data->session, callbacks, session_data); + nghttp2_session_server_new2(&session_data->session, callbacks, session_data, + option); nghttp2_session_callbacks_del(callbacks); + nghttp2_option_del(option); } /* Send HTTP/2 client connection header, which includes 24 bytes @@ -661,31 +623,11 @@ static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) { http2_session_data *session_data = (http2_session_data *)ptr; if (events & BEV_EVENT_CONNECTED) { - const unsigned char *alpn = NULL; - unsigned int alpnlen = 0; - SSL *ssl; - fprintf(stderr, "%s connected\n", session_data->client_addr); - ssl = bufferevent_openssl_get_ssl(session_data->bev); - - SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (alpn == NULL) { - SSL_get0_alpn_selected(ssl, &alpn, &alpnlen); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) { - fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr); - delete_http2_session_data(session_data); - return; - } - initialize_nghttp2_session(session_data); - if (send_server_connection_header(session_data) != 0 || - session_send(session_data) != 0) { + if (send_server_connection_header(session_data) != 0) { delete_http2_session_data(session_data); return; } @@ -729,13 +671,13 @@ rv = getaddrinfo(NULL, service, &hints, &res); if (rv != 0) { - errx(1, "Could not resolve server address"); + errx(1, NULL); } for (rp = res; rp; rp = rp->ai_next) { struct evconnlistener *listener; listener = evconnlistener_new_bind( evbase, acceptcb, app_ctx, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, - 16, rp->ai_addr, (int)rp->ai_addrlen); + 16, rp->ai_addr, rp->ai_addrlen); if (listener) { freeaddrinfo(res); @@ -781,6 +723,8 @@ act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, NULL); + OPENSSL_config(NULL); + OpenSSL_add_all_algorithms(); SSL_load_error_strings(); SSL_library_init(); diff -Nru nghttp2-1.13.0/examples/Makefile.am nghttp2-0.6.7/examples/Makefile.am --- nghttp2-1.13.0/examples/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -21,13 +21,10 @@ # 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 = CMakeLists.txt - if ENABLE_EXAMPLES -AM_CFLAGS = $(WARNCFLAGS) -AM_CXXFLAGS = $(WARNCXXFLAGS) $(CXX1XCXXFLAGS) AM_CPPFLAGS = \ + -Wall \ -I$(top_srcdir)/lib/includes \ -I$(top_builddir)/lib/includes \ -I$(top_srcdir)/src/includes \ @@ -35,11 +32,12 @@ @LIBEVENT_OPENSSL_CFLAGS@ \ @OPENSSL_CFLAGS@ \ @DEFS@ -LDADD = $(top_builddir)/lib/libnghttp2.la \ - $(top_builddir)/third-party/libhttp-parser.la \ +AM_LDFLAGS = \ @LIBEVENT_OPENSSL_LIBS@ \ - @OPENSSL_LIBS@ \ - @APPLDFLAGS@ + @OPENSSL_LIBS@ +LDADD = \ + $(top_builddir)/lib/libnghttp2.la \ + $(top_builddir)/third-party/libhttp-parser.la noinst_PROGRAMS = client libevent-client libevent-server deflate @@ -61,37 +59,26 @@ if ENABLE_ASIO_LIB -noinst_PROGRAMS += asio-sv asio-sv2 asio-cl asio-cl2 +noinst_PROGRAMS += asio-sv asio-sv2 asio-sv3 -# AM_CPPFLAGS must be placed first, so that header file (e.g., -# nghttp2/nghttp2.h) in this package is used rather than installed -# one. -ASIOCPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS} -ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \ - $(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \ - $(top_builddir)/third-party/libhttp-parser.la \ - ${BOOST_LDFLAGS} \ - ${BOOST_ASIO_LIB} \ - ${BOOST_THREAD_LIB} \ - ${BOOST_SYSTEM_LIB} \ - @OPENSSL_LIBS@ \ - @APPLDFLAGS@ +ASIOCPPFLAGS = ${BOOST_CPPFLAGS} ${AM_CPPFLAGS} +ASIOLDFLAGS = @JEMALLOC_LIBS@ +ASIOLDADD = $(top_builddir)/src/libnghttp2_asio.la asio_sv_SOURCES = asio-sv.cc asio_sv_CPPFLAGS = ${ASIOCPPFLAGS} +asio_sv_LDFLAGS = ${ASIOLDFLAGS} asio_sv_LDADD = ${ASIOLDADD} asio_sv2_SOURCES = asio-sv2.cc asio_sv2_CPPFLAGS = ${ASIOCPPFLAGS} +asio_sv2_LDFLAGS = ${ASIOLDFLAGS} asio_sv2_LDADD = ${ASIOLDADD} -asio_cl_SOURCES = asio-cl.cc -asio_cl_CPPFLAGS = ${ASIOCPPFLAGS} -asio_cl_LDADD = ${ASIOLDADD} - -asio_cl2_SOURCES = asio-cl2.cc -asio_cl2_CPPFLAGS = ${ASIOCPPFLAGS} -asio_cl2_LDADD = ${ASIOLDADD} +asio_sv3_SOURCES = asio-sv3.cc +asio_sv3_CPPFLAGS = ${ASIOCPPFLAGS} +asio_sv3_LDFLAGS = ${ASIOLDFLAGS} +asio_sv3_LDADD = ${ASIOLDADD} endif # ENABLE_ASIO_LIB diff -Nru nghttp2-1.13.0/examples/Makefile.in nghttp2-0.6.7/examples/Makefile.in --- nghttp2-1.13.0/examples/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/examples/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -38,17 +38,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -118,8 +108,10 @@ @ENABLE_EXAMPLES_TRUE@ deflate$(EXEEXT) $(am__EXEEXT_1) \ @ENABLE_EXAMPLES_TRUE@ $(am__EXEEXT_2) @ENABLE_EXAMPLES_TRUE@@ENABLE_TINY_NGHTTPD_TRUE@am__append_1 = tiny-nghttpd -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@am__append_2 = asio-sv asio-sv2 asio-cl asio-cl2 +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@am__append_2 = asio-sv asio-sv2 asio-sv3 subdir = examples +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -129,13 +121,11 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -144,37 +134,36 @@ @ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@am__EXEEXT_2 = \ @ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ asio-sv$(EXEEXT) \ @ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ asio-sv2$(EXEEXT) \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ asio-cl$(EXEEXT) \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ asio-cl2$(EXEEXT) +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ asio-sv3$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) -am__asio_cl_SOURCES_DIST = asio-cl.cc -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@am_asio_cl_OBJECTS = asio_cl-asio-cl.$(OBJEXT) -asio_cl_OBJECTS = $(am_asio_cl_OBJECTS) -am__DEPENDENCIES_1 = -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@am__DEPENDENCIES_2 = $(top_builddir)/lib/libnghttp2.la \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(top_builddir)/src/libnghttp2_asio.la \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(top_builddir)/third-party/libhttp-parser.la \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(am__DEPENDENCIES_1) \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(am__DEPENDENCIES_1) \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(am__DEPENDENCIES_1) \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(am__DEPENDENCIES_1) -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_cl_DEPENDENCIES = $(am__DEPENDENCIES_2) +am__asio_sv_SOURCES_DIST = asio-sv.cc +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@am_asio_sv_OBJECTS = asio_sv-asio-sv.$(OBJEXT) +asio_sv_OBJECTS = $(am_asio_sv_OBJECTS) +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv_DEPENDENCIES = \ +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(ASIOLDADD) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -am__asio_cl2_SOURCES_DIST = asio-cl2.cc -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@am_asio_cl2_OBJECTS = asio_cl2-asio-cl2.$(OBJEXT) -asio_cl2_OBJECTS = $(am_asio_cl2_OBJECTS) -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_cl2_DEPENDENCIES = $(am__DEPENDENCIES_2) -am__asio_sv_SOURCES_DIST = asio-sv.cc -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@am_asio_sv_OBJECTS = asio_sv-asio-sv.$(OBJEXT) -asio_sv_OBJECTS = $(am_asio_sv_OBJECTS) -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv_DEPENDENCIES = $(am__DEPENDENCIES_2) +asio_sv_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(asio_sv_LDFLAGS) $(LDFLAGS) -o $@ am__asio_sv2_SOURCES_DIST = asio-sv2.cc @ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@am_asio_sv2_OBJECTS = asio_sv2-asio-sv2.$(OBJEXT) asio_sv2_OBJECTS = $(am_asio_sv2_OBJECTS) -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv2_DEPENDENCIES = $(am__DEPENDENCIES_2) +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv2_DEPENDENCIES = \ +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(ASIOLDADD) +asio_sv2_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(asio_sv2_LDFLAGS) $(LDFLAGS) -o $@ +am__asio_sv3_SOURCES_DIST = asio-sv3.cc +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@am_asio_sv3_OBJECTS = asio_sv3-asio-sv3.$(OBJEXT) +asio_sv3_OBJECTS = $(am_asio_sv3_OBJECTS) +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv3_DEPENDENCIES = \ +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(ASIOLDADD) +asio_sv3_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(asio_sv3_LDFLAGS) $(LDFLAGS) -o $@ am__client_SOURCES_DIST = client.c @ENABLE_EXAMPLES_TRUE@am_client_OBJECTS = client.$(OBJEXT) client_OBJECTS = $(am_client_OBJECTS) @@ -264,14 +253,13 @@ am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = -SOURCES = $(asio_cl_SOURCES) $(asio_cl2_SOURCES) $(asio_sv_SOURCES) \ - $(asio_sv2_SOURCES) $(client_SOURCES) $(deflate_SOURCES) \ +SOURCES = $(asio_sv_SOURCES) $(asio_sv2_SOURCES) $(asio_sv3_SOURCES) \ + $(client_SOURCES) $(deflate_SOURCES) \ $(libevent_client_SOURCES) $(libevent_server_SOURCES) \ $(tiny_nghttpd_SOURCES) -DIST_SOURCES = $(am__asio_cl_SOURCES_DIST) \ - $(am__asio_cl2_SOURCES_DIST) $(am__asio_sv_SOURCES_DIST) \ - $(am__asio_sv2_SOURCES_DIST) $(am__client_SOURCES_DIST) \ - $(am__deflate_SOURCES_DIST) \ +DIST_SOURCES = $(am__asio_sv_SOURCES_DIST) \ + $(am__asio_sv2_SOURCES_DIST) $(am__asio_sv3_SOURCES_DIST) \ + $(am__client_SOURCES_DIST) $(am__deflate_SOURCES_DIST) \ $(am__libevent_client_SOURCES_DIST) \ $(am__libevent_server_SOURCES_DIST) \ $(am__tiny_nghttpd_SOURCES_DIST) @@ -299,12 +287,10 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -323,7 +309,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -339,7 +324,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -355,10 +339,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -370,7 +350,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -408,11 +387,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -467,7 +445,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -480,10 +457,8 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -EXTRA_DIST = CMakeLists.txt -@ENABLE_EXAMPLES_TRUE@AM_CFLAGS = $(WARNCFLAGS) -@ENABLE_EXAMPLES_TRUE@AM_CXXFLAGS = $(WARNCXXFLAGS) $(CXX1XCXXFLAGS) @ENABLE_EXAMPLES_TRUE@AM_CPPFLAGS = \ +@ENABLE_EXAMPLES_TRUE@ -Wall \ @ENABLE_EXAMPLES_TRUE@ -I$(top_srcdir)/lib/includes \ @ENABLE_EXAMPLES_TRUE@ -I$(top_builddir)/lib/includes \ @ENABLE_EXAMPLES_TRUE@ -I$(top_srcdir)/src/includes \ @@ -492,44 +467,34 @@ @ENABLE_EXAMPLES_TRUE@ @OPENSSL_CFLAGS@ \ @ENABLE_EXAMPLES_TRUE@ @DEFS@ -@ENABLE_EXAMPLES_TRUE@LDADD = $(top_builddir)/lib/libnghttp2.la \ -@ENABLE_EXAMPLES_TRUE@ $(top_builddir)/third-party/libhttp-parser.la \ +@ENABLE_EXAMPLES_TRUE@AM_LDFLAGS = \ @ENABLE_EXAMPLES_TRUE@ @LIBEVENT_OPENSSL_LIBS@ \ -@ENABLE_EXAMPLES_TRUE@ @OPENSSL_LIBS@ \ -@ENABLE_EXAMPLES_TRUE@ @APPLDFLAGS@ +@ENABLE_EXAMPLES_TRUE@ @OPENSSL_LIBS@ + +@ENABLE_EXAMPLES_TRUE@LDADD = \ +@ENABLE_EXAMPLES_TRUE@ $(top_builddir)/lib/libnghttp2.la \ +@ENABLE_EXAMPLES_TRUE@ $(top_builddir)/third-party/libhttp-parser.la @ENABLE_EXAMPLES_TRUE@client_SOURCES = client.c @ENABLE_EXAMPLES_TRUE@libevent_client_SOURCES = libevent-client.c @ENABLE_EXAMPLES_TRUE@libevent_server_SOURCES = libevent-server.c @ENABLE_EXAMPLES_TRUE@deflate_SOURCES = deflate.c @ENABLE_EXAMPLES_TRUE@@ENABLE_TINY_NGHTTPD_TRUE@tiny_nghttpd_SOURCES = tiny-nghttpd.c - -# AM_CPPFLAGS must be placed first, so that header file (e.g., -# nghttp2/nghttp2.h) in this package is used rather than installed -# one. -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ASIOCPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS} -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ $(top_builddir)/third-party/libhttp-parser.la \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ ${BOOST_LDFLAGS} \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ ${BOOST_ASIO_LIB} \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ ${BOOST_THREAD_LIB} \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ ${BOOST_SYSTEM_LIB} \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ @OPENSSL_LIBS@ \ -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ @APPLDFLAGS@ - +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ASIOCPPFLAGS = ${BOOST_CPPFLAGS} ${AM_CPPFLAGS} +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ASIOLDFLAGS = @JEMALLOC_LIBS@ +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@ASIOLDADD = $(top_builddir)/src/libnghttp2_asio.la @ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv_SOURCES = asio-sv.cc @ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv_CPPFLAGS = ${ASIOCPPFLAGS} +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv_LDFLAGS = ${ASIOLDFLAGS} @ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv_LDADD = ${ASIOLDADD} @ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv2_SOURCES = asio-sv2.cc @ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv2_CPPFLAGS = ${ASIOCPPFLAGS} +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv2_LDFLAGS = ${ASIOLDFLAGS} @ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv2_LDADD = ${ASIOLDADD} -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_cl_SOURCES = asio-cl.cc -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_cl_CPPFLAGS = ${ASIOCPPFLAGS} -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_cl_LDADD = ${ASIOLDADD} -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_cl2_SOURCES = asio-cl2.cc -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_cl2_CPPFLAGS = ${ASIOCPPFLAGS} -@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_cl2_LDADD = ${ASIOLDADD} +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv3_SOURCES = asio-sv3.cc +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv3_CPPFLAGS = ${ASIOCPPFLAGS} +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv3_LDFLAGS = ${ASIOLDFLAGS} +@ENABLE_ASIO_LIB_TRUE@@ENABLE_EXAMPLES_TRUE@asio_sv3_LDADD = ${ASIOLDADD} all: all-am .SUFFIXES: @@ -546,6 +511,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu examples/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -573,21 +539,17 @@ echo " rm -f" $$list; \ rm -f $$list -asio-cl$(EXEEXT): $(asio_cl_OBJECTS) $(asio_cl_DEPENDENCIES) $(EXTRA_asio_cl_DEPENDENCIES) - @rm -f asio-cl$(EXEEXT) - $(AM_V_CXXLD)$(CXXLINK) $(asio_cl_OBJECTS) $(asio_cl_LDADD) $(LIBS) - -asio-cl2$(EXEEXT): $(asio_cl2_OBJECTS) $(asio_cl2_DEPENDENCIES) $(EXTRA_asio_cl2_DEPENDENCIES) - @rm -f asio-cl2$(EXEEXT) - $(AM_V_CXXLD)$(CXXLINK) $(asio_cl2_OBJECTS) $(asio_cl2_LDADD) $(LIBS) - asio-sv$(EXEEXT): $(asio_sv_OBJECTS) $(asio_sv_DEPENDENCIES) $(EXTRA_asio_sv_DEPENDENCIES) @rm -f asio-sv$(EXEEXT) - $(AM_V_CXXLD)$(CXXLINK) $(asio_sv_OBJECTS) $(asio_sv_LDADD) $(LIBS) + $(AM_V_CXXLD)$(asio_sv_LINK) $(asio_sv_OBJECTS) $(asio_sv_LDADD) $(LIBS) asio-sv2$(EXEEXT): $(asio_sv2_OBJECTS) $(asio_sv2_DEPENDENCIES) $(EXTRA_asio_sv2_DEPENDENCIES) @rm -f asio-sv2$(EXEEXT) - $(AM_V_CXXLD)$(CXXLINK) $(asio_sv2_OBJECTS) $(asio_sv2_LDADD) $(LIBS) + $(AM_V_CXXLD)$(asio_sv2_LINK) $(asio_sv2_OBJECTS) $(asio_sv2_LDADD) $(LIBS) + +asio-sv3$(EXEEXT): $(asio_sv3_OBJECTS) $(asio_sv3_DEPENDENCIES) $(EXTRA_asio_sv3_DEPENDENCIES) + @rm -f asio-sv3$(EXEEXT) + $(AM_V_CXXLD)$(asio_sv3_LINK) $(asio_sv3_OBJECTS) $(asio_sv3_LDADD) $(LIBS) client$(EXEEXT): $(client_OBJECTS) $(client_DEPENDENCIES) $(EXTRA_client_DEPENDENCIES) @rm -f client$(EXEEXT) @@ -615,10 +577,9 @@ distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asio_cl-asio-cl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asio_cl2-asio-cl2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asio_sv-asio-sv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asio_sv2-asio-sv2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asio_sv3-asio-sv3.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/deflate.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libevent-client.Po@am__quote@ @@ -673,34 +634,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< -asio_cl-asio-cl.o: asio-cl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_cl_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT asio_cl-asio-cl.o -MD -MP -MF $(DEPDIR)/asio_cl-asio-cl.Tpo -c -o asio_cl-asio-cl.o `test -f 'asio-cl.cc' || echo '$(srcdir)/'`asio-cl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/asio_cl-asio-cl.Tpo $(DEPDIR)/asio_cl-asio-cl.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio-cl.cc' object='asio_cl-asio-cl.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_cl_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o asio_cl-asio-cl.o `test -f 'asio-cl.cc' || echo '$(srcdir)/'`asio-cl.cc - -asio_cl-asio-cl.obj: asio-cl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_cl_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT asio_cl-asio-cl.obj -MD -MP -MF $(DEPDIR)/asio_cl-asio-cl.Tpo -c -o asio_cl-asio-cl.obj `if test -f 'asio-cl.cc'; then $(CYGPATH_W) 'asio-cl.cc'; else $(CYGPATH_W) '$(srcdir)/asio-cl.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/asio_cl-asio-cl.Tpo $(DEPDIR)/asio_cl-asio-cl.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio-cl.cc' object='asio_cl-asio-cl.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_cl_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o asio_cl-asio-cl.obj `if test -f 'asio-cl.cc'; then $(CYGPATH_W) 'asio-cl.cc'; else $(CYGPATH_W) '$(srcdir)/asio-cl.cc'; fi` - -asio_cl2-asio-cl2.o: asio-cl2.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_cl2_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT asio_cl2-asio-cl2.o -MD -MP -MF $(DEPDIR)/asio_cl2-asio-cl2.Tpo -c -o asio_cl2-asio-cl2.o `test -f 'asio-cl2.cc' || echo '$(srcdir)/'`asio-cl2.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/asio_cl2-asio-cl2.Tpo $(DEPDIR)/asio_cl2-asio-cl2.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio-cl2.cc' object='asio_cl2-asio-cl2.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_cl2_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o asio_cl2-asio-cl2.o `test -f 'asio-cl2.cc' || echo '$(srcdir)/'`asio-cl2.cc - -asio_cl2-asio-cl2.obj: asio-cl2.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_cl2_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT asio_cl2-asio-cl2.obj -MD -MP -MF $(DEPDIR)/asio_cl2-asio-cl2.Tpo -c -o asio_cl2-asio-cl2.obj `if test -f 'asio-cl2.cc'; then $(CYGPATH_W) 'asio-cl2.cc'; else $(CYGPATH_W) '$(srcdir)/asio-cl2.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/asio_cl2-asio-cl2.Tpo $(DEPDIR)/asio_cl2-asio-cl2.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio-cl2.cc' object='asio_cl2-asio-cl2.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_cl2_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o asio_cl2-asio-cl2.obj `if test -f 'asio-cl2.cc'; then $(CYGPATH_W) 'asio-cl2.cc'; else $(CYGPATH_W) '$(srcdir)/asio-cl2.cc'; fi` - asio_sv-asio-sv.o: asio-sv.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_sv_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT asio_sv-asio-sv.o -MD -MP -MF $(DEPDIR)/asio_sv-asio-sv.Tpo -c -o asio_sv-asio-sv.o `test -f 'asio-sv.cc' || echo '$(srcdir)/'`asio-sv.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/asio_sv-asio-sv.Tpo $(DEPDIR)/asio_sv-asio-sv.Po @@ -729,6 +662,20 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_sv2_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o asio_sv2-asio-sv2.obj `if test -f 'asio-sv2.cc'; then $(CYGPATH_W) 'asio-sv2.cc'; else $(CYGPATH_W) '$(srcdir)/asio-sv2.cc'; fi` +asio_sv3-asio-sv3.o: asio-sv3.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_sv3_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT asio_sv3-asio-sv3.o -MD -MP -MF $(DEPDIR)/asio_sv3-asio-sv3.Tpo -c -o asio_sv3-asio-sv3.o `test -f 'asio-sv3.cc' || echo '$(srcdir)/'`asio-sv3.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/asio_sv3-asio-sv3.Tpo $(DEPDIR)/asio_sv3-asio-sv3.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio-sv3.cc' object='asio_sv3-asio-sv3.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_sv3_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o asio_sv3-asio-sv3.o `test -f 'asio-sv3.cc' || echo '$(srcdir)/'`asio-sv3.cc + +asio_sv3-asio-sv3.obj: asio-sv3.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_sv3_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT asio_sv3-asio-sv3.obj -MD -MP -MF $(DEPDIR)/asio_sv3-asio-sv3.Tpo -c -o asio_sv3-asio-sv3.obj `if test -f 'asio-sv3.cc'; then $(CYGPATH_W) 'asio-sv3.cc'; else $(CYGPATH_W) '$(srcdir)/asio-sv3.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/asio_sv3-asio-sv3.Tpo $(DEPDIR)/asio_sv3-asio-sv3.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio-sv3.cc' object='asio_sv3-asio-sv3.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(asio_sv3_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o asio_sv3-asio-sv3.obj `if test -f 'asio-sv3.cc'; then $(CYGPATH_W) 'asio-sv3.cc'; else $(CYGPATH_W) '$(srcdir)/asio-sv3.cc'; fi` + mostlyclean-libtool: -rm -f *.lo @@ -938,8 +885,6 @@ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am -.PRECIOUS: Makefile - # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru nghttp2-1.13.0/examples/tiny-nghttpd.c nghttp2-0.6.7/examples/tiny-nghttpd.c --- nghttp2-1.13.0/examples/tiny-nghttpd.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/examples/tiny-nghttpd.c 2014-11-30 14:15:07.000000000 +0000 @@ -30,30 +30,18 @@ #ifdef HAVE_CONFIG_H #include -#endif /* HAVE_CONFIG_H */ +#endif /* !HAVE_CONFIG_H */ #include -#ifdef HAVE_SYS_SOCKET_H #include -#endif /* HAVE_SYS_SOCKET_H */ #include -#ifdef HAVE_FCNTL_H #include -#endif /* HAVE_FCNTL_H */ -#ifdef HAVE_NETDB_H #include -#endif /* HAVE_NETDB_H */ -#ifdef HAVE_NETINET_IN_H #include -#endif /* HAVE_NETINET_IN_H */ #include -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ #include -#ifdef HAVE_TIME_H #include -#endif /* HAVE_TIME_H */ #include #include #include @@ -81,9 +69,9 @@ #define array_size(a) (sizeof((a)) / sizeof((a)[0])) /* Returns the length of remaning data in buffer */ -#define io_buf_len(iobuf) ((size_t)((iobuf)->last - (iobuf)->pos)) +#define io_buf_len(iobuf) ((iobuf)->last - (iobuf)->pos) /* Returns the space buffer can still accept */ -#define io_buf_left(iobuf) ((size_t)((iobuf)->end - (iobuf)->last)) +#define io_buf_left(iobuf) ((iobuf)->end - (iobuf)->last) typedef struct { /* beginning of buffer */ @@ -160,11 +148,12 @@ } timer; /* document root */ -static const char *docroot; +const char *docroot; /* length of docroot */ -static size_t docrootlen; +size_t docrootlen; -static nghttp2_session_callbacks *shared_callbacks; +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,57 +179,13 @@ return (char *)start; } -static int memeq(const void *a, const void *b, size_t n) { - return memcmp(a, b, n) == 0; -} +static int memseq(const uint8_t *a, size_t alen, const char *b) { + const uint8_t *last = a + alen; -#define streq(A, B, N) ((sizeof((A)) - 1) == (N) && memeq((A), (B), (N))) + for (; a != last && *b && *a == *b; ++a, ++b) + ; -typedef enum { - NGHTTP2_TOKEN__AUTHORITY, - NGHTTP2_TOKEN__METHOD, - NGHTTP2_TOKEN__PATH, - NGHTTP2_TOKEN__SCHEME, - NGHTTP2_TOKEN_HOST -} nghttp2_token; - -/* Inspired by h2o header lookup. https://github.com/h2o/h2o */ -static int lookup_token(const uint8_t *name, size_t namelen) { - switch (namelen) { - case 5: - switch (name[namelen - 1]) { - case 'h': - if (streq(":pat", name, 4)) { - return NGHTTP2_TOKEN__PATH; - } - break; - } - break; - case 7: - switch (name[namelen - 1]) { - case 'd': - if (streq(":metho", name, 6)) { - return NGHTTP2_TOKEN__METHOD; - } - break; - case 'e': - if (streq(":schem", name, 6)) { - return NGHTTP2_TOKEN__SCHEME; - } - break; - } - break; - case 10: - switch (name[namelen - 1]) { - case 'y': - if (streq(":authorit", name, 9)) { - return NGHTTP2_TOKEN__AUTHORITY; - } - break; - } - break; - } - return -1; + return a == last && *b == 0; } static char *cpydig(char *buf, int n, size_t len) { @@ -248,7 +193,7 @@ p = buf + len - 1; do { - *p-- = (char)((n % 10) + '0'); + *p-- = (n % 10) + '0'; n /= 10; } while (p >= buf); @@ -289,13 +234,13 @@ memcpy(p, " GMT", 4); p += 4; - return (size_t)(p - buf); + return p - buf; } static char date[29]; -static size_t datelen; +static char datelen; -static void update_date(void) { datelen = http_date(date, time(NULL)); } +static void update_date() { datelen = http_date(date, time(NULL)); } static size_t utos(char *buf, size_t len, uint64_t n) { size_t nwrite = 0; @@ -319,7 +264,7 @@ buf += nwrite - 1; do { - *buf-- = (char)((n % 10) + '0'); + *buf-- = (n % 10) + '0'; n /= 10; } while (n); @@ -399,7 +344,8 @@ conn = malloc(sizeof(connection)); - rv = nghttp2_session_server_new(&conn->session, shared_callbacks, conn); + rv = nghttp2_session_server_new2(&conn->session, shared_callbacks, conn, + shared_option); if (rv != 0) { goto cleanup; @@ -668,52 +614,19 @@ 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 -= (size_t)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 _U_, + int32_t stream_id _U_, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data _U_) { stream *strm = source->ptr; - ssize_t nread = - (int64_t)length < strm->fileleft ? (int64_t)length : strm->fileleft; - - *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY; + ssize_t nread; + 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) { @@ -730,7 +643,7 @@ nghttp2_data_source *source, void *user_data _U_) { stream *strm = source->ptr; - size_t left = (size_t)(strm->res_end - strm->res_begin); + size_t left = strm->res_end - strm->res_begin; size_t nwrite = length < left ? length : left; memcpy(buf, strm->res_begin, nwrite); @@ -740,7 +653,7 @@ *data_flags |= NGHTTP2_DATA_FLAG_EOF; } - return (ssize_t)nwrite; + return nwrite; } static int hex_digit(char c) { @@ -750,14 +663,14 @@ static unsigned int hex_to_uint(char c) { if (c <= '9') { - return (unsigned int)(c - '0'); + return c - '0'; } if (c <= 'F') { - return (unsigned int)(c - 'A' + 10); + return c - 'A' + 10; } - return (unsigned int)(c - 'a' + 10); + return c - 'a' + 10; } static void percent_decode(io_buf *buf, const char *s) { @@ -767,13 +680,12 @@ } if (*s == '%' && hex_digit(*(s + 1)) && hex_digit(*(s + 2))) { - *buf->last++ = - (uint8_t)((hex_to_uint(*(s + 1)) << 4) + hex_to_uint(*(s + 2))); + *buf->last++ = (hex_to_uint(*(s + 1)) << 4) + hex_to_uint(*(s + 2)); s += 2; continue; } - *buf->last++ = (uint8_t)*s; + *buf->last++ = *s; } } @@ -808,7 +720,7 @@ *pathbuf->last++ = '\0'; - if (!check_path((const char *)p, (size_t)(pathbuf->last - 1 - p))) { + if (!check_path((const char *)p, pathbuf->last - 1 - p)) { return -1; } @@ -959,8 +871,7 @@ strm->fileleft = stbuf.st_size; lastmodlen = http_date(lastmod, stbuf.st_mtim.tv_sec); - contentlengthlen = - utos(contentlength, sizeof(contentlength), (uint64_t)stbuf.st_size); + contentlengthlen = utos(contentlength, sizeof(contentlength), stbuf.st_size); nva[nvlen].value = (uint8_t *)contentlength; nva[nvlen].valuelen = contentlengthlen; @@ -1014,7 +925,8 @@ const nghttp2_frame *frame, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags _U_, - void *user_data _U_) { + void *user_data) { + connection *conn = user_data; stream *strm; if (frame->hd.type != NGHTTP2_HEADERS || @@ -1028,42 +940,74 @@ return 0; } - switch (lookup_token(name, namelen)) { - case NGHTTP2_TOKEN__METHOD: + if (!nghttp2_check_header_name(name, namelen) || + !nghttp2_check_header_value(value, valuelen)) { + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + + if (memseq(name, namelen, ":method")) { + if (strm->method) { + stream_error(conn, strm->stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } strm->method = io_buf_add_str(&strm->scrbuf, value, valuelen); if (!strm->method) { return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } strm->methodlen = valuelen; - break; - case NGHTTP2_TOKEN__SCHEME: + return 0; + } + + if (memseq(name, namelen, ":scheme")) { + if (strm->scheme) { + stream_error(conn, strm->stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } strm->scheme = io_buf_add_str(&strm->scrbuf, value, valuelen); if (!strm->scheme) { return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } strm->schemelen = valuelen; - break; - case NGHTTP2_TOKEN__AUTHORITY: + return 0; + } + + if (memseq(name, namelen, ":authority")) { + if (strm->authority) { + stream_error(conn, strm->stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } strm->authority = io_buf_add_str(&strm->scrbuf, value, valuelen); if (!strm->authority) { return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } strm->authoritylen = valuelen; - break; - case NGHTTP2_TOKEN__PATH: + return 0; + } + + if (memseq(name, namelen, ":path")) { + if (strm->path) { + stream_error(conn, strm->stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } strm->path = io_buf_add_str(&strm->scrbuf, value, valuelen); if (!strm->path) { return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } strm->pathlen = valuelen; - break; - case NGHTTP2_TOKEN_HOST: + return 0; + } + + if (name[0] == ':') { + stream_error(conn, strm->stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + + if (memseq(name, namelen, "host") && !strm->host) { strm->host = io_buf_add_str(&strm->scrbuf, value, valuelen); if (!strm->host) { return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } strm->hostlen = valuelen; - break; } return 0; @@ -1085,6 +1029,12 @@ return 0; } + if (!strm->method || !strm->scheme || !strm->path || + (!strm->authority && !strm->host)) { + stream_error(conn, strm->stream_id, NGHTTP2_PROTOCOL_ERROR); + return 0; + } + if (!strm->host) { strm->host = strm->authority; strm->hostlen = strm->authoritylen; @@ -1151,7 +1101,7 @@ return -1; } - nproc = nghttp2_session_mem_recv(conn->session, buf, (size_t)nread); + nproc = nghttp2_session_mem_recv(conn->session, buf, nread); if (nproc < 0) { return -1; @@ -1206,13 +1156,13 @@ break; } - if (io_buf_left(&conn->buf) < (size_t)n) { + if (io_buf_left(&conn->buf) < n) { conn->cache = b; - conn->cachelen = (size_t)n; + conn->cachelen = n; break; } - io_buf_add(&conn->buf, b, (size_t)n); + io_buf_add(&conn->buf, b, n); } } } @@ -1319,8 +1269,14 @@ shared_callbacks, on_stream_close_callback); nghttp2_session_callbacks_set_on_frame_not_send_callback( shared_callbacks, on_frame_not_send_callback); - nghttp2_session_callbacks_set_send_data_callback(shared_callbacks, - send_data_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); rv = io_loop_add(&loop, serv.fd, EPOLLIN, &serv); @@ -1338,6 +1294,7 @@ io_loop_run(&loop, &serv); + nghttp2_option_del(shared_option); nghttp2_session_callbacks_del(shared_callbacks); return 0; diff -Nru nghttp2-1.13.0/install-sh nghttp2-0.6.7/install-sh --- nghttp2-1.13.0/install-sh 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/install-sh 2014-11-30 14:15:34.000000000 +0000 @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2014-09-12.12; # UTC +scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -41,15 +41,19 @@ # This script is compatible with the BSD install script, but was written # from scratch. -tab=' ' nl=' ' -IFS=" $tab$nl" +IFS=" "" $nl" -# Set DOITPROG to "echo" to test this script. +# set DOITPROG to echo to test this script +# Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} -doit_exec=${doit:-exec} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi # Put in absolute file names if you don't have them in your path; # or use environment vars. @@ -64,6 +68,17 @@ rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + posix_mkdir= # Desired mode of installed file. @@ -82,7 +97,7 @@ dst_arg= copy_on_change=false -is_target_a_directory=possibly +no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE @@ -122,57 +137,46 @@ -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" - shift;; + shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 - case $mode in - *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; -o) chowncmd="$chownprog $2" - shift;; + shift;; -s) stripcmd=$stripprog;; - -t) - is_target_a_directory=always - dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; - -T) is_target_a_directory=never;; + -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; - --) shift - break;; + --) shift + break;; - -*) echo "$0: invalid option: $1" >&2 - exit 1;; + -*) echo "$0: invalid option: $1" >&2 + exit 1;; *) break;; esac shift done -# We allow the use of options -d and -T together, by making -d -# take the precedence; this is for compatibility with GNU install. - -if test -n "$dir_arg"; then - if test -n "$dst_arg"; then - echo "$0: target directory not allowed when installing a directory." >&2 - exit 1 - fi -fi - if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. @@ -204,15 +208,6 @@ fi if test -z "$dir_arg"; then - if test $# -gt 1 || test "$is_target_a_directory" = always; then - if test ! -d "$dst_arg"; then - echo "$0: $dst_arg: Is not a directory." >&2 - exit 1 - fi - fi -fi - -if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 @@ -228,16 +223,16 @@ *[0-7]) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw='% 200' + u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw=,u+rw + u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac @@ -274,15 +269,41 @@ # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then - if test "$is_target_a_directory" = never; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else - dstdir=`dirname "$dst"` + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + test -d "$dstdir" dstdir_status=$? fi @@ -293,81 +314,74 @@ if test $dstdir_status != 0; then case $posix_mkdir in '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - # $RANDOM is not portable (e.g. dash); use it when possible to - # lower collision chance - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 - - # As "mkdir -p" follows symlinks and we work in /tmp possibly; so - # create the $tmpdir first (and fail if unsuccessful) to make sure - # that nobody tries to guess the $tmpdir name. - if (umask $mkdir_umask && - $mkdirprog $mkdir_mode "$tmpdir" && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - test_tmpdir="$tmpdir/a" - ls_ld_tmpdir=`ls -ld "$test_tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null - fi - trap '' 0;; - esac;; + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; esac if $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else @@ -377,51 +391,53 @@ # directory the slow way, step by step, checking for races as we go. case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; esac + eval "$initialize_posix_glob" + oIFS=$IFS IFS=/ - set -f + $posix_glob set -f set fnord $dstdir shift - set +f + $posix_glob set +f IFS=$oIFS prefixes= for d do - test X"$d" = X && continue + test X"$d" = X && continue - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ done if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true fi fi fi @@ -456,12 +472,15 @@ # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - set -f && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && - set +f && + $posix_glob set +f && + test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then @@ -474,24 +493,24 @@ # to itself, or perhaps because mv is so ancient that it does not # support -f. { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 diff -Nru nghttp2-1.13.0/integration-tests/alt-server.crt nghttp2-0.6.7/integration-tests/alt-server.crt --- nghttp2-1.13.0/integration-tests/alt-server.crt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/alt-server.crt 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDhzCCAm+gAwIBAgIJANfuEldiquMNMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV -BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCmFsdC1kb21haW4wHhcNMTUwMTI1MDYy -NTQxWhcNMjUwMTIyMDYyNTQxWjBaMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29t -ZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRMwEQYD -VQQDDAphbHQtZG9tYWluMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA -0IwhDOGDipGrJQ9IoRSzPdkU/Ii4aJgGKHlXminym42X0VI3IW61RLvOHRlHVmVH -JQjFuDo2x+y81t9NlDg3HGUbSpzOzpm6StiutB7c4hreT5G4r0YKya1ugiemN0+p -qjIPJWm2jVnf448eZvUKRKEQ9W0MLZjiNjVGKrKlwo7fIlXg4N3+YixLYffAT1NV -d1T6V5jzlbruj15gK2nGjMQ9D1h1t9vTbTxY+mtk72aX0Y64IE6pPBWLFSSH8ozU -idDoL3AZwz2Jker+ALKK8CM4uho/RPpyW1C06HH+HLdH2MqEjDOROde/Nzxm668O -gK/JWGIEyUqYiUXx0yhFxwIDAQABo1AwTjAdBgNVHQ4EFgQU/Y0GDN2uPjbyePcu -95ZvYEK/gHIwHwYDVR0jBBgwFoAU/Y0GDN2uPjbyePcu95ZvYEK/gHIwDAYDVR0T -BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAodD6LVCzL3wfsZ6TxTzf9TfgIdbj -ilL3SEMT/xnfTXT3SLYScTRqQIAI29Y7dOLMq89p4hY2wmeUEhBUAz+y9G2JVr8o -6EbxXrQpWgNJogELqoNnMdrDxB5RsmDDKEJ/rLjDfSkjWbK7B2PZsqVTDgjekCFw -u6FqTIjn/O1O/L5tjwxwxjHmQod/maFCvXoDOVBuwdHnkp298tqlvsHfHO8m++Wj -+XYB8plMIjpeTh9v4w9Jc4QZ59lK/3Tt4qaENeQrMEubKSY/Zen7L2bzhk+cChWT -GSGz9uNXieoZaH79D0wnyZaSZ5Ds4ActMevnGg3iYXuzuFqx8Pungn74Vg== ------END CERTIFICATE----- diff -Nru nghttp2-1.13.0/integration-tests/alt-server.key nghttp2-0.6.7/integration-tests/alt-server.key --- nghttp2-1.13.0/integration-tests/alt-server.key 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/alt-server.key 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDQjCEM4YOKkasl -D0ihFLM92RT8iLhomAYoeVeaKfKbjZfRUjchbrVEu84dGUdWZUclCMW4OjbH7LzW -302UODccZRtKnM7OmbpK2K60HtziGt5PkbivRgrJrW6CJ6Y3T6mqMg8labaNWd/j -jx5m9QpEoRD1bQwtmOI2NUYqsqXCjt8iVeDg3f5iLEth98BPU1V3VPpXmPOVuu6P -XmAracaMxD0PWHW329NtPFj6a2TvZpfRjrggTqk8FYsVJIfyjNSJ0OgvcBnDPYmR -6v4AsorwIzi6Gj9E+nJbULTocf4ct0fYyoSMM5E51783PGbrrw6Ar8lYYgTJSpiJ -RfHTKEXHAgMBAAECggEBALTrjFSXY72YB+h7rN+JjMIwDIPUvF6I3HbKZhQpJf6K -xNVkRM2tNHavku0tm/S4ohLf3F+pqRKiL2Udjjjy1+S7VgTRqpwTQ0lhV5aNW8SP -2KMg4R61XfB+k+s4KHu9kYxEJ12mqydPe+r3o0FgfYryTDsOYk1AX6b1aqzqFOGF -7GaqLALSbKU59tcJJ1SZNBbpIKFUrAT9nZt9dW02/foqP5bzUk43Yjw48xmLwegc -bMXXcpZhNZSktltvwRw7Q4Foc9kuRlMdTAnAD9PnMCcZwicS/YeVVF6Rz4fGviKv -7/kPHQ7g4YpFktVDzuZ5xw6GDVFeJ6uGMVUX8+EePvkCgYEA+/nrcn82nFHCxm8Q -0iiUhi/AoXjZg+O5Ytaje9O/YNoX+c4ywe13h0+TXKH79O0KfTwXeJyDgPZbAIFV -9oURellRYUzKDafnBHis2f+Ywn6GqHL5e2X30ZxIp1GK46pcvne1YuvJhgGmiVay -vd7sRx09OKU124dG22rIFCis6asCgYEA0+CsA6LrEwQ/aPJYASY3VHNO/WoAOnPg -Cwsg+02XWsPEwP//lNmpanz8TUm2URS063ZK8bx7t3ejvDgBdsRwwjiMlDp7XTUU -3Zk+mhCV2qkMi02aKemvz29bDhmh5JoH7W3IwsXtJYO0yZDYrDR3ioiKRccioPoE -b/Nq781sEFUCgYEA4xqx9xRpaCLY5nicNI6WrwrDF8YQZisNn+PMnYKP7v8itOgA -H4GkRbSXINpueKZc2dsbXH3UmJtyEdaAYBw3UIrIKmZHhl9afFE3mZQhXssjGxfl -fC6/WZD+eq+n+uJFjPXf6jSSAdHjA828dB1D4CSeVTuyexZF6uUnR+QRVNkCgYEA -i+pb7XLSpZYygY03zFp+Q0h6KyKqz+7hTqmkuA8/GfMZpRHop1UtaWLsAeXhfZ2c -87kEOKptUHSzLYIWhWWnyLorK1+LQ7vf8Y5XJso5C1KDNCKk4XSuYt94U9FddWa6 -QXI0F1s5BYL6Cfma++0R2+va08Vy+rbf40XtojoXWJkCgYEA0hMQSCvok7is27nQ -G80KXfmghU2eEB7zif3T00/fwJycxEbmnNeof+SKmhdY4ZgqTscfOxlQPflV/eqB -xs4GnFDDeM0F8KH0BimOXxr7sJPFCg22PCCQQcRtM/KoU+ip/kNmTfwrsC0xMFPU -HD8M1JCZF2eLMekXXP3cB0U4sUs= ------END PRIVATE KEY----- diff -Nru nghttp2-1.13.0/integration-tests/CMakeLists.txt nghttp2-0.6.7/integration-tests/CMakeLists.txt --- nghttp2-1.13.0/integration-tests/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -set(GO_FILES - nghttpx_http1_test.go - nghttpx_http2_test.go - nghttpx_spdy_test.go - server_tester.go -) - -# XXX unused -set(EXTRA_DIST - ${GO_FILES} - server.key - server.crt - alt-server.key - alt-server.crt - setenv - req-set-header.rb - resp-set-header.rb - req-return.rb - resp-return.rb -) - -add_custom_target(itprep - COMMAND go get -d -v golang.org/x/net/http2 - COMMAND go get -d -v github.com/tatsuhiro-t/go-nghttp2 - COMMAND go get -d -v github.com/tatsuhiro-t/spdy - COMMAND go get -d -v golang.org/x/net/websocket -) - -# 'go test' requires both config.go and the test files in the same directory. -# For out-of-tree builds, config.go is normally not placed next to the source -# files, so copy the tests to the build directory as a workaround. -set(GO_BUILD_FILES) -if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) - foreach(gofile IN LISTS GO_FILES) - set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${gofile}") - add_custom_command(OUTPUT "${outfile}" - COMMAND ${CMAKE_COMMAND} -E copy - "${CMAKE_CURRENT_SOURCE_DIR}/${gofile}" "${outfile}" - DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${gofile}" - ) - list(APPEND GO_BUILD_FILES "${outfile}") - endforeach() -endif() - -add_custom_target(it - COMMAND sh setenv go test -v - DEPENDS ${GO_BUILD_FILES} -) diff -Nru nghttp2-1.13.0/integration-tests/config.go.in nghttp2-0.6.7/integration-tests/config.go.in --- nghttp2-1.13.0/integration-tests/config.go.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/config.go.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -package nghttp2 - -const ( - buildDir = "@top_builddir@" - sourceDir = "@top_srcdir@" -) diff -Nru nghttp2-1.13.0/integration-tests/Makefile.am nghttp2-0.6.7/integration-tests/Makefile.am --- nghttp2-1.13.0/integration-tests/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/Makefile.am 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -# nghttp2 - HTTP/2 C Library - -# Copyright (c) 2015 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. - -GO_FILES = \ - nghttpx_http1_test.go \ - nghttpx_http2_test.go \ - nghttpx_spdy_test.go \ - server_tester.go - -EXTRA_DIST = \ - CMakeLists.txt \ - $(GO_FILES) \ - server.key \ - server.crt \ - alt-server.key \ - alt-server.crt \ - setenv \ - req-set-header.rb \ - resp-set-header.rb \ - req-return.rb \ - resp-return.rb - -itprep: - go get -d -v golang.org/x/net/http2 - go get -d -v github.com/tatsuhiro-t/go-nghttp2 - go get -d -v github.com/tatsuhiro-t/spdy - go get -d -v golang.org/x/net/websocket - -it: - for i in $(GO_FILES); do [ -e $(builddir)/$$i ] || cp $(srcdir)/$$i $(builddir); done - sh setenv go test -v diff -Nru nghttp2-1.13.0/integration-tests/Makefile.in nghttp2-0.6.7/integration-tests/Makefile.in --- nghttp2-1.13.0/integration-tests/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/Makefile.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,564 +0,0 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2014 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# nghttp2 - HTTP/2 C Library - -# Copyright (c) 2015 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. -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -target_triplet = @target@ -subdir = integration-tests -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ - $(top_srcdir)/m4/ax_boost_base.m4 \ - $(top_srcdir)/m4/ax_boost_system.m4 \ - $(top_srcdir)/m4/ax_boost_thread.m4 \ - $(top_srcdir)/m4/ax_check_compile_flag.m4 \ - $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ - $(top_srcdir)/m4/ax_have_epoll.m4 \ - $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = config.go setenv -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.go.in \ - $(srcdir)/setenv.in -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -BOOST_ASIO_LIB = @BOOST_ASIO_LIB@ -BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ -BOOST_LDFLAGS = @BOOST_LDFLAGS@ -BOOST_SYSTEM_LIB = @BOOST_SYSTEM_LIB@ -BOOST_THREAD_LIB = @BOOST_THREAD_LIB@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CUNIT_CFLAGS = @CUNIT_CFLAGS@ -CUNIT_LIBS = @CUNIT_LIBS@ -CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -CYTHON = @CYTHON@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_CXX11 = @HAVE_CXX11@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JANSSON_CFLAGS = @JANSSON_CFLAGS@ -JANSSON_LIBS = @JANSSON_LIBS@ -JEMALLOC_LIBS = @JEMALLOC_LIBS@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ -LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ -LIBSPDYLAY_LIBS = @LIBSPDYLAY_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -PYTHON = @PYTHON@ -PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ -PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ -PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ -VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ -XML2_CONFIG = @XML2_CONFIG@ -XML_CPPFLAGS = @XML_CPPFLAGS@ -XML_LIBS = @XML_LIBS@ -ZLIB_CFLAGS = @ZLIB_CFLAGS@ -ZLIB_LIBS = @ZLIB_LIBS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target = @target@ -target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -GO_FILES = \ - nghttpx_http1_test.go \ - nghttpx_http2_test.go \ - nghttpx_spdy_test.go \ - server_tester.go - -EXTRA_DIST = \ - CMakeLists.txt \ - $(GO_FILES) \ - server.key \ - server.crt \ - alt-server.key \ - alt-server.crt \ - setenv \ - req-set-header.rb \ - resp-set-header.rb \ - req-return.rb \ - resp-return.rb - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu integration-tests/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu integration-tests/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -config.go: $(top_builddir)/config.status $(srcdir)/config.go.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -setenv: $(top_builddir)/config.status $(srcdir)/setenv.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -tags TAGS: - -ctags CTAGS: - -cscope cscopelist: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic clean-libtool \ - cscopelist-am ctags-am distclean distclean-generic \ - distclean-libtool distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags-am uninstall uninstall-am - -.PRECIOUS: Makefile - - -itprep: - go get -d -v golang.org/x/net/http2 - go get -d -v github.com/tatsuhiro-t/go-nghttp2 - go get -d -v github.com/tatsuhiro-t/spdy - go get -d -v golang.org/x/net/websocket - -it: - for i in $(GO_FILES); do [ -e $(builddir)/$$i ] || cp $(srcdir)/$$i $(builddir); done - sh setenv go test -v - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff -Nru nghttp2-1.13.0/integration-tests/nghttpx_http1_test.go nghttp2-0.6.7/integration-tests/nghttpx_http1_test.go --- nghttp2-1.13.0/integration-tests/nghttpx_http1_test.go 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/nghttpx_http1_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,990 +0,0 @@ -package nghttp2 - -import ( - "bufio" - "bytes" - "encoding/json" - "fmt" - "golang.org/x/net/http2/hpack" - "golang.org/x/net/websocket" - "io" - "net/http" - "syscall" - "testing" - "time" -) - -// TestH1H1PlainGET tests whether simple HTTP/1 GET request works. -func TestH1H1PlainGET(t *testing.T) { - st := newServerTester(nil, t, noopHandler) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H1PlainGET", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - want := 200 - if got := res.status; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH1H1PlainGETClose tests whether simple HTTP/1 GET request with -// Connetion: close request header field works. -func TestH1H1PlainGETClose(t *testing.T) { - st := newServerTester(nil, t, noopHandler) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H1PlainGETClose", - header: []hpack.HeaderField{ - pair("Connection", "close"), - }, - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - want := 200 - if got := res.status; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH1H1InvalidMethod tests that server rejects invalid method with -// 501 status code -func TestH1H1InvalidMethod(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward this request") - }) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H1InvalidMethod", - method: "get", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - if got, want := res.status, 501; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH1H1MultipleRequestCL tests that server rejects request which -// contains multiple Content-Length header fields. -func TestH1H1MultipleRequestCL(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward bad request") - }) - defer st.Close() - - if _, err := io.WriteString(st.conn, fmt.Sprintf(`GET / HTTP/1.1 -Host: %v -Test-Case: TestH1H1MultipleRequestCL -Content-Length: 0 -Content-Length: 0 - -`, st.authority)); err != nil { - t.Fatalf("Error io.WriteString() = %v", err) - } - - resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil) - if err != nil { - t.Fatalf("Error http.ReadResponse() = %v", err) - } - - want := 400 - if got := resp.StatusCode; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// // TestH1H1ConnectFailure tests that server handles the situation that -// // connection attempt to HTTP/1 backend failed. -// func TestH1H1ConnectFailure(t *testing.T) { -// st := newServerTester(nil, t, noopHandler) -// defer st.Close() - -// // shutdown backend server to simulate backend connect failure -// st.ts.Close() - -// res, err := st.http1(requestParam{ -// name: "TestH1H1ConnectFailure", -// }) -// if err != nil { -// t.Fatalf("Error st.http1() = %v", err) -// } -// want := 503 -// if got := res.status; got != want { -// t.Errorf("status: %v; want %v", got, want) -// } -// } - -// TestH1H1GracefulShutdown tests graceful shutdown. -func TestH1H1GracefulShutdown(t *testing.T) { - st := newServerTester(nil, t, noopHandler) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H1GracefulShutdown-1", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - - st.cmd.Process.Signal(syscall.SIGQUIT) - time.Sleep(150 * time.Millisecond) - - res, err = st.http1(requestParam{ - name: "TestH1H1GracefulShutdown-2", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - - if got, want := res.connClose, true; got != want { - t.Errorf("res.connClose: %v; want %v", got, want) - } - - want := io.EOF - if _, err := st.conn.Read(nil); err == nil || err != want { - t.Errorf("st.conn.Read(): %v; want %v", err, want) - } -} - -// TestH1H1HostRewrite tests that server rewrites Host header field -func TestH1H1HostRewrite(t *testing.T) { - st := newServerTester([]string{"--host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("request-host", r.Host) - }) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H1HostRewrite", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - if got, want := res.header.Get("request-host"), st.backendHost; got != want { - t.Errorf("request-host: %v; want %v", got, want) - } -} - -// TestH1H1BadHost tests that server rejects request including bad -// characters in host header field. -func TestH1H1BadHost(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward this request") - }) - defer st.Close() - - if _, err := io.WriteString(st.conn, "GET / HTTP/1.1\r\nTest-Case: TestH1H1HBadHost\r\nHost: foo\"bar\r\n\r\n"); err != nil { - t.Fatalf("Error io.WriteString() = %v", err) - } - resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil) - if err != nil { - t.Fatalf("Error http.ReadResponse() = %v", err) - } - if got, want := resp.StatusCode, 400; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH1H1BadAuthority tests that server rejects request including -// bad characters in authority component of requset URI. -func TestH1H1BadAuthority(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward this request") - }) - defer st.Close() - - if _, err := io.WriteString(st.conn, "GET http://foo\"bar/ HTTP/1.1\r\nTest-Case: TestH1H1HBadAuthority\r\nHost: foobar\r\n\r\n"); err != nil { - t.Fatalf("Error io.WriteString() = %v", err) - } - resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil) - if err != nil { - t.Fatalf("Error http.ReadResponse() = %v", err) - } - if got, want := resp.StatusCode, 400; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH1H1BadScheme tests that server rejects request including -// bad characters in scheme component of requset URI. -func TestH1H1BadScheme(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward this request") - }) - defer st.Close() - - if _, err := io.WriteString(st.conn, "GET http*://example.com/ HTTP/1.1\r\nTest-Case: TestH1H1HBadScheme\r\nHost: example.com\r\n\r\n"); err != nil { - t.Fatalf("Error io.WriteString() = %v", err) - } - resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil) - if err != nil { - t.Fatalf("Error http.ReadResponse() = %v", err) - } - if got, want := resp.StatusCode, 400; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH1H1HTTP10 tests that server can accept HTTP/1.0 request -// without Host header field -func TestH1H1HTTP10(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("request-host", r.Host) - }) - defer st.Close() - - if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H1HTTP10\r\n\r\n"); err != nil { - t.Fatalf("Error io.WriteString() = %v", err) - } - - resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil) - if err != nil { - t.Fatalf("Error http.ReadResponse() = %v", err) - } - - if got, want := resp.StatusCode, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - if got, want := resp.Header.Get("request-host"), st.backendHost; got != want { - t.Errorf("request-host: %v; want %v", got, want) - } -} - -// TestH1H1HTTP10NoHostRewrite tests that server generates host header -// field using actual backend server even if --no-http-rewrite is -// used. -func TestH1H1HTTP10NoHostRewrite(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("request-host", r.Host) - }) - defer st.Close() - - if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H1HTTP10NoHostRewrite\r\n\r\n"); err != nil { - t.Fatalf("Error io.WriteString() = %v", err) - } - - resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil) - if err != nil { - t.Fatalf("Error http.ReadResponse() = %v", err) - } - - if got, want := resp.StatusCode, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - if got, want := resp.Header.Get("request-host"), st.backendHost; got != want { - t.Errorf("request-host: %v; want %v", got, want) - } -} - -// TestH1H1RequestTrailer tests request trailer part is forwarded to -// backend. -func TestH1H1RequestTrailer(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - buf := make([]byte, 4096) - for { - _, err := r.Body.Read(buf) - if err == io.EOF { - break - } - if err != nil { - t.Fatalf("r.Body.Read() = %v", err) - } - } - if got, want := r.Trailer.Get("foo"), "bar"; got != want { - t.Errorf("r.Trailer.Get(foo): %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H1RequestTrailer", - body: []byte("1"), - trailer: []hpack.HeaderField{ - pair("foo", "bar"), - }, - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } -} - -// 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) - } -} - -// TestH1H1Websocket tests that HTTP Upgrade to WebSocket works. -func TestH1H1Websocket(t *testing.T) { - st := newServerTesterHandler(nil, t, websocket.Handler(func(ws *websocket.Conn) { - io.Copy(ws, ws) - })) - defer st.Close() - - content := []byte("hello world") - res, err := st.websocket(requestParam{ - name: "TestH1H1Websocket", - body: content, - }) - if err != nil { - t.Fatalf("Error st.websocket() = %v", err) - } - if got, want := res.body, content; !bytes.Equal(got, want) { - t.Errorf("echo: %q; want %q", got, want) - } -} - -// TestH1H1ReqPhaseSetHeader tests mruby request phase hook -// modifies request header fields. -func TestH1H1ReqPhaseSetHeader(t *testing.T) { - st := newServerTester([]string{"--mruby-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("User-Agent"), "mruby"; got != want { - t.Errorf("User-Agent = %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H1ReqPhaseSetHeader", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH1H1ReqPhaseReturn tests mruby request phase hook returns -// custom response. -func TestH1H1ReqPhaseReturn(t *testing.T) { - st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H1ReqPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "20"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from req"; got != want { - t.Errorf("body = %v; want %v", got, want) - } -} - -// TestH1H1RespPhaseSetHeader tests mruby response phase hook modifies -// response header fields. -func TestH1H1RespPhaseSetHeader(t *testing.T) { - st := newServerTester([]string{"--mruby-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H1RespPhaseSetHeader", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - if got, want := res.header.Get("alpha"), "bravo"; got != want { - t.Errorf("alpha = %v; want %v", got, want) - } -} - -// TestH1H1RespPhaseReturn tests mruby response phase hook returns -// custom response. -func TestH1H1RespPhaseReturn(t *testing.T) { - st := newServerTester([]string{"--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H1RespPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "21"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from resp"; got != want { - t.Errorf("body = %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) { -// st := newServerTester([]string{"--http2-bridge"}, t, noopHandler) -// defer st.Close() - -// // simulate backend connect attempt failure -// st.ts.Close() - -// res, err := st.http1(requestParam{ -// name: "TestH1H2ConnectFailure", -// }) -// if err != nil { -// t.Fatalf("Error st.http1() = %v", err) -// } -// want := 503 -// if got := res.status; got != want { -// t.Errorf("status: %v; want %v", got, want) -// } -// } - -// TestH1H2NoHost tests that server rejects request without Host -// header field for HTTP/2 backend. -func TestH1H2NoHost(t *testing.T) { - st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward bad request") - }) - defer st.Close() - - // without Host header field, we expect 400 response - if _, err := io.WriteString(st.conn, "GET / HTTP/1.1\r\nTest-Case: TestH1H2NoHost\r\n\r\n"); err != nil { - t.Fatalf("Error io.WriteString() = %v", err) - } - - resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil) - if err != nil { - t.Fatalf("Error http.ReadResponse() = %v", err) - } - - want := 400 - if got := resp.StatusCode; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH1H2HTTP10 tests that server can accept HTTP/1.0 request -// without Host header field -func TestH1H2HTTP10(t *testing.T) { - st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("request-host", r.Host) - }) - defer st.Close() - - if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H2HTTP10\r\n\r\n"); err != nil { - t.Fatalf("Error io.WriteString() = %v", err) - } - - resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil) - if err != nil { - t.Fatalf("Error http.ReadResponse() = %v", err) - } - - if got, want := resp.StatusCode, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - if got, want := resp.Header.Get("request-host"), st.backendHost; got != want { - t.Errorf("request-host: %v; want %v", got, want) - } -} - -// TestH1H2HTTP10NoHostRewrite tests that server generates host header -// field using actual backend server even if --no-http-rewrite is -// used. -func TestH1H2HTTP10NoHostRewrite(t *testing.T) { - st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("request-host", r.Host) - }) - defer st.Close() - - if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H2HTTP10NoHostRewrite\r\n\r\n"); err != nil { - t.Fatalf("Error io.WriteString() = %v", err) - } - - resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil) - if err != nil { - t.Fatalf("Error http.ReadResponse() = %v", err) - } - - if got, want := resp.StatusCode, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - if got, want := resp.Header.Get("request-host"), st.backendHost; got != want { - t.Errorf("request-host: %v; want %v", got, want) - } -} - -// TestH1H2CrumbleCookie tests that Cookies are crumbled and assembled -// when forwarding to HTTP/2 backend link. go-nghttp2 server -// concatenates crumbled Cookies automatically, so this test is not -// much effective now. -func TestH1H2CrumbleCookie(t *testing.T) { - st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want { - t.Errorf("Cookie: %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H2CrumbleCookie", - header: []hpack.HeaderField{ - pair("Cookie", "alpha; bravo; charlie"), - }, - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH1H2GenerateVia tests that server generates Via header field to and -// from backend server. -func TestH1H2GenerateVia(t *testing.T) { - st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Via"), "1.1 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H2GenerateVia", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.header.Get("Via"), "2 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } -} - -// TestH1H2AppendVia tests that server adds value to existing Via -// header field to and from backend server. -func TestH1H2AppendVia(t *testing.T) { - st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Via"), "foo, 1.1 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } - w.Header().Add("Via", "bar") - }) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H2AppendVia", - header: []hpack.HeaderField{ - pair("via", "foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.header.Get("Via"), "bar, 2 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } -} - -// TestH1H2NoVia tests that server does not add value to existing Via -// header field to and from backend server. -func TestH1H2NoVia(t *testing.T) { - st := newServerTester([]string{"--http2-bridge", "--no-via"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Via"), "foo"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } - w.Header().Add("Via", "bar") - }) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H2NoVia", - header: []hpack.HeaderField{ - pair("via", "foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.header.Get("Via"), "bar"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } -} - -// TestH1H2ReqPhaseReturn tests mruby request phase hook returns -// custom response. -func TestH1H2ReqPhaseReturn(t *testing.T) { - st := newServerTester([]string{"--http2-bridge", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H2ReqPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "20"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from req"; got != want { - t.Errorf("body = %v; want %v", got, want) - } -} - -// TestH1H2RespPhaseReturn tests mruby response phase hook returns -// custom response. -func TestH1H2RespPhaseReturn(t *testing.T) { - st := newServerTester([]string{"--http2-bridge", "--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1H2RespPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "21"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from resp"; got != want { - t.Errorf("body = %v; want %v", got, want) - } -} - -// TestH1APIBackendconfig exercise backendconfig API endpoint routine -// for successful case. -func TestH1APIBackendconfig(t *testing.T) { - st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1APIBackendconfig", - path: "/api/v1beta1/backendconfig", - method: "PUT", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Success"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 200; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestH1APIBackendconfigQuery exercise backendconfig API endpoint -// routine with query. -func TestH1APIBackendconfigQuery(t *testing.T) { - st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1APIBackendconfigQuery", - path: "/api/v1beta1/backendconfig?foo=bar", - method: "PUT", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Success"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 200; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestH1APIBackendconfigBadMethod exercise backendconfig API endpoint -// routine with bad method. -func TestH1APIBackendconfigBadMethod(t *testing.T) { - st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1APIBackendconfigBadMethod", - path: "/api/v1beta1/backendconfig", - method: "GET", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.status, 405; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Failure"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 405; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestH1APINotFound exercise backendconfig API endpoint routine when -// API endpoint is not found. -func TestH1APINotFound(t *testing.T) { - st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1APINotFound", - path: "/api/notfound", - method: "GET", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.status, 404; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Failure"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 404; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestH1Healthmon tests health monitor endpoint. -func TestH1Healthmon(t *testing.T) { - st := newServerTesterConnectPort([]string{"-f127.0.0.1,3011;healthmon;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3011) - defer st.Close() - - res, err := st.http1(requestParam{ - name: "TestH1Healthmon", - path: "/alpha/bravo", - }) - if err != nil { - t.Fatalf("Error st.http1() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } -} - -// TestH1ResponseBeforeRequestEnd tests the situation where response -// ends before request body finishes. -func TestH1ResponseBeforeRequestEnd(t *testing.T) { - st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatal("request should not be forwarded") - }) - defer st.Close() - - if _, err := io.WriteString(st.conn, fmt.Sprintf(`POST / HTTP/1.1 -Host: %v -Test-Case: TestH1ResponseBeforeRequestEnd -Content-Length: 1000000 - -`, st.authority)); err != nil { - t.Fatalf("Error io.WriteString() = %v", err) - } - - resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil) - if err != nil { - t.Fatalf("Error http.ReadResponse() = %v", err) - } - - if got, want := resp.StatusCode, 404; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} diff -Nru nghttp2-1.13.0/integration-tests/nghttpx_http2_test.go nghttp2-0.6.7/integration-tests/nghttpx_http2_test.go --- nghttp2-1.13.0/integration-tests/nghttpx_http2_test.go 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/nghttpx_http2_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,2033 +0,0 @@ -package nghttp2 - -import ( - "crypto/tls" - "encoding/json" - "fmt" - "golang.org/x/net/http2" - "golang.org/x/net/http2/hpack" - "io" - "io/ioutil" - "net/http" - "regexp" - "strings" - "syscall" - "testing" - "time" -) - -// TestH2H1PlainGET tests whether simple HTTP/2 GET request works. -func TestH2H1PlainGET(t *testing.T) { - st := newServerTester(nil, t, noopHandler) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1PlainGET", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - - want := 200 - if res.status != want { - t.Errorf("status = %v; want %v", res.status, want) - } -} - -// TestH2H1AddXff tests that server generates X-Forwarded-For header -// field when forwarding request to backend. -func TestH2H1AddXff(t *testing.T) { - st := newServerTester([]string{"--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) { - xff := r.Header.Get("X-Forwarded-For") - want := "127.0.0.1" - if xff != want { - t.Errorf("X-Forwarded-For = %v; want %v", xff, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1AddXff", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH2H1AddXff2 tests that server appends X-Forwarded-For header -// field to existing one when forwarding request to backend. -func TestH2H1AddXff2(t *testing.T) { - st := newServerTester([]string{"--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) { - xff := r.Header.Get("X-Forwarded-For") - want := "host, 127.0.0.1" - if xff != want { - t.Errorf("X-Forwarded-For = %v; want %v", xff, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1AddXff2", - header: []hpack.HeaderField{ - pair("x-forwarded-for", "host"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH2H1StripXff tests that --strip-incoming-x-forwarded-for -// option. -func TestH2H1StripXff(t *testing.T) { - st := newServerTester([]string{"--strip-incoming-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) { - if xff, found := r.Header["X-Forwarded-For"]; found { - t.Errorf("X-Forwarded-For = %v; want nothing", xff) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1StripXff", - header: []hpack.HeaderField{ - pair("x-forwarded-for", "host"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH2H1StripAddXff tests that --strip-incoming-x-forwarded-for and -// --add-x-forwarded-for options. -func TestH2H1StripAddXff(t *testing.T) { - args := []string{ - "--strip-incoming-x-forwarded-for", - "--add-x-forwarded-for", - } - st := newServerTester(args, t, func(w http.ResponseWriter, r *http.Request) { - xff := r.Header.Get("X-Forwarded-For") - want := "127.0.0.1" - if xff != want { - t.Errorf("X-Forwarded-For = %v; want %v", xff, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1StripAddXff", - header: []hpack.HeaderField{ - pair("x-forwarded-for", "host"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH2H1AddForwardedObfuscated tests that server generates -// Forwarded header field with obfuscated "by" and "for" parameters. -func TestH2H1AddForwardedObfuscated(t *testing.T) { - st := newServerTester([]string{"--add-forwarded=by,for,host,proto"}, t, func(w http.ResponseWriter, r *http.Request) { - pattern := fmt.Sprintf(`by=_[^;]+;for=_[^;]+;host="127\.0\.0\.1:%v";proto=http`, serverPort) - validFwd := regexp.MustCompile(pattern) - got := r.Header.Get("Forwarded") - - if !validFwd.MatchString(got) { - t.Errorf("Forwarded = %v; want pattern %v", got, pattern) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1AddForwardedObfuscated", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H1AddForwardedByIP tests that server generates Forwarded header -// field with IP address in "by" parameter. -func TestH2H1AddForwardedByIP(t *testing.T) { - st := newServerTester([]string{"--add-forwarded=by,for", "--forwarded-by=ip"}, t, func(w http.ResponseWriter, r *http.Request) { - pattern := fmt.Sprintf(`by="127\.0\.0\.1:%v";for=_[^;]+`, serverPort) - validFwd := regexp.MustCompile(pattern) - if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) { - t.Errorf("Forwarded = %v; want pattern %v", got, pattern) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1AddForwardedByIP", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H1AddForwardedForIP tests that server generates Forwarded header -// field with IP address in "for" parameters. -func TestH2H1AddForwardedForIP(t *testing.T) { - st := newServerTester([]string{"--add-forwarded=by,for,host,proto", "--forwarded-by=_alpha", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) { - want := fmt.Sprintf(`by=_alpha;for=127.0.0.1;host="127.0.0.1:%v";proto=http`, serverPort) - if got := r.Header.Get("Forwarded"); got != want { - t.Errorf("Forwarded = %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1AddForwardedForIP", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H1AddForwardedMerge tests that server generates Forwarded -// header field with IP address in "by" and "for" parameters. The -// generated values must be appended to the existing value. -func TestH2H1AddForwardedMerge(t *testing.T) { - st := newServerTester([]string{"--add-forwarded=proto"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Forwarded"), `host=foo, proto=http`; got != want { - t.Errorf("Forwarded = %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1AddForwardedMerge", - header: []hpack.HeaderField{ - pair("forwarded", "host=foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H1AddForwardedStrip tests that server generates Forwarded -// header field with IP address in "by" and "for" parameters. The -// generated values must not include the existing value. -func TestH2H1AddForwardedStrip(t *testing.T) { - st := newServerTester([]string{"--strip-incoming-forwarded", "--add-forwarded=proto"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Forwarded"), `proto=http`; got != want { - t.Errorf("Forwarded = %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1AddForwardedStrip", - header: []hpack.HeaderField{ - pair("forwarded", "host=foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H1StripForwarded tests that server strips incoming Forwarded -// header field. -func TestH2H1StripForwarded(t *testing.T) { - st := newServerTester([]string{"--strip-incoming-forwarded"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, found := r.Header["Forwarded"]; found { - t.Errorf("Forwarded = %v; want nothing", got) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1StripForwarded", - header: []hpack.HeaderField{ - pair("forwarded", "host=foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H1AddForwardedStatic tests that server generates Forwarded -// header field with the given static obfuscated string for "by" -// parameter. -func TestH2H1AddForwardedStatic(t *testing.T) { - st := newServerTester([]string{"--add-forwarded=by,for", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) { - pattern := `by=_alpha;for=_[^;]+` - validFwd := regexp.MustCompile(pattern) - if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) { - t.Errorf("Forwarded = %v; want pattern %v", got, pattern) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1AddForwardedStatic", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H1GenerateVia tests that server generates Via header field to and -// from backend server. -func TestH2H1GenerateVia(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Via"), "2 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1GenerateVia", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.header.Get("Via"), "1.1 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } -} - -// TestH2H1AppendVia tests that server adds value to existing Via -// header field to and from backend server. -func TestH2H1AppendVia(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Via"), "foo, 2 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } - w.Header().Add("Via", "bar") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1AppendVia", - header: []hpack.HeaderField{ - pair("via", "foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.header.Get("Via"), "bar, 1.1 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } -} - -// TestH2H1NoVia tests that server does not add value to existing Via -// header field to and from backend server. -func TestH2H1NoVia(t *testing.T) { - st := newServerTester([]string{"--no-via"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Via"), "foo"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } - w.Header().Add("Via", "bar") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1NoVia", - header: []hpack.HeaderField{ - pair("via", "foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.header.Get("Via"), "bar"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } -} - -// TestH2H1HostRewrite tests that server rewrites host header field -func TestH2H1HostRewrite(t *testing.T) { - st := newServerTester([]string{"--host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("request-host", r.Host) - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1HostRewrite", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - if got, want := res.header.Get("request-host"), st.backendHost; got != want { - t.Errorf("request-host: %v; want %v", got, want) - } -} - -// TestH2H1NoHostRewrite tests that server does not rewrite host -// header field -func TestH2H1NoHostRewrite(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("request-host", r.Host) - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1NoHostRewrite", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - if got, want := res.header.Get("request-host"), st.frontendHost; got != want { - t.Errorf("request-host: %v; want %v", got, want) - } -} - -// TestH2H1BadRequestCL tests that server rejects request whose -// content-length header field value does not match its request body -// size. -func TestH2H1BadRequestCL(t *testing.T) { - st := newServerTester(nil, t, noopHandler) - defer st.Close() - - // we set content-length: 1024, but the actual request body is - // 3 bytes. - res, err := st.http2(requestParam{ - name: "TestH2H1BadRequestCL", - method: "POST", - header: []hpack.HeaderField{ - pair("content-length", "1024"), - }, - body: []byte("foo"), - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - - want := http2.ErrCodeProtocol - if res.errCode != want { - t.Errorf("res.errCode = %v; want %v", res.errCode, want) - } -} - -// TestH2H1BadResponseCL tests that server returns error when -// content-length response header field value does not match its -// response body size. -func TestH2H1BadResponseCL(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - // we set content-length: 1024, but only send 3 bytes. - w.Header().Add("Content-Length", "1024") - w.Write([]byte("foo")) - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1BadResponseCL", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - - want := http2.ErrCodeProtocol - if res.errCode != want { - t.Errorf("res.errCode = %v; want %v", res.errCode, want) - } -} - -// TestH2H1LocationRewrite tests location header field rewriting -// works. -func TestH2H1LocationRewrite(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - // TODO we cannot get st.ts's port number here.. 8443 - // is just a place holder. We ignore it on rewrite. - w.Header().Add("Location", "http://127.0.0.1:8443/p/q?a=b#fragment") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1LocationRewrite", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - - want := fmt.Sprintf("http://127.0.0.1:%v/p/q?a=b#fragment", serverPort) - if got := res.header.Get("Location"); got != want { - t.Errorf("Location: %v; want %v", got, want) - } -} - -// TestH2H1ChunkedRequestBody tests that chunked request body works. -func TestH2H1ChunkedRequestBody(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - want := "[chunked]" - if got := fmt.Sprint(r.TransferEncoding); got != want { - t.Errorf("Transfer-Encoding: %v; want %v", got, want) - } - body, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatalf("Error reading r.body: %v", err) - } - want = "foo" - if got := string(body); got != want { - t.Errorf("body: %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1ChunkedRequestBody", - method: "POST", - body: []byte("foo"), - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH2H1MultipleRequestCL tests that server rejects request with -// multiple Content-Length request header fields. -func TestH2H1MultipleRequestCL(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward bad request") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1MultipleRequestCL", - header: []hpack.HeaderField{ - pair("content-length", "1"), - pair("content-length", "1"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.errCode, http2.ErrCodeProtocol; got != want { - t.Errorf("res.errCode: %v; want %v", got, want) - } -} - -// TestH2H1InvalidRequestCL tests that server rejects request with -// Content-Length which cannot be parsed as a number. -func TestH2H1InvalidRequestCL(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward bad request") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1InvalidRequestCL", - header: []hpack.HeaderField{ - pair("content-length", ""), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.errCode, http2.ErrCodeProtocol; got != want { - t.Errorf("res.errCode: %v; want %v", got, want) - } -} - -// // TestH2H1ConnectFailure tests that server handles the situation that -// // connection attempt to HTTP/1 backend failed. -// func TestH2H1ConnectFailure(t *testing.T) { -// st := newServerTester(nil, t, noopHandler) -// defer st.Close() - -// // shutdown backend server to simulate backend connect failure -// st.ts.Close() - -// res, err := st.http2(requestParam{ -// name: "TestH2H1ConnectFailure", -// }) -// if err != nil { -// t.Fatalf("Error st.http2() = %v", err) -// } -// want := 503 -// if got := res.status; got != want { -// t.Errorf("status: %v; want %v", got, want) -// } -// } - -// TestH2H1InvalidMethod tests that server rejects invalid method with -// 501. -func TestH2H1InvalidMethod(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward this request") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1InvalidMethod", - method: "get", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 501; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H1BadAuthority tests that server rejects request including -// bad characters in :authority header field. -func TestH2H1BadAuthority(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward this request") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1BadAuthority", - authority: `foo\bar`, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.errCode, http2.ErrCodeProtocol; got != want { - t.Errorf("res.errCode: %v; want %v", got, want) - } -} - -// TestH2H1BadScheme tests that server rejects request including -// bad characters in :scheme header field. -func TestH2H1BadScheme(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward this request") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1BadScheme", - scheme: "http*", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.errCode, http2.ErrCodeProtocol; got != want { - t.Errorf("res.errCode: %v; want %v", got, want) - } -} - -// TestH2H1AssembleCookies tests that crumbled cookies in HTTP/2 -// request is assembled into 1 when forwarding to HTTP/1 backend link. -func TestH2H1AssembleCookies(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want { - t.Errorf("Cookie: %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1AssembleCookies", - header: []hpack.HeaderField{ - pair("cookie", "alpha"), - pair("cookie", "bravo"), - pair("cookie", "charlie"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H1TETrailers tests that server accepts TE request header -// field if it has trailers only. -func TestH2H1TETrailers(t *testing.T) { - st := newServerTester(nil, t, noopHandler) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1TETrailers", - header: []hpack.HeaderField{ - pair("te", "trailers"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H1TEGzip tests that server resets stream if TE request header -// field contains gzip. -func TestH2H1TEGzip(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - t.Error("server should not forward bad request") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1TEGzip", - header: []hpack.HeaderField{ - pair("te", "gzip"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.errCode, http2.ErrCodeProtocol; got != want { - t.Errorf("res.errCode = %v; want %v", res.errCode, want) - } -} - -// TestH2H1SNI tests server's TLS SNI extension feature. It must -// choose appropriate certificate depending on the indicated -// server_name from client. -func TestH2H1SNI(t *testing.T) { - st := newServerTesterTLSConfig([]string{"--subcert=" + testDir + "/alt-server.key:" + testDir + "/alt-server.crt"}, t, noopHandler, &tls.Config{ - ServerName: "alt-domain", - }) - defer st.Close() - - tlsConn := st.conn.(*tls.Conn) - connState := tlsConn.ConnectionState() - cert := connState.PeerCertificates[0] - - if got, want := cert.Subject.CommonName, "alt-domain"; got != want { - t.Errorf("CommonName: %v; want %v", got, want) - } -} - -// TestH2H1TLSXfp tests nghttpx sends x-forwarded-proto header field -// with http value since :scheme is http, even if the frontend -// connection is encrypted. -func TestH2H1TLSXfp(t *testing.T) { - st := newServerTesterTLS(nil, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want { - t.Errorf("x-forwarded-proto: want %v; got %v", want, got) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1TLSXfp", - }) - 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) - } -} - -// TestH2H1ServerPush tests server push using Link header field from -// backend server. -func TestH2H1ServerPush(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - // only resources marked as rel=preload are pushed - if !strings.HasPrefix(r.URL.Path, "/css/") { - w.Header().Add("Link", "; rel=preload, , ; rel=preload") - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1ServerPush", - }) - 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) - } - if got, want := len(res.pushResponse), 2; got != want { - t.Fatalf("len(res.pushResponse): %v; want %v", got, want) - } - mainCSS := res.pushResponse[0] - if got, want := mainCSS.status, 200; got != want { - t.Errorf("mainCSS.status: %v; want %v", got, want) - } - themeCSS := res.pushResponse[1] - if got, want := themeCSS.status, 200; got != want { - t.Errorf("themeCSS.status: %v; want %v", got, want) - } -} - -// TestH2H1RequestTrailer tests request trailer part is forwarded to -// backend. -func TestH2H1RequestTrailer(t *testing.T) { - st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { - buf := make([]byte, 4096) - for { - _, err := r.Body.Read(buf) - if err == io.EOF { - break - } - if err != nil { - t.Fatalf("r.Body.Read() = %v", err) - } - } - if got, want := r.Trailer.Get("foo"), "bar"; got != want { - t.Errorf("r.Trailer.Get(foo): %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1RequestTrailer", - body: []byte("1"), - trailer: []hpack.HeaderField{ - pair("foo", "bar"), - }, - }) - 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) - } -} - -// 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) - } -} - -// TestH2H1ReqPhaseSetHeader tests mruby request phase hook -// modifies request header fields. -func TestH2H1ReqPhaseSetHeader(t *testing.T) { - st := newServerTester([]string{"--mruby-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("User-Agent"), "mruby"; got != want { - t.Errorf("User-Agent = %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1ReqPhaseSetHeader", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH2H1ReqPhaseReturn tests mruby request phase hook returns -// custom response. -func TestH2H1ReqPhaseReturn(t *testing.T) { - st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1ReqPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "20"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from req"; got != want { - t.Errorf("body = %v; want %v", got, want) - } -} - -// TestH2H1RespPhaseSetHeader tests mruby response phase hook modifies -// response header fields. -func TestH2H1RespPhaseSetHeader(t *testing.T) { - st := newServerTester([]string{"--mruby-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1RespPhaseSetHeader", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - if got, want := res.header.Get("alpha"), "bravo"; got != want { - t.Errorf("alpha = %v; want %v", got, want) - } -} - -// TestH2H1RespPhaseReturn tests mruby response phase hook returns -// custom response. -func TestH2H1RespPhaseReturn(t *testing.T) { - st := newServerTester([]string{"--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H1RespPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "21"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from resp"; got != want { - t.Errorf("body = %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) - } -} - -// TestH2H1ProxyProtocolV1TCP4 tests PROXY protocol version 1 -// containing TCP4 entry is accepted and X-Forwarded-For contains -// advertised src address. -func TestH2H1ProxyProtocolV1TCP4(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want { - t.Errorf("X-Forwarded-For: %v; want %v", got, want) - } - }) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP4 192.168.0.2 192.168.0.100 12345 8080\r\n")) - - res, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1TCP4", - }) - - 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) - } -} - -// TestH2H1ProxyProtocolV1TCP6 tests PROXY protocol version 1 -// containing TCP6 entry is accepted and X-Forwarded-For contains -// advertised src address. -func TestH2H1ProxyProtocolV1TCP6(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want { - t.Errorf("X-Forwarded-For: %v; want %v", got, want) - } - }) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 2001:0db8:85a3:0000:0000:8a2e:0370:7334 ::1 12345 8080\r\n")) - - res, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1TCP6", - }) - - 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) - } -} - -// TestH2H1ProxyProtocolV1Unknown tests PROXY protocol version 1 -// containing UNKNOWN entry is accepted. -func TestH2H1ProxyProtocolV1Unknown(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, notWant := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got == notWant { - t.Errorf("X-Forwarded-For: %v") - } - }) - defer st.Close() - - st.conn.Write([]byte("PROXY UNKNOWN 192.168.0.2 192.168.0.100 12345 8080\r\n")) - - res, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1Unknown", - }) - - 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) - } -} - -// TestH2H1ProxyProtocolV1JustUnknown tests PROXY protocol version 1 -// containing only "PROXY UNKNOWN" is accepted. -func TestH2H1ProxyProtocolV1JustUnknown(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY UNKNOWN\r\n")) - - res, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1JustUnknown", - }) - - 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) - } -} - -// TestH2H1ProxyProtocolV1TooLongLine tests PROXY protocol version 1 -// line longer than 107 bytes must be rejected -func TestH2H1ProxyProtocolV1TooLongLine(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY UNKNOWN ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 655350\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1TooLongLine", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1BadLineEnd tests that PROXY protocol version -// 1 line ending without \r\n should be rejected. -func TestH2H1ProxyProtocolV1BadLineEnd(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 8080\r \n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1BadLineEnd", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1NoEnd tests that PROXY protocol version 1 -// line containing no \r\n should be rejected. -func TestH2H1ProxyProtocolV1NoEnd(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 8080")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1NoEnd", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1EmbeddedNULL tests that PROXY protocol -// version 1 line containing NULL character should be rejected. -func TestH2H1ProxyProtocolV1EmbeddedNULL(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - b := []byte("PROXY TCP6 ::1*foo ::1 12345 8080\r\n") - b[14] = 0 - st.conn.Write(b) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1EmbeddedNULL", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1MissingSrcPort tests that PROXY protocol -// version 1 line without src port should be rejected. -func TestH2H1ProxyProtocolV1MissingSrcPort(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 ::1 ::1 8080\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1MissingSrcPort", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1MissingDstPort tests that PROXY protocol -// version 1 line without dst port should be rejected. -func TestH2H1ProxyProtocolV1MissingDstPort(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 \r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1MissingDstPort", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1InvalidSrcPort tests that PROXY protocol -// containing invalid src port should be rejected. -func TestH2H1ProxyProtocolV1InvalidSrcPort(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 ::1 ::1 123x 8080\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1InvalidSrcPort", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1InvalidDstPort tests that PROXY protocol -// containing invalid dst port should be rejected. -func TestH2H1ProxyProtocolV1InvalidDstPort(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 ::1 ::1 123456 80x\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1InvalidDstPort", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1LeadingZeroPort tests that PROXY protocol -// version 1 line with non zero port with leading zero should be -// rejected. -func TestH2H1ProxyProtocolV1LeadingZeroPort(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 ::1 ::1 03000 8080\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1LeadingZeroPort", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1TooLargeSrcPort tests that PROXY protocol -// containing too large src port should be rejected. -func TestH2H1ProxyProtocolV1TooLargeSrcPort(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 ::1 ::1 65536 8080\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1TooLargeSrcPort", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1TooLargeDstPort tests that PROXY protocol -// containing too large dst port should be rejected. -func TestH2H1ProxyProtocolV1TooLargeDstPort(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 ::1 ::1 12345 65536\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1TooLargeDstPort", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1InvalidSrcAddr tests that PROXY protocol -// containing invalid src addr should be rejected. -func TestH2H1ProxyProtocolV1InvalidSrcAddr(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 192.168.0.1 ::1 12345 8080\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1InvalidSrcAddr", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1InvalidDstAddr tests that PROXY protocol -// containing invalid dst addr should be rejected. -func TestH2H1ProxyProtocolV1InvalidDstAddr(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY TCP6 ::1 192.168.0.1 12345 8080\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1InvalidDstAddr", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1InvalidProtoFamily tests that PROXY protocol -// containing invalid protocol family should be rejected. -func TestH2H1ProxyProtocolV1InvalidProtoFamily(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PROXY UNIX ::1 ::1 12345 8080\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1InvalidProtoFamily", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1ProxyProtocolV1InvalidID tests that PROXY protocol -// containing invalid PROXY protocol version 1 ID should be rejected. -func TestH2H1ProxyProtocolV1InvalidID(t *testing.T) { - st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler) - defer st.Close() - - st.conn.Write([]byte("PR0XY TCP6 ::1 ::1 12345 8080\r\n")) - - _, err := st.http2(requestParam{ - name: "TestH2H1ProxyProtocolV1InvalidID", - }) - - if err == nil { - t.Fatalf("connection was not terminated") - } -} - -// TestH2H1GracefulShutdown tests graceful shutdown. -func TestH2H1GracefulShutdown(t *testing.T) { - st := newServerTester(nil, t, noopHandler) - defer st.Close() - - fmt.Fprint(st.conn, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n") - if err := st.fr.WriteSettings(); err != nil { - t.Fatalf("st.fr.WriteSettings(): %v", err) - } - - header := []hpack.HeaderField{ - pair(":method", "GET"), - pair(":scheme", "http"), - pair(":authority", st.authority), - pair(":path", "/"), - } - - for _, h := range header { - _ = st.enc.WriteField(h) - } - - if err := st.fr.WriteHeaders(http2.HeadersFrameParam{ - StreamID: 1, - EndStream: false, - EndHeaders: true, - BlockFragment: st.headerBlkBuf.Bytes(), - }); err != nil { - t.Fatalf("st.fr.WriteHeaders(): %v", err) - } - - // send SIGQUIT signal to nghttpx to perform graceful shutdown - st.cmd.Process.Signal(syscall.SIGQUIT) - time.Sleep(150 * time.Millisecond) - - // after signal, finish request body - if err := st.fr.WriteData(1, true, nil); err != nil { - t.Fatalf("st.fr.WriteData(): %v", err) - } - - numGoAway := 0 - - for { - fr, err := st.readFrame() - if err != nil { - if err == io.EOF { - want := 2 - if got := numGoAway; got != want { - t.Fatalf("numGoAway: %v; want %v", got, want) - } - return - } - t.Fatalf("st.readFrame(): %v", err) - } - switch f := fr.(type) { - case *http2.GoAwayFrame: - numGoAway += 1 - want := http2.ErrCodeNo - if got := f.ErrCode; got != want { - t.Fatalf("f.ErrCode(%v): %v; want %v", numGoAway, got, want) - } - switch numGoAway { - case 1: - want := (uint32(1) << 31) - 1 - if got := f.LastStreamID; got != want { - t.Fatalf("f.LastStreamID(%v): %v; want %v", numGoAway, got, want) - } - case 2: - want := uint32(1) - if got := f.LastStreamID; got != want { - t.Fatalf("f.LastStreamID(%v): %v; want %v", numGoAway, got, want) - } - case 3: - t.Fatalf("too many GOAWAYs received") - } - } - } -} - -// TestH2H2MultipleResponseCL tests that server returns error if -// multiple Content-Length response header fields are received. -func TestH2H2MultipleResponseCL(t *testing.T) { - st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("content-length", "1") - w.Header().Add("content-length", "1") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2MultipleResponseCL", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.errCode, http2.ErrCodeInternal; got != want { - t.Errorf("res.errCode: %v; want %v", got, want) - } -} - -// TestH2H2InvalidResponseCL tests that server returns error if -// Content-Length response header field value cannot be parsed as a -// number. -func TestH2H2InvalidResponseCL(t *testing.T) { - st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("content-length", "") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2InvalidResponseCL", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.errCode, http2.ErrCodeInternal; got != want { - t.Errorf("res.errCode: %v; want %v", got, want) - } -} - -// // TestH2H2ConnectFailure tests that server handles the situation that -// // connection attempt to HTTP/2 backend failed. -// func TestH2H2ConnectFailure(t *testing.T) { -// st := newServerTester([]string{"--http2-bridge"}, t, noopHandler) -// defer st.Close() - -// // simulate backend connect attempt failure -// st.ts.Close() - -// res, err := st.http2(requestParam{ -// name: "TestH2H2ConnectFailure", -// }) -// if err != nil { -// t.Fatalf("Error st.http2() = %v", err) -// } -// want := 503 -// if got := res.status; got != want { -// t.Errorf("status: %v; want %v", got, want) -// } -// } - -// TestH2H2HostRewrite tests that server rewrites host header field -func TestH2H2HostRewrite(t *testing.T) { - st := newServerTester([]string{"--http2-bridge", "--host-rewrite"}, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("request-host", r.Host) - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2HostRewrite", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - if got, want := res.header.Get("request-host"), st.backendHost; got != want { - t.Errorf("request-host: %v; want %v", got, want) - } -} - -// TestH2H2NoHostRewrite tests that server does not rewrite host -// header field -func TestH2H2NoHostRewrite(t *testing.T) { - st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("request-host", r.Host) - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2NoHostRewrite", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } - if got, want := res.header.Get("request-host"), st.frontendHost; got != want { - t.Errorf("request-host: %v; want %v", got, want) - } -} - -// TestH2H2TLSXfp tests nghttpx sends x-forwarded-proto header field -// with http value since :scheme is http, even if the frontend -// connection is encrypted. -func TestH2H2TLSXfp(t *testing.T) { - st := newServerTesterTLS([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want { - t.Errorf("x-forwarded-proto: want %v; got %v", want, got) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2TLSXfp", - }) - 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) - } -} - -// TestH2H2AddXff tests that server generates X-Forwarded-For header -// field when forwarding request to backend. -func TestH2H2AddXff(t *testing.T) { - st := newServerTesterTLS([]string{"--http2-bridge", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) { - xff := r.Header.Get("X-Forwarded-For") - want := "127.0.0.1" - if xff != want { - t.Errorf("X-Forwarded-For = %v; want %v", xff, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2AddXff", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH2H2AddXff2 tests that server appends X-Forwarded-For header -// field to existing one when forwarding request to backend. -func TestH2H2AddXff2(t *testing.T) { - st := newServerTesterTLS([]string{"--http2-bridge", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) { - xff := r.Header.Get("X-Forwarded-For") - want := "host, 127.0.0.1" - if xff != want { - t.Errorf("X-Forwarded-For = %v; want %v", xff, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2AddXff2", - header: []hpack.HeaderField{ - pair("x-forwarded-for", "host"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH2H2StripXff tests that --strip-incoming-x-forwarded-for -// option. -func TestH2H2StripXff(t *testing.T) { - st := newServerTesterTLS([]string{"--http2-bridge", "--strip-incoming-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) { - if xff, found := r.Header["X-Forwarded-For"]; found { - t.Errorf("X-Forwarded-For = %v; want nothing", xff) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2StripXff", - header: []hpack.HeaderField{ - pair("x-forwarded-for", "host"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH2H2StripAddXff tests that --strip-incoming-x-forwarded-for and -// --add-x-forwarded-for options. -func TestH2H2StripAddXff(t *testing.T) { - st := newServerTesterTLS([]string{"--http2-bridge", "--strip-incoming-x-forwarded-for", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) { - xff := r.Header.Get("X-Forwarded-For") - want := "127.0.0.1" - if xff != want { - t.Errorf("X-Forwarded-For = %v; want %v", xff, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2StripAddXff", - header: []hpack.HeaderField{ - pair("x-forwarded-for", "host"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestH2H2AddForwarded tests that server generates Forwarded header -// field using static obfuscated "by" parameter. -func TestH2H2AddForwarded(t *testing.T) { - st := newServerTesterTLS([]string{"--http2-bridge", "--add-forwarded=by,for,host,proto", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) { - pattern := fmt.Sprintf(`by=_alpha;for=_[^;]+;host="127\.0\.0\.1:%v";proto=https`, serverPort) - validFwd := regexp.MustCompile(pattern) - if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) { - t.Errorf("Forwarded = %v; want pattern %v", got, pattern) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2AddForwarded", - scheme: "https", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H2AddForwardedMerge tests that server generates Forwarded -// header field using static obfuscated "by" parameter, and -// existing Forwarded header field. -func TestH2H2AddForwardedMerge(t *testing.T) { - st := newServerTesterTLS([]string{"--http2-bridge", "--add-forwarded=by,host,proto", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) { - want := fmt.Sprintf(`host=foo, by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort) - if got := r.Header.Get("Forwarded"); got != want { - t.Errorf("Forwarded = %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2AddForwardedMerge", - scheme: "https", - header: []hpack.HeaderField{ - pair("forwarded", "host=foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H2AddForwardedStrip tests that server generates Forwarded -// header field using static obfuscated "by" parameter, and -// existing Forwarded header field stripped. -func TestH2H2AddForwardedStrip(t *testing.T) { - st := newServerTesterTLS([]string{"--http2-bridge", "--strip-incoming-forwarded", "--add-forwarded=by,host,proto", "--forwarded-by=_alpha"}, t, func(w http.ResponseWriter, r *http.Request) { - want := fmt.Sprintf(`by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort) - if got := r.Header.Get("Forwarded"); got != want { - t.Errorf("Forwarded = %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2AddForwardedStrip", - scheme: "https", - header: []hpack.HeaderField{ - pair("forwarded", "host=foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H2StripForwarded tests that server strips incoming Forwarded -// header field. -func TestH2H2StripForwarded(t *testing.T) { - st := newServerTesterTLS([]string{"--http2-bridge", "--strip-incoming-forwarded"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, found := r.Header["Forwarded"]; found { - t.Errorf("Forwarded = %v; want nothing", got) - } - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2StripForwarded", - scheme: "https", - header: []hpack.HeaderField{ - pair("forwarded", "host=foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestH2H2ReqPhaseReturn tests mruby request phase hook returns -// custom response. -func TestH2H2ReqPhaseReturn(t *testing.T) { - st := newServerTester([]string{"--http2-bridge", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2ReqPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "20"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from req"; got != want { - t.Errorf("body = %v; want %v", got, want) - } -} - -// TestH2H2RespPhaseReturn tests mruby response phase hook returns -// custom response. -func TestH2H2RespPhaseReturn(t *testing.T) { - st := newServerTester([]string{"--http2-bridge", "--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2H2RespPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "21"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from resp"; got != want { - t.Errorf("body = %v; want %v", got, want) - } -} - -// TestH2APIBackendconfig exercise backendconfig API endpoint routine -// for successful case. -func TestH2APIBackendconfig(t *testing.T) { - st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2APIBackendconfig", - path: "/api/v1beta1/backendconfig", - method: "PUT", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - 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) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Success"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 200; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestH2APIBackendconfigQuery exercise backendconfig API endpoint -// routine with query. -func TestH2APIBackendconfigQuery(t *testing.T) { - st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2APIBackendconfigQuery", - path: "/api/v1beta1/backendconfig?foo=bar", - method: "PUT", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - 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) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Success"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 200; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestH2APIBackendconfigBadMethod exercise backendconfig API endpoint -// routine with bad method. -func TestH2APIBackendconfigBadMethod(t *testing.T) { - st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2APIBackendconfigBadMethod", - path: "/api/v1beta1/backendconfig", - method: "GET", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 405; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Failure"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 405; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestH2APINotFound exercise backendconfig API endpoint routine when -// API endpoint is not found. -func TestH2APINotFound(t *testing.T) { - st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2APINotFound", - path: "/api/notfound", - method: "GET", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 404; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Failure"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 404; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestH2Healthmon tests health monitor endpoint. -func TestH2Healthmon(t *testing.T) { - st := newServerTesterConnectPort([]string{"-f127.0.0.1,3011;healthmon;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3011) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2Healthmon", - path: "/alpha/bravo", - }) - 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) - } -} - -// TestH2ResponseBeforeRequestEnd tests the situation where response -// ends before request body finishes. -func TestH2ResponseBeforeRequestEnd(t *testing.T) { - st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatal("request should not be forwarded") - }) - defer st.Close() - - res, err := st.http2(requestParam{ - name: "TestH2ResponseBeforeRequestEnd", - noEndStream: true, - }) - if err != nil { - t.Fatalf("Error st.http2() = %v", err) - } - if got, want := res.status, 404; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } -} diff -Nru nghttp2-1.13.0/integration-tests/nghttpx_spdy_test.go nghttp2-0.6.7/integration-tests/nghttpx_spdy_test.go --- nghttp2-1.13.0/integration-tests/nghttpx_spdy_test.go 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/nghttpx_spdy_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,664 +0,0 @@ -package nghttp2 - -import ( - "encoding/json" - "github.com/tatsuhiro-t/spdy" - "golang.org/x/net/http2/hpack" - "net/http" - "testing" -) - -// TestS3H1PlainGET tests whether simple SPDY GET request works. -func TestS3H1PlainGET(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, noopHandler) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1PlainGET", - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - - want := 200 - if got := res.status; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestS3H1BadRequestCL tests that server rejects request whose -// content-length header field value does not match its request body -// size. -func TestS3H1BadRequestCL(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, noopHandler) - defer st.Close() - - // we set content-length: 1024, but the actual request body is - // 3 bytes. - res, err := st.spdy(requestParam{ - name: "TestS3H1BadRequestCL", - method: "POST", - header: []hpack.HeaderField{ - pair("content-length", "1024"), - }, - body: []byte("foo"), - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - - want := spdy.ProtocolError - if got := res.spdyRstErrCode; got != want { - t.Errorf("res.spdyRstErrCode = %v; want %v", got, want) - } -} - -// TestS3H1MultipleRequestCL tests that server rejects request with -// multiple Content-Length request header fields. -func TestS3H1MultipleRequestCL(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward bad request") - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1MultipleRequestCL", - header: []hpack.HeaderField{ - pair("content-length", "1"), - pair("content-length", "1"), - }, - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - want := 400 - if got := res.status; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestS3H1InvalidRequestCL tests that server rejects request with -// Content-Length which cannot be parsed as a number. -func TestS3H1InvalidRequestCL(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward bad request") - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1InvalidRequestCL", - header: []hpack.HeaderField{ - pair("content-length", ""), - }, - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - want := 400 - if got := res.status; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestS3H1GenerateVia tests that server generates Via header field to and -// from backend server. -func TestS3H1GenerateVia(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Via"), "1.1 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1GenerateVia", - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.header.Get("Via"), "1.1 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } -} - -// TestS3H1AppendVia tests that server adds value to existing Via -// header field to and from backend server. -func TestS3H1AppendVia(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Via"), "foo, 1.1 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } - w.Header().Add("Via", "bar") - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1AppendVia", - header: []hpack.HeaderField{ - pair("via", "foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.header.Get("Via"), "bar, 1.1 nghttpx"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } -} - -// TestS3H1NoVia tests that server does not add value to existing Via -// header field to and from backend server. -func TestS3H1NoVia(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--no-via"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Via"), "foo"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } - w.Header().Add("Via", "bar") - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1NoVia", - header: []hpack.HeaderField{ - pair("via", "foo"), - }, - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.header.Get("Via"), "bar"; got != want { - t.Errorf("Via: %v; want %v", got, want) - } -} - -// 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) - } -} - -// TestS3H1InvalidMethod tests that server rejects invalid method with -// 501. -func TestS3H1InvalidMethod(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward this request") - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1InvalidMethod", - method: "get", - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.status, 501; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestS3H1BadHost tests that server rejects request including bad -// character in :host header field. -func TestS3H1BadHost(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward this request") - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1BadHost", - authority: `foo\bar`, - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.status, 400; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestS3H1BadScheme tests that server rejects request including bad -// character in :scheme header field. -func TestS3H1BadScheme(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Errorf("server should not forward this request") - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1BadScheme", - scheme: `http*`, - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.status, 400; got != want { - t.Errorf("status: %v; want %v", got, want) - } -} - -// TestS3H1ReqPhaseSetHeader tests mruby request phase hook -// modifies request header fields. -func TestS3H1ReqPhaseSetHeader(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("User-Agent"), "mruby"; got != want { - t.Errorf("User-Agent = %v; want %v", got, want) - } - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1ReqPhaseSetHeader", - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } -} - -// TestS3H1ReqPhaseReturn tests mruby request phase hook returns -// custom response. -func TestS3H1ReqPhaseReturn(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1ReqPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "20"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from req"; got != want { - t.Errorf("body = %v; want %v", got, want) - } -} - -// TestS3H1RespPhaseSetHeader tests mruby response phase hook modifies -// response header fields. -func TestS3H1RespPhaseSetHeader(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1RespPhaseSetHeader", - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - - if got, want := res.status, 200; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - if got, want := res.header.Get("alpha"), "bravo"; got != want { - t.Errorf("alpha = %v; want %v", got, want) - } -} - -// TestS3H1RespPhaseReturn tests mruby response phase hook returns -// custom response. -func TestS3H1RespPhaseReturn(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H1RespPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "21"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from resp"; got != want { - t.Errorf("body = %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) { -// st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge"}, t, noopHandler) -// defer st.Close() - -// // simulate backend connect attempt failure -// st.ts.Close() - -// res, err := st.spdy(requestParam{ -// name: "TestS3H2ConnectFailure", -// }) -// if err != nil { -// t.Fatalf("Error st.spdy() = %v", err) -// } -// want := 503 -// if got := res.status; got != want { -// t.Errorf("status: %v; want %v", got, want) -// } -// } - -// TestS3H2ReqPhaseReturn tests mruby request phase hook returns -// custom response. -func TestS3H2ReqPhaseReturn(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H2ReqPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "20"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from req"; got != want { - t.Errorf("body = %v; want %v", got, want) - } -} - -// TestS3H2RespPhaseReturn tests mruby response phase hook returns -// custom response. -func TestS3H2RespPhaseReturn(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge", "--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3H2RespPhaseReturn", - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - - if got, want := res.status, 404; got != want { - t.Errorf("status = %v; want %v", got, want) - } - - hdtests := []struct { - k, v string - }{ - {"content-length", "21"}, - {"from", "mruby"}, - } - for _, tt := range hdtests { - if got, want := res.header.Get(tt.k), tt.v; got != want { - t.Errorf("%v = %v; want %v", tt.k, got, want) - } - } - - if got, want := string(res.body), "Hello World from resp"; got != want { - t.Errorf("body = %v; want %v", got, want) - } -} - -// TestS3APIBackendconfig exercise backendconfig API endpoint routine -// for successful case. -func TestS3APIBackendconfig(t *testing.T) { - st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3APIBackendconfig", - path: "/api/v1beta1/backendconfig", - method: "PUT", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Success"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 200; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestS3APIBackendconfigQuery exercise backendconfig API endpoint -// routine with query. -func TestS3APIBackendconfigQuery(t *testing.T) { - st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3APIBackendconfigQuery", - path: "/api/v1beta1/backendconfig?foo=bar", - method: "PUT", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Success"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 200; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestS3APIBackendconfigBadMethod exercise backendconfig API endpoint -// routine with bad method. -func TestS3APIBackendconfigBadMethod(t *testing.T) { - st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3APIBackendconfigBadMethod", - path: "/api/v1beta1/backendconfig", - method: "GET", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.status, 405; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Failure"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 405; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestS3APINotFound exercise backendconfig API endpoint routine when -// API endpoint is not found. -func TestS3APINotFound(t *testing.T) { - st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3010) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3APINotFound", - path: "/api/notfound", - method: "GET", - body: []byte(`# comment -backend=127.0.0.1,3011 - -`), - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.status, 404; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } - - var apiResp APIResponse - err = json.Unmarshal(res.body, &apiResp) - if err != nil { - t.Fatalf("Error unmarshaling API response: %v", err) - } - if got, want := apiResp.Status, "Failure"; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } - if got, want := apiResp.Code, 404; got != want { - t.Errorf("apiResp.Status: %v; want %v", got, want) - } -} - -// TestS3Healthmon tests health monitor endpoint. -func TestS3Healthmon(t *testing.T) { - st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3011;healthmon"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatalf("request should not be forwarded") - }, 3011) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3Healthmon", - path: "/alpha/bravo", - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.status, 200; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } -} - -// TestS3ResponseBeforeRequestEnd tests the situation where response -// ends before request body finishes. -func TestS3ResponseBeforeRequestEnd(t *testing.T) { - st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { - t.Fatal("request should not be forwarded") - }) - defer st.Close() - - res, err := st.spdy(requestParam{ - name: "TestS3ResponseBeforeRequestEnd", - noEndStream: true, - }) - if err != nil { - t.Fatalf("Error st.spdy() = %v", err) - } - if got, want := res.status, 404; got != want { - t.Errorf("res.status: %v; want %v", got, want) - } -} diff -Nru nghttp2-1.13.0/integration-tests/req-return.rb nghttp2-0.6.7/integration-tests/req-return.rb --- nghttp2-1.13.0/integration-tests/req-return.rb 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/req-return.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -class App - def on_req(env) - resp = env.resp - - resp.clear_headers - resp.status = 404 - resp.add_header "from", "mruby" - resp.return "Hello World from req" - end -end - -App.new diff -Nru nghttp2-1.13.0/integration-tests/req-set-header.rb nghttp2-0.6.7/integration-tests/req-set-header.rb --- nghttp2-1.13.0/integration-tests/req-set-header.rb 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/req-set-header.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -class App - def on_req(env) - env.req.set_header "User-Agent", "mruby" - end -end - -App.new diff -Nru nghttp2-1.13.0/integration-tests/resp-return.rb nghttp2-0.6.7/integration-tests/resp-return.rb --- nghttp2-1.13.0/integration-tests/resp-return.rb 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/resp-return.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -class App - def on_resp(env) - resp = env.resp - - resp.clear_headers - resp.status = 404 - resp.add_header "from", "mruby" - resp.return "Hello World from resp" - end -end - -App.new diff -Nru nghttp2-1.13.0/integration-tests/resp-set-header.rb nghttp2-0.6.7/integration-tests/resp-set-header.rb --- nghttp2-1.13.0/integration-tests/resp-set-header.rb 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/resp-set-header.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -class App - def on_resp(env) - env.resp.set_header "Alpha", "bravo" - end -end - -App.new diff -Nru nghttp2-1.13.0/integration-tests/server.crt nghttp2-0.6.7/integration-tests/server.crt --- nghttp2-1.13.0/integration-tests/server.crt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/server.crt 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDhTCCAm2gAwIBAgIJAOvIx8xIxgyOMA0GCSqGSIb3DQEBCwUAMFkxCzAJBgNV -BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -aWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCTEyNy4wLjAuMTAeFw0xNTAxMjMxMjI0 -MjdaFw0yNTAxMjAxMjI0MjdaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21l -LVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNV -BAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMuI -QZRI/iBaxPTjTWGemt8tCEfzZWxuIW3hY/gIhwJDfH2SbourBh1s9vqcqhBq5vmo -kdfVQXAnNLjIG1uhWmcHuNnKrE5hU82N6i9RsmuM5TQRvhsamHri4G+EXJMu9GqF -Mso8g7MWpRSGKf+8gfjAVNwfCHFiu8oBcMmy3l54MFHgRLSveAMhiPB0e3Xlnpr5 -2bS/oGTx5ynwPgBpEn2FrpT4Z/aLCLzJ/ysgNH8BXEh7n/v7xM3vd5grqB039rd5 -JoxlWvp+4XpzKp5upaqmOcVUq4pDSFUQ3w6C+v33Z3OK6Qaon7GMxLv3Us3b7PZ3 -1CLoWJR2o3OSnUfO/gUCAwEAAaNQME4wHQYDVR0OBBYEFLc5JWPUUVx4GJesogMV -w2Rz0L3yMB8GA1UdIwQYMBaAFLc5JWPUUVx4GJesogMVw2Rz0L3yMAwGA1UdEwQF -MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAP/cJWpM+GEjmVYHFacKTdbXBMox2Xn -QY2NLm00WPOGvKnO7czMFfX/pEmiq71kD45rLLfbaJP205QpxqiAIvhFhuq50Co7 -sTDtwcDTPLX9H7Ugjt4sTMPiwC14uVXFfoT/J46zMjXwP00qKyfszc2tkIgHfrTl -h4M1hkdfmMximir/Ii7TdYYJ3oGS8tdcYb6D4DZwAljKmxF6iUOwFCUgpTmqDBT5 -irXY8D27DzuNN5Pg07rwAlwXLCzrJE10UtO4MmRVXwpzmoaRQD4/tna6bZzdetvs -gPdGP6W1o0q85gullieMJWeKyQA/wasoE7fypn4pHAdTZm/vH+v7GHg= ------END CERTIFICATE----- diff -Nru nghttp2-1.13.0/integration-tests/server.key nghttp2-0.6.7/integration-tests/server.key --- nghttp2-1.13.0/integration-tests/server.key 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/server.key 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLiEGUSP4gWsT0 -401hnprfLQhH82VsbiFt4WP4CIcCQ3x9km6LqwYdbPb6nKoQaub5qJHX1UFwJzS4 -yBtboVpnB7jZyqxOYVPNjeovUbJrjOU0Eb4bGph64uBvhFyTLvRqhTLKPIOzFqUU -hin/vIH4wFTcHwhxYrvKAXDJst5eeDBR4ES0r3gDIYjwdHt15Z6a+dm0v6Bk8ecp -8D4AaRJ9ha6U+Gf2iwi8yf8rIDR/AVxIe5/7+8TN73eYK6gdN/a3eSaMZVr6fuF6 -cyqebqWqpjnFVKuKQ0hVEN8Ogvr992dziukGqJ+xjMS791LN2+z2d9Qi6FiUdqNz -kp1Hzv4FAgMBAAECggEACG26GYP0Ui6wHVwUZkiFLVzWDPS9bIIbDEvbMfhYbvWQ -gDrCLTKF7E4I5FP8jvV+XzRl5cRFE3nsKwLObzr9XWrqcsp73DsXl1mbKx58/ws0 -qrVZZBHz4pLmrHeUxduZ75dYhRuAcLgtWe48awTJdR2x5fO7C8cE89afbxrjLpJE -tVyiw6vVB0GfWTZodxtAFMTX1KVm4bTngXfg0NF1FBNHAX3Cm6t4YCE41hKSc0IQ -Jr3C4e9uj8poze1B17k79bGB8HNMbbc8Ws0sdbxi5xnY+HUA/mYQrmGXo8sdqiYC -EYCMqPm3iJrCmmpHukGf2Vt9k1aLlJ+lxOclSwFO+QKBgQDoRmoprfdmU20LyxYH -eVeVqggqmhNohwnuhIvOAyrWGUkbDsssqx2Vv82z0WHAAkwEvQ984UzaYWCCL3m3 -+JzpF2dz6aKhXIaYnXBlk3STMGUCDT5ysPvsin9z/unzkffh3vrbDBARGFYWG18x -eUyTDOVVeTZNHUJXGjRyiftCkwKBgQDgUkR6dHU4ciSt7Y0UkyAgtZ7POR41T05L -bcxbjJeqm6qlj+oP9WUk7JxeSEFUbrMiROABLPPqTwmGo4xrDRx/e7WrqN6QBKC+ -Y8CfalrKRb0np60x7Mxx0kbmHp5cwv9QDKznKViOYSgKxFrOFZyMAEXQdZ3FvjXF -OQWrw86kBwKBgQDXuxa9MWO3uUJtkqkaNfw/+FVvY/0kt09lJdxHci+l/IQmyl2w -Vhm7TRK7sXvtfvSl7gblgMgFiC2/nGKbmR/7ag5e3R98aVhlhMywuvyp/GfEORLI -KVNChfwMezVFUUx+j8BEFHcTuZuzGqcWZ0fUyER0V4k0pDlKdv9BZqBkWwKBgCdP -o3qGQCilMDJex/OMGPxCd9M+4kFbZZAobMC6cbXPU+dxwgYL7i67XGfVZ8WBJNlj -kpICK7irIzM6JBh6krzwlBTCIkbA2N6kopQNUl3SPOTfKKXwJp/nxs77HKuK7K09 -m2tjPoatFhRU9sjY1rdeMN3oTr7hp5CpfonsZaEvAoGAEPsZcDd4N9ap5bgaeDy9 -NOfLsIyaxT5k6moRIiy83QPihvCuECP16+r6M5tiSfgt/PtCimdjhRiqXzIHNRhh -Nfsv13vUtZgt8cYXuTdI4a8feKI7Q4876ME8Qp3WM5/UNZWq6/sWCuZFqbXUhqM0 -mwNEi5Zddzf8VsSL2gCraQg= ------END PRIVATE KEY----- diff -Nru nghttp2-1.13.0/integration-tests/server_tester.go nghttp2-0.6.7/integration-tests/server_tester.go --- nghttp2-1.13.0/integration-tests/server_tester.go 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/server_tester.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,769 +0,0 @@ -package nghttp2 - -import ( - "bufio" - "bytes" - "crypto/tls" - "errors" - "fmt" - "github.com/tatsuhiro-t/go-nghttp2" - "github.com/tatsuhiro-t/spdy" - "golang.org/x/net/http2" - "golang.org/x/net/http2/hpack" - "golang.org/x/net/websocket" - "io" - "io/ioutil" - "net" - "net/http" - "net/http/httptest" - "net/url" - "os/exec" - "sort" - "strconv" - "strings" - "syscall" - "testing" - "time" -) - -const ( - serverBin = buildDir + "/src/nghttpx" - serverPort = 3009 - testDir = sourceDir + "/integration-tests" - logDir = buildDir + "/integration-tests" -) - -func pair(name, value string) hpack.HeaderField { - return hpack.HeaderField{ - Name: name, - Value: value, - } -} - -type serverTester struct { - args []string // command-line arguments - cmd *exec.Cmd // test frontend server process, which is test subject - url string // test frontend server URL - t *testing.T - ts *httptest.Server // backend server - frontendHost string // frontend server host - backendHost string // backend server host - conn net.Conn // connection to frontend server - h2PrefaceSent bool // HTTP/2 preface was sent in conn - nextStreamID uint32 // next stream ID - fr *http2.Framer // HTTP/2 framer - spdyFr *spdy.Framer // SPDY/3.1 framer - headerBlkBuf bytes.Buffer // buffer to store encoded header block - enc *hpack.Encoder // HTTP/2 HPACK encoder - header http.Header // received header fields - dec *hpack.Decoder // HTTP/2 HPACK decoder - authority string // server's host:port - frCh chan http2.Frame // used for incoming HTTP/2 frame - spdyFrCh chan spdy.Frame // used for incoming SPDY frame - errCh chan error -} - -// newServerTester creates test context for plain TCP frontend -// connection. -func newServerTester(args []string, t *testing.T, handler http.HandlerFunc) *serverTester { - return newServerTesterInternal(args, t, handler, false, serverPort, nil) -} - -func newServerTesterConnectPort(args []string, t *testing.T, handler http.HandlerFunc, port int) *serverTester { - return newServerTesterInternal(args, t, handler, false, port, nil) -} - -func newServerTesterHandler(args []string, t *testing.T, handler http.Handler) *serverTester { - return newServerTesterInternal(args, t, handler, false, serverPort, nil) -} - -// newServerTester creates test context for TLS frontend connection. -func newServerTesterTLS(args []string, t *testing.T, handler http.HandlerFunc) *serverTester { - return newServerTesterInternal(args, t, handler, true, serverPort, nil) -} - -func newServerTesterTLSConnectPort(args []string, t *testing.T, handler http.HandlerFunc, port int) *serverTester { - return newServerTesterInternal(args, t, handler, true, port, nil) -} - -// newServerTester creates test context for TLS frontend connection -// with given clientConfig -func newServerTesterTLSConfig(args []string, t *testing.T, handler http.HandlerFunc, clientConfig *tls.Config) *serverTester { - return newServerTesterInternal(args, t, handler, true, serverPort, clientConfig) -} - -// newServerTesterInternal creates test context. If frontendTLS is -// true, set up TLS frontend connection. connectPort is the server -// side port where client connection is made. -func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handler, frontendTLS bool, connectPort int, clientConfig *tls.Config) *serverTester { - ts := httptest.NewUnstartedServer(handler) - - args := []string{} - - backendTLS := false - for _, k := range src_args { - switch k { - case "--http2-bridge": - backendTLS = true - default: - args = append(args, k) - } - } - if backendTLS { - nghttp2.ConfigureServer(ts.Config, &nghttp2.Server{}) - // According to httptest/server.go, we have to set - // NextProtos separately for ts.TLS. NextProtos set - // in nghttp2.ConfigureServer is effectively ignored. - ts.TLS = new(tls.Config) - ts.TLS.NextProtos = append(ts.TLS.NextProtos, "h2") - ts.StartTLS() - args = append(args, "-k", "--backend-tls") - } else { - ts.Start() - } - scheme := "http" - if frontendTLS { - scheme = "https" - args = append(args, testDir+"/server.key", testDir+"/server.crt") - } - - backendURL, err := url.Parse(ts.URL) - if err != nil { - t.Fatalf("Error parsing URL from httptest.Server: %v", err) - } - - // URL.Host looks like "127.0.0.1:8080", but we want - // "127.0.0.1,8080" - b := "-b" + strings.Replace(backendURL.Host, ":", ",", -1) - if backendTLS { - b += ";;proto=h2;tls" - } - - noTLS := "no-tls" - if frontendTLS { - noTLS = "" - } - - args = append(args, fmt.Sprintf("-f127.0.0.1,%v;%v", serverPort, noTLS), b, - "--errorlog-file="+logDir+"/log.txt", "-LINFO") - - authority := fmt.Sprintf("127.0.0.1:%v", connectPort) - - st := &serverTester{ - cmd: exec.Command(serverBin, args...), - t: t, - ts: ts, - url: fmt.Sprintf("%v://%v", scheme, authority), - frontendHost: fmt.Sprintf("127.0.0.1:%v", serverPort), - backendHost: backendURL.Host, - nextStreamID: 1, - authority: authority, - frCh: make(chan http2.Frame), - spdyFrCh: make(chan spdy.Frame), - errCh: make(chan error), - } - - if err := st.cmd.Start(); err != nil { - st.t.Fatalf("Error starting %v: %v", serverBin, err) - } - - retry := 0 - for { - time.Sleep(50 * time.Millisecond) - - var conn net.Conn - var err error - if frontendTLS { - var tlsConfig *tls.Config - if clientConfig == nil { - tlsConfig = new(tls.Config) - } else { - tlsConfig = clientConfig - } - tlsConfig.InsecureSkipVerify = true - tlsConfig.NextProtos = []string{"h2", "spdy/3.1"} - conn, err = tls.Dial("tcp", authority, tlsConfig) - } else { - conn, err = net.Dial("tcp", authority) - } - if err != nil { - retry += 1 - if retry >= 100 { - st.Close() - st.t.Fatalf("Error server is not responding too long; server command-line arguments may be invalid") - } - continue - } - if frontendTLS { - tlsConn := conn.(*tls.Conn) - cs := tlsConn.ConnectionState() - if !cs.NegotiatedProtocolIsMutual { - st.Close() - st.t.Fatalf("Error negotiated next protocol is not mutual") - } - } - st.conn = conn - break - } - - st.fr = http2.NewFramer(st.conn, st.conn) - spdyFr, err := spdy.NewFramer(st.conn, st.conn) - if err != nil { - st.Close() - st.t.Fatalf("Error spdy.NewFramer: %v", err) - } - st.spdyFr = spdyFr - st.enc = hpack.NewEncoder(&st.headerBlkBuf) - st.dec = hpack.NewDecoder(4096, func(f hpack.HeaderField) { - st.header.Add(f.Name, f.Value) - }) - - return st -} - -func (st *serverTester) Close() { - if st.conn != nil { - st.conn.Close() - } - if st.cmd != nil { - done := make(chan struct{}) - go func() { - st.cmd.Wait() - done <- struct{}{} - }() - - st.cmd.Process.Signal(syscall.SIGQUIT) - - select { - case <-done: - case <-time.After(10 * time.Second): - st.cmd.Process.Kill() - <-done - } - } - if st.ts != nil { - st.ts.Close() - } -} - -func (st *serverTester) readFrame() (http2.Frame, error) { - go func() { - f, err := st.fr.ReadFrame() - if err != nil { - st.errCh <- err - return - } - st.frCh <- f - }() - - select { - case f := <-st.frCh: - return f, nil - case err := <-st.errCh: - return nil, err - case <-time.After(5 * time.Second): - return nil, errors.New("timeout waiting for frame") - } -} - -func (st *serverTester) readSpdyFrame() (spdy.Frame, error) { - go func() { - f, err := st.spdyFr.ReadFrame() - if err != nil { - st.errCh <- err - return - } - st.spdyFrCh <- f - }() - - select { - case f := <-st.spdyFrCh: - return f, nil - case err := <-st.errCh: - return nil, err - case <-time.After(2 * time.Second): - return nil, errors.New("timeout waiting for frame") - } -} - -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 - httpUpgrade bool // true if upgraded to HTTP/2 through HTTP Upgrade - noEndStream bool // true if END_STREAM should not be sent -} - -// wrapper for request body to set trailer part -type chunkedBodyReader struct { - trailer []hpack.HeaderField - trailerWritten bool - body io.Reader - req *http.Request -} - -func (cbr *chunkedBodyReader) Read(p []byte) (n int, err error) { - // document says that we have to set http.Request.Trailer - // after request was sent and before body returns EOF. - if !cbr.trailerWritten { - cbr.trailerWritten = true - for _, h := range cbr.trailer { - cbr.req.Trailer.Set(h.Name, h.Value) - } - } - return cbr.body.Read(p) -} - -func (st *serverTester) websocket(rp requestParam) (*serverResponse, error) { - urlstring := st.url + "/echo" - - config, err := websocket.NewConfig(urlstring, st.url) - if err != nil { - st.t.Fatalf("websocket.NewConfig(%q, %q) returned error: %v", urlstring, st.url, err) - } - - config.Header.Add("Test-Case", rp.name) - for _, h := range rp.header { - config.Header.Add(h.Name, h.Value) - } - - ws, err := websocket.NewClient(config, st.conn) - if err != nil { - st.t.Fatalf("Error creating websocket client: %v", err) - } - - if _, err := ws.Write(rp.body); err != nil { - st.t.Fatalf("ws.Write() returned error: %v", err) - } - - msg := make([]byte, 1024) - var n int - if n, err = ws.Read(msg); err != nil { - st.t.Fatalf("ws.Read() returned error: %v", err) - } - - res := &serverResponse{ - body: msg[:n], - } - - return res, nil -} - -func (st *serverTester) http1(rp requestParam) (*serverResponse, error) { - method := "GET" - if rp.method != "" { - method = rp.method - } - - var body io.Reader - var cbr *chunkedBodyReader - if rp.body != nil { - body = bytes.NewBuffer(rp.body) - if len(rp.trailer) != 0 { - cbr = &chunkedBodyReader{ - trailer: rp.trailer, - body: body, - } - body = cbr - } - } - - 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 = "" - u.RawQuery = "" - reqURL = u.String() + rp.path - } - - req, err := http.NewRequest(method, reqURL, body) - if err != nil { - return nil, err - } - for _, h := range rp.header { - req.Header.Add(h.Name, h.Value) - } - req.Header.Add("Test-Case", rp.name) - if cbr != nil { - cbr.req = req - // this makes request use chunked encoding - req.ContentLength = -1 - req.Trailer = make(http.Header) - for _, h := range cbr.trailer { - req.Trailer.Set(h.Name, "") - } - } - if err := req.Write(st.conn); err != nil { - return nil, err - } - resp, err := http.ReadResponse(bufio.NewReader(st.conn), req) - if err != nil { - return nil, err - } - respBody, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - resp.Body.Close() - - res := &serverResponse{ - status: resp.StatusCode, - header: resp.Header, - body: respBody, - connClose: resp.Close, - } - - return res, nil -} - -func (st *serverTester) spdy(rp requestParam) (*serverResponse, error) { - res := &serverResponse{} - - var id spdy.StreamId - if rp.streamID != 0 { - id = spdy.StreamId(rp.streamID) - if id >= spdy.StreamId(st.nextStreamID) && id%2 == 1 { - st.nextStreamID = uint32(id) + 2 - } - } else { - id = spdy.StreamId(st.nextStreamID) - st.nextStreamID += 2 - } - - method := "GET" - if rp.method != "" { - method = rp.method - } - - scheme := "http" - if rp.scheme != "" { - scheme = rp.scheme - } - - host := st.authority - if rp.authority != "" { - host = rp.authority - } - - path := "/" - if rp.path != "" { - path = rp.path - } - - header := make(http.Header) - header.Add(":method", method) - header.Add(":scheme", scheme) - header.Add(":host", host) - header.Add(":path", path) - header.Add(":version", "HTTP/1.1") - header.Add("test-case", rp.name) - for _, h := range rp.header { - header.Add(h.Name, h.Value) - } - - var synStreamFlags spdy.ControlFlags - if len(rp.body) == 0 && !rp.noEndStream { - synStreamFlags = spdy.ControlFlagFin - } - if err := st.spdyFr.WriteFrame(&spdy.SynStreamFrame{ - CFHeader: spdy.ControlFrameHeader{ - Flags: synStreamFlags, - }, - StreamId: id, - Headers: header, - }); err != nil { - return nil, err - } - - if len(rp.body) != 0 { - var dataFlags spdy.DataFlags - if !rp.noEndStream { - dataFlags = spdy.DataFlagFin - } - if err := st.spdyFr.WriteFrame(&spdy.DataFrame{ - StreamId: id, - Flags: dataFlags, - Data: rp.body, - }); err != nil { - return nil, err - } - } - -loop: - for { - fr, err := st.readSpdyFrame() - if err != nil { - return res, err - } - switch f := fr.(type) { - case *spdy.SynReplyFrame: - if f.StreamId != id { - break - } - res.header = cloneHeader(f.Headers) - if _, err := fmt.Sscan(res.header.Get(":status"), &res.status); err != nil { - return res, fmt.Errorf("Error parsing status code: %v", err) - } - if f.CFHeader.Flags&spdy.ControlFlagFin != 0 { - break loop - } - case *spdy.DataFrame: - if f.StreamId != id { - break - } - res.body = append(res.body, f.Data...) - if f.Flags&spdy.DataFlagFin != 0 { - break loop - } - case *spdy.RstStreamFrame: - if f.StreamId != id { - break - } - res.spdyRstErrCode = f.Status - break loop - case *spdy.GoAwayFrame: - if f.Status == spdy.GoAwayOK { - break - } - res.spdyGoAwayErrCode = f.Status - break loop - } - } - return res, nil -} - -func (st *serverTester) http2(rp requestParam) (*serverResponse, error) { - st.headerBlkBuf.Reset() - st.header = make(http.Header) - - var id uint32 - if rp.streamID != 0 { - id = rp.streamID - if id >= st.nextStreamID && id%2 == 1 { - st.nextStreamID = id + 2 - } - } else { - id = st.nextStreamID - st.nextStreamID += 2 - } - - if !st.h2PrefaceSent { - st.h2PrefaceSent = true - fmt.Fprint(st.conn, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n") - if err := st.fr.WriteSettings(); err != nil { - return nil, err - } - } - - res := &serverResponse{ - streamID: id, - } - - streams := make(map[uint32]*serverResponse) - streams[id] = res - - if !rp.httpUpgrade { - 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 && !rp.noEndStream, - 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.noEndStream, 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() - if err != nil { - return res, err - } - switch f := fr.(type) { - case *http2.HeadersFrame: - _, err := st.dec.Write(f.HeaderBlockFragment()) - if err != nil { - return res, err - } - sr, ok := streams[f.FrameHeader.StreamID] - if !ok { - st.header = make(http.Header) - break - } - sr.header = cloneHeader(st.header) - var status int - status, err = strconv.Atoi(sr.header.Get(":status")) - if err != nil { - return res, fmt.Errorf("Error parsing status code: %v", err) - } - sr.status = status - if f.StreamEnded() { - if streamEnded(res, streams, sr) { - break loop - } - } - case *http2.PushPromiseFrame: - _, err := st.dec.Write(f.HeaderBlockFragment()) - if err != nil { - return res, err - } - sr := &serverResponse{ - streamID: f.PromiseID, - reqHeader: cloneHeader(st.header), - } - streams[sr.streamID] = sr - case *http2.DataFrame: - sr, ok := streams[f.FrameHeader.StreamID] - if !ok { - break - } - sr.body = append(sr.body, f.Data()...) - if f.StreamEnded() { - if streamEnded(res, streams, sr) { - break loop - } - } - case *http2.RSTStreamFrame: - sr, ok := streams[f.FrameHeader.StreamID] - if !ok { - break - } - sr.errCode = f.ErrCode - if streamEnded(res, streams, sr) { - break loop - } - case *http2.GoAwayFrame: - if f.ErrCode == http2.ErrCodeNo { - break - } - res.errCode = f.ErrCode - res.connErr = true - break loop - case *http2.SettingsFrame: - if f.IsAck() { - break - } - if err := st.fr.WriteSettingsAck(); err != nil { - return res, err - } - } - } - sort.Sort(ByStreamID(res.pushResponse)) - return res, nil -} - -func streamEnded(mainSr *serverResponse, streams map[uint32]*serverResponse, sr *serverResponse) bool { - delete(streams, sr.streamID) - if mainSr.streamID != sr.streamID { - mainSr.pushResponse = append(mainSr.pushResponse, sr) - } - return len(streams) == 0 -} - -type serverResponse struct { - status int // HTTP status code - header http.Header // response header fields - body []byte // response body - streamID uint32 // stream ID in HTTP/2 - errCode http2.ErrCode // error code received in HTTP/2 RST_STREAM or GOAWAY - connErr bool // true if HTTP/2 connection error - spdyGoAwayErrCode spdy.GoAwayStatus // status code received in SPDY RST_STREAM - spdyRstErrCode spdy.RstStreamStatus // status code received in SPDY GOAWAY - connClose bool // Conection: close is included in response header in HTTP/1 test - reqHeader http.Header // http request header, currently only sotres pushed request header - pushResponse []*serverResponse // pushed response -} - -type ByStreamID []*serverResponse - -func (b ByStreamID) Len() int { - return len(b) -} - -func (b ByStreamID) Swap(i, j int) { - b[i], b[j] = b[j], b[i] -} - -func (b ByStreamID) Less(i, j int) bool { - return b[i].streamID < b[j].streamID -} - -func cloneHeader(h http.Header) http.Header { - h2 := make(http.Header, len(h)) - for k, vv := range h { - vv2 := make([]string, len(vv)) - copy(vv2, vv) - h2[k] = vv2 - } - return h2 -} - -func noopHandler(w http.ResponseWriter, r *http.Request) {} - -type APIResponse struct { - Status string `json:"status,omitempty"` - Code int `json:"code,omitempty"` -} diff -Nru nghttp2-1.13.0/integration-tests/setenv nghttp2-0.6.7/integration-tests/setenv --- nghttp2-1.13.0/integration-tests/setenv 2016-07-21 13:48:06.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/setenv 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#!/bin/sh -e - -libdir="/mnt/nghttp2/lib" -if [ -d "$libdir/.libs" ]; then - libdir="$libdir/.libs" -fi - -export CGO_CFLAGS="-I/mnt/nghttp2/lib/includes -I/mnt/nghttp2/lib/includes" -export CGO_LDFLAGS="-L$libdir" -export LD_LIBRARY_PATH="$libdir" -export GODEBUG=cgocheck=0 -"$@" diff -Nru nghttp2-1.13.0/integration-tests/setenv.in nghttp2-0.6.7/integration-tests/setenv.in --- nghttp2-1.13.0/integration-tests/setenv.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/integration-tests/setenv.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -#!/bin/sh -e - -libdir="@abs_top_builddir@/lib" -if [ -d "$libdir/.libs" ]; then - libdir="$libdir/.libs" -fi - -export CGO_CFLAGS="-I@abs_top_srcdir@/lib/includes -I@abs_top_builddir@/lib/includes" -export CGO_LDFLAGS="-L$libdir" -export LD_LIBRARY_PATH="$libdir" -export GODEBUG=cgocheck=0 -"$@" diff -Nru nghttp2-1.13.0/lib/CMakeLists.txt nghttp2-0.6.7/lib/CMakeLists.txt --- nghttp2-1.13.0/lib/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -add_subdirectory(includes) - -include_directories( - "${CMAKE_CURRENT_SOURCE_DIR}/includes" - "${CMAKE_CURRENT_BINARY_DIR}/includes" -) - -add_definitions(-DBUILDING_NGHTTP2) - -set(NGHTTP2_SOURCES - 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_rcbuf.c -) - -# Public shared library -add_library(nghttp2 SHARED ${NGHTTP2_SOURCES}) -set_target_properties(nghttp2 PROPERTIES - COMPILE_FLAGS "${WARNCFLAGS}" - VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION} - C_VISIBILITY_PRESET hidden -) - -if(HAVE_CUNIT) - # Static library (for unittests because of symbol visibility) - add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES}) - set_target_properties(nghttp2_static PROPERTIES - COMPILE_FLAGS "${WARNCFLAGS}" - VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION} - ARCHIVE_OUTPUT_NAME nghttp2 - ) - target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB") -endif() - -install(TARGETS nghttp2 - DESTINATION "${CMAKE_INSTALL_LIBDIR}") - -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") diff -Nru nghttp2-1.13.0/lib/includes/CMakeLists.txt nghttp2-0.6.7/lib/includes/CMakeLists.txt --- nghttp2-1.13.0/lib/includes/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/includes/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -install(FILES - nghttp2/nghttp2.h - "${CMAKE_CURRENT_BINARY_DIR}/nghttp2/nghttp2ver.h" - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/nghttp2") diff -Nru nghttp2-1.13.0/lib/includes/Makefile.am nghttp2-0.6.7/lib/includes/Makefile.am --- nghttp2-1.13.0/lib/includes/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/includes/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -20,7 +20,4 @@ # 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. - -EXTRA_DIST = CMakeLists.txt - nobase_include_HEADERS = nghttp2/nghttp2.h nghttp2/nghttp2ver.h diff -Nru nghttp2-1.13.0/lib/includes/Makefile.in nghttp2-0.6.7/lib/includes/Makefile.in --- nghttp2-1.13.0/lib/includes/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/lib/includes/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -29,26 +29,8 @@ # 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. - VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -113,6 +95,8 @@ host_triplet = @host@ target_triplet = @target@ subdir = lib/includes +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(nobase_include_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -122,14 +106,11 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(nobase_include_HEADERS) \ - $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -201,12 +182,10 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -225,7 +204,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -241,7 +219,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -257,10 +234,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -272,7 +245,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -310,11 +282,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -369,7 +340,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -382,7 +352,14 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -EXTRA_DIST = CMakeLists.txt + +# 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. nobase_include_HEADERS = nghttp2/nghttp2.h nghttp2/nghttp2ver.h all: all-am @@ -399,6 +376,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/includes/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/includes/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -648,8 +626,6 @@ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-nobase_includeHEADERS -.PRECIOUS: Makefile - # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru nghttp2-1.13.0/lib/includes/nghttp2/nghttp2.h nghttp2-0.6.7/lib/includes/nghttp2/nghttp2.h --- nghttp2-1.13.0/lib/includes/nghttp2/nghttp2.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/includes/nghttp2/nghttp2.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,76 +25,29 @@ #ifndef NGHTTP2_H #define NGHTTP2_H -/* Define WIN32 when build target is Win32 API (borrowed from - libcurl) */ -#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -#define WIN32 -#endif - #ifdef __cplusplus extern "C" { #endif #include -#if defined(_MSC_VER) && (_MSC_VER < 1800) -/* MSVC < 2013 does not have inttypes.h because it is not C99 - compliant. See compiler macros and version number in - https://sourceforge.net/p/predef/wiki/Compilers/ */ #include -#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ -#include -#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ #include #include -#ifdef NGHTTP2_STATICLIB -#define NGHTTP2_EXTERN -#elif defined(WIN32) -#ifdef BUILDING_NGHTTP2 -#define NGHTTP2_EXTERN __declspec(dllexport) -#else /* !BUILDING_NGHTTP2 */ -#define NGHTTP2_EXTERN __declspec(dllimport) -#endif /* !BUILDING_NGHTTP2 */ -#else /* !defined(WIN32) */ -#ifdef BUILDING_NGHTTP2 -#define NGHTTP2_EXTERN __attribute__((visibility("default"))) -#else /* !BUILDING_NGHTTP2 */ -#define NGHTTP2_EXTERN -#endif /* !BUILDING_NGHTTP2 */ -#endif /* !defined(WIN32) */ - /** * @macro * * The protocol version identification string of this library * supports. This identifier is used if HTTP/2 is used over TLS. */ -#define NGHTTP2_PROTO_VERSION_ID "h2" +#define NGHTTP2_PROTO_VERSION_ID "h2-14" /** * @macro * * The length of :macro:`NGHTTP2_PROTO_VERSION_ID`. */ -#define NGHTTP2_PROTO_VERSION_ID_LEN 2 - -/** - * @macro - * - * The serialized form of ALPN protocol identifier this library - * supports. Notice that first byte is the length of following - * protocol identifier. This is the same wire format of `TLS ALPN - * extension `_. This is useful - * to process incoming ALPN tokens in wire format. - */ -#define NGHTTP2_PROTO_ALPN "\x2h2" - -/** - * @macro - * - * The length of :macro:`NGHTTP2_PROTO_ALPN`. - */ -#define NGHTTP2_PROTO_ALPN_LEN (sizeof(NGHTTP2_PROTO_ALPN) - 1) +#define NGHTTP2_PROTO_VERSION_ID_LEN 5 /** * @macro @@ -103,14 +56,14 @@ * supports. This identifier is used if HTTP/2 is used over cleartext * TCP. */ -#define NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "h2c" +#define NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "h2c-14" /** * @macro * * The length of :macro:`NGHTTP2_CLEARTEXT_PROTO_VERSION_ID`. */ -#define NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN 3 +#define NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN 6 struct nghttp2_session; /** @@ -209,17 +162,32 @@ /** * @macro * - * The client magic string, which is the first 24 bytes byte string of - * client connection preface. + * The client connection preface. + */ +#define NGHTTP2_CLIENT_CONNECTION_PREFACE "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" + +/** + * @macro + * + * The length of :macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`. + */ +#define NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN 24 + +/** + * @macro + * + * The client connection header. This macro is obsoleted by + * NGHTTP2_CLIENT_CONNECTION_PREFACE. */ -#define NGHTTP2_CLIENT_MAGIC "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" +#define NGHTTP2_CLIENT_CONNECTION_HEADER NGHTTP2_CLIENT_CONNECTION_PREFACE /** * @macro * - * The length of :macro:`NGHTTP2_CLIENT_MAGIC`. + * The length of :macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`. */ -#define NGHTTP2_CLIENT_MAGIC_LEN 24 +#define NGHTTP2_CLIENT_CONNECTION_HEADER_LEN \ + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN /** * @enum @@ -233,7 +201,7 @@ */ NGHTTP2_ERR_INVALID_ARGUMENT = -501, /** - * Out of buffer space. + * Ouf of buffer space. */ NGHTTP2_ERR_BUFFER_ERROR = -502, /** @@ -241,9 +209,8 @@ */ NGHTTP2_ERR_UNSUPPORTED_VERSION = -503, /** - * Used as a return value from :type:`nghttp2_send_callback`, - * :type:`nghttp2_recv_callback` and - * :type:`nghttp2_send_data_callback` to indicate that the operation + * Used as a return value from :type:`nghttp2_send_callback` and + * :type:`nghttp2_recv_callback` to indicate that the operation * would block. */ NGHTTP2_ERR_WOULDBLOCK = -504, @@ -354,39 +321,11 @@ */ NGHTTP2_ERR_PUSH_DISABLED = -528, /** - * DATA or HEADERS frame for a given stream has been already - * submitted and has not been fully processed yet. Application - * should wait for the transmission of the previously submitted - * frame before submitting another. + * DATA frame for a given stream has been already submitted and has + * not been fully processed yet. */ NGHTTP2_ERR_DATA_EXIST = -529, /** - * The current session is closing due to a connection error or - * `nghttp2_session_terminate_session()` is called. - */ - NGHTTP2_ERR_SESSION_CLOSING = -530, - /** - * Invalid HTTP header field was received and stream is going to be - * closed. - */ - NGHTTP2_ERR_HTTP_HEADER = -531, - /** - * Violation in HTTP messaging rule. - */ - NGHTTP2_ERR_HTTP_MESSAGING = -532, - /** - * Stream was refused. - */ - NGHTTP2_ERR_REFUSED_STREAM = -533, - /** - * Unexpected internal error, but recovered. - */ - NGHTTP2_ERR_INTERNAL = -534, - /** - * Indicates that a processing was canceled. - */ - NGHTTP2_ERR_CANCEL = -535, - /** * The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is * under unexpected condition and processing was terminated (e.g., * out of memory). If application receives this error code, it must @@ -404,71 +343,13 @@ */ NGHTTP2_ERR_CALLBACK_FAILURE = -902, /** - * Invalid client magic (see :macro:`NGHTTP2_CLIENT_MAGIC`) was - * received and further processing is not possible. - */ - NGHTTP2_ERR_BAD_CLIENT_MAGIC = -903, - /** - * Possible flooding by peer was detected in this HTTP/2 session. - * Flooding is measured by how many PING and SETTINGS frames with - * ACK flag set are queued for transmission. These frames are - * response for the peer initiated frames, and peer can cause memory - * exhaustion on server side to send these frames forever and does - * not read network. + * Invalid connection preface was received and further processing is + * not possible. */ - NGHTTP2_ERR_FLOODED = -904 + NGHTTP2_ERR_BAD_PREFACE = -903 } nghttp2_error; /** - * @struct - * - * The object representing single contiguous buffer. - */ -typedef struct { - /** - * The pointer to the buffer. - */ - uint8_t *base; - /** - * The length of the buffer. - */ - size_t len; -} nghttp2_vec; - -struct nghttp2_rcbuf; - -/** - * @struct - * - * The object representing reference counted buffer. The details of - * this structure are intentionally hidden from the public API. - */ -typedef struct nghttp2_rcbuf nghttp2_rcbuf; - -/** - * @function - * - * Increments the reference count of |rcbuf| by 1. - */ -NGHTTP2_EXTERN void nghttp2_rcbuf_incref(nghttp2_rcbuf *rcbuf); - -/** - * @function - * - * Decrements the reference count of |rcbuf| by 1. If the reference - * count becomes zero, the object pointed by |rcbuf| will be freed. - * In this case, application must not use |rcbuf| again. - */ -NGHTTP2_EXTERN void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf); - -/** - * @function - * - * Returns the underlying buffer managed by |rcbuf|. - */ -NGHTTP2_EXTERN nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf); - -/** * @enum * * The flags for header field name/value pair. @@ -479,23 +360,9 @@ */ NGHTTP2_NV_FLAG_NONE = 0, /** - * Indicates that this name/value pair must not be indexed ("Literal - * Header Field never Indexed" representation must be used in HPACK - * encoding). Other implementation calls this bit as "sensitive". - */ - NGHTTP2_NV_FLAG_NO_INDEX = 0x01, - /** - * This flag is set solely by application. If this flag is set, the - * library does not make a copy of header field name. This could - * improve performance. - */ - NGHTTP2_NV_FLAG_NO_COPY_NAME = 0x02, - /** - * This flag is set solely by application. If this flag is set, the - * library does not make a copy of header field value. This could - * improve performance. + * Indicates that this name/value pair must not be indexed. */ - NGHTTP2_NV_FLAG_NO_COPY_VALUE = 0x04 + NGHTTP2_NV_FLAG_NO_INDEX = 0x01 } nghttp2_nv_flag; /** @@ -505,37 +372,21 @@ */ typedef struct { /** - * The |name| byte string. If this struct is presented from library - * (e.g., :type:`nghttp2_on_frame_recv_callback`), |name| is - * guaranteed to be NULL-terminated. For some callbacks - * (:type:`nghttp2_before_frame_send_callback`, - * :type:`nghttp2_on_frame_send_callback`, and - * :type:`nghttp2_on_frame_not_send_callback`), it may not be - * NULL-terminated if header field is passed from application with - * the flag :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`). When application - * is constructing this struct, |name| is not required to be - * NULL-terminated. + * The |name| byte string, which is not necessarily ``NULL`` + * terminated. */ uint8_t *name; /** - * The |value| byte string. If this struct is presented from - * library (e.g., :type:`nghttp2_on_frame_recv_callback`), |value| - * is guaranteed to be NULL-terminated. For some callbacks - * (:type:`nghttp2_before_frame_send_callback`, - * :type:`nghttp2_on_frame_send_callback`, and - * :type:`nghttp2_on_frame_not_send_callback`), it may not be - * NULL-terminated if header field is passed from application with - * the flag :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE`). When - * application is constructing this struct, |value| is not required - * to be NULL-terminated. + * The |value| byte string, which is not necessarily ``NULL`` + * terminated. */ uint8_t *value; /** - * The length of the |name|, excluding terminating NULL. + * The length of the |name|. */ size_t namelen; /** - * The length of the |value|, excluding terminating NULL. + * The length of the |value|. */ size_t valuelen; /** @@ -587,17 +438,25 @@ */ NGHTTP2_WINDOW_UPDATE = 0x08, /** - * The CONTINUATION frame. This frame type won't be passed to any - * callbacks because the library processes this frame type and its - * preceding HEADERS/PUSH_PROMISE as a single frame. + * The CONTINUATION frame. */ - NGHTTP2_CONTINUATION = 0x09, + NGHTTP2_CONTINUATION = 0x09 +} nghttp2_frame_type; + +/** + * @enum + * + * The extension frame types. + * + * TODO: The assigned frame types were carried from draft-12, and now + * actually TBD. + */ +typedef enum { /** - * The ALTSVC frame, which is defined in `RFC 7383 - * `_. + * The ALTSVC extension frame. */ - NGHTTP2_ALTSVC = 0x0a -} nghttp2_frame_type; + NGHTTP2_EXT_ALTSVC = 0x0a +} nghttp2_ext_frame_type; /** * @enum @@ -667,16 +526,7 @@ /** * @macro - * - * Default maximum number of incoming concurrent streams. Use - * `nghttp2_submit_settings()` with - * :enum:`NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS` to change the - * maximum number of incoming concurrent streams. - * - * .. note:: - * - * The maximum number of outgoing concurrent streams is 100 by - * default. + * Default maximum concurrent streams. */ #define NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1) @@ -802,19 +652,7 @@ /** * Indicates EOF was sensed. */ - NGHTTP2_DATA_FLAG_EOF = 0x01, - /** - * Indicates that END_STREAM flag must not be set even if - * NGHTTP2_DATA_FLAG_EOF is set. Usually this flag is used to send - * trailer fields with `nghttp2_submit_request()` or - * `nghttp2_submit_response()`. - */ - NGHTTP2_DATA_FLAG_NO_END_STREAM = 0x02, - /** - * Indicates that application will send complete DATA frame in - * :type:`nghttp2_send_data_callback`. - */ - NGHTTP2_DATA_FLAG_NO_COPY = 0x04 + NGHTTP2_DATA_FLAG_EOF = 0x01 } nghttp2_data_flag; /** @@ -827,30 +665,6 @@ * them in |buf| and return number of data stored in |buf|. If EOF is * reached, set :enum:`NGHTTP2_DATA_FLAG_EOF` flag in |*data_flags|. * - * Sometime it is desirable to avoid copying data into |buf| and let - * application to send data directly. To achieve this, set - * :enum:`NGHTTP2_DATA_FLAG_NO_COPY` to |*data_flags| (and possibly - * other flags, just like when we do copy), and return the number of - * bytes to send without copying data into |buf|. The library, seeing - * :enum:`NGHTTP2_DATA_FLAG_NO_COPY`, will invoke - * :type:`nghttp2_send_data_callback`. The application must send - * complete DATA frame in that callback. - * - * If this callback is set by `nghttp2_submit_request()`, - * `nghttp2_submit_response()` or `nghttp2_submit_headers()` and - * `nghttp2_submit_data()` with flag parameter - * :enum:`NGHTTP2_FLAG_END_STREAM` set, and - * :enum:`NGHTTP2_DATA_FLAG_EOF` flag is set to |*data_flags|, DATA - * frame will have END_STREAM flag set. Usually, this is expected - * behaviour and all are fine. One exception is send trailer fields. - * You cannot send trailer fields after sending frame with END_STREAM - * set. To avoid this problem, one can set - * :enum:`NGHTTP2_DATA_FLAG_NO_END_STREAM` along with - * :enum:`NGHTTP2_DATA_FLAG_EOF` to signal the library not to set - * END_STREAM in DATA frame. Then application can use - * `nghttp2_submit_trailer()` to send trailer fields. - * `nghttp2_submit_trailer()` can be called inside this callback. - * * If the application wants to postpone DATA frames (e.g., * asynchronous I/O, or reading data blocks for long time), it is * achieved by returning :enum:`NGHTTP2_ERR_DEFERRED` without reading @@ -907,9 +721,9 @@ * * The category of HEADERS, which indicates the role of the frame. In * HTTP/2 spec, request, response, push response and other arbitrary - * headers (e.g., trailer fields) are all called just HEADERS. To - * give the application the role of incoming HEADERS frame, we define - * several categories. + * headers (e.g., trailers) are all called just HEADERS. To give the + * application the role of incoming HEADERS frame, we define several + * categories. */ typedef enum { /** @@ -1176,13 +990,53 @@ * The pointer to extension payload. The exact pointer type is * determined by hd.type. * - * Currently, no extension is supported. This is a place holder for - * the future extensions. + * If hd.type == :enum:`NGHTTP2_EXT_ALTSVC`, it is a pointer to + * :type:`nghttp2_ext_altsvc`. */ void *payload; } nghttp2_extension; /** + * @struct + * + * The ALTSVC extension frame payload. It has following members: + */ +typedef struct { + /** + * Protocol ID + */ + uint8_t *protocol_id; + /** + * Host + */ + uint8_t *host; + /** + * Origin + */ + uint8_t *origin; + /** + * The length of |protocol_id| + */ + size_t protocol_id_len; + /** + * The length of |host| + */ + size_t host_len; + /** + * The length of |origin| + */ + size_t origin_len; + /** + * Max-Age + */ + uint32_t max_age; + /** + * Port + */ + uint16_t port; +} nghttp2_ext_altsvc; + +/** * @union * * This union includes all frames to pass them to various function @@ -1256,15 +1110,6 @@ * * To set this callback to :type:`nghttp2_session_callbacks`, use * `nghttp2_session_callbacks_set_send_callback()`. - * - * .. note:: - * - * The |length| may be very small. If that is the case, and - * application disables Nagle algorithm (``TCP_NODELAY``), then just - * writing |data| to the network stack leads to very small packet, - * and it is very inefficient. An application should be responsible - * to buffer up small chunks of data as necessary to avoid this - * situation. */ typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session, const uint8_t *data, size_t length, @@ -1273,51 +1118,6 @@ /** * @functypedef * - * Callback function invoked when :enum:`NGHTTP2_DATA_FLAG_NO_COPY` is - * used in :type:`nghttp2_data_source_read_callback` to send complete - * DATA frame. - * - * The |frame| is a DATA frame to send. The |framehd| is the - * serialized frame header (9 bytes). The |length| is the length of - * application data to send (this does not include padding). The - * |source| is the same pointer passed to - * :type:`nghttp2_data_source_read_callback`. - * - * The application first must send frame header |framehd| of length 9 - * bytes. If ``frame->data.padlen > 0``, send 1 byte of value - * ``frame->data.padlen - 1``. Then send exactly |length| bytes of - * application data. Finally, if ``frame->data.padlen > 1``, send - * ``frame->data.padlen - 1`` bytes of zero as padding. - * - * The application has to send complete DATA frame in this callback. - * If all data were written successfully, return 0. - * - * If it cannot send any data at all, just return - * :enum:`NGHTTP2_ERR_WOULDBLOCK`; the library will call this callback - * with the same parameters later (It is recommended to send complete - * DATA frame at once in this function to deal with error; if partial - * frame data has already sent, it is impossible to send another data - * in that state, and all we can do is tear down connection). When - * data is fully processed, but application wants to make - * `nghttp2_session_mem_send()` or `nghttp2_session_send()` return - * immediately without processing next frames, return - * :enum:`NGHTTP2_ERR_PAUSE`. If application decided to reset this - * stream, return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`, then - * the library will send RST_STREAM with INTERNAL_ERROR as error code. - * The application can also return - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, which will result in - * connection closure. Returning any other value is treated as - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. - */ -typedef int (*nghttp2_send_data_callback)(nghttp2_session *session, - nghttp2_frame *frame, - const uint8_t *framehd, size_t length, - nghttp2_data_source *source, - void *user_data); - -/** - * @functypedef - * * Callback function invoked when |session| wants to receive data from * the remote peer. The implementation of this function must read at * most |length| bytes of data and store it in |buf|. The |flags| is @@ -1346,10 +1146,10 @@ /** * @functypedef * - * Callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when a frame is received. The - * |user_data| pointer is the third argument passed in to the call to - * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. + * Callback function invoked by `nghttp2_session_recv()` when a frame + * is received. The |user_data| pointer is the third argument passed + * in to the call to `nghttp2_session_client_new()` or + * `nghttp2_session_server_new()`. * * If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen`` * member of their data structure are always ``NULL`` and 0 @@ -1384,14 +1184,14 @@ /** * @functypedef * - * Callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when an invalid non-DATA frame is - * received. The error is indicated by the |lib_error_code|, which is - * one of the values defined in :type:`nghttp2_error`. When this - * callback function is invoked, the library automatically submits - * either RST_STREAM or GOAWAY frame. The |user_data| pointer is the - * third argument passed in to the call to - * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`. + * Callback function invoked by `nghttp2_session_recv()` when an + * invalid non-DATA frame is received. The |error_code| indicates the + * error. It is usually one of the :enum:`nghttp2_error_code` but + * that is not guaranteed. When this callback function is invoked, + * the library automatically submits either RST_STREAM or GOAWAY + * frame. The |user_data| pointer is the third argument passed in to + * the call to `nghttp2_session_client_new()` or + * `nghttp2_session_server_new()`. * * If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen`` * member of their data structure are always ``NULL`` and 0 @@ -1399,14 +1199,14 @@ * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions + * `nghttp2_session_recv()` and `nghttp2_session_send()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use * `nghttp2_session_callbacks_set_on_invalid_frame_recv_callback()`. */ typedef int (*nghttp2_on_invalid_frame_recv_callback)( - nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code, + nghttp2_session *session, const nghttp2_frame *frame, uint32_t error_code, void *user_data); /** @@ -1432,7 +1232,7 @@ * region included in the input bytes. * * The implementation of this function must return 0 if it succeeds. - * If nonzero is returned, it is treated as fatal error, and + * If nonzero is returned, it is treated as fatal error and * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * @@ -1454,19 +1254,9 @@ * `nghttp2_session_server_new()`. * * The implementation of this function must return 0 if it succeeds. - * It can also return :enum:`NGHTTP2_ERR_CANCEL` to cancel the - * transmission of the given frame. - * - * If there is a fatal error while executing this callback, the - * implementation should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, - * which makes `nghttp2_session_send()` and - * `nghttp2_session_mem_send()` functions immediately return - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. - * - * If the other value is returned, it is treated as if - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. But the - * implementation should not rely on this since the library may define - * new return value to extend its capability. + * If nonzero is returned, it is treated as fatal error and + * `nghttp2_session_recv()` and `nghttp2_session_send()` functions + * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use * `nghttp2_session_callbacks_set_before_frame_send_callback()`. @@ -1484,7 +1274,7 @@ * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions + * `nghttp2_session_recv()` and `nghttp2_session_send()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use @@ -1506,12 +1296,9 @@ * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions + * `nghttp2_session_recv()` and `nghttp2_session_send()` functions * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * - * `nghttp2_session_get_stream_user_data()` can be used to get - * associated data. - * * To set this callback to :type:`nghttp2_session_callbacks`, use * `nghttp2_session_callbacks_set_on_frame_not_send_callback()`. */ @@ -1536,9 +1323,8 @@ * * The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and - * `nghttp2_session_recv()`, `nghttp2_session_mem_recv()`, - * `nghttp2_session_send()`, and `nghttp2_session_mem_send()` - * functions immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * `nghttp2_session_recv()` and `nghttp2_session_send()` functions + * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use * `nghttp2_session_callbacks_set_on_stream_close_callback()`. @@ -1561,45 +1347,11 @@ * not need to care about that because the header name/value pairs are * emitted transparently regardless of CONTINUATION frames. * - * The server applications probably create an object to store - * information about new stream if ``frame->hd.type == - * NGHTTP2_HEADERS`` and ``frame->headers.cat == - * NGHTTP2_HCAT_REQUEST``. If |session| is configured as server side, - * ``frame->headers.cat`` is either ``NGHTTP2_HCAT_REQUEST`` - * containing request headers or ``NGHTTP2_HCAT_HEADERS`` containing - * trailer fields and never get PUSH_PROMISE in this callback. - * - * For the client applications, ``frame->hd.type`` is either - * ``NGHTTP2_HEADERS`` or ``NGHTTP2_PUSH_PROMISE``. In case of - * ``NGHTTP2_HEADERS``, ``frame->headers.cat == - * NGHTTP2_HCAT_RESPONSE`` means that it is the first response - * headers, but it may be non-final response which is indicated by 1xx - * status code. In this case, there may be zero or more HEADERS frame - * with ``frame->headers.cat == NGHTTP2_HCAT_HEADERS`` which has - * non-final response code and finally client gets exactly one HEADERS - * frame with ``frame->headers.cat == NGHTTP2_HCAT_HEADERS`` - * containing final response headers (non-1xx status code). The - * trailer fields also has ``frame->headers.cat == - * NGHTTP2_HCAT_HEADERS`` which does not contain any status code. - * - * Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close - * the stream (promised stream if frame is PUSH_PROMISE) by issuing - * RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. In this case, - * :type:`nghttp2_on_header_callback` and - * :type:`nghttp2_on_frame_recv_callback` will not be invoked. If a - * different error code is desirable, use - * `nghttp2_submit_rst_stream()` with a desired error code and then - * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Again, use - * ``frame->push_promise.promised_stream_id`` as stream_id parameter - * in `nghttp2_submit_rst_stream()` if frame is PUSH_PROMISE. - * - * The implementation of this function must return 0 if it succeeds. - * It can return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` to - * reset the stream (promised stream if frame is PUSH_PROMISE). For - * critical errors, it must return - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the other value is - * returned, it is treated as if :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` - * is returned. If :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, + * The implementation of this function must return 0 if it succeeds or + * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If nonzero value other than + * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, it is treated as + * if :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. If + * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, * `nghttp2_session_mem_recv()` function will immediately return * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * @@ -1620,8 +1372,7 @@ * * If :enum:`NGHTTP2_NV_FLAG_NO_INDEX` is set in |flags|, the receiver * must not index this name/value pair when forwarding it to the next - * hop. More specifically, "Literal Header Field never Indexed" - * representation must be used in HPACK encoding. + * hop. * * When this callback is invoked, ``frame->hd.type`` is either * :enum:`NGHTTP2_HEADERS` or :enum:`NGHTTP2_PUSH_PROMISE`. After all @@ -1631,18 +1382,21 @@ * :type:`nghttp2_on_frame_recv_callback` for the |frame| will not be * invoked. * - * Both |name| and |value| are guaranteed to be NULL-terminated. The - * |namelen| and |valuelen| do not include terminal NULL. If - * `nghttp2_option_set_no_http_messaging()` is used with nonzero - * value, NULL character may be included in |name| or |value| before - * terminating NULL. - * - * Please note that unless `nghttp2_option_set_no_http_messaging()` is - * used, nghttp2 library does perform validation against the |name| - * and the |value| using `nghttp2_check_header_name()` and - * `nghttp2_check_header_value()`. In addition to this, nghttp2 - * performs validation based on HTTP Messaging rule, which is briefly - * explained in :ref:`http-messaging` section. + * The |name| may be ``NULL`` if the |namelen| is 0. The same thing + * can be said about the |value|. + * + * Please note that nghttp2 library does not perform any validity + * check against the |name| and the |value|. For example, the + * |namelen| could be 0, and/or the |value| contains ``0x0a`` or + * ``0x0d``. The application must check them if it matters. The + * helper function `nghttp2_check_header_name()` and + * `nghttp2_check_header_value()` provide simple validation against + * HTTP2 header field construction rule. + * + * HTTP/2 specification requires that pseudo header fields (header + * field starting with ':') must appear in front of regular header + * fields. The library does not validate this requirement. The + * application must check them if it matters. * * If the application uses `nghttp2_session_mem_recv()`, it can return * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()` @@ -1654,15 +1408,12 @@ * included in the input bytes. * * Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close - * the stream (promised stream if frame is PUSH_PROMISE) by issuing - * RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. In this case, - * :type:`nghttp2_on_header_callback` and + * the stream by issuing RST_STREAM with + * :enum:`NGHTTP2_INTERNAL_ERROR`. In this case, * :type:`nghttp2_on_frame_recv_callback` will not be invoked. If a * different error code is desirable, use * `nghttp2_submit_rst_stream()` with a desired error code and then - * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Again, use - * ``frame->push_promise.promised_stream_id`` as stream_id parameter - * in `nghttp2_submit_rst_stream()` if frame is PUSH_PROMISE. + * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. * * The implementation of this function must return 0 if it succeeds. * It may return :enum:`NGHTTP2_ERR_PAUSE` or @@ -1676,14 +1427,6 @@ * * To set this callback to :type:`nghttp2_session_callbacks`, use * `nghttp2_session_callbacks_set_on_header_callback()`. - * - * .. warning:: - * - * Application should properly limit the total buffer size to store - * incoming header fields. Without it, peer may send large number - * of header fields or large header fields to cause out of memory in - * local endpoint. Due to how HPACK works, peer can do this - * effectively without using much memory on their own. */ typedef int (*nghttp2_on_header_callback)(nghttp2_session *session, const nghttp2_frame *frame, @@ -1694,32 +1437,6 @@ /** * @functypedef * - * Callback function invoked when a header name/value pair is received - * for the |frame|. The |name| is header name. The |value| is header - * value. The |flags| is bitwise OR of one or more of - * :type:`nghttp2_nv_flag`. - * - * This callback behaves like :type:`nghttp2_on_header_callback`, - * except that |name| and |value| are stored in reference counted - * buffer. If application wishes to keep these references without - * copying them, use `nghttp2_rcbuf_incref()` to increment their - * reference count. It is the application's responsibility to call - * `nghttp2_rcbuf_decref()` if they called `nghttp2_rcbuf_incref()` so - * as not to leak memory. If the |session| is created by - * `nghttp2_session_server_new3()` or `nghttp2_session_client_new3()`, - * the function to free memory is the one belongs to the mem - * parameter. As long as this free function alives, |name| and - * |value| can live after |session| was destroyed. - */ -typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session, - const nghttp2_frame *frame, - nghttp2_rcbuf *name, - nghttp2_rcbuf *value, uint8_t flags, - void *user_data); - -/** - * @functypedef - * * Callback function invoked when the library asks application how * many padding bytes are required for the transmission of the * |frame|. The application must choose the total length of payload @@ -1728,8 +1445,8 @@ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Returning * ``frame->hd.length`` means no padding is added. Returning * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will make - * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. + * `nghttp2_session_send()` function immediately return + * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. * * To set this callback to :type:`nghttp2_session_callbacks`, use * `nghttp2_session_callbacks_set_select_padding_callback()`. @@ -1794,124 +1511,6 @@ const nghttp2_frame_hd *hd, void *user_data); -/** - * @functypedef - * - * Callback function invoked when chunk of extension frame payload is - * received. The |hd| points to frame header. The received - * chunk is |data| of length |len|. - * - * The implementation of this function must return 0 if it succeeds. - * - * To abort processing this extension frame, return - * :enum:`NGHTTP2_ERR_CANCEL`. - * - * If fatal error occurred, application should return - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the - * other values are returned, currently they are treated as - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. - */ -typedef int (*nghttp2_on_extension_chunk_recv_callback)( - nghttp2_session *session, const nghttp2_frame_hd *hd, const uint8_t *data, - size_t len, void *user_data); - -/** - * @functypedef - * - * Callback function invoked when library asks the application to - * unpack extension payload from its wire format. The extension - * payload has been passed to the application using - * :type:`nghttp2_on_extension_chunk_recv_callback`. The frame header - * is already unpacked by the library and provided as |hd|. - * - * To receive extension frames, the application must tell desired - * extension frame type to the library using - * `nghttp2_option_set_user_recv_extension_type()`. - * - * The implementation of this function may store the pointer to the - * created object as a result of unpacking in |*payload|, and returns - * 0. The pointer stored in |*payload| is opaque to the library, and - * the library does not own its pointer. |*payload| is initialized as - * ``NULL``. The |*payload| is available as ``frame->ext.payload`` in - * :type:`nghttp2_on_frame_recv_callback`. Therefore if application - * can free that memory inside :type:`nghttp2_on_frame_recv_callback` - * callback. Of course, application has a liberty not ot use - * |*payload|, and do its own mechanism to process extension frames. - * - * To abort processing this extension frame, return - * :enum:`NGHTTP2_ERR_CANCEL`. - * - * If fatal error occurred, application should return - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions - * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the - * other values are returned, currently they are treated as - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. - */ -typedef int (*nghttp2_unpack_extension_callback)(nghttp2_session *session, - void **payload, - const nghttp2_frame_hd *hd, - void *user_data); - -/** - * @functypedef - * - * Callback function invoked when library asks the application to pack - * extension payload in its wire format. The frame header will be - * packed by library. Application must pack payload only. - * ``frame->ext.payload`` is the object passed to - * `nghttp2_submit_extension()` as payload parameter. Application - * must pack extension payload to the |buf| of its capacity |len| - * bytes. The |len| is at least 16KiB. - * - * The implementation of this function should return the number of - * bytes written into |buf| when it succeeds. - * - * To abort processing this extension frame, return - * :enum:`NGHTTP2_ERR_CANCEL`, and - * :type:`nghttp2_on_frame_not_send_callback` will be invoked. - * - * If fatal error occurred, application should return - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions - * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the - * other values are returned, currently they are treated as - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the return value is - * strictly larger than |len|, it is treated as - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. - */ -typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session, - uint8_t *buf, size_t len, - const nghttp2_frame *frame, - void *user_data); - -/** - * @functypedef - * - * Callback function invoked when library provides the error message - * intended for human consumption. This callback is solely for - * debugging purpose. The |msg| is typically NULL-terminated string - * of length |len|. |len| does not include the sentinel NULL - * character. - * - * The format of error message may change between nghttp2 library - * versions. The application should not depend on the particular - * format. - * - * Normally, application should return 0 from this callback. If fatal - * error occurred while doing something in this callback, application - * should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case, - * library will return immediately with return value - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Currently, if nonzero value - * is returned from this callback, they are treated as - * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, but application should not - * rely on this details. - */ -typedef int (*nghttp2_error_callback)(nghttp2_session *session, const char *msg, - size_t len, void *user_data); - struct nghttp2_session_callbacks; /** @@ -1939,8 +1538,7 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int -nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr); +int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr); /** * @function @@ -1948,8 +1546,7 @@ * Frees any resources allocated for |callbacks|. If |callbacks| is * ``NULL``, this function does nothing. */ -NGHTTP2_EXTERN void -nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks); +void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks); /** * @function @@ -1959,7 +1556,7 @@ * uses solely `nghttp2_session_mem_send()` to serialize data to * transmit. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_callback( +void nghttp2_session_callbacks_set_send_callback( nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback); /** @@ -1970,28 +1567,26 @@ * application uses solely `nghttp2_session_mem_recv()` to process * received data. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_recv_callback( +void nghttp2_session_callbacks_set_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback); /** * @function * - * Sets callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when a frame is received. + * Sets callback function invoked by `nghttp2_session_recv()` when a + * frame is received. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_recv_callback( +void nghttp2_session_callbacks_set_on_frame_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_on_frame_recv_callback on_frame_recv_callback); /** * @function * - * Sets callback function invoked by `nghttp2_session_recv()` and - * `nghttp2_session_mem_recv()` when an invalid non-DATA frame is - * received. + * Sets callback function invoked by `nghttp2_session_recv()` when an + * invalid non-DATA frame is received. */ -NGHTTP2_EXTERN void -nghttp2_session_callbacks_set_on_invalid_frame_recv_callback( +void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback); @@ -2001,7 +1596,7 @@ * Sets callback function invoked when a chunk of data in DATA frame * is received. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_data_chunk_recv_callback( +void nghttp2_session_callbacks_set_on_data_chunk_recv_callback( nghttp2_session_callbacks *cbs, nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback); @@ -2010,7 +1605,7 @@ * * Sets callback function invoked before a non-DATA frame is sent. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_before_frame_send_callback( +void nghttp2_session_callbacks_set_before_frame_send_callback( nghttp2_session_callbacks *cbs, nghttp2_before_frame_send_callback before_frame_send_callback); @@ -2019,7 +1614,7 @@ * * Sets callback function invoked after a frame is sent. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_send_callback( +void nghttp2_session_callbacks_set_on_frame_send_callback( nghttp2_session_callbacks *cbs, nghttp2_on_frame_send_callback on_frame_send_callback); @@ -2029,7 +1624,7 @@ * Sets callback function invoked when a non-DATA frame is not sent * because of an error. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_not_send_callback( +void nghttp2_session_callbacks_set_on_frame_not_send_callback( nghttp2_session_callbacks *cbs, nghttp2_on_frame_not_send_callback on_frame_not_send_callback); @@ -2038,7 +1633,7 @@ * * Sets callback function invoked when the stream is closed. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_stream_close_callback( +void nghttp2_session_callbacks_set_on_stream_close_callback( nghttp2_session_callbacks *cbs, nghttp2_on_stream_close_callback on_stream_close_callback); @@ -2048,7 +1643,7 @@ * Sets callback function invoked when the reception of header block * in HEADERS or PUSH_PROMISE is started. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_begin_headers_callback( +void nghttp2_session_callbacks_set_on_begin_headers_callback( nghttp2_session_callbacks *cbs, nghttp2_on_begin_headers_callback on_begin_headers_callback); @@ -2056,24 +1651,11 @@ * @function * * Sets callback function invoked when a header name/value pair is - * received. If both - * `nghttp2_session_callbacks_set_on_header_callback()` and - * `nghttp2_session_callbacks_set_on_header_callback2()` are used to - * set callbacks, the latter has the precedence. - */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback( - nghttp2_session_callbacks *cbs, - nghttp2_on_header_callback on_header_callback); - -/** - * @function - * - * Sets callback function invoked when a header name/value pair is * received. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback2( +void nghttp2_session_callbacks_set_on_header_callback( nghttp2_session_callbacks *cbs, - nghttp2_on_header_callback2 on_header_callback2); + nghttp2_on_header_callback on_header_callback); /** * @function @@ -2082,7 +1664,7 @@ * how many padding bytes are required for the transmission of the * given frame. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_select_padding_callback( +void nghttp2_session_callbacks_set_select_padding_callback( nghttp2_session_callbacks *cbs, nghttp2_select_padding_callback select_padding_callback); @@ -2092,8 +1674,7 @@ * Sets callback function determine the length allowed in * :type:`nghttp2_data_source_read_callback`. */ -NGHTTP2_EXTERN void -nghttp2_session_callbacks_set_data_source_read_length_callback( +void nghttp2_session_callbacks_set_data_source_read_length_callback( nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback data_source_read_length_callback); @@ -2102,343 +1683,94 @@ * * Sets callback function invoked when a frame header is received. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_begin_frame_callback( +void nghttp2_session_callbacks_set_on_begin_frame_callback( nghttp2_session_callbacks *cbs, nghttp2_on_begin_frame_callback on_begin_frame_callback); -/** - * @function - * - * Sets callback function invoked when - * :enum:`NGHTTP2_DATA_FLAG_NO_COPY` is used in - * :type:`nghttp2_data_source_read_callback` to avoid data copy. - */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_data_callback( - nghttp2_session_callbacks *cbs, - nghttp2_send_data_callback send_data_callback); +struct nghttp2_option; /** - * @function + * @struct * - * Sets callback function invoked when the library asks the - * application to pack extension frame payload in wire format. + * Configuration options for :type:`nghttp2_session`. The details of + * this structure are intentionally hidden from the public API. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_pack_extension_callback( - nghttp2_session_callbacks *cbs, - nghttp2_pack_extension_callback pack_extension_callback); +typedef struct nghttp2_option nghttp2_option; /** * @function * - * Sets callback function invoked when the library asks the - * application to unpack extension frame payload from wire format. + * Initializes |*option_ptr| with default values. + * + * When the application finished using this object, it can use + * `nghttp2_option_del()` to free its memory. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`NGHTTP2_ERR_NOMEM` + * Out of memory. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_unpack_extension_callback( - nghttp2_session_callbacks *cbs, - nghttp2_unpack_extension_callback unpack_extension_callback); +int nghttp2_option_new(nghttp2_option **option_ptr); /** * @function * - * Sets callback function invoked when chunk of extension frame - * payload is received. + * Frees any resources allocated for |option|. If |option| is + * ``NULL``, this function does nothing. */ -NGHTTP2_EXTERN void -nghttp2_session_callbacks_set_on_extension_chunk_recv_callback( - nghttp2_session_callbacks *cbs, - nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback); +void nghttp2_option_del(nghttp2_option *option); /** * @function * - * Sets callback function invoked when library tells error message to - * the application. + * This option prevents the library from sending WINDOW_UPDATE for a + * connection automatically. If this option is set to nonzero, the + * library won't send WINDOW_UPDATE for DATA until application calls + * `nghttp2_session_consume()` to indicate the consumed amount of + * data. Don't use `nghttp2_submit_window_update()` for this purpose. + * By default, this option is set to zero. */ -NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback( - nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback); +void nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val); /** - * @functypedef + * @function * - * Custom memory allocator to replace malloc(). The |mem_user_data| - * is the mem_user_data member of :type:`nghttp2_mem` structure. + * This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of + * remote endpoint as if it is received in SETTINGS frame. Without + * specifying this option, before the local endpoint receives + * SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote + * endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may + * cause problem if local endpoint submits lots of requests initially + * and sending them at once to the remote peer may lead to the + * rejection of some requests. Specifying this option to the sensible + * value, say 100, may avoid this kind of issue. This value will be + * overwritten if the local endpoint receives + * SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint. */ -typedef void *(*nghttp2_malloc)(size_t size, void *mem_user_data); +void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option, + uint32_t val); /** - * @functypedef + * @function * - * Custom memory allocator to replace free(). The |mem_user_data| is - * the mem_user_data member of :type:`nghttp2_mem` structure. - */ -typedef void (*nghttp2_free)(void *ptr, void *mem_user_data); - -/** - * @functypedef + * By default, nghttp2 library only handles HTTP/2 frames and does not + * recognize first 24 bytes of client connection preface. This design + * choice is done due to the fact that server may want to detect the + * application protocol based on first few bytes on clear text + * communication. But for simple servers which only speak HTTP/2, it + * is easier for developers if nghttp2 library takes care of client + * connection preface. * - * Custom memory allocator to replace calloc(). The |mem_user_data| - * is the mem_user_data member of :type:`nghttp2_mem` structure. + * If this option is used with nonzero |val|, nghttp2 library checks + * first 24 bytes client connection preface. If it is not a valid + * one, `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` will + * return error :enum:`NGHTTP2_ERR_BAD_PREFACE`, which is fatal error. */ -typedef void *(*nghttp2_calloc)(size_t nmemb, size_t size, void *mem_user_data); +void nghttp2_option_set_recv_client_preface(nghttp2_option *option, int val); /** - * @functypedef - * - * Custom memory allocator to replace realloc(). The |mem_user_data| - * is the mem_user_data member of :type:`nghttp2_mem` structure. - */ -typedef void *(*nghttp2_realloc)(void *ptr, size_t size, void *mem_user_data); - -/** - * @struct - * - * Custom memory allocator functions and user defined pointer. The - * |mem_user_data| member is passed to each allocator function. This - * can be used, for example, to achieve per-session memory pool. - * - * In the following example code, ``my_malloc``, ``my_free``, - * ``my_calloc`` and ``my_realloc`` are the replacement of the - * standard allocators ``malloc``, ``free``, ``calloc`` and - * ``realloc`` respectively:: - * - * void *my_malloc_cb(size_t size, void *mem_user_data) { - * return my_malloc(size); - * } - * - * void my_free_cb(void *ptr, void *mem_user_data) { my_free(ptr); } - * - * void *my_calloc_cb(size_t nmemb, size_t size, void *mem_user_data) { - * return my_calloc(nmemb, size); - * } - * - * void *my_realloc_cb(void *ptr, size_t size, void *mem_user_data) { - * return my_realloc(ptr, size); - * } - * - * void session_new() { - * nghttp2_session *session; - * nghttp2_session_callbacks *callbacks; - * nghttp2_mem mem = {NULL, my_malloc_cb, my_free_cb, my_calloc_cb, - * my_realloc_cb}; - * - * ... - * - * nghttp2_session_client_new3(&session, callbacks, NULL, NULL, &mem); - * - * ... - * } - */ -typedef struct { - /** - * An arbitrary user supplied data. This is passed to each - * allocator function. - */ - void *mem_user_data; - /** - * Custom allocator function to replace malloc(). - */ - nghttp2_malloc malloc; - /** - * Custom allocator function to replace free(). - */ - nghttp2_free free; - /** - * Custom allocator function to replace calloc(). - */ - nghttp2_calloc calloc; - /** - * Custom allocator function to replace realloc(). - */ - nghttp2_realloc realloc; -} nghttp2_mem; - -struct nghttp2_option; - -/** - * @struct - * - * Configuration options for :type:`nghttp2_session`. The details of - * this structure are intentionally hidden from the public API. - */ -typedef struct nghttp2_option nghttp2_option; - -/** - * @function - * - * Initializes |*option_ptr| with default values. - * - * When the application finished using this object, it can use - * `nghttp2_option_del()` to free its memory. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - */ -NGHTTP2_EXTERN int nghttp2_option_new(nghttp2_option **option_ptr); - -/** - * @function - * - * Frees any resources allocated for |option|. If |option| is - * ``NULL``, this function does nothing. - */ -NGHTTP2_EXTERN void nghttp2_option_del(nghttp2_option *option); - -/** - * @function - * - * This option prevents the library from sending WINDOW_UPDATE for a - * connection automatically. If this option is set to nonzero, the - * library won't send WINDOW_UPDATE for DATA until application calls - * `nghttp2_session_consume()` to indicate the consumed amount of - * data. Don't use `nghttp2_submit_window_update()` for this purpose. - * By default, this option is set to zero. - */ -NGHTTP2_EXTERN void -nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val); - -/** - * @function - * - * This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of - * remote endpoint as if it is received in SETTINGS frame. Without - * specifying this option, before the local endpoint receives - * SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote - * endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may - * cause problem if local endpoint submits lots of requests initially - * and sending them at once to the remote peer may lead to the - * rejection of some requests. Specifying this option to the sensible - * value, say 100, may avoid this kind of issue. This value will be - * overwritten if the local endpoint receives - * SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint. - */ -NGHTTP2_EXTERN void -nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option, - uint32_t val); - -/** - * @function - * - * By default, nghttp2 library, if configured as server, requires - * first 24 bytes of client magic byte string (MAGIC). In most cases, - * this will simplify the implementation of server. But sometimes - * server may want to detect the application protocol based on first - * few bytes on clear text communication. - * - * If this option is used with nonzero |val|, nghttp2 library does not - * handle MAGIC. It still checks following SETTINGS frame. This - * means that applications should deal with MAGIC by themselves. - * - * If this option is not used or used with zero value, if MAGIC does - * not match :macro:`NGHTTP2_CLIENT_MAGIC`, `nghttp2_session_recv()` - * and `nghttp2_session_mem_recv()` will return error - * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC`, which is fatal error. - */ -NGHTTP2_EXTERN void -nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val); - -/** - * @function - * - * By default, nghttp2 library enforces subset of HTTP Messaging rules - * described in `HTTP/2 specification, section 8 - * `_. See - * :ref:`http-messaging` section for details. For those applications - * who use nghttp2 library as non-HTTP use, give nonzero to |val| to - * disable this enforcement. - */ -NGHTTP2_EXTERN void nghttp2_option_set_no_http_messaging(nghttp2_option *option, - int val); - -/** - * @function - * - * RFC 7540 does not enforce any limit on the number of incoming - * reserved streams (in RFC 7540 terms, streams in reserved (remote) - * state). This only affects client side, since only server can push - * streams. Malicious server can push arbitrary number of streams, - * and make client's memory exhausted. This option can set the - * maximum number of such incoming streams to avoid possible memory - * exhaustion. If this option is set, and pushed streams are - * automatically closed on reception, without calling user provided - * callback, if they exceed the given limit. The default value is - * 200. If session is configured as server side, this option has no - * effect. Server can control the number of streams to push. - */ -NGHTTP2_EXTERN void -nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option, - uint32_t val); - -/** - * @function - * - * Sets extension frame type the application is willing to handle with - * user defined callbacks (see - * :type:`nghttp2_on_extension_chunk_recv_callback` and - * :type:`nghttp2_unpack_extension_callback`). The |type| is - * extension frame type, and must be strictly greater than 0x9. - * Otherwise, this function does nothing. The application can call - * this function multiple times to set more than one frame type to - * receive. The application does not have to call this function if it - * just sends extension frames. - */ -NGHTTP2_EXTERN void -nghttp2_option_set_user_recv_extension_type(nghttp2_option *option, - uint8_t type); - -/** - * @function - * - * Sets extension frame type the application is willing to receive - * using builtin handler. The |type| is the extension frame type to - * receive, and must be strictly greater than 0x9. Otherwise, this - * function does nothing. The application can call this function - * multiple times to set more than one frame type to receive. The - * application does not have to call this function if it just sends - * extension frames. - * - * If same frame type is passed to both - * `nghttp2_option_set_builtin_recv_extension_type()` and - * `nghttp2_option_set_user_recv_extension_type()`, the latter takes - * precedence. - */ -NGHTTP2_EXTERN void -nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option, - uint8_t type); - -/** - * @function - * - * This option prevents the library from sending PING frame with ACK - * flag set automatically when PING frame without ACK flag set is - * received. If this option is set to nonzero, the library won't send - * PING frame with ACK flag set in the response for incoming PING - * frame. The application can send PING frame with ACK flag set using - * `nghttp2_submit_ping()` with :enum:`NGHTTP2_FLAG_ACK` as flags - * parameter. - */ -NGHTTP2_EXTERN void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option, - int val); - -/** - * @function - * - * This option sets the maximum length of header block (a set of - * header fields per one HEADERS frame) to send. The length of a - * given set of header fields is calculated using - * `nghttp2_hd_deflate_bound()`. The default value is 64KiB. If - * application attempts to send header fields larger than this limit, - * the transmission of the frame fails with error code - * :enum:`NGHTTP2_ERR_FRAME_SIZE_ERROR`. - */ -NGHTTP2_EXTERN void -nghttp2_option_set_max_send_header_block_length(nghttp2_option *option, - size_t val); - -/** - * @function + * @function * * Initializes |*session_ptr| for client use. The all members of * |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr| @@ -2458,10 +1790,9 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int -nghttp2_session_client_new(nghttp2_session **session_ptr, - const nghttp2_session_callbacks *callbacks, - void *user_data); +int nghttp2_session_client_new(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data); /** * @function @@ -2484,10 +1815,9 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int -nghttp2_session_server_new(nghttp2_session **session_ptr, - const nghttp2_session_callbacks *callbacks, - void *user_data); +int nghttp2_session_server_new(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data); /** * @function @@ -2510,10 +1840,9 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int -nghttp2_session_client_new2(nghttp2_session **session_ptr, - const nghttp2_session_callbacks *callbacks, - void *user_data, const nghttp2_option *option); +int nghttp2_session_client_new2(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data, const nghttp2_option *option); /** * @function @@ -2536,60 +1865,9 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int -nghttp2_session_server_new2(nghttp2_session **session_ptr, - const nghttp2_session_callbacks *callbacks, - void *user_data, const nghttp2_option *option); - -/** - * @function - * - * Like `nghttp2_session_client_new2()`, but with additional custom - * memory allocator specified in the |mem|. - * - * The |mem| can be ``NULL`` and the call is equivalent to - * `nghttp2_session_client_new2()`. - * - * This function does not take ownership |mem|. The application is - * responsible for freeing |mem|. - * - * The library code does not refer to |mem| pointer after this - * function returns, so the application can safely free it. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - */ -NGHTTP2_EXTERN int nghttp2_session_client_new3( - nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, - void *user_data, const nghttp2_option *option, nghttp2_mem *mem); - -/** - * @function - * - * Like `nghttp2_session_server_new2()`, but with additional custom - * memory allocator specified in the |mem|. - * - * The |mem| can be ``NULL`` and the call is equivalent to - * `nghttp2_session_server_new2()`. - * - * This function does not take ownership |mem|. The application is - * responsible for freeing |mem|. - * - * The library code does not refer to |mem| pointer after this - * function returns, so the application can safely free it. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - */ -NGHTTP2_EXTERN int nghttp2_session_server_new3( - nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, - void *user_data, const nghttp2_option *option, nghttp2_mem *mem); +int nghttp2_session_server_new2(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data, const nghttp2_option *option); /** * @function @@ -2597,7 +1875,7 @@ * Frees any resources allocated for |session|. If |session| is * ``NULL``, this function does nothing. */ -NGHTTP2_EXTERN void nghttp2_session_del(nghttp2_session *session); +void nghttp2_session_del(nghttp2_session *session); /** * @function @@ -2629,20 +1907,14 @@ * * 6. :type:`nghttp2_before_frame_send_callback` is invoked. * - * 7. If :enum:`NGHTTP2_ERR_CANCEL` is returned from - * :type:`nghttp2_before_frame_send_callback`, the current frame - * transmission is canceled, and - * :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort - * the following steps. - * - * 8. :type:`nghttp2_send_callback` is invoked one or more times to + * 7. :type:`nghttp2_send_callback` is invoked one or more times to * send the frame. * - * 9. :type:`nghttp2_on_frame_send_callback` is invoked. + * 8. :type:`nghttp2_on_frame_send_callback` is invoked. * - * 10. If the transmission of the frame triggers closure of the - * stream, the stream is closed and - * :type:`nghttp2_on_stream_close_callback` is invoked. + * 9. If the transmission of the frame triggers closure of the stream, + * the stream is closed and + * :type:`nghttp2_on_stream_close_callback` is invoked. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -2652,7 +1924,7 @@ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` * The callback function failed. */ -NGHTTP2_EXTERN int nghttp2_session_send(nghttp2_session *session); +int nghttp2_session_send(nghttp2_session *session); /** * @function @@ -2683,18 +1955,9 @@ * * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. - * - * .. note:: - * - * This function may produce very small byte string. If that is the - * case, and application disables Nagle algorithm (``TCP_NODELAY``), - * then writing this small chunk leads to very small packet, and it - * is very inefficient. An application should be responsible to - * buffer up small chunks of data as necessary to avoid this - * situation. */ -NGHTTP2_EXTERN ssize_t -nghttp2_session_mem_send(nghttp2_session *session, const uint8_t **data_ptr); +ssize_t nghttp2_session_mem_send(nghttp2_session *session, + const uint8_t **data_ptr); /** * @function @@ -2754,16 +2017,12 @@ * Out of memory. * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` * The callback function failed. - * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC` - * Invalid client magic was detected. This error only returns + * :enum:`NGHTTP2_ERR_BAD_PREFACE` + * Invalid client preface was detected. This error only returns * when |session| was configured as server and - * `nghttp2_option_set_no_recv_client_magic()` is not used with - * nonzero value. - * :enum:`NGHTTP2_ERR_FLOODED` - * Flooding was detected in this HTTP/2 session, and it must be - * closed. This is most likely caused by misbehaviour of peer. + * `nghttp2_option_set_recv_client_preface()` is used. */ -NGHTTP2_EXTERN int nghttp2_session_recv(nghttp2_session *session); +int nghttp2_session_recv(nghttp2_session *session); /** * @function @@ -2793,18 +2052,13 @@ * Out of memory. * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` * The callback function failed. - * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC` - * Invalid client magic was detected. This error only returns + * :enum:`NGHTTP2_ERR_BAD_PREFACE` + * Invalid client preface was detected. This error only returns * when |session| was configured as server and - * `nghttp2_option_set_no_recv_client_magic()` is not used with - * nonzero value. - * :enum:`NGHTTP2_ERR_FLOODED` - * Flooding was detected in this HTTP/2 session, and it must be - * closed. This is most likely caused by misbehaviour of peer. - */ -NGHTTP2_EXTERN ssize_t nghttp2_session_mem_recv(nghttp2_session *session, - const uint8_t *in, - size_t inlen); + * `nghttp2_option_set_recv_client_preface()` is used. + */ +ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, + size_t inlen); /** * @function @@ -2820,8 +2074,7 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int nghttp2_session_resume_data(nghttp2_session *session, - int32_t stream_id); +int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id); /** * @function @@ -2833,7 +2086,7 @@ * `nghttp2_session_want_write()` return 0, the application should * drop the connection. */ -NGHTTP2_EXTERN int nghttp2_session_want_read(nghttp2_session *session); +int nghttp2_session_want_read(nghttp2_session *session); /** * @function @@ -2845,7 +2098,7 @@ * `nghttp2_session_want_write()` return 0, the application should * drop the connection. */ -NGHTTP2_EXTERN int nghttp2_session_want_write(nghttp2_session *session); +int nghttp2_session_want_write(nghttp2_session *session); /** * @function @@ -2859,9 +2112,8 @@ * ``NULL``. If the stream does not exist, this function returns * ``NULL``. */ -NGHTTP2_EXTERN void * -nghttp2_session_get_stream_user_data(nghttp2_session *session, - int32_t stream_id); +void *nghttp2_session_get_stream_user_data(nghttp2_session *session, + int32_t stream_id); /** * @function @@ -2881,9 +2133,9 @@ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * The stream does not exist */ -NGHTTP2_EXTERN int -nghttp2_session_set_stream_user_data(nghttp2_session *session, - int32_t stream_id, void *stream_user_data); +int nghttp2_session_set_stream_user_data(nghttp2_session *session, + int32_t stream_id, + void *stream_user_data); /** * @function @@ -2891,8 +2143,7 @@ * Returns the number of frames in the outbound queue. This does not * include the deferred DATA frames. */ -NGHTTP2_EXTERN size_t -nghttp2_session_get_outbound_queue_size(nghttp2_session *session); +size_t nghttp2_session_get_outbound_queue_size(nghttp2_session *session); /** * @function @@ -2908,7 +2159,7 @@ * * This function returns -1 if it fails. */ -NGHTTP2_EXTERN int32_t +int32_t nghttp2_session_get_stream_effective_recv_data_length(nghttp2_session *session, int32_t stream_id); @@ -2922,7 +2173,7 @@ * * This function returns -1 if it fails. */ -NGHTTP2_EXTERN int32_t +int32_t nghttp2_session_get_stream_effective_local_window_size(nghttp2_session *session, int32_t stream_id); @@ -2940,7 +2191,7 @@ * * This function returns -1 if it fails. */ -NGHTTP2_EXTERN int32_t +int32_t nghttp2_session_get_effective_recv_data_length(nghttp2_session *session); /** @@ -2953,7 +2204,7 @@ * * This function returns -1 if it fails. */ -NGHTTP2_EXTERN int32_t +int32_t nghttp2_session_get_effective_local_window_size(nghttp2_session *session); /** @@ -2970,9 +2221,8 @@ * * This function returns -1 if it fails. */ -NGHTTP2_EXTERN int32_t -nghttp2_session_get_stream_remote_window_size(nghttp2_session *session, - int32_t stream_id); +int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session *session, + int32_t stream_id); /** * @function @@ -2981,8 +2231,7 @@ * * This function always succeeds. */ -NGHTTP2_EXTERN int32_t -nghttp2_session_get_remote_window_size(nghttp2_session *session); +int32_t nghttp2_session_get_remote_window_size(nghttp2_session *session); /** * @function @@ -2990,9 +2239,8 @@ * Returns 1 if local peer half closed the given stream |stream_id|. * Returns 0 if it did not. Returns -1 if no such stream exists. */ -NGHTTP2_EXTERN int -nghttp2_session_get_stream_local_close(nghttp2_session *session, - int32_t stream_id); +int nghttp2_session_get_stream_local_close(nghttp2_session *session, + int32_t stream_id); /** * @function @@ -3000,9 +2248,8 @@ * Returns 1 if remote peer half closed the given stream |stream_id|. * Returns 0 if it did not. Returns -1 if no such stream exists. */ -NGHTTP2_EXTERN int -nghttp2_session_get_stream_remote_close(nghttp2_session *session, - int32_t stream_id); +int nghttp2_session_get_stream_remote_close(nghttp2_session *session, + int32_t stream_id); /** * @function @@ -3030,8 +2277,8 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int nghttp2_session_terminate_session(nghttp2_session *session, - uint32_t error_code); +int nghttp2_session_terminate_session(nghttp2_session *session, + uint32_t error_code); /** * @function @@ -3059,46 +2306,9 @@ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * The |last_stream_id| is invalid. */ -NGHTTP2_EXTERN int nghttp2_session_terminate_session2(nghttp2_session *session, - int32_t last_stream_id, - uint32_t error_code); - -/** - * @function - * - * Signals to the client that the server started graceful shutdown - * procedure. - * - * This function is only usable for server. If this function is - * called with client side session, this function returns - * :enum:`NGHTTP2_ERR_INVALID_STATE`. - * - * To gracefully shutdown HTTP/2 session, server should call this - * function to send GOAWAY with last_stream_id (1u << 31) - 1. And - * after some delay (e.g., 1 RTT), send another GOAWAY with the stream - * ID that the server has some processing using - * `nghttp2_submit_goaway()`. See also - * `nghttp2_session_get_last_proc_stream_id()`. - * - * Unlike `nghttp2_submit_goaway()`, this function just sends GOAWAY - * and does nothing more. This is a mere indication to the client - * that session shutdown is imminent. The application should call - * `nghttp2_submit_goaway()` with appropriate last_stream_id after - * this call. - * - * If one or more GOAWAY frame have been already sent by either - * `nghttp2_submit_goaway()` or `nghttp2_session_terminate_session()`, - * this function has no effect. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - * :enum:`NGHTTP2_ERR_INVALID_STATE` - * The |session| is initialized as client. - */ -NGHTTP2_EXTERN int nghttp2_submit_shutdown_notice(nghttp2_session *session); +int nghttp2_session_terminate_session2(nghttp2_session *session, + int32_t last_stream_id, + uint32_t error_code); /** * @function @@ -3107,49 +2317,15 @@ * The |id| must be one of values defined in * :enum:`nghttp2_settings_id`. */ -NGHTTP2_EXTERN uint32_t -nghttp2_session_get_remote_settings(nghttp2_session *session, - nghttp2_settings_id id); - -/** - * @function - * - * Tells the |session| that next stream ID is |next_stream_id|. The - * |next_stream_id| must be equal or greater than the value returned - * by `nghttp2_session_get_next_stream_id()`. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * The |next_stream_id| is strictly less than the value - * `nghttp2_session_get_next_stream_id()` returns; or - * |next_stream_id| is invalid (e.g., even integer for client, or - * odd integer for server). - */ -NGHTTP2_EXTERN int nghttp2_session_set_next_stream_id(nghttp2_session *session, - int32_t next_stream_id); - -/** - * @function - * - * Returns the next outgoing stream ID. Notice that return type is - * uint32_t. If we run out of stream ID for this session, this - * function returns 1 << 31. - */ -NGHTTP2_EXTERN uint32_t -nghttp2_session_get_next_stream_id(nghttp2_session *session); +uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session, + nghttp2_settings_id id); /** * @function * * Tells the |session| that |size| bytes for a stream denoted by * |stream_id| were consumed by application and are ready to - * WINDOW_UPDATE. The consumed bytes are counted towards both - * connection and stream level WINDOW_UPDATE (see - * `nghttp2_session_consume_connection()` and - * `nghttp2_session_consume_stream()` to update consumption - * independently). This function is intended to be used without + * WINDOW_UPDATE. This function is intended to be used without * automatic window update (see * `nghttp2_option_set_no_auto_window_update()`). * @@ -3163,128 +2339,8 @@ * :enum:`NGHTTP2_ERR_INVALID_STATE` * Automatic WINDOW_UPDATE is not disabled. */ -NGHTTP2_EXTERN int nghttp2_session_consume(nghttp2_session *session, - int32_t stream_id, size_t size); - -/** - * @function - * - * Like `nghttp2_session_consume()`, but this only tells library that - * |size| bytes were consumed only for connection level. Note that - * HTTP/2 maintains connection and stream level flow control windows - * independently. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - * :enum:`NGHTTP2_ERR_INVALID_STATE` - * Automatic WINDOW_UPDATE is not disabled. - */ -NGHTTP2_EXTERN int nghttp2_session_consume_connection(nghttp2_session *session, - size_t size); - -/** - * @function - * - * Like `nghttp2_session_consume()`, but this only tells library that - * |size| bytes were consumed only for stream denoted by |stream_id|. - * Note that HTTP/2 maintains connection and stream level flow control - * windows independently. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * The |stream_id| is 0. - * :enum:`NGHTTP2_ERR_INVALID_STATE` - * Automatic WINDOW_UPDATE is not disabled. - */ -NGHTTP2_EXTERN int nghttp2_session_consume_stream(nghttp2_session *session, - int32_t stream_id, - size_t size); - -/** - * @function - * - * Changes priority of existing stream denoted by |stream_id|. The - * new priority specification is |pri_spec|. - * - * The priority is changed silently and instantly, and no PRIORITY - * frame will be sent to notify the peer of this change. This - * function may be useful for server to change the priority of pushed - * stream. - * - * If |session| is initialized as server, and ``pri_spec->stream_id`` - * points to the idle stream, the idle stream is created if it does - * not exist. The created idle stream will depend on root stream - * (stream 0) with weight 16. - * - * Otherwise, if stream denoted by ``pri_spec->stream_id`` is not - * found, we use default priority instead of given |pri_spec|. That - * is make stream depend on root stream with weight 16. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * Attempted to depend on itself; or no stream exist for the given - * |stream_id|; or |stream_id| is 0 - */ -NGHTTP2_EXTERN int -nghttp2_session_change_stream_priority(nghttp2_session *session, - int32_t stream_id, - const nghttp2_priority_spec *pri_spec); - -/** - * @function - * - * Creates idle stream with the given |stream_id|, and priority - * |pri_spec|. - * - * The stream creation is done without sending PRIORITY frame, which - * means that peer does not know about the existence of this idle - * stream in the local endpoint. - * - * RFC 7540 does not disallow the use of creation of idle stream with - * odd or even stream ID regardless of client or server. So this - * function can create odd or even stream ID regardless of client or - * server. But probably it is a bit safer to use the stream ID the - * local endpoint can initiate (in other words, use odd stream ID for - * client, and even stream ID for server), to avoid potential - * collision from peer's instruction. Also we can use - * `nghttp2_session_set_next_stream_id()` to avoid to open created - * idle streams accidentally if we follow this recommendation. - * - * If |session| is initialized as server, and ``pri_spec->stream_id`` - * points to the idle stream, the idle stream is created if it does - * not exist. The created idle stream will depend on root stream - * (stream 0) with weight 16. - * - * Otherwise, if stream denoted by ``pri_spec->stream_id`` is not - * found, we use default priority instead of given |pri_spec|. That - * is make stream depend on root stream with weight 16. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * Attempted to depend on itself; or stream denoted by |stream_id| - * already exists; or |stream_id| cannot be used to create idle - * stream (in other words, local endpoint has already opened - * stream ID greater than or equal to the given stream ID; or - * |stream_id| is 0 - */ -NGHTTP2_EXTERN int -nghttp2_session_create_idle_stream(nghttp2_session *session, int32_t stream_id, - const nghttp2_priority_spec *pri_spec); +int nghttp2_session_consume(nghttp2_session *session, int32_t stream_id, + size_t size); /** * @function @@ -3293,17 +2349,6 @@ * be called from both client and server, but the behavior is very * different in each other. * - * .. warning:: - * - * This function is deprecated in favor of - * `nghttp2_session_upgrade2()`, because this function lacks the - * parameter to tell the library the request method used in the - * original HTTP request. This information is required for client - * to validate actual response body length against content-length - * header field (see `nghttp2_option_set_no_http_messaging()`). If - * HEAD is used in request, the length of response body must be 0 - * regardless of value included in content-length header field. - * * If called from client side, the |settings_payload| must be the * value sent in ``HTTP2-Settings`` header field and must be decoded * by base64url decoder. The |settings_payloadlen| is the length of @@ -3333,55 +2378,9 @@ * :enum:`NGHTTP2_ERR_PROTO` * The stream ID 1 is already used or closed; or is not available. */ -NGHTTP2_EXTERN int nghttp2_session_upgrade(nghttp2_session *session, - const uint8_t *settings_payload, - size_t settings_payloadlen, - void *stream_user_data); - -/** - * @function - * - * Performs post-process of HTTP Upgrade request. This function can - * be called from both client and server, but the behavior is very - * different in each other. - * - * If called from client side, the |settings_payload| must be the - * value sent in ``HTTP2-Settings`` header field and must be decoded - * by base64url decoder. The |settings_payloadlen| is the length of - * |settings_payload|. The |settings_payload| is unpacked and its - * setting values will be submitted using `nghttp2_submit_settings()`. - * This means that the client application code does not need to submit - * SETTINGS by itself. The stream with stream ID=1 is opened and the - * |stream_user_data| is used for its stream_user_data. The opened - * stream becomes half-closed (local) state. - * - * If called from server side, the |settings_payload| must be the - * value received in ``HTTP2-Settings`` header field and must be - * decoded by base64url decoder. The |settings_payloadlen| is the - * length of |settings_payload|. It is treated as if the SETTINGS - * frame with that payload is received. Thus, callback functions for - * the reception of SETTINGS frame will be invoked. The stream with - * stream ID=1 is opened. The |stream_user_data| is ignored. The - * opened stream becomes half-closed (remote). - * - * If the request method is HEAD, pass nonzero value to - * |head_request|. Otherwise, pass 0. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * The |settings_payload| is badly formed. - * :enum:`NGHTTP2_ERR_PROTO` - * The stream ID 1 is already used or closed; or is not available. - */ -NGHTTP2_EXTERN int nghttp2_session_upgrade2(nghttp2_session *session, - const uint8_t *settings_payload, - size_t settings_payloadlen, - int head_request, - void *stream_user_data); +int nghttp2_session_upgrade(nghttp2_session *session, + const uint8_t *settings_payload, + size_t settings_payloadlen, void *stream_user_data); /** * @function @@ -3404,9 +2403,9 @@ * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE` * The provided |buflen| size is too small to hold the output. */ -NGHTTP2_EXTERN ssize_t -nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen, - const nghttp2_settings_entry *iv, size_t niv); +ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen, + const nghttp2_settings_entry *iv, + size_t niv); /** * @function @@ -3414,17 +2413,7 @@ * Returns string describing the |lib_error_code|. The * |lib_error_code| must be one of the :enum:`nghttp2_error`. */ -NGHTTP2_EXTERN const char *nghttp2_strerror(int lib_error_code); - -/** - * @function - * - * Returns string representation of HTTP/2 error code |error_code| - * (e.g., ``PROTOCOL_ERROR`` is returned if ``error_code == - * NGHTTP2_PROTOCOL_ERROR``). If string representation is unknown for - * given |error_code|, this function returns string ``unknown``. - */ -NGHTTP2_EXTERN const char *nghttp2_http2_strerror(uint32_t error_code); +const char *nghttp2_strerror(int lib_error_code); /** * @function @@ -3436,9 +2425,9 @@ * The |weight| must be in [:enum:`NGHTTP2_MIN_WEIGHT`, * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. */ -NGHTTP2_EXTERN void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec, - int32_t stream_id, - int32_t weight, int exclusive); +void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec, + int32_t stream_id, int32_t weight, + int exclusive); /** * @function @@ -3447,16 +2436,14 @@ * are: stream_id = 0, weight = :macro:`NGHTTP2_DEFAULT_WEIGHT` and * exclusive = 0. */ -NGHTTP2_EXTERN void -nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec); +void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec); /** * @function * * Returns nonzero if the |pri_spec| is filled with default values. */ -NGHTTP2_EXTERN int -nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec); +int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec); /** * @function @@ -3469,8 +2456,8 @@ * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``, * this function will copy its data members. * - * The ``pri_spec->weight`` must be in [:enum:`NGHTTP2_MIN_WEIGHT`, - * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is + * The `pri_spec->weight` must be in [:enum:`NGHTTP2_MIN_WEIGHT`, + * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If `pri_spec->weight` is * strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes * :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`. @@ -3483,15 +2470,7 @@ * * This function creates copies of all name/value pairs in |nva|. It * also lower-cases all names in |nva|. The order of elements in - * |nva| is preserved. For header fields with - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name - * and value are not copied respectively. With - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to - * pass header field name in lowercase. The application should - * maintain the references to them until - * :type:`nghttp2_on_frame_send_callback` or - * :type:`nghttp2_on_frame_not_send_callback` is called. + * |nva| is preserved. * * HTTP/2 specification has requirement about header fields in the * request HEADERS. See the specification for more details. @@ -3499,13 +2478,13 @@ * If |data_prd| is not ``NULL``, it provides data which will be sent * in subsequent DATA frames. In this case, a method that allows * request message bodies - * (https://tools.ietf.org/html/rfc7231#section-4) must be specified - * with ``:method`` key in |nva| (e.g. ``POST``). This function does - * not take ownership of the |data_prd|. The function copies the - * members of the |data_prd|. If |data_prd| is ``NULL``, HEADERS have - * END_STREAM set. The |stream_user_data| is data associated to the - * stream opened by this request and can be an arbitrary pointer, - * which can be retrieved later by + * (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9) must + * be specified with ``:method`` key in |nva| (e.g. ``POST``). This + * function does not take ownership of the |data_prd|. The function + * copies the members of the |data_prd|. If |data_prd| is ``NULL``, + * HEADERS have END_STREAM set. The |stream_user_data| is data + * associated to the stream opened by this request and can be an + * arbitrary pointer, which can be retrieved later by * `nghttp2_session_get_stream_user_data()`. * * This function returns assigned stream ID if it succeeds, or one of @@ -3516,11 +2495,6 @@ * :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE` * No stream ID is available because maximum stream ID was * reached. - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * Trying to depend on itself (new stream ID equals - * ``pri_spec->stream_id``). - * :enum:`NGHTTP2_ERR_PROTO` - * The |session| is server session. * * .. warning:: * @@ -3531,12 +2505,11 @@ * frame. * */ -NGHTTP2_EXTERN int32_t -nghttp2_submit_request(nghttp2_session *session, - const nghttp2_priority_spec *pri_spec, - const nghttp2_nv *nva, size_t nvlen, - const nghttp2_data_provider *data_prd, - void *stream_user_data); +int32_t nghttp2_submit_request(nghttp2_session *session, + const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider *data_prd, + void *stream_user_data); /** * @function @@ -3552,15 +2525,7 @@ * * This function creates copies of all name/value pairs in |nva|. It * also lower-cases all names in |nva|. The order of elements in - * |nva| is preserved. For header fields with - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name - * and value are not copied respectively. With - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to - * pass header field name in lowercase. The application should - * maintain the references to them until - * :type:`nghttp2_on_frame_send_callback` or - * :type:`nghttp2_on_frame_not_send_callback` is called. + * |nva| is preserved. * * HTTP/2 specification has requirement about header fields in the * response HEADERS. See the specification for more details. @@ -3588,80 +2553,10 @@ * Out of memory. * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * The |stream_id| is 0. - * :enum:`NGHTTP2_ERR_DATA_EXIST` - * DATA or HEADERS has been already submitted and not fully - * processed yet. Normally, this does not happen, but when - * application wrongly calls `nghttp2_submit_response()` twice, - * this may happen. - * :enum:`NGHTTP2_ERR_PROTO` - * The |session| is client session. - * - * .. warning:: - * - * Calling this function twice for the same stream ID may lead to - * program crash. It is generally considered to a programming error - * to commit response twice. - */ -NGHTTP2_EXTERN int -nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, - const nghttp2_nv *nva, size_t nvlen, - const nghttp2_data_provider *data_prd); - -/** - * @function - * - * Submits trailer fields HEADERS against the stream |stream_id|. - * - * The |nva| is an array of name/value pair :type:`nghttp2_nv` with - * |nvlen| elements. The application is responsible not to include - * pseudo-header fields (header field whose name starts with ":") in - * |nva|. - * - * This function creates copies of all name/value pairs in |nva|. It - * also lower-cases all names in |nva|. The order of elements in - * |nva| is preserved. For header fields with - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name - * and value are not copied respectively. With - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to - * pass header field name in lowercase. The application should - * maintain the references to them until - * :type:`nghttp2_on_frame_send_callback` or - * :type:`nghttp2_on_frame_not_send_callback` is called. - * - * For server, trailer fields must follow response HEADERS or response - * DATA without END_STREAM flat set. The library does not enforce - * this requirement, and applications should do this for themselves. - * If `nghttp2_submit_trailer()` is called before any response HEADERS - * submission (usually by `nghttp2_submit_response()`), the content of - * |nva| will be sent as response headers, which will result in error. - * - * This function has the same effect with `nghttp2_submit_headers()`, - * with flags = :enum:`NGHTTP2_FLAG_END_STREAM` and both pri_spec and - * stream_user_data to NULL. - * - * To submit trailer fields after `nghttp2_submit_response()` is - * called, the application has to specify - * :type:`nghttp2_data_provider` to `nghttp2_submit_response()`. - * Inside of :type:`nghttp2_data_source_read_callback`, when setting - * :enum:`NGHTTP2_DATA_FLAG_EOF`, also set - * :enum:`NGHTTP2_DATA_FLAG_NO_END_STREAM`. After that, the - * application can send trailer fields using - * `nghttp2_submit_trailer()`. `nghttp2_submit_trailer()` can be used - * inside :type:`nghttp2_data_source_read_callback`. - * - * This function returns 0 if it succeeds and |stream_id| is -1. - * Otherwise, this function returns 0 if it succeeds, or one of the - * following negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * The |stream_id| is 0. */ -NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session, - int32_t stream_id, - const nghttp2_nv *nva, size_t nvlen); +int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider *data_prd); /** * @function @@ -3689,8 +2584,8 @@ * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``, * this function will copy its data members. * - * The ``pri_spec->weight`` must be in [:enum:`NGHTTP2_MIN_WEIGHT`, - * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is + * The `pri_spec->weight` must be in [:enum:`NGHTTP2_MIN_WEIGHT`, + * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If `pri_spec->weight` is * strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes * :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`. @@ -3703,15 +2598,7 @@ * * This function creates copies of all name/value pairs in |nva|. It * also lower-cases all names in |nva|. The order of elements in - * |nva| is preserved. For header fields with - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name - * and value are not copied respectively. With - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to - * pass header field name in lowercase. The application should - * maintain the references to them until - * :type:`nghttp2_on_frame_send_callback` or - * :type:`nghttp2_on_frame_not_send_callback` is called. + * |nva| is preserved. * * The |stream_user_data| is a pointer to an arbitrary data which is * associated to the stream this frame will open. Therefore it is @@ -3720,8 +2607,7 @@ * * This function is low-level in a sense that the application code can * specify flags directly. For usual HTTP request, - * `nghttp2_submit_request()` is useful. Likewise, for HTTP response, - * prefer `nghttp2_submit_response()`. + * `nghttp2_submit_request()` is useful. * * This function returns newly assigned stream ID if it succeeds and * |stream_id| is -1. Otherwise, this function returns 0 if it @@ -3733,14 +2619,7 @@ * No stream ID is available because maximum stream ID was * reached. * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * The |stream_id| is 0; or trying to depend on itself (stream ID - * equals ``pri_spec->stream_id``). - * :enum:`NGHTTP2_ERR_DATA_EXIST` - * DATA or HEADERS has been already submitted and not fully - * processed yet. This happens if stream denoted by |stream_id| - * is in reserved state. - * :enum:`NGHTTP2_ERR_PROTO` - * The |stream_id| is -1, and |session| is server session. + * The |stream_id| is 0. * * .. warning:: * @@ -3751,11 +2630,11 @@ * frame. * */ -NGHTTP2_EXTERN int32_t -nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, - int32_t stream_id, const nghttp2_priority_spec *pri_spec, - const nghttp2_nv *nva, size_t nvlen, - void *stream_user_data); +int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_priority_spec *pri_spec, + const nghttp2_nv *nva, size_t nvlen, + void *stream_user_data); /** * @function @@ -3774,32 +2653,26 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. * :enum:`NGHTTP2_ERR_DATA_EXIST` - * DATA or HEADERS has been already submitted and not fully - * processed yet. + * DATA has been already submitted and not fully processed yet. * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * The |stream_id| is 0. * :enum:`NGHTTP2_ERR_STREAM_CLOSED` - * The stream was already closed; or the |stream_id| is invalid. + * The stream was alreay closed; or the |stream_id| is invalid. * * .. note:: * - * Currently, only one DATA or HEADERS is allowed for a stream at a - * time. Submitting these frames more than once before first DATA - * or HEADERS is finished results in :enum:`NGHTTP2_ERR_DATA_EXIST` - * error code. The earliest callback which tells that previous - * frame is done is :type:`nghttp2_on_frame_send_callback`. In side - * that callback, new data can be submitted using - * `nghttp2_submit_data()`. Of course, all data except for last one - * must not have :enum:`NGHTTP2_FLAG_END_STREAM` flag set in - * |flags|. This sounds a bit complicated, and we recommend to use - * `nghttp2_submit_request()` and `nghttp2_submit_response()` to - * avoid this cascading issue. The experience shows that for HTTP - * use, these two functions are enough to implement both client and - * server. - */ -NGHTTP2_EXTERN int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, - int32_t stream_id, - const nghttp2_data_provider *data_prd); + * Currently, only one data is allowed for a stream at a time. + * Submitting data more than once before first data is finished + * results in :enum:`NGHTTP2_ERR_DATA_EXIST` error code. The + * earliest callback which tells that previous data is done is + * :type:`nghttp2_on_frame_send_callback`. In side that callback, + * new data can be submitted using `nghttp2_submit_data()`. Of + * course, all data except for last one must not have + * :enum:`NGHTTP2_FLAG_END_STREAM` flag set in |flags|. + */ +int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_data_provider *data_prd); /** * @function @@ -3815,8 +2688,8 @@ * `nghttp2_priority_spec_init()`. This function will copy its data * members. * - * The ``pri_spec->weight`` must be in [:enum:`NGHTTP2_MIN_WEIGHT`, - * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is + * The `pri_spec->weight` must be in [:enum:`NGHTTP2_MIN_WEIGHT`, + * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If `pri_spec->weight` is * strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes * :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`. @@ -3830,10 +2703,9 @@ * The |stream_id| is 0; or the |pri_spec| is NULL; or trying to * depend on itself. */ -NGHTTP2_EXTERN int -nghttp2_submit_priority(nghttp2_session *session, uint8_t flags, - int32_t stream_id, - const nghttp2_priority_spec *pri_spec); +int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + const nghttp2_priority_spec *pri_spec); /** * @function @@ -3854,9 +2726,8 @@ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * The |stream_id| is 0. */ -NGHTTP2_EXTERN int nghttp2_submit_rst_stream(nghttp2_session *session, - uint8_t flags, int32_t stream_id, - uint32_t error_code); +int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags, + int32_t stream_id, uint32_t error_code); /** * @function @@ -3884,13 +2755,15 @@ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * The |iv| contains invalid value (e.g., initial window size * strictly greater than (1 << 31) - 1. + * :enum:`NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS` + * There is already another in-flight SETTINGS. Note that the + * current implementation only allows 1 in-flight SETTINGS frame + * without ACK flag set. * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int nghttp2_submit_settings(nghttp2_session *session, - uint8_t flags, - const nghttp2_settings_entry *iv, - size_t niv); +int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags, + const nghttp2_settings_entry *iv, size_t niv); /** * @function @@ -3911,15 +2784,7 @@ * * This function creates copies of all name/value pairs in |nva|. It * also lower-cases all names in |nva|. The order of elements in - * |nva| is preserved. For header fields with - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name - * and value are not copied respectively. With - * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to - * pass header field name in lowercase. The application should - * maintain the references to them until - * :type:`nghttp2_on_frame_send_callback` or - * :type:`nghttp2_on_frame_not_send_callback` is called. + * |nva| is preserved. * * The |promised_stream_user_data| is a pointer to an arbitrary data * which is associated to the promised stream this frame will open and @@ -3930,9 +2795,6 @@ * * The client side is not allowed to use this function. * - * To submit response headers and data, use - * `nghttp2_submit_response()`. - * * This function returns assigned promised stream ID if it succeeds, * or one of the following negative error codes: * @@ -3947,26 +2809,20 @@ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * The |stream_id| is 0; The |stream_id| does not designate stream * that peer initiated. - * :enum:`NGHTTP2_ERR_STREAM_CLOSED` - * The stream was already closed; or the |stream_id| is invalid. * * .. warning:: * * This function returns assigned promised stream ID if it succeeds. - * As of 1.16.0, stream object for pushed resource is created when - * this function succeeds. In that case, the application can submit - * push response for the promised frame. - * - * In 1.15.0 or prior versions, pushed stream is not opened yet when - * this function succeeds. The application must not submit frame to - * that stream ID before :type:`nghttp2_before_frame_send_callback` - * is called for this frame. + * But that stream is not opened yet. The application must not + * submit frame to that stream ID before + * :type:`nghttp2_before_frame_send_callback` is called for this + * frame. * */ -NGHTTP2_EXTERN int32_t -nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags, - int32_t stream_id, const nghttp2_nv *nva, - size_t nvlen, void *promised_stream_user_data); +int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags, + int32_t stream_id, const nghttp2_nv *nva, + size_t nvlen, + void *promised_stream_user_data); /** * @function @@ -3975,12 +2831,8 @@ * received PING frame. The library automatically submits PING frame * in this case. * - * The |flags| is bitwise OR of 0 or more of the following value. - * - * * :enum:`NGHTTP2_FLAG_ACK` - * - * Unless `nghttp2_option_set_no_auto_ping_ack()` is used, the |flags| - * should be :enum:`NGHTTP2_FLAG_NONE`. + * The |flags| is currently ignored and should be + * :enum:`NGHTTP2_FLAG_NONE`. * * If the |opaque_data| is non ``NULL``, then it should point to the 8 * bytes array of memory to specify opaque data to send with PING @@ -3993,8 +2845,8 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags, - const uint8_t *opaque_data); +int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags, + const uint8_t *opaque_data); /** * @function @@ -4025,13 +2877,6 @@ * keep this memory after the return of this function. If the * |opaque_data_len| is 0, the |opaque_data| could be ``NULL``. * - * After successful transmission of GOAWAY, following things happen. - * All incoming streams having strictly more than |last_stream_id| are - * closed. All incoming HEADERS which starts new stream are simply - * ignored. After all active streams are handled, both - * `nghttp2_session_want_read()` and `nghttp2_session_want_write()` - * return 0 and the application can close session. - * * This function returns 0 if it succeeds, or one of the following * negative error codes: * @@ -4041,51 +2886,9 @@ * The |opaque_data_len| is too large; the |last_stream_id| is * invalid. */ -NGHTTP2_EXTERN int nghttp2_submit_goaway(nghttp2_session *session, - uint8_t flags, int32_t last_stream_id, - uint32_t error_code, - const uint8_t *opaque_data, - size_t opaque_data_len); - -/** - * @function - * - * Returns the last stream ID of a stream for which - * :type:`nghttp2_on_frame_recv_callback` was invoked most recently. - * The returned value can be used as last_stream_id parameter for - * `nghttp2_submit_goaway()` and - * `nghttp2_session_terminate_session2()`. - * - * This function always succeeds. - */ -NGHTTP2_EXTERN int32_t -nghttp2_session_get_last_proc_stream_id(nghttp2_session *session); - -/** - * @function - * - * Returns nonzero if new request can be sent from local endpoint. - * - * This function return 0 if request is not allowed for this session. - * There are several reasons why request is not allowed. Some of the - * reasons are: session is server; stream ID has been spent; GOAWAY - * has been sent or received. - * - * The application can call `nghttp2_submit_request()` without - * consulting this function. In that case, `nghttp2_submit_request()` - * may return error. Or, request is failed to sent, and - * :type:`nghttp2_on_stream_close_callback` is called. - */ -NGHTTP2_EXTERN int -nghttp2_session_check_request_allowed(nghttp2_session *session); - -/** - * @function - * - * Returns nonzero if |session| is initialized as server side session. - */ -NGHTTP2_EXTERN int -nghttp2_session_check_server_session(nghttp2_session *session); +int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags, + int32_t last_stream_id, uint32_t error_code, + const uint8_t *opaque_data, size_t opaque_data_len); /** * @function @@ -4095,24 +2898,18 @@ * The |flags| is currently ignored and should be * :enum:`NGHTTP2_FLAG_NONE`. * - * The |stream_id| is the stream ID to send this WINDOW_UPDATE. To - * send connection level WINDOW_UPDATE, specify 0 to |stream_id|. - * * If the |window_size_increment| is positive, the WINDOW_UPDATE with * that value as window_size_increment is queued. If the * |window_size_increment| is larger than the received bytes from the * remote endpoint, the local window size is increased by that - * difference. If the sole purpose is to increase the local window - * size, consider to use `nghttp2_session_set_local_window_size()`. + * difference. * * If the |window_size_increment| is negative, the local window size * is decreased by -|window_size_increment|. If automatic * WINDOW_UPDATE is enabled * (`nghttp2_option_set_no_auto_window_update()`), and the library * decided that the WINDOW_UPDATE should be submitted, then - * WINDOW_UPDATE is queued with the current received bytes count. If - * the sole purpose is to decrease the local window size, consider to - * use `nghttp2_session_set_local_window_size()`. + * WINDOW_UPDATE is queued with the current received bytes count. * * If the |window_size_increment| is 0, the function does nothing and * returns 0. @@ -4125,164 +2922,45 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int nghttp2_submit_window_update(nghttp2_session *session, - uint8_t flags, - int32_t stream_id, - int32_t window_size_increment); +int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags, + int32_t stream_id, + int32_t window_size_increment); /** * @function * - * Set local window size (local endpoints's window size) to the given - * |window_size| for the given stream denoted by |stream_id|. To - * change connection level window size, specify 0 to |stream_id|. To - * increase window size, this function may submit WINDOW_UPDATE frame - * to transmission queue. + * Submits ALTSVC frame with given parameters. * * The |flags| is currently ignored and should be * :enum:`NGHTTP2_FLAG_NONE`. * - * This sounds similar to `nghttp2_submit_window_update()`, but there - * are 2 differences. The first difference is that this function - * takes the absolute value of window size to set, rather than the - * delta. To change the window size, this may be easier to use since - * the application just declares the intended window size, rather than - * calculating delta. The second difference is that - * `nghttp2_submit_window_update()` affects the received bytes count - * which has not acked yet. By the specification of - * `nghttp2_submit_window_update()`, to strictly increase the local - * window size, we have to submit delta including all received bytes - * count, which might not be desirable in some cases. On the other - * hand, this function does not affect the received bytes count. It - * just sets the local window size to the given value. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * The |stream_id| is negative. - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - */ -NGHTTP2_EXTERN int -nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags, - int32_t stream_id, int32_t window_size); - -/** - * @function - * - * Submits extension frame. - * - * Application can pass arbitrary frame flags and stream ID in |flags| - * and |stream_id| respectively. The |payload| is opaque pointer, and - * it can be accessible though ``frame->ext.payload`` in - * :type:`nghttp2_pack_extension_callback`. The library will not own - * passed |payload| pointer. - * - * The application must set :type:`nghttp2_pack_extension_callback` - * using `nghttp2_session_callbacks_set_pack_extension_callback()`. - * - * The application should retain the memory pointed by |payload| until - * the transmission of extension frame is done (which is indicated by - * :type:`nghttp2_on_frame_send_callback`), or transmission fails - * (which is indicated by :type:`nghttp2_on_frame_not_send_callback`). - * If application does not touch this memory region after packing it - * into a wire format, application can free it inside - * :type:`nghttp2_pack_extension_callback`. - * - * The standard HTTP/2 frame cannot be sent with this function, so - * |type| must be strictly grater than 0x9. Otherwise, this function - * will fail with error code :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * :enum:`NGHTTP2_ERR_INVALID_STATE` - * If :type:`nghttp2_pack_extension_callback` is not set. - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * If |type| specifies standard HTTP/2 frame type. The frame - * types in the rage [0x0, 0x9], both inclusive, are standard - * HTTP/2 frame type, and cannot be sent using this function. - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory - */ -NGHTTP2_EXTERN int nghttp2_submit_extension(nghttp2_session *session, - uint8_t type, uint8_t flags, - int32_t stream_id, void *payload); - -/** - * @struct - * - * The payload of ALTSVC frame. ALTSVC frame is a non-critical - * extension to HTTP/2. If this frame is received, and - * `nghttp2_option_set_user_recv_extension_type()` is not set, and - * `nghttp2_option_set_builtin_recv_extension_type()` is set for - * :enum:`NGHTTP2_ALTSVC`, ``nghttp2_extension.payload`` will point to - * this struct. - * - * It has the following members: - */ -typedef struct { - /** - * The pointer to origin which this alternative service is - * associated with. This is not necessarily NULL-terminated. - */ - uint8_t *origin; - /** - * The length of the |origin|. - */ - size_t origin_len; - /** - * The pointer to Alt-Svc field value contained in ALTSVC frame. - * This is not necessarily NULL-terminated. - */ - uint8_t *field_value; - /** - * The length of the |field_value|. - */ - size_t field_value_len; -} nghttp2_ext_altsvc; - -/** - * @function - * - * Submits ALTSVC frame. + * Only the server can send the ALTSVC frame. If |session| is + * initialized as client, this function fails and returns + * :enum:`NGHTTP2_ERR_PROTO`. * - * ALTSVC frame is a non-critical extension to HTTP/2, and defined in - * is defined in `RFC 7383 - * `_. + * If the |protocol_id_len| is 0, the |protocol_id| could be ``NULL``. * - * The |flags| is currently ignored and should be - * :enum:`NGHTTP2_FLAG_NONE`. + * If the |host_len| is 0, the |host| could be ``NULL``. * - * The |origin| points to the origin this alternative service is - * associated with. The |origin_len| is the length of the origin. If - * |stream_id| is 0, the origin must be specified. If |stream_id| is - * not zero, the origin must be empty (in other words, |origin_len| - * must be 0). - * - * The ALTSVC frame is only usable from server side. If this function - * is invoked with client side session, this function returns - * :enum:`NGHTTP2_ERR_INVALID_STATE`. + * If the |origin_len| is 0, the |origin| could be ``NULL``. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory - * :enum:`NGHTTP2_ERR_INVALID_STATE` - * The function is called from client side session + * Out of memory. + * :enum:`NGHTTP2_ERR_PROTO` + * The function is invoked with |session| which was initialized as + * client. * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * The sum of |origin_len| and |field_value_len| is larger than - * 16382; or |origin_len| is 0 while |stream_id| is 0; or - * |origin_len| is not 0 while |stream_id| is not 0. - */ -NGHTTP2_EXTERN int nghttp2_submit_altsvc(nghttp2_session *session, - uint8_t flags, int32_t stream_id, - const uint8_t *origin, - size_t origin_len, - const uint8_t *field_value, - size_t field_value_len); + * The combined length of |protocol_id_len|, |host_len| and + * |origin_len| is is too large. + */ +int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags, + int32_t stream_id, uint32_t max_age, uint16_t port, + const uint8_t *protocol_id, size_t protocol_id_len, + const uint8_t *host, size_t host_len, + const uint8_t *origin, size_t origin_len); /** * @function @@ -4293,8 +2971,7 @@ * returns positive integer if ``lhs->name`` is found to be greater * than ``rhs->name``; or returns 0 otherwise. */ -NGHTTP2_EXTERN int nghttp2_nv_compare_name(const nghttp2_nv *lhs, - const nghttp2_nv *rhs); +int nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs); /** * @function @@ -4302,14 +2979,14 @@ * A helper function for dealing with NPN in client side or ALPN in * server side. The |in| contains peer's protocol list in preferable * order. The format of |in| is length-prefixed and not - * null-terminated. For example, ``h2`` and + * null-terminated. For example, ``HTTP-draft-04/2.0`` and * ``http/1.1`` stored in |in| like this:: * - * in[0] = 2 - * in[1..2] = "h2" - * in[3] = 8 - * in[4..11] = "http/1.1" - * inlen = 12 + * in[0] = 17 + * in[1..17] = "HTTP-draft-04/2.0" + * in[18] = 8 + * in[19..26] = "http/1.1" + * inlen = 27 * * The selection algorithm is as follows: * @@ -4323,10 +3000,12 @@ * non-overlap case). In this case, |out| and |outlen| are left * untouched. * - * Selecting ``h2`` means that ``h2`` is written into |*out| and its - * length (which is 2) is assigned to |*outlen|. + * Selecting ``HTTP-draft-04/2.0`` means that ``HTTP-draft-04/2.0`` is + * written into |*out| and its length (which is 17) is assigned to + * |*outlen|. * - * For ALPN, refer to https://tools.ietf.org/html/rfc7301 + * For ALPN, refer to + * https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-05 * * See http://technotes.googlecode.com/git/nextprotoneg.html for more * details about NPN. @@ -4342,10 +3021,7 @@ * { * int rv; * rv = nghttp2_select_next_protocol(out, outlen, in, inlen); - * if (rv == -1) { - * return SSL_TLSEXT_ERR_NOACK; - * } - * if (rv == 1) { + * if(rv == 1) { * ((MyType*)arg)->http2_selected = 1; * } * return SSL_TLSEXT_ERR_OK; @@ -4354,10 +3030,8 @@ * SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj); * */ -NGHTTP2_EXTERN int nghttp2_select_next_protocol(unsigned char **out, - unsigned char *outlen, - const unsigned char *in, - unsigned int inlen); +int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen); /** * @function @@ -4368,7 +3042,7 @@ * version number and if the condition is not met, this function will * return a ``NULL``. Pass in 0 to skip the version checking. */ -NGHTTP2_EXTERN nghttp2_info *nghttp2_version(int least_version); +nghttp2_info *nghttp2_version(int least_version); /** * @function @@ -4376,7 +3050,7 @@ * Returns nonzero if the :type:`nghttp2_error` library error code * |lib_error| is fatal. */ -NGHTTP2_EXTERN int nghttp2_is_fatal(int lib_error_code); +int nghttp2_is_fatal(int lib_error); /** * @function @@ -4387,7 +3061,7 @@ * Because this is a header field name in HTTP2, the upper cased alphabet * is treated as error. */ -NGHTTP2_EXTERN int nghttp2_check_header_name(const uint8_t *name, size_t len); +int nghttp2_check_header_name(const uint8_t *name, size_t len); /** * @function @@ -4396,7 +3070,7 @@ * is valid according to * http://tools.ietf.org/html/rfc7230#section-3.2 */ -NGHTTP2_EXTERN int nghttp2_check_header_value(const uint8_t *value, size_t len); +int nghttp2_check_header_value(const uint8_t *value, size_t len); /* HPACK API */ @@ -4425,34 +3099,15 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, - size_t deflate_hd_table_bufsize_max); - -/** - * @function - * - * Like `nghttp2_hd_deflate_new()`, but with additional custom memory - * allocator specified in the |mem|. - * - * The |mem| can be ``NULL`` and the call is equivalent to - * `nghttp2_hd_deflate_new()`. - * - * This function does not take ownership |mem|. The application is - * responsible for freeing |mem|. - * - * The library code does not refer to |mem| pointer after this - * function returns, so the application can safely free it. - */ -NGHTTP2_EXTERN int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr, - size_t deflate_hd_table_bufsize_max, - nghttp2_mem *mem); +int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, + size_t deflate_hd_table_bufsize_max); /** * @function * * Deallocates any resources allocated for |deflater|. */ -NGHTTP2_EXTERN void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater); +void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater); /** * @function @@ -4477,9 +3132,8 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int -nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater, - size_t settings_hd_table_bufsize_max); +int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater, + size_t settings_hd_table_bufsize_max); /** * @function @@ -4508,9 +3162,9 @@ * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE` * The provided |buflen| size is too small to hold the output. */ -NGHTTP2_EXTERN ssize_t -nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, - size_t buflen, const nghttp2_nv *nva, size_t nvlen); +ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, + size_t buflen, const nghttp2_nv *nva, + size_t nvlen); /** * @function @@ -4518,51 +3172,8 @@ * Returns an upper bound on the compressed size after deflation of * |nva| of length |nvlen|. */ -NGHTTP2_EXTERN size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, - const nghttp2_nv *nva, - size_t nvlen); - -/** - * @function - * - * Returns the number of entries that header table of |deflater| - * contains. This is the sum of the number of static table and - * dynamic table, so the return value is at least 61. - */ -NGHTTP2_EXTERN -size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater); - -/** - * @function - * - * Returns the table entry denoted by |idx| from header table of - * |deflater|. The |idx| is 1-based, and idx=1 returns first entry of - * static table. idx=62 returns first entry of dynamic table if it - * exists. Specifying idx=0 is error, and this function returns NULL. - * If |idx| is strictly greater than the number of entries the tables - * contain, this function returns NULL. - */ -NGHTTP2_EXTERN -const nghttp2_nv * -nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx); - -/** - * @function - * - * Returns the used dynamic table size, including the overhead 32 - * bytes per entry described in RFC 7541. - */ -NGHTTP2_EXTERN -size_t nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater); - -/** - * @function - * - * Returns the maximum dynamic table size. - */ -NGHTTP2_EXTERN -size_t -nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater); +size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, + const nghttp2_nv *nva, size_t nvlen); struct nghttp2_hd_inflater; @@ -4586,32 +3197,14 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -NGHTTP2_EXTERN int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr); - -/** - * @function - * - * Like `nghttp2_hd_inflate_new()`, but with additional custom memory - * allocator specified in the |mem|. - * - * The |mem| can be ``NULL`` and the call is equivalent to - * `nghttp2_hd_inflate_new()`. - * - * This function does not take ownership |mem|. The application is - * responsible for freeing |mem|. - * - * The library code does not refer to |mem| pointer after this - * function returns, so the application can safely free it. - */ -NGHTTP2_EXTERN int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr, - nghttp2_mem *mem); +int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr); /** * @function * * Deallocates any resources allocated for |inflater|. */ -NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater); +void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater); /** * @function @@ -4622,26 +3215,14 @@ * The |settings_hd_table_bufsize_max| should be the value transmitted * in SETTINGS_HEADER_TABLE_SIZE. * - * This function must not be called while header block is being - * inflated. In other words, this function must be called after - * initialization of |inflater|, but before calling - * `nghttp2_hd_inflate_hd2()`, or after - * `nghttp2_hd_inflate_end_headers()`. Otherwise, - * `NGHTTP2_ERR_INVALID_STATE` was returned. - * * This function returns 0 if it succeeds, or one of the following * negative error codes: * * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. - * :enum:`NGHTTP2_ERR_INVALID_STATE` - * The function is called while header block is being inflated. - * Probably, application missed to call - * `nghttp2_hd_inflate_end_headers()`. - */ -NGHTTP2_EXTERN int -nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater, - size_t settings_hd_table_bufsize_max); + */ +int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater, + size_t settings_hd_table_bufsize_max); /** * @enum @@ -4666,10 +3247,6 @@ /** * @function * - * .. warning:: - * - * Deprecated. Use `nghttp2_hd_inflate_hd2()` instead. - * * Inflates name/value block stored in |in| with length |inlen|. This * function performs decompression. For each successful emission of * header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in @@ -4700,7 +3277,7 @@ * :enum:`NGHTTP2_ERR_HEADER_COMP` * Inflation process has failed. * :enum:`NGHTTP2_ERR_BUFFER_ERROR` - * The header field name or value is too large. + * The heder field name or value is too large. * * Example follows:: * @@ -4744,92 +3321,9 @@ * } * */ -NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, - nghttp2_nv *nv_out, - int *inflate_flags, uint8_t *in, - size_t inlen, int in_final); - -/** - * @function - * - * Inflates name/value block stored in |in| with length |inlen|. This - * function performs decompression. For each successful emission of - * header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in - * |*inflate_flags| and name/value pair is assigned to the |nv_out| - * and the function returns. The caller must not free the members of - * |nv_out|. - * - * The |nv_out| may include pointers to the memory region in the |in|. - * The caller must retain the |in| while the |nv_out| is used. - * - * The application should call this function repeatedly until the - * ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and - * return value is non-negative. This means the all input values are - * processed successfully. Then the application must call - * `nghttp2_hd_inflate_end_headers()` to prepare for the next header - * block input. - * - * The caller can feed complete compressed header block. It also can - * feed it in several chunks. The caller must set |in_final| to - * nonzero if the given input is the last block of the compressed - * header. - * - * This function returns the number of bytes processed if it succeeds, - * or one of the following negative error codes: - * - * :enum:`NGHTTP2_ERR_NOMEM` - * Out of memory. - * :enum:`NGHTTP2_ERR_HEADER_COMP` - * Inflation process has failed. - * :enum:`NGHTTP2_ERR_BUFFER_ERROR` - * The header field name or value is too large. - * - * Example follows:: - * - * int inflate_header_block(nghttp2_hd_inflater *hd_inflater, - * uint8_t *in, size_t inlen, int final) - * { - * ssize_t rv; - * - * for(;;) { - * nghttp2_nv nv; - * int inflate_flags = 0; - * - * rv = nghttp2_hd_inflate_hd2(hd_inflater, &nv, &inflate_flags, - * in, inlen, final); - * - * if(rv < 0) { - * fprintf(stderr, "inflate failed with error code %zd", rv); - * return -1; - * } - * - * in += rv; - * inlen -= rv; - * - * if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { - * fwrite(nv.name, nv.namelen, 1, stderr); - * fprintf(stderr, ": "); - * fwrite(nv.value, nv.valuelen, 1, stderr); - * fprintf(stderr, "\n"); - * } - * if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) { - * nghttp2_hd_inflate_end_headers(hd_inflater); - * break; - * } - * if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && - * inlen == 0) { - * break; - * } - * } - * - * return 0; - * } - * - */ -NGHTTP2_EXTERN ssize_t -nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, - int *inflate_flags, const uint8_t *in, size_t inlen, - int in_final); +ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, + int *inflate_flags, uint8_t *in, size_t inlen, + int in_final); /** * @function @@ -4839,185 +3333,7 @@ * This function returns 0 if it succeeds. Currently this function * always succeeds. */ -NGHTTP2_EXTERN int -nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater); - -/** - * @function - * - * Returns the number of entries that header table of |inflater| - * contains. This is the sum of the number of static table and - * dynamic table, so the return value is at least 61. - */ -NGHTTP2_EXTERN -size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater); - -/** - * @function - * - * Returns the table entry denoted by |idx| from header table of - * |inflater|. The |idx| is 1-based, and idx=1 returns first entry of - * static table. idx=62 returns first entry of dynamic table if it - * exists. Specifying idx=0 is error, and this function returns NULL. - * If |idx| is strictly greater than the number of entries the tables - * contain, this function returns NULL. - */ -NGHTTP2_EXTERN -const nghttp2_nv * -nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx); - -/** - * @function - * - * Returns the used dynamic table size, including the overhead 32 - * bytes per entry described in RFC 7541. - */ -NGHTTP2_EXTERN -size_t nghttp2_hd_inflate_get_dynamic_table_size(nghttp2_hd_inflater *inflater); - -/** - * @function - * - * Returns the maximum dynamic table size. - */ -NGHTTP2_EXTERN -size_t -nghttp2_hd_inflate_get_max_dynamic_table_size(nghttp2_hd_inflater *inflater); - -struct nghttp2_stream; - -/** - * @struct - * - * The structure to represent HTTP/2 stream. The details of this - * structure are intentionally hidden from the public API. - */ -typedef struct nghttp2_stream nghttp2_stream; - -/** - * @function - * - * Returns pointer to :type:`nghttp2_stream` object denoted by - * |stream_id|. If stream was not found, returns NULL. - * - * Returns imaginary root stream (see - * `nghttp2_session_get_root_stream()`) if 0 is given in |stream_id|. - * - * Unless |stream_id| == 0, the returned pointer is valid until next - * call of `nghttp2_session_send()`, `nghttp2_session_mem_send()`, - * `nghttp2_session_recv()`, and `nghttp2_session_mem_recv()`. - */ -NGHTTP2_EXTERN nghttp2_stream * -nghttp2_session_find_stream(nghttp2_session *session, int32_t stream_id); - -/** - * @enum - * - * State of stream as described in RFC 7540. - */ -typedef enum { - /** - * idle state. - */ - NGHTTP2_STREAM_STATE_IDLE = 1, - /** - * open state. - */ - NGHTTP2_STREAM_STATE_OPEN, - /** - * reserved (local) state. - */ - NGHTTP2_STREAM_STATE_RESERVED_LOCAL, - /** - * reserved (remote) state. - */ - NGHTTP2_STREAM_STATE_RESERVED_REMOTE, - /** - * half closed (local) state. - */ - NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL, - /** - * half closed (remote) state. - */ - NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE, - /** - * closed state. - */ - NGHTTP2_STREAM_STATE_CLOSED -} nghttp2_stream_proto_state; - -/** - * @function - * - * Returns state of |stream|. The root stream retrieved by - * `nghttp2_session_get_root_stream()` will have stream state - * :enum:`NGHTTP2_STREAM_STATE_IDLE`. - */ -NGHTTP2_EXTERN nghttp2_stream_proto_state -nghttp2_stream_get_state(nghttp2_stream *stream); - -/** - * @function - * - * Returns root of dependency tree, which is imaginary stream with - * stream ID 0. The returned pointer is valid until |session| is - * freed by `nghttp2_session_del()`. - */ -NGHTTP2_EXTERN nghttp2_stream * -nghttp2_session_get_root_stream(nghttp2_session *session); - -/** - * @function - * - * Returns the parent stream of |stream| in dependency tree. Returns - * NULL if there is no such stream. - */ -NGHTTP2_EXTERN nghttp2_stream * -nghttp2_stream_get_parent(nghttp2_stream *stream); - -NGHTTP2_EXTERN int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream); - -/** - * @function - * - * Returns the next sibling stream of |stream| in dependency tree. - * Returns NULL if there is no such stream. - */ -NGHTTP2_EXTERN nghttp2_stream * -nghttp2_stream_get_next_sibling(nghttp2_stream *stream); - -/** - * @function - * - * Returns the previous sibling stream of |stream| in dependency tree. - * Returns NULL if there is no such stream. - */ -NGHTTP2_EXTERN nghttp2_stream * -nghttp2_stream_get_previous_sibling(nghttp2_stream *stream); - -/** - * @function - * - * Returns the first child stream of |stream| in dependency tree. - * Returns NULL if there is no such stream. - */ -NGHTTP2_EXTERN nghttp2_stream * -nghttp2_stream_get_first_child(nghttp2_stream *stream); - -/** - * @function - * - * Returns dependency weight to the parent stream of |stream|. - */ -NGHTTP2_EXTERN int32_t nghttp2_stream_get_weight(nghttp2_stream *stream); - -/** - * @function - * - * Returns the sum of the weight for |stream|'s children. - */ -NGHTTP2_EXTERN int32_t -nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream); +int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater); #ifdef __cplusplus } diff -Nru nghttp2-1.13.0/lib/includes/nghttp2/nghttp2ver.h nghttp2-0.6.7/lib/includes/nghttp2/nghttp2ver.h --- nghttp2-1.13.0/lib/includes/nghttp2/nghttp2ver.h 2016-07-21 13:48:06.000000000 +0000 +++ nghttp2-0.6.7/lib/includes/nghttp2/nghttp2ver.h 2014-11-30 14:15:56.000000000 +0000 @@ -29,7 +29,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "1.13.0" +#define NGHTTP2_VERSION "0.6.7" /** * @macro @@ -37,6 +37,6 @@ * release. This is a 24 bit number with 8 bits for major number, 8 bits * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. */ -#define NGHTTP2_VERSION_NUM 0x010d00 +#define NGHTTP2_VERSION_NUM 0x000607 #endif /* NGHTTP2VER_H */ diff -Nru nghttp2-1.13.0/lib/Makefile.am nghttp2-0.6.7/lib/Makefile.am --- nghttp2-1.13.0/lib/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -22,11 +22,10 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = includes -EXTRA_DIST = Makefile.msvc CMakeLists.txt +EXTRA_DIST = Makefile.msvc -AM_CFLAGS = $(WARNCFLAGS) $(EXTRACFLAG) -AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes -DBUILDING_NGHTTP2 \ - @DEFS@ +AM_CFLAGS = -Wall +AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes @DEFS@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libnghttp2.pc @@ -45,10 +44,7 @@ nghttp2_version.c \ nghttp2_priority_spec.c \ nghttp2_option.c \ - nghttp2_callbacks.c \ - nghttp2_mem.c \ - nghttp2_http.c \ - nghttp2_rcbuf.c + nghttp2_callbacks.c HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ nghttp2_frame.h \ @@ -60,10 +56,7 @@ nghttp2_hd.h nghttp2_hd_huffman.h \ nghttp2_priority_spec.h \ nghttp2_option.h \ - nghttp2_callbacks.h \ - nghttp2_mem.h \ - nghttp2_http.h \ - nghttp2_rcbuf.h + nghttp2_callbacks.h libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS) libnghttp2_la_LDFLAGS = -no-undefined \ diff -Nru nghttp2-1.13.0/lib/Makefile.in nghttp2-0.6.7/lib/Makefile.in --- nghttp2-1.13.0/lib/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/lib/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -31,17 +31,7 @@ VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -106,6 +96,8 @@ host_triplet = @host@ target_triplet = @target@ subdir = lib +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(srcdir)/libnghttp2.pc.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -115,13 +107,11 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = libnghttp2.pc @@ -163,8 +153,7 @@ nghttp2_helper.lo nghttp2_npn.lo nghttp2_hd.lo \ nghttp2_hd_huffman.lo nghttp2_hd_huffman_data.lo \ nghttp2_version.lo nghttp2_priority_spec.lo nghttp2_option.lo \ - nghttp2_callbacks.lo nghttp2_mem.lo nghttp2_http.lo \ - nghttp2_rcbuf.lo + nghttp2_callbacks.lo am_libnghttp2_la_OBJECTS = $(am__objects_1) $(am__objects_2) libnghttp2_la_OBJECTS = $(am_libnghttp2_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -252,8 +241,6 @@ ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) -am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/libnghttp2.pc.in \ - $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -283,7 +270,6 @@ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -302,7 +288,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -318,7 +303,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -334,10 +318,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -349,7 +329,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -387,11 +366,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -446,7 +424,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -468,11 +445,9 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = includes -EXTRA_DIST = Makefile.msvc CMakeLists.txt -AM_CFLAGS = $(WARNCFLAGS) $(EXTRACFLAG) -AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes -DBUILDING_NGHTTP2 \ - @DEFS@ - +EXTRA_DIST = Makefile.msvc +AM_CFLAGS = -Wall +AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes @DEFS@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libnghttp2.pc DISTCLEANFILES = $(pkgconfig_DATA) @@ -488,10 +463,7 @@ nghttp2_version.c \ nghttp2_priority_spec.c \ nghttp2_option.c \ - nghttp2_callbacks.c \ - nghttp2_mem.c \ - nghttp2_http.c \ - nghttp2_rcbuf.c + nghttp2_callbacks.c HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ nghttp2_frame.h \ @@ -503,10 +475,7 @@ nghttp2_hd.h nghttp2_hd_huffman.h \ nghttp2_priority_spec.h \ nghttp2_option.h \ - nghttp2_callbacks.h \ - nghttp2_mem.h \ - nghttp2_http.h \ - nghttp2_rcbuf.h + nghttp2_callbacks.h libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS) libnghttp2_la_LDFLAGS = -no-undefined \ @@ -528,6 +497,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -599,16 +569,13 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_hd_huffman.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_hd_huffman_data.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_helper.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_http.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_map.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_mem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_npn.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_option.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_outbound_item.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_pq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_priority_spec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_queue.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_rcbuf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_submit.Plo@am__quote@ @@ -947,8 +914,6 @@ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-pkgconfigDATA -.PRECIOUS: Makefile - # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru nghttp2-1.13.0/lib/Makefile.msvc nghttp2-0.6.7/lib/Makefile.msvc --- nghttp2-1.13.0/lib/Makefile.msvc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/Makefile.msvc 2014-11-30 14:15:07.000000000 +0000 @@ -2,107 +2,81 @@ # GNU Makefile for nghttp2 / MSVC. # # By G. Vanem 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. # -THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) +ZLIB_ROOT = g:/MingW32/src/Compression/zlib-1.2.8 +USE_CYTHON = 1 -USE_CYTHON := 0 -#USE_CYTHON := 1 +_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV], //g') +_VERSION := $(subst ., ,$(_VERSION)) +VER_MAJOR = $(word 1,$(_VERSION)) +VER_MINOR = $(word 2,$(_VERSION)) +VER_MICRO = $(word 3,$(_VERSION)) +VERSION = $(VER_MAJOR).$(VER_MINOR).$(VER_MICRO) +VERSION_NUM = ($(VER_MAJOR) << 16) + ($(VER_MINOR) << 8) + $(VER_MICRO) -_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV//g' -e 's/], //g') -_VERSION := $(subst ., ,$(_VERSION)) -VER_MAJOR := $(word 1,$(_VERSION)) -VER_MINOR := $(word 2,$(_VERSION)) -VER_MICRO := $(word 3,$(_VERSION)) -VERSION := $(VER_MAJOR).$(VER_MINOR).$(VER_MICRO) -VERSION_NUM := (($(VER_MAJOR) << 16) + ($(VER_MINOR) << 8) + $(VER_MICRO)) - -GENERATED := 'Generated by $(realpath Makefile.MSVC)' - -OBJ_DIR := MSVC_obj -#SUFFIX :=-vc90-mt-x86 +GENERATED = 'Generated by $(realpath Makefile.MSVC)' # # Where to copy nghttp2.dll + lib + headers to. # Note: 'make install' is not in default targets. Do it explicitly. # -TARGET_DIR ?= ../_VC_ROOT -VC_ROOT := $(abspath $(TARGET_DIR)) -INSTALL_BIN := $(VC_ROOT)/bin -INSTALL_LIB := $(VC_ROOT)/lib -INSTALL_HDR := $(VC_ROOT)/include -DLL_R := $(OBJ_DIR)/nghttp2$(SUFFIX).dll -DLL_D := $(OBJ_DIR)/nghttp2d$(SUFFIX).dll -LIB_R := $(OBJ_DIR)/nghttp2-static.lib -LIB_D := $(OBJ_DIR)/nghttp2d-static.lib -IMP_R := $(OBJ_DIR)/nghttp2.lib -IMP_D := $(OBJ_DIR)/nghttp2d.lib +VC_ROOT = $(realpath $(VCINSTALLDIR)) +INSTALL_BIN = $(VC_ROOT)/bin +INSTALL_LIB = $(VC_ROOT)/lib +INSTALL_HDR = $(VC_ROOT)/include # # Build for DEBUG-model and RELEASE at the same time. # -TARGETS := $(LIB_R) $(DLL_R) $(IMP_R) \ - $(LIB_D) $(DLL_D) $(IMP_D) +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 -NGHTTP2_PDB_R := $(OBJ_DIR)/nghttp2.pdb -NGHTTP2_PDB_D := $(OBJ_DIR)/nghttp2d.pdb +NGHTTP2_PDB_R = $(OBJ_DIR)/nghttp2.pdb +NGHTTP2_PDB_D = $(OBJ_DIR)/nghttp2d.pdb CC = cl -LD := link -AR := lib -#CC := icl -#LD := xilink -#AR := xilib -RC := rc -CFLAGS := -I./includes -Dssize_t=long -D_U_="" +CFLAGS = -I./includes -I$(ZLIB_ROOT) -DHAVE_WINSOCK2_H -Dssize_t=long -CFLAGS_R := -nologo -MD -W3 -Z7 -DBUILDING_NGHTTP2 -CFLAGS_D := -nologo -MDd -W3 -Z7 -DBUILDING_NGHTTP2 \ +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 -MAP -debug -incremental:no -opt:ref,icf -MANIFEST # -verbose +LDFLAGS = -nologo -machine:i386 -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_rcbuf.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))) - -.PHONY: all intro test_ver install copy_headers_and_libs \ - install_nghttp2_pyd_0 install_nghttp2_pyd_1 \ - build_nghttp2_pyd_0 build_nghttp2_pyd_1 \ - clean_nghttp2_pyd_0 clean_nghttp2_pyd_1 +NGHTTP2_OBJ_R = $(addprefix $(OBJ_DIR)/r_, $(notdir $(NGHTTP2_SRC:.c=.obj))) +NGHTTP2_OBJ_D = $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj))) - -all: intro includes/nghttp2/nghttp2ver.h $(OBJ_DIR) $(TARGETS) build_nghttp2_pyd_$(USE_CYTHON) +all: intro $(OBJ_DIR) $(TARGETS) @echo 'Welcome to NgHTTP2 (release + debug).' @echo 'Do a "make -f Makefile.MSVC install" at own risk!' @@ -120,91 +94,76 @@ - mkdir $(OBJ_DIR) install: includes/nghttp2/nghttp2.h includes/nghttp2/nghttp2ver.h \ - $(TARGETS) \ - copy_headers_and_libs install_nghttp2_pyd_$(USE_CYTHON) + nghttp2.dll nghttp2.lib nghttp2_imp.lib \ + nghttp2d.dll nghttp2d.lib nghttp2d_imp.lib \ + copy_headers_and_libs install_nghttp2_pyd_$(USE_CYTHON) # # This MUST be done before using the 'install_nghttp2_pyd_1' rule. # copy_headers_and_libs: - - mkdir -p $(INSTALL_HDR)/nghttp2 $(INSTALL_BIN) $(INSTALL_LIB) + - mkdir $(INSTALL_HDR)/nghttp2 cp --update $(addprefix includes/nghttp2/, nghttp2.h nghttp2ver.h) $(INSTALL_HDR)/nghttp2 - cp --update $(DLL_R) $(DLL_D) $(NGHTTP2_PDB_R) $(NGHTTP2_PDB_D) $(INSTALL_BIN) - cp --update $(IMP_R) $(IMP_D) $(LIB_R) $(LIB_D) $(INSTALL_LIB) + cp --update nghttp2.dll nghttp2d.dll $(NGHTTP2_PDB_R) $(NGHTTP2_PDB_D) $(INSTALL_BIN) + cp --update nghttp2.lib nghttp2d.lib nghttp2_imp.lib nghttp2d_imp.lib $(INSTALL_LIB) @echo -$(LIB_R): $(NGHTTP2_OBJ_R) - $(AR) -nologo -out:$@ $^ +nghttp2.lib: $(NGHTTP2_OBJ_R) + lib -nologo -out:$@ $^ @echo -$(LIB_D): $(NGHTTP2_OBJ_D) - $(AR) -nologo -out:$@ $^ +nghttp2d.lib: $(NGHTTP2_OBJ_D) + lib -nologo -out:$@ $^ @echo - -$(IMP_R): $(DLL_R) - -$(DLL_R): $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res - $(LD) $(LDFLAGS) -dll -out:$@ -implib:$(IMP_R) $(NGHTTP2_OBJ_R) -PDB:$(NGHTTP2_PDB_R) $(OBJ_DIR)/r_nghttp2.res $(EXT_LIBS) - mt -nologo -manifest $@.manifest -outputresource:$@\;2 +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_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(EXT_LIBS) @echo -$(IMP_D): $(DLL_D) - -$(DLL_D): $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res - $(LD) $(LDFLAGS) -dll -out:$@ -implib:$(IMP_D) $(NGHTTP2_OBJ_D) -PDB:$(NGHTTP2_PDB_D) $(OBJ_DIR)/d_nghttp2.res $(EXT_LIBS) - mt -nologo -manifest $@.manifest -outputresource:$@\;2 +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 \ + $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(EXT_LIBS) @echo +install_nghttp2_pyd_0: ; -WIN_OBJDIR:=$(shell cygpath -w $(abspath $(OBJ_DIR))) -WIN_OBJDIR:=$(subst \,/,$(WIN_OBJDIR)) - -../python/setup.py: ../python/setup.py.in $(THIS_MAKEFILE) +install_nghttp2_pyd_1: $(addprefix ../python/, setup.py.in nghttp2.pyx) cd ../python ; \ echo '# $(GENERATED). DO NOT EDIT.' > setup.py ; \ sed -e 's/@top_srcdir@/../' \ - -e 's%@top_builddir@%$(WIN_OBJDIR)%' \ - -e 's/@PACKAGE_VERSION@/$(VERSION)/' setup.py.in >> setup.py ; - -build_nghttp2_pyd_0: ; - -build_nghttp2_pyd_1: $(addprefix ../python/, setup.py nghttp2.pyx) - cd ../python ; \ - python setup.py build_ext -i -f bdist_wininst - -install_nghttp2_pyd_0: ; - -install_nghttp2_pyd_1: $(addprefix ../python/, setup.py nghttp2.pyx) - cd ../python ; \ - pip install . + -e 's/@top_builddir@/../' \ + -e 's/@PACKAGE_VERSION@/$(VERSION)/' setup.py.in >> setup.py ; \ + cython -v nghttp2.pyx ; \ + python setup.py install clean_nghttp2_pyd_0: ; clean_nghttp2_pyd_1: cd ../python ; \ - rm -fR build dist + rm -f setup.py nghttp2.c ; \ + rm -fR build/* -$(OBJ_DIR)/r_%.obj: %.c $(THIS_MAKEFILE) +$(OBJ_DIR)/r_%.obj: %.c $(CC) $(CFLAGS_R) $(CFLAGS) -Fo$@ -c $< @echo -$(OBJ_DIR)/d_%.obj: %.c $(THIS_MAKEFILE) +$(OBJ_DIR)/d_%.obj: %.c $(CC) $(CFLAGS_D) $(CFLAGS) -Fo$@ -c $< @echo -$(OBJ_DIR)/r_nghttp2.res: $(OBJ_DIR)/nghttp2.rc $(THIS_MAKEFILE) - $(RC) -D_RELEASE -Fo $@ $< +$(OBJ_DIR)/r_nghttp2.res: nghttp2.rc + rc -nologo -D_RELEASE -Fo $@ $< @echo -$(OBJ_DIR)/d_nghttp2.res: $(OBJ_DIR)/nghttp2.rc $(THIS_MAKEFILE) - $(RC) -D_DEBUG -Fo $@ $< +$(OBJ_DIR)/d_nghttp2.res: nghttp2.rc + rc -nologo -D_DEBUG -Fo $@ $< @echo -includes/nghttp2/nghttp2ver.h: includes/nghttp2/nghttp2ver.h.in $(THIS_MAKEFILE) +includes/nghttp2/nghttp2ver.h: includes/nghttp2/nghttp2ver.h.in sed < includes/nghttp2/nghttp2ver.h.in \ -e 's/@PACKAGE_VERSION@/$(VERSION)/g' \ - -e 's/@PACKAGE_VERSION_NUM@/$(VERSION_NUM)/g' > $@ + -e 's/@PACKAGE_VERSION_NUM@/($(VERSION_NUM))/g' > $@ touch --reference=includes/nghttp2/nghttp2ver.h.in $@ @@ -241,6 +200,8 @@ VALUE "OriginalFilename", "nghttp2" DBG ".dll" VALUE "ProductName", "NGHTTP2." VALUE "ProductVersion", VER_STR + VALUE "PrivateBuild", "The privat build of ." + VALUE "SpecialBuild", "" END END BLOCK "VarFileInfo" @@ -252,19 +213,38 @@ export RES_FILE -$(OBJ_DIR)/nghttp2.rc: Makefile.MSVC +nghttp2.rc: Makefile.MSVC @echo 'Generating $@...' @echo ' /* $(GENERATED). DO NOT EDIT.' > $@ @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)/* includes/nghttp2/nghttp2ver.h + rm -f $(OBJ_DIR)/* nghttp2_imp.exp nghttp2_imp.exp \ + nghttp2.map nghttp2d.map nghttp2.rc includes/nghttp2/nghttp2ver.h @echo vclean realclean: clean clean_nghttp2_pyd_$(USE_CYTHON) - - rm -rf $(OBJ_DIR) - - rm -f .depend.MSVC + rm -f $(TARGETS) nghttp2.pdb nghttp2d.pdb nghttp2_imp.exp nghttp2d_imp.exp .depend.MSVC + - rmdir $(OBJ_DIR) # # Use gcc to generated the dependencies. No MSVC specific args please! @@ -283,4 +263,4 @@ sed -e $(REPLACE_D) .depend.tmp >> .depend.MSVC rm -f .depend.tmp --include .depend.MSVC +-include .depend.MSVC \ No newline at end of file diff -Nru nghttp2-1.13.0/lib/nghttp2_buf.c nghttp2-0.6.7/lib/nghttp2_buf.c --- nghttp2-1.13.0/lib/nghttp2_buf.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_buf.c 2014-11-30 14:15:07.000000000 +0000 @@ -36,21 +36,21 @@ buf->mark = NULL; } -int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem) { +int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial) { nghttp2_buf_init(buf); - return nghttp2_buf_reserve(buf, initial, mem); + return nghttp2_buf_reserve(buf, initial); } -void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem) { +void nghttp2_buf_free(nghttp2_buf *buf) { if (buf == NULL) { return; } - nghttp2_mem_free(mem, buf->begin); + free(buf->begin); buf->begin = NULL; } -int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem) { +int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap) { uint8_t *ptr; size_t cap; @@ -62,7 +62,7 @@ new_cap = nghttp2_max(new_cap, cap * 2); - ptr = nghttp2_mem_realloc(mem, buf->begin, new_cap); + ptr = realloc(buf->begin, new_cap); if (ptr == NULL) { return NGHTTP2_ERR_NOMEM; } @@ -85,45 +85,42 @@ buf->end = begin + len; } -static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length, - nghttp2_mem *mem) { +static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length) { int rv; - *chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain)); + *chain = malloc(sizeof(nghttp2_buf_chain)); if (*chain == NULL) { return NGHTTP2_ERR_NOMEM; } (*chain)->next = NULL; - rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length, mem); + rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length); if (rv != 0) { - nghttp2_mem_free(mem, *chain); + free(*chain); return NGHTTP2_ERR_NOMEM; } return 0; } -static void buf_chain_del(nghttp2_buf_chain *chain, nghttp2_mem *mem) { - nghttp2_buf_free(&chain->buf, mem); - nghttp2_mem_free(mem, chain); +static void buf_chain_del(nghttp2_buf_chain *chain) { + nghttp2_buf_free(&chain->buf); + free(chain); } -int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk, - nghttp2_mem *mem) { - return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0, mem); +int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, + size_t max_chunk) { + return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0); } int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length, - size_t max_chunk, size_t offset, nghttp2_mem *mem) { - return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset, - mem); + size_t max_chunk, size_t offset) { + return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset); } int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length, - size_t max_chunk, size_t chunk_keep, size_t offset, - nghttp2_mem *mem) { + size_t max_chunk, size_t chunk_keep, size_t offset) { int rv; nghttp2_buf_chain *chain; @@ -131,12 +128,11 @@ return NGHTTP2_ERR_INVALID_ARGUMENT; } - rv = buf_chain_new(&chain, chunk_length, mem); + rv = buf_chain_new(&chain, chunk_length); if (rv != 0) { return rv; } - bufs->mem = mem; bufs->offset = offset; bufs->head = chain; @@ -160,7 +156,7 @@ return NGHTTP2_ERR_INVALID_ARGUMENT; } - rv = buf_chain_new(&chain, chunk_length, bufs->mem); + rv = buf_chain_new(&chain, chunk_length); if (rv != 0) { return rv; } @@ -188,7 +184,7 @@ for (chain = bufs->head; chain;) { next_chain = chain->next; - buf_chain_del(chain, bufs->mem); + buf_chain_del(chain); chain = next_chain; } @@ -196,11 +192,10 @@ bufs->head = NULL; } -int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len, - nghttp2_mem *mem) { +int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len) { nghttp2_buf_chain *chain; - chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain)); + chain = malloc(sizeof(nghttp2_buf_chain)); if (chain == NULL) { return NGHTTP2_ERR_NOMEM; } @@ -209,7 +204,6 @@ nghttp2_buf_wrap_init(&chain->buf, begin, len); - bufs->mem = mem; bufs->offset = 0; bufs->head = chain; @@ -228,7 +222,7 @@ return; } - nghttp2_mem_free(bufs->mem, bufs->head); + free(bufs->head); bufs->head = NULL; } @@ -244,9 +238,9 @@ } } -size_t nghttp2_bufs_len(nghttp2_bufs *bufs) { +ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs) { nghttp2_buf_chain *ci; - size_t len; + ssize_t len; len = 0; for (ci = bufs->head; ci; ci = ci->next) { @@ -256,10 +250,10 @@ return len; } -static size_t bufs_avail(nghttp2_bufs *bufs) { - return nghttp2_buf_avail(&bufs->cur->buf) + - (bufs->chunk_length - bufs->offset) * - (bufs->max_chunk - bufs->chunk_used); +static ssize_t bufs_avail(nghttp2_bufs *bufs) { + return (ssize_t)(nghttp2_buf_avail(&bufs->cur->buf) + + (bufs->chunk_length - bufs->offset) * + (bufs->max_chunk - bufs->chunk_used)); } static int bufs_alloc_chain(nghttp2_bufs *bufs) { @@ -276,7 +270,7 @@ return NGHTTP2_ERR_BUFFER_ERROR; } - rv = buf_chain_new(&chain, bufs->chunk_length, bufs->mem); + rv = buf_chain_new(&chain, bufs->chunk_length); if (rv != 0) { return rv; } @@ -301,7 +295,7 @@ nghttp2_buf *buf; const uint8_t *p; - if (bufs_avail(bufs) < len) { + if (bufs_avail(bufs) < (ssize_t)len) { return NGHTTP2_ERR_BUFFER_ERROR; } @@ -310,7 +304,7 @@ while (len) { buf = &bufs->cur->buf; - nwrite = nghttp2_min(nghttp2_buf_avail(buf), len); + nwrite = nghttp2_min((size_t)nghttp2_buf_avail(buf), len); if (nwrite == 0) { rv = bufs_alloc_chain(bufs); if (rv != 0) { @@ -320,7 +314,7 @@ } buf->last = nghttp2_cpymem(buf->last, p, nwrite); - p += nwrite; + p += len; len -= nwrite; } @@ -410,44 +404,34 @@ len += nghttp2_buf_len(&chain->buf); } - if (len == 0) { + if (!len) { res = NULL; - return 0; - } + } else { + res = malloc(len); - res = nghttp2_mem_malloc(bufs->mem, len); - if (res == NULL) { - return NGHTTP2_ERR_NOMEM; + if (res == NULL) { + return NGHTTP2_ERR_NOMEM; + } } nghttp2_buf_wrap_init(&resbuf, res, len); for (chain = bufs->head; chain; chain = chain->next) { buf = &chain->buf; - resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf)); - } - *out = res; - - 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; + if (resbuf.last) { + resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf)); + } - len = nghttp2_bufs_len(bufs); + nghttp2_buf_reset(buf); + nghttp2_buf_shift_right(&chain->buf, bufs->offset); + } - nghttp2_buf_wrap_init(&resbuf, out, len); + bufs->cur = bufs->head; - for (chain = bufs->head; chain; chain = chain->next) { - buf = &chain->buf; - resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf)); - } + *out = res; - return len; + return (ssize_t)len; } void nghttp2_bufs_reset(nghttp2_bufs *bufs) { @@ -472,7 +456,7 @@ for (ci = chain; ci;) { chain = ci->next; - buf_chain_del(ci, bufs->mem); + buf_chain_del(ci); ci = chain; } diff -Nru nghttp2-1.13.0/lib/nghttp2_buf.h nghttp2-0.6.7/lib/nghttp2_buf.h --- nghttp2-1.13.0/lib/nghttp2_buf.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_buf.h 2014-11-30 14:15:07.000000000 +0000 @@ -32,7 +32,6 @@ #include #include "nghttp2_int.h" -#include "nghttp2_mem.h" typedef struct { /* This points to the beginning of the buffer. The effective range @@ -51,13 +50,13 @@ uint8_t *mark; } nghttp2_buf; -#define nghttp2_buf_len(BUF) ((size_t)((BUF)->last - (BUF)->pos)) -#define nghttp2_buf_avail(BUF) ((size_t)((BUF)->end - (BUF)->last)) -#define nghttp2_buf_mark_avail(BUF) ((size_t)((BUF)->mark - (BUF)->last)) -#define nghttp2_buf_cap(BUF) ((size_t)((BUF)->end - (BUF)->begin)) +#define nghttp2_buf_len(BUF) ((ssize_t)((BUF)->last - (BUF)->pos)) +#define nghttp2_buf_avail(BUF) ((ssize_t)((BUF)->end - (BUF)->last)) +#define nghttp2_buf_mark_avail(BUF) ((ssize_t)((BUF)->mark - (BUF)->last)) +#define nghttp2_buf_cap(BUF) ((ssize_t)((BUF)->end - (BUF)->begin)) -#define nghttp2_buf_pos_offset(BUF) ((size_t)((BUF)->pos - (BUF)->begin)) -#define nghttp2_buf_last_offset(BUF) ((size_t)((BUF)->last - (BUF)->begin)) +#define nghttp2_buf_pos_offset(BUF) ((ssize_t)((BUF)->pos - (BUF)->begin)) +#define nghttp2_buf_last_offset(BUF) ((ssize_t)((BUF)->last - (BUF)->begin)) #define nghttp2_buf_shift_right(BUF, AMT) \ do { \ @@ -73,7 +72,7 @@ /* * Initializes the |buf|. No memory is allocated in this function. Use - * nghttp2_buf_reserve() to allocate memory. + * nghttp2_buf_reserve() or nghttp2_buf_reserve2() to allocate memory. */ void nghttp2_buf_init(nghttp2_buf *buf); @@ -87,12 +86,12 @@ * NGHTTP2_ERR_NOMEM * Out of memory */ -int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem); +int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial); /* * Frees buffer in |buf|. */ -void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem); +void nghttp2_buf_free(nghttp2_buf *buf); /* * Extends buffer so that nghttp2_buf_cap() returns at least @@ -105,7 +104,7 @@ * NGHTTP2_ERR_NOMEM * Out of memory */ -int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem); +int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap); /* * Resets pos, last, mark member of |buf| to buf->begin. @@ -136,8 +135,6 @@ nghttp2_buf_chain *head; /* Buffer pointer where write occurs. */ nghttp2_buf_chain *cur; - /* Memory allocator */ - nghttp2_mem *mem; /* The buffer capacity of each buf */ size_t chunk_length; /* The maximum number of nghttp2_buf_chain */ @@ -156,15 +153,15 @@ * This is the same as calling nghttp2_bufs_init2 with the given * arguments and offset = 0. */ -int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk, - nghttp2_mem *mem); +int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, + size_t max_chunk); /* * This is the same as calling nghttp2_bufs_init3 with the given * arguments and chunk_keep = max_chunk. */ int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length, - size_t max_chunk, size_t offset, nghttp2_mem *mem); + size_t max_chunk, size_t offset); /* * Initializes |bufs|. Each buffer size is given in the @@ -186,8 +183,7 @@ * long. */ int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length, - size_t max_chunk, size_t chunk_keep, size_t offset, - nghttp2_mem *mem); + size_t max_chunk, size_t chunk_keep, size_t offset); /* * Frees any related resources to the |bufs|. @@ -207,8 +203,7 @@ * NGHTTP2_ERR_NOMEM * Out of memory. */ -int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len, - nghttp2_mem *mem); +int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len); /* * Frees any related resource to the |bufs|. This function does not @@ -300,24 +295,22 @@ #define nghttp2_bufs_fast_orb(BUFS, B) \ do { \ - uint8_t **p = &(BUFS)->cur->buf.last; \ - **p = (uint8_t)(**p | (B)); \ - ++(*p); \ + *(BUFS)->cur->buf.last++ |= B; \ } while (0) #define nghttp2_bufs_fast_orb_hold(BUFS, B) \ do { \ - uint8_t *p = (BUFS)->cur->buf.last; \ - *p = (uint8_t)(*p | (B)); \ + *(BUFS)->cur->buf.last |= B; \ } while (0) /* - * Copies all data stored in |bufs| to the contiguous buffer. This - * function allocates the contiguous memory to store all data in + * Copies all data stored in |bufs| to the contagious buffer. This + * function allocates the contagious memory to store all data in * |bufs| and assigns it to |*out|. * - * The contents of |bufs| is left unchanged. - * + * On successful return, nghttp2_bufs_len(bufs) returns 0, just like + * after calling nghttp2_bufs_reset(). + * This function returns the length of copied data and assigns the * pointer to copied data to |*out| if it succeeds, or one of the * following negative error codes: @@ -328,17 +321,6 @@ 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. */ void nghttp2_bufs_reset(nghttp2_bufs *bufs); @@ -383,6 +365,6 @@ /* * Returns the buffer length of |bufs|. */ -size_t nghttp2_bufs_len(nghttp2_bufs *bufs); +ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs); #endif /* NGHTTP2_BUF_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_callbacks.c nghttp2-0.6.7/lib/nghttp2_callbacks.c --- nghttp2-1.13.0/lib/nghttp2_callbacks.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_callbacks.c 2014-11-30 14:15:07.000000000 +0000 @@ -104,12 +104,6 @@ cbs->on_header_callback = on_header_callback; } -void nghttp2_session_callbacks_set_on_header_callback2( - nghttp2_session_callbacks *cbs, - nghttp2_on_header_callback2 on_header_callback2) { - cbs->on_header_callback2 = on_header_callback2; -} - void nghttp2_session_callbacks_set_select_padding_callback( nghttp2_session_callbacks *cbs, nghttp2_select_padding_callback select_padding_callback) { @@ -127,32 +121,3 @@ 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; -} - -void nghttp2_session_callbacks_set_pack_extension_callback( - nghttp2_session_callbacks *cbs, - nghttp2_pack_extension_callback pack_extension_callback) { - cbs->pack_extension_callback = pack_extension_callback; -} - -void nghttp2_session_callbacks_set_unpack_extension_callback( - nghttp2_session_callbacks *cbs, - nghttp2_unpack_extension_callback unpack_extension_callback) { - cbs->unpack_extension_callback = unpack_extension_callback; -} - -void nghttp2_session_callbacks_set_on_extension_chunk_recv_callback( - nghttp2_session_callbacks *cbs, - nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback) { - cbs->on_extension_chunk_recv_callback = on_extension_chunk_recv_callback; -} - -void nghttp2_session_callbacks_set_error_callback( - nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback) { - cbs->error_callback = error_callback; -} diff -Nru nghttp2-1.13.0/lib/nghttp2_callbacks.h nghttp2-0.6.7/lib/nghttp2_callbacks.h --- nghttp2-1.13.0/lib/nghttp2_callbacks.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_callbacks.h 2014-11-30 14:15:07.000000000 +0000 @@ -91,7 +91,6 @@ * received. */ nghttp2_on_header_callback on_header_callback; - nghttp2_on_header_callback2 on_header_callback2; /** * Callback function invoked when the library asks application how * many padding bytes are required for the transmission of the given @@ -107,11 +106,6 @@ * 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; - nghttp2_pack_extension_callback pack_extension_callback; - nghttp2_unpack_extension_callback unpack_extension_callback; - nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback; - nghttp2_error_callback error_callback; }; #endif /* NGHTTP2_CALLBACKS_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_frame.c nghttp2-0.6.7/lib/nghttp2_frame.c --- nghttp2-1.13.0/lib/nghttp2_frame.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_frame.c 2014-11-30 14:15:07.000000000 +0000 @@ -37,7 +37,7 @@ nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8)); buf[3] = hd->type; buf[4] = hd->flags; - nghttp2_put_uint32be(&buf[5], (uint32_t)hd->stream_id); + nghttp2_put_uint32be(&buf[5], hd->stream_id); /* ignore hd->reserved for now */ } @@ -75,8 +75,8 @@ } } -void nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem) { - nghttp2_nv_array_del(frame->nva, mem); +void nghttp2_frame_headers_free(nghttp2_headers *frame) { + nghttp2_nv_array_del(frame->nva); } void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id, @@ -105,9 +105,7 @@ frame->iv = iv; } -void nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem) { - nghttp2_mem_free(mem, frame->iv); -} +void nghttp2_frame_settings_free(nghttp2_settings *frame) { free(frame->iv); } void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags, int32_t stream_id, @@ -121,9 +119,8 @@ frame->reserved = 0; } -void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame, - nghttp2_mem *mem) { - nghttp2_nv_array_del(frame->nva, mem); +void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame) { + nghttp2_nv_array_del(frame->nva); } void nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags, @@ -150,8 +147,8 @@ frame->reserved = 0; } -void nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem) { - nghttp2_mem_free(mem, frame->opaque_data); +void nghttp2_frame_goaway_free(nghttp2_goaway *frame) { + free(frame->opaque_data); } void nghttp2_frame_window_update_init(nghttp2_window_update *frame, @@ -164,59 +161,56 @@ void nghttp2_frame_window_update_free(nghttp2_window_update *frame _U_) {} -size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen) { - /* We have iframe->padlen == 0, but iframe->frame.hd.flags may have - NGHTTP2_FLAG_PADDED set. This happens when receiving - CONTINUATION frame, since we don't reset flags after HEADERS was - received. */ - if (padlen == 0) { - return 0; - } - return padlen - ((frame->hd.flags & NGHTTP2_FLAG_PADDED) > 0); -} - -void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags, - int32_t stream_id) { - /* At this moment, the length of DATA frame is unknown */ - nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_DATA, flags, stream_id); - frame->padlen = 0; -} - -void nghttp2_frame_data_free(nghttp2_data *frame _U_) {} - -void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type, - uint8_t flags, int32_t stream_id, - void *payload) { - nghttp2_frame_hd_init(&frame->hd, 0, type, flags, stream_id); - frame->payload = payload; -} - -void nghttp2_frame_extension_free(nghttp2_extension *frame _U_) {} - void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id, - uint8_t *origin, size_t origin_len, - uint8_t *field_value, size_t field_value_len) { + uint32_t max_age, uint16_t port, + uint8_t *protocol_id, size_t protocol_id_len, + uint8_t *host, size_t host_len, uint8_t *origin, + size_t origin_len) { + size_t payloadlen; nghttp2_ext_altsvc *altsvc; - nghttp2_frame_hd_init(&frame->hd, 2 + origin_len + field_value_len, - NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, stream_id); - altsvc = frame->payload; + + payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len + host_len + origin_len; + + nghttp2_frame_hd_init(&frame->hd, payloadlen, NGHTTP2_EXT_ALTSVC, + NGHTTP2_FLAG_NONE, stream_id); + + altsvc->max_age = max_age; + altsvc->port = port; + altsvc->protocol_id = protocol_id; + altsvc->protocol_id_len = protocol_id_len; + altsvc->host = host; + altsvc->host_len = host_len; altsvc->origin = origin; altsvc->origin_len = origin_len; - altsvc->field_value = field_value; - altsvc->field_value_len = field_value_len; } -void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) { +void nghttp2_frame_altsvc_free(nghttp2_extension *frame) { nghttp2_ext_altsvc *altsvc; altsvc = frame->payload; - /* We use the same buffer for altsvc->origin and - altsvc->field_value. */ - nghttp2_mem_free(mem, altsvc->origin); + + if (altsvc == NULL) { + return; + } + + free(altsvc->protocol_id); +} + +size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen) { + return padlen - ((frame->hd.flags & NGHTTP2_FLAG_PADDED) > 0); +} + +void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags, + int32_t stream_id) { + /* At this moment, the length of DATA frame is unknown */ + nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_DATA, flags, stream_id); + frame->padlen = 0; } +void nghttp2_frame_data_free(nghttp2_data *frame _U_) {} + size_t nghttp2_frame_priority_len(uint8_t flags) { if (flags & NGHTTP2_FLAG_PRIORITY) { return NGHTTP2_PRIORITY_SPECLEN; @@ -259,7 +253,7 @@ CONTINUATION frame is involved. Remove END_HEADERS flag from the first frame. */ if (bufs->head != bufs->cur) { - hd.flags = (uint8_t)(hd.flags & ~NGHTTP2_FLAG_END_HEADERS); + hd.flags &= ~NGHTTP2_FLAG_END_HEADERS; } buf->pos -= NGHTTP2_FRAME_HDLEN; @@ -340,11 +334,11 @@ void nghttp2_frame_pack_priority_spec(uint8_t *buf, const nghttp2_priority_spec *pri_spec) { - nghttp2_put_uint32be(buf, (uint32_t)pri_spec->stream_id); + nghttp2_put_uint32be(buf, pri_spec->stream_id); if (pri_spec->exclusive) { buf[0] |= 0x80; } - buf[4] = (uint8_t)(pri_spec->weight - 1); + buf[4] = pri_spec->weight - 1; } void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec, @@ -438,7 +432,7 @@ buf = &bufs->head->buf; - if (nghttp2_buf_avail(buf) < frame->hd.length) { + if (nghttp2_buf_avail(buf) < (ssize_t)frame->hd.length) { return NGHTTP2_ERR_FRAME_SIZE_ERROR; } @@ -457,17 +451,31 @@ size_t niv) { size_t i; for (i = 0; i < niv; ++i, buf += NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) { - nghttp2_put_uint16be(buf, (uint16_t)iv[i].settings_id); + nghttp2_put_uint16be(buf, iv[i].settings_id); nghttp2_put_uint32be(buf + 2, iv[i].value); } return NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH * niv; } -void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame, - nghttp2_settings_entry *iv, - size_t niv) { - frame->iv = iv; +int nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame, + nghttp2_settings_entry *iv, + size_t niv) { + size_t payloadlen = niv * sizeof(nghttp2_settings_entry); + + if (niv == 0) { + frame->iv = NULL; + } else { + frame->iv = malloc(payloadlen); + + if (frame->iv == NULL) { + return NGHTTP2_ERR_NOMEM; + } + + memcpy(frame->iv, iv, payloadlen); + } + frame->niv = niv; + return 0; } void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv, @@ -479,8 +487,7 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr, size_t *niv_ptr, const uint8_t *payload, - size_t payloadlen, - nghttp2_mem *mem) { + size_t payloadlen) { size_t i; *niv_ptr = payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH; @@ -491,8 +498,7 @@ return 0; } - *iv_ptr = - nghttp2_mem_malloc(mem, (*niv_ptr) * sizeof(nghttp2_settings_entry)); + *iv_ptr = malloc((*niv_ptr) * sizeof(nghttp2_settings_entry)); if (*iv_ptr == NULL) { return NGHTTP2_ERR_NOMEM; @@ -533,7 +539,7 @@ return rv; } - nghttp2_put_uint32be(buf->pos, (uint32_t)frame->promised_stream_id); + nghttp2_put_uint32be(buf->pos, frame->promised_stream_id); frame->padlen = 0; frame->hd.length = nghttp2_bufs_len(bufs); @@ -588,7 +594,7 @@ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); - nghttp2_put_uint32be(buf->last, (uint32_t)frame->last_stream_id); + nghttp2_put_uint32be(buf->last, frame->last_stream_id); buf->last += 4; nghttp2_put_uint32be(buf->last, frame->error_code); @@ -621,7 +627,7 @@ int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame, const uint8_t *payload, - size_t payloadlen, nghttp2_mem *mem) { + size_t payloadlen) { uint8_t *var_gift_payload; size_t var_gift_payloadlen; @@ -636,7 +642,7 @@ if (!var_gift_payloadlen) { var_gift_payload = NULL; } else { - var_gift_payload = nghttp2_mem_malloc(mem, var_gift_payloadlen); + var_gift_payload = malloc(var_gift_payloadlen); if (var_gift_payload == NULL) { return NGHTTP2_ERR_NOMEM; @@ -665,7 +671,7 @@ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); - nghttp2_put_uint32be(buf->last, (uint32_t)frame->window_size_increment); + nghttp2_put_uint32be(buf->last, frame->window_size_increment); buf->last += 4; return 0; @@ -683,76 +689,103 @@ nghttp2_buf *buf; nghttp2_ext_altsvc *altsvc; + assert(bufs->head == bufs->cur); + altsvc = frame->payload; buf = &bufs->head->buf; - assert(nghttp2_buf_avail(buf) >= - 2 + altsvc->origin_len + altsvc->field_value_len); - buf->pos -= NGHTTP2_FRAME_HDLEN; nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); - nghttp2_put_uint16be(buf->last, (uint16_t)altsvc->origin_len); + nghttp2_put_uint32be(buf->last, altsvc->max_age); + buf->last += 4; + + nghttp2_put_uint16be(buf->last, altsvc->port); buf->last += 2; - rv = nghttp2_bufs_add(bufs, altsvc->origin, altsvc->origin_len); + buf->last[0] = altsvc->protocol_id_len; + ++buf->last; - assert(rv == 0); + rv = nghttp2_bufs_add(bufs, altsvc->protocol_id, altsvc->protocol_id_len); + if (rv != 0) { + goto fail; + } - rv = nghttp2_bufs_add(bufs, altsvc->field_value, altsvc->field_value_len); + rv = nghttp2_bufs_addb(bufs, altsvc->host_len); + if (rv != 0) { + goto fail; + } - assert(rv == 0); + rv = nghttp2_bufs_add(bufs, altsvc->host, altsvc->host_len); + if (rv != 0) { + goto fail; + } + + rv = nghttp2_bufs_add(bufs, altsvc->origin, altsvc->origin_len); + if (rv != 0) { + goto fail; + } return 0; + +fail: + + if (rv == NGHTTP2_ERR_BUFFER_ERROR) { + return NGHTTP2_ERR_FRAME_SIZE_ERROR; + } + + return rv; } -void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame, - size_t origin_len, uint8_t *payload, - size_t payloadlen) { +int nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame, + const uint8_t *payload, + size_t payloadlen _U_, + uint8_t *var_gift_payload, + size_t var_gift_payloadlen) { + nghttp2_buf buf; nghttp2_ext_altsvc *altsvc; - uint8_t *p; altsvc = frame->payload; - p = payload; - altsvc->origin = p; + altsvc->max_age = nghttp2_get_uint32(payload); + payload += 4; - p += origin_len; + altsvc->port = nghttp2_get_uint16(payload); + payload += 2; - altsvc->origin_len = origin_len; + altsvc->protocol_id_len = *payload; - altsvc->field_value = p; - altsvc->field_value_len = (size_t)(payload + payloadlen - p); -} - -int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame, - const uint8_t *payload, - size_t payloadlen, nghttp2_mem *mem) { - uint8_t *buf; - size_t origin_len; + nghttp2_buf_wrap_init(&buf, var_gift_payload, var_gift_payloadlen); + buf.last += var_gift_payloadlen; - if (payloadlen < 2) { - return NGHTTP2_FRAME_SIZE_ERROR; + /* 1 for Host-Len */ + if (nghttp2_buf_len(&buf) < 1 + (ssize_t)altsvc->protocol_id_len) { + return NGHTTP2_ERR_FRAME_SIZE_ERROR; } - origin_len = nghttp2_get_uint16(payload); + altsvc->protocol_id = buf.pos; + buf.pos += altsvc->protocol_id_len; - buf = nghttp2_mem_malloc(mem, payloadlen - 2); - if (!buf) { - return NGHTTP2_ERR_NOMEM; + altsvc->host_len = *buf.pos; + ++buf.pos; + + if (nghttp2_buf_len(&buf) < (ssize_t)altsvc->host_len) { + return NGHTTP2_ERR_FRAME_SIZE_ERROR; } - nghttp2_cpymem(buf, payload + 2, payloadlen - 2); + altsvc->host = buf.pos; + buf.pos += altsvc->host_len; - nghttp2_frame_unpack_altsvc_payload(frame, origin_len, buf, payloadlen - 2); + altsvc->origin = buf.pos; + altsvc->origin_len = nghttp2_buf_len(&buf); return 0; } nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv, - size_t niv, nghttp2_mem *mem) { + size_t niv) { nghttp2_settings_entry *iv_copy; size_t len = niv * sizeof(nghttp2_settings_entry); @@ -760,7 +793,7 @@ return NULL; } - iv_copy = nghttp2_mem_malloc(mem, len); + iv_copy = malloc(len); if (iv_copy == NULL) { return NULL; @@ -777,9 +810,7 @@ memcmp(a->value, b->value, a->valuelen) == 0; } -void nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem) { - nghttp2_mem_free(mem, nva); -} +void nghttp2_nv_array_del(nghttp2_nv *nva) { free(nva); } static int bytes_compar(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen) { @@ -831,31 +862,25 @@ } int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva, - size_t nvlen, nghttp2_mem *mem) { + size_t nvlen) { size_t i; - uint8_t *data = NULL; + uint8_t *data; size_t buflen = 0; nghttp2_nv *p; + for (i = 0; i < nvlen; ++i) { + buflen += nva[i].namelen + nva[i].valuelen; + } + if (nvlen == 0) { *nva_ptr = NULL; return 0; } - for (i = 0; i < nvlen; ++i) { - /* + 1 for null-termination */ - if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) == 0) { - buflen += nva[i].namelen + 1; - } - if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) == 0) { - buflen += nva[i].valuelen + 1; - } - } - buflen += sizeof(nghttp2_nv) * nvlen; - *nva_ptr = nghttp2_mem_malloc(mem, buflen); + *nva_ptr = malloc(buflen); if (*nva_ptr == NULL) { return NGHTTP2_ERR_NOMEM; @@ -867,29 +892,15 @@ for (i = 0; i < nvlen; ++i) { p->flags = nva[i].flags; - if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) { - p->name = nva[i].name; - p->namelen = nva[i].namelen; - } else { - memcpy(data, nva[i].name, nva[i].namelen); - p->name = data; - p->namelen = nva[i].namelen; - data[p->namelen] = '\0'; - nghttp2_downcase(p->name, p->namelen); - data += nva[i].namelen + 1; - } - - if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) { - p->value = nva[i].value; - p->valuelen = nva[i].valuelen; - } else { - memcpy(data, nva[i].value, nva[i].valuelen); - p->value = data; - p->valuelen = nva[i].valuelen; - data[p->valuelen] = '\0'; - data += nva[i].valuelen + 1; - } - + memcpy(data, nva[i].name, nva[i].namelen); + p->name = data; + p->namelen = nva[i].namelen; + nghttp2_downcase(p->name, p->namelen); + data += nva[i].namelen; + memcpy(data, nva[i].value, nva[i].valuelen); + p->value = data; + p->valuelen = nva[i].valuelen; + data += nva[i].valuelen; ++p; } return 0; @@ -900,6 +911,9 @@ for (i = 0; i < niv; ++i) { switch (iv[i].settings_id) { case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: + if (iv[i].value > NGHTTP2_MAX_HEADER_TABLE_SIZE) { + return 0; + } break; case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: break; @@ -926,7 +940,7 @@ return 1; } -static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) { +static void frame_set_pad(nghttp2_buf *buf, size_t padlen) { size_t trail_padlen; size_t newlen; @@ -941,22 +955,20 @@ 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] = (uint8_t)trail_padlen; + buf->pos[NGHTTP2_FRAME_HDLEN] = trail_padlen; /* zero out padding */ memset(buf->last, 0, trail_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, int framehd_only) { + size_t padlen) { nghttp2_buf *buf; if (padlen == 0) { @@ -987,9 +999,9 @@ buf = &bufs->head->buf; - assert(nghttp2_buf_avail(buf) >= padlen - 1); + assert(nghttp2_buf_avail(buf) >= (ssize_t)padlen - 1); - frame_set_pad(buf, padlen, framehd_only); + frame_set_pad(buf, padlen); hd->length += padlen; hd->flags |= NGHTTP2_FLAG_PADDED; diff -Nru nghttp2-1.13.0/lib/nghttp2_frame.h nghttp2-0.6.7/lib/nghttp2_frame.h --- nghttp2-1.13.0/lib/nghttp2_frame.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_frame.h 2014-11-30 14:15:07.000000000 +0000 @@ -52,20 +52,35 @@ #define NGHTTP2_FRAMEBUF_CHUNKLEN \ (NGHTTP2_FRAME_HDLEN + 1 + NGHTTP2_MAX_PAYLOADLEN) -/* The default length of DATA frame payload. */ -#define NGHTTP2_DATA_PAYLOADLEN NGHTTP2_MAX_FRAME_SIZE_MIN +/* Number of inbound buffer */ +#define NGHTTP2_FRAMEBUF_MAX_NUM 5 -/* Maximum headers block size to send, calculated using - nghttp2_hd_deflate_bound(). This is the default value, and can be - overridden by nghttp2_option_set_max_send_header_block_size(). */ +/* The default length of DATA frame payload. This should be small enough + * for the data payload and the header to fit into 1 TLS record */ +#define NGHTTP2_DATA_PAYLOADLEN \ + ((NGHTTP2_MAX_FRAME_SIZE_MIN) - (NGHTTP2_FRAME_HDLEN)) + +/* Maximum headers payload length, calculated in compressed form. + This applies to transmission only. */ #define NGHTTP2_MAX_HEADERSLEN 65536 /* The number of bytes for each SETTINGS entry */ #define NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH 6 +/* The maximum header table size in SETTINGS_HEADER_TABLE_SIZE */ +#define NGHTTP2_MAX_HEADER_TABLE_SIZE ((1u << 31) - 1) + /* Length of priority related fields in HEADERS/PRIORITY frames */ #define NGHTTP2_PRIORITY_SPECLEN 5 +/* Length of fixed part in ALTSVC frame, that is the sum of fields of + Max-Age, Port and Proto-Len. */ +#define NGHTTP2_ALTSVC_FIXED_PARTLEN 7 + +/* Minimum length of ALTSVC extension frame payload. + NGHTTP2_ALTSVC_FIXED_PARTLEN + Host-Len. */ +#define NGHTTP2_ALTSVC_MINLEN 8 + /* Maximum length of padding in bytes. */ #define NGHTTP2_MAX_PADLEN 256 @@ -213,12 +228,18 @@ const uint8_t *payload); /* - * Initializes payload of frame->settings. The |frame| takes - * ownership of |iv|. + * Makes a copy of |iv| in frame->settings.iv. The |niv| is assigned + * to frame->settings.niv. + * + * This function returns 0 if it succeeds or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. */ -void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame, - nghttp2_settings_entry *iv, - size_t niv); +int nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame, + nghttp2_settings_entry *iv, + size_t niv); /* * Unpacks SETTINGS payload into |*iv_ptr|. The number of entries are @@ -235,7 +256,7 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr, size_t *niv_ptr, const uint8_t *payload, - size_t payloadlen, nghttp2_mem *mem); + size_t payloadlen); /* * Packs PUSH_PROMISE frame |frame| in wire format and store it in @@ -338,7 +359,7 @@ */ int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame, const uint8_t *payload, - size_t payloadlen, nghttp2_mem *mem); + size_t payloadlen); /* * Packs WINDOW_UPDATE frame |frame| in wire frame format and store it @@ -360,43 +381,47 @@ size_t payloadlen); /* - * Packs ALTSVC frame |frame| in wire frame format and store it in - * |bufs|. + * Packs ALTSVC frame |frame| in wire format and store it in |bufs|. + * This function expands |bufs| as necessary to store frame. * * The caller must make sure that nghttp2_bufs_reset(bufs) is called * before calling this function. * - * This function always succeeds and returns 0. - */ -int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *ext); - -/* - * Unpacks ALTSVC wire format into |frame|. The |payload| of - * |payloadlen| bytes contains frame payload. This function assumes - * that frame->payload points to the nghttp2_ext_altsvc object. + * The caller must make sure that frame->payload points to + * nghttp2_ext_altsvc object. * - * This function always succeeds and returns 0. + * This function returns 0 if it succeeds or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + * NGHTTP2_ERR_FRAME_SIZE_ERROR + * The length of the frame is too large. */ -void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame, - size_t origin_len, uint8_t *payload, - size_t payloadlen); +int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame); /* - * Unpacks ALTSVC wire format into |frame|. This function only exists - * for unit test. After allocating buffer for fields, this function - * internally calls nghttp2_frame_unpack_altsvc_payload(). + * Unpacks ALTSVC frame byte sequence into |frame|. + * The |payload| of length |payloadlen| contains first 8 bytes of + * payload. The |var_gift_payload| of length |var_gift_payloadlen| + * contains remaining payload and its buffer is gifted to the function + * and then |frame|. The |var_gift_payloadlen| must be freed by + * nghttp2_frame_altsvc_free(). * - * This function returns 0 if it succeeds, or one of the following + * The caller must make sure that frame->payload points to + * nghttp2_ext_altsvc object. + * + * This function returns 0 if it succeeds or one of the following * negative error codes: * - * NGHTTP2_ERR_NOMEM - * Out of memory. * NGHTTP2_ERR_FRAME_SIZE_ERROR - * The payload is too small. + * The |var_gift_payload| does not contain required data. */ -int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame, - const uint8_t *payload, - size_t payloadlen, nghttp2_mem *mem); +int nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame, + const uint8_t *payload, + size_t payloadlen, + uint8_t *var_gift_payload, + size_t var_gift_payloadlen); /* * Initializes HEADERS frame |frame| with given values. |frame| takes @@ -408,7 +433,7 @@ const nghttp2_priority_spec *pri_spec, nghttp2_nv *nva, size_t nvlen); -void nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem); +void nghttp2_frame_headers_free(nghttp2_headers *frame); void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id, const nghttp2_priority_spec *pri_spec); @@ -429,8 +454,7 @@ int32_t promised_stream_id, nghttp2_nv *nva, size_t nvlen); -void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame, - nghttp2_mem *mem); +void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame); /* * Initializes SETTINGS frame |frame| with given values. |frame| takes @@ -440,7 +464,7 @@ void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags, nghttp2_settings_entry *iv, size_t niv); -void nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem); +void nghttp2_frame_settings_free(nghttp2_settings *frame); /* * Initializes PING frame |frame| with given values. If the @@ -462,7 +486,7 @@ uint32_t error_code, uint8_t *opaque_data, size_t opaque_data_len); -void nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem); +void nghttp2_frame_goaway_free(nghttp2_goaway *frame); void nghttp2_frame_window_update_init(nghttp2_window_update *frame, uint8_t flags, int32_t stream_id, @@ -470,36 +494,28 @@ void nghttp2_frame_window_update_free(nghttp2_window_update *frame); -void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type, - uint8_t flags, int32_t stream_id, - void *payload); - -void nghttp2_frame_extension_free(nghttp2_extension *frame); - -/* - * Initializes ALTSVC frame |frame| with given values. This function - * assumes that frame->payload points to nghttp2_ext_altsvc object. - * Also |origin| and |field_value| are allocated in single buffer, - * starting |origin|. On success, this function takes ownership of - * |origin|, so caller must not free it. - */ +/* protocol_id, host and origin must be allocated to the one chunk of + memory region and protocol_id must point to it. We only free + protocol_id. This means that |protocol_id| is not NULL even if + |protocol_id_len| == 0 and |host_len| + |origin_len| > 0. If + |protocol_id_len|, |host_len| and |origin_len| are all zero, + |protocol_id| can be NULL. */ void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id, - uint8_t *origin, size_t origin_len, - uint8_t *field_value, size_t field_value_len); + uint32_t max_age, uint16_t port, + uint8_t *protocol_id, size_t protocol_id_len, + uint8_t *host, size_t host_len, uint8_t *origin, + size_t origin_len); /* - * Frees up resources under |frame|. This function does not free - * nghttp2_ext_altsvc object pointed by frame->payload. This function - * only frees origin pointed by nghttp2_ext_altsvc.origin. Therefore, - * other fields must be allocated in the same buffer with origin. + * Frees resources used by |frame|. This function does not free + * frame->payload itself. */ -void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem); +void nghttp2_frame_altsvc_free(nghttp2_extension *frame); /* * Returns the number of padding bytes after payload. The total * padding length is given in the |padlen|. The returned value does - * not include the Pad Length field. If |padlen| is 0, this function - * returns 0, regardless of frame->hd.flags. + * not include the Pad Length field. */ size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen); @@ -514,7 +530,7 @@ * it succeeds, or NULL. */ nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv, - size_t niv, nghttp2_mem *mem); + size_t niv); /* * Sorts the |nva| in ascending order of name and value. If names are @@ -525,9 +541,7 @@ /* * Copies name/value pairs from |nva|, which contains |nvlen| pairs, * to |*nva_ptr|, which is dynamically allocated so that all items can - * be stored. The resultant name and value in nghttp2_nv are - * guaranteed to be NULL-terminated even if the input is not - * null-terminated. + * be stored. * * The |*nva_ptr| must be freed using nghttp2_nv_array_del(). * @@ -538,7 +552,7 @@ * Out of memory. */ int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva, - size_t nvlen, nghttp2_mem *mem); + size_t nvlen); /* * Returns nonzero if the name/value pair |a| equals to |b|. The name @@ -550,7 +564,7 @@ /* * Frees |nva|. */ -void nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem); +void nghttp2_nv_array_del(nghttp2_nv *nva); /* * Checks that the |iv|, which includes |niv| entries, does not have @@ -564,8 +578,7 @@ * 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. This function fills zeros padding region - * unless framehd_only is nonzero. + * for the serialized data. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -576,6 +589,6 @@ * The length of the resulting frame is too large. */ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd, - size_t padlen, int framehd_only); + size_t padlen); #endif /* NGHTTP2_FRAME_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_hd.c nghttp2-0.6.7/lib/nghttp2_hd.c --- nghttp2-1.13.0/lib/nghttp2_hd.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_hd.c 2014-11-30 14:15:07.000000000 +0000 @@ -31,580 +31,185 @@ #include "nghttp2_helper.h" #include "nghttp2_int.h" -/* Make scalar initialization form of nghttp2_hd_entry */ -#define MAKE_STATIC_ENT(N, V, T, H) \ +#define STATIC_TABLE_LENGTH 61 + +/* Make scalar initialization form of nghttp2_nv */ +#define MAKE_STATIC_ENT(I, N, V, NH, VH) \ { \ - { NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1 } \ - , {NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \ - {(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \ - T, H \ + { \ + { (uint8_t *) N, (uint8_t *)V, sizeof(N) - 1, sizeof(V) - 1, 0 } \ + , NH, VH, 1, NGHTTP2_HD_FLAG_NONE \ + } \ + , I \ } /* Generated by mkstatictbl.py */ -/* 3rd parameter is nghttp2_token value for header field name. We use - first enum value if same header names are repeated (e.g., - :status). */ +/* Sorted by hash(name) and its table index */ static nghttp2_hd_static_entry static_table[] = { - MAKE_STATIC_ENT(":authority", "", 0, 3153725150u), - MAKE_STATIC_ENT(":method", "GET", 1, 695666056u), - MAKE_STATIC_ENT(":method", "POST", 1, 695666056u), - MAKE_STATIC_ENT(":path", "/", 3, 3292848686u), - MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u), - MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u), - MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u), - MAKE_STATIC_ENT(":status", "200", 7, 4000288983u), - MAKE_STATIC_ENT(":status", "204", 7, 4000288983u), - MAKE_STATIC_ENT(":status", "206", 7, 4000288983u), - MAKE_STATIC_ENT(":status", "304", 7, 4000288983u), - MAKE_STATIC_ENT(":status", "400", 7, 4000288983u), - MAKE_STATIC_ENT(":status", "404", 7, 4000288983u), - MAKE_STATIC_ENT(":status", "500", 7, 4000288983u), - MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u), - MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u), - MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u), - MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u), - MAKE_STATIC_ENT("accept", "", 18, 136609321u), - MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u), - MAKE_STATIC_ENT("age", "", 20, 742476188u), - MAKE_STATIC_ENT("allow", "", 21, 2930878514u), - MAKE_STATIC_ENT("authorization", "", 22, 2436257726u), - MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u), - MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u), - MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u), - MAKE_STATIC_ENT("content-language", "", 26, 24973587u), - MAKE_STATIC_ENT("content-length", "", 27, 1308181789u), - MAKE_STATIC_ENT("content-location", "", 28, 2302364718u), - MAKE_STATIC_ENT("content-range", "", 29, 3555523146u), - MAKE_STATIC_ENT("content-type", "", 30, 4244048277u), - MAKE_STATIC_ENT("cookie", "", 31, 2007449791u), - MAKE_STATIC_ENT("date", "", 32, 3564297305u), - MAKE_STATIC_ENT("etag", "", 33, 113792960u), - MAKE_STATIC_ENT("expect", "", 34, 2530896728u), - MAKE_STATIC_ENT("expires", "", 35, 1049544579u), - MAKE_STATIC_ENT("from", "", 36, 2513272949u), - MAKE_STATIC_ENT("host", "", 37, 2952701295u), - MAKE_STATIC_ENT("if-match", "", 38, 3597694698u), - MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u), - MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u), - MAKE_STATIC_ENT("if-range", "", 41, 2340978238u), - MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u), - MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u), - MAKE_STATIC_ENT("link", "", 44, 232457833u), - MAKE_STATIC_ENT("location", "", 45, 200649126u), - MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u), - MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u), - MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u), - MAKE_STATIC_ENT("range", "", 49, 4208725202u), - MAKE_STATIC_ENT("referer", "", 50, 3969579366u), - MAKE_STATIC_ENT("refresh", "", 51, 3572655668u), - MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u), - MAKE_STATIC_ENT("server", "", 53, 1085029842u), - MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u), - MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u), - MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u), - MAKE_STATIC_ENT("user-agent", "", 57, 606444526u), - MAKE_STATIC_ENT("vary", "", 58, 1085005381u), - MAKE_STATIC_ENT("via", "", 59, 1762798611u), - MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u), + MAKE_STATIC_ENT(20, "age", "", 96511u, 0u), + MAKE_STATIC_ENT(59, "via", "", 116750u, 0u), + MAKE_STATIC_ENT(32, "date", "", 3076014u, 0u), + MAKE_STATIC_ENT(33, "etag", "", 3123477u, 0u), + MAKE_STATIC_ENT(36, "from", "", 3151786u, 0u), + MAKE_STATIC_ENT(37, "host", "", 3208616u, 0u), + MAKE_STATIC_ENT(44, "link", "", 3321850u, 0u), + MAKE_STATIC_ENT(58, "vary", "", 3612210u, 0u), + MAKE_STATIC_ENT(38, "if-match", "", 34533653u, 0u), + MAKE_STATIC_ENT(41, "if-range", "", 39145613u, 0u), + MAKE_STATIC_ENT(3, ":path", "/", 56997727u, 47u), + MAKE_STATIC_ENT(4, ":path", "/index.html", 56997727u, 2144181430u), + MAKE_STATIC_ENT(21, "allow", "", 92906313u, 0u), + MAKE_STATIC_ENT(49, "range", "", 108280125u, 0u), + MAKE_STATIC_ENT(14, "accept-charset", "", 124285319u, 0u), + MAKE_STATIC_ENT(43, "last-modified", "", 150043680u, 0u), + MAKE_STATIC_ENT(48, "proxy-authorization", "", 329532250u, 0u), + MAKE_STATIC_ENT(57, "user-agent", "", 486342275u, 0u), + MAKE_STATIC_ENT(40, "if-none-match", "", 646073760u, 0u), + MAKE_STATIC_ENT(30, "content-type", "", 785670158u, 0u), + MAKE_STATIC_ENT(16, "accept-language", "", 802785917u, 0u), + MAKE_STATIC_ENT(50, "referer", "", 1085069613u, 0u), + MAKE_STATIC_ENT(51, "refresh", "", 1085444827u, 0u), + MAKE_STATIC_ENT(55, "strict-transport-security", "", 1153852136u, 0u), + MAKE_STATIC_ENT(54, "set-cookie", "", 1237214767u, 0u), + MAKE_STATIC_ENT(56, "transfer-encoding", "", 1274458357u, 0u), + MAKE_STATIC_ENT(17, "accept-ranges", "", 1397189435u, 0u), + MAKE_STATIC_ENT(42, "if-unmodified-since", "", 1454068927u, 0u), + MAKE_STATIC_ENT(46, "max-forwards", "", 1619948695u, 0u), + MAKE_STATIC_ENT(45, "location", "", 1901043637u, 0u), + MAKE_STATIC_ENT(52, "retry-after", "", 1933352567u, 0u), + MAKE_STATIC_ENT(25, "content-encoding", "", 2095084583u, 0u), + MAKE_STATIC_ENT(28, "content-location", "", 2284906121u, 0u), + MAKE_STATIC_ENT(39, "if-modified-since", "", 2302095846u, 0u), + MAKE_STATIC_ENT(18, "accept", "", 2871506184u, 0u), + MAKE_STATIC_ENT(29, "content-range", "", 2878374633u, 0u), + MAKE_STATIC_ENT(22, "authorization", "", 2909397113u, 0u), + MAKE_STATIC_ENT(31, "cookie", "", 2940209764u, 0u), + MAKE_STATIC_ENT(0, ":authority", "", 2962729033u, 0u), + MAKE_STATIC_ENT(35, "expires", "", 2985731892u, 0u), + MAKE_STATIC_ENT(34, "expect", "", 3005803609u, 0u), + MAKE_STATIC_ENT(24, "content-disposition", "", 3027699811u, 0u), + MAKE_STATIC_ENT(26, "content-language", "", 3065240108u, 0u), + MAKE_STATIC_ENT(1, ":method", "GET", 3153018267u, 70454u), + MAKE_STATIC_ENT(2, ":method", "POST", 3153018267u, 2461856u), + MAKE_STATIC_ENT(27, "content-length", "", 3162187450u, 0u), + MAKE_STATIC_ENT(19, "access-control-allow-origin", "", 3297999203u, 0u), + MAKE_STATIC_ENT(5, ":scheme", "http", 3322585695u, 3213448u), + MAKE_STATIC_ENT(6, ":scheme", "https", 3322585695u, 99617003u), + MAKE_STATIC_ENT(7, ":status", "200", 3338091692u, 49586u), + MAKE_STATIC_ENT(8, ":status", "204", 3338091692u, 49590u), + MAKE_STATIC_ENT(9, ":status", "206", 3338091692u, 49592u), + MAKE_STATIC_ENT(10, ":status", "304", 3338091692u, 50551u), + MAKE_STATIC_ENT(11, ":status", "400", 3338091692u, 51508u), + MAKE_STATIC_ENT(12, ":status", "404", 3338091692u, 51512u), + MAKE_STATIC_ENT(13, ":status", "500", 3338091692u, 52469u), + MAKE_STATIC_ENT(53, "server", "", 3389140803u, 0u), + MAKE_STATIC_ENT(47, "proxy-authenticate", "", 3993199572u, 0u), + MAKE_STATIC_ENT(60, "www-authenticate", "", 4051929931u, 0u), + MAKE_STATIC_ENT(23, "cache-control", "", 4086191634u, 0u), + MAKE_STATIC_ENT(15, "accept-encoding", "gzip, deflate", 4127597688u, + 1733326877u), }; -static int memeq(const void *s1, const void *s2, size_t n) { - return memcmp(s1, s2, n) == 0; -} +/* Index to the position in static_table */ +const size_t static_table_index[] = { + 38, 43, 44, 10, 11, 47, 48, 49, 50, 51, 52, 53, 54, 55, 14, 60, + 20, 26, 34, 46, 0, 12, 36, 59, 41, 31, 42, 45, 32, 35, 19, 37, + 2, 3, 40, 39, 4, 5, 8, 33, 18, 9, 27, 15, 6, 29, 28, 57, + 16, 13, 21, 22, 30, 56, 24, 23, 25, 17, 7, 1, 58}; -/* - * This function was generated by genlibtokenlookup.py. Inspired by - * h2o header lookup. https://github.com/h2o/h2o - */ -static int32_t lookup_token(const uint8_t *name, size_t namelen) { - switch (namelen) { - case 2: - switch (name[1]) { - case 'e': - if (lstreq("t", name, 1)) { - return NGHTTP2_TOKEN_TE; - } - break; - } - break; - case 3: - switch (name[2]) { - case 'a': - if (lstreq("vi", name, 2)) { - return NGHTTP2_TOKEN_VIA; - } - break; - case 'e': - if (lstreq("ag", name, 2)) { - return NGHTTP2_TOKEN_AGE; - } - break; - } - break; - case 4: - switch (name[3]) { - case 'e': - if (lstreq("dat", name, 3)) { - return NGHTTP2_TOKEN_DATE; - } - break; - case 'g': - if (lstreq("eta", name, 3)) { - return NGHTTP2_TOKEN_ETAG; - } - break; - case 'k': - if (lstreq("lin", name, 3)) { - return NGHTTP2_TOKEN_LINK; - } - break; - case 'm': - if (lstreq("fro", name, 3)) { - return NGHTTP2_TOKEN_FROM; - } - break; - case 't': - if (lstreq("hos", name, 3)) { - return NGHTTP2_TOKEN_HOST; - } - break; - case 'y': - if (lstreq("var", name, 3)) { - return NGHTTP2_TOKEN_VARY; - } - break; - } - break; - case 5: - switch (name[4]) { - case 'e': - if (lstreq("rang", name, 4)) { - return NGHTTP2_TOKEN_RANGE; - } - break; - case 'h': - if (lstreq(":pat", name, 4)) { - return NGHTTP2_TOKEN__PATH; - } - if (lstreq(":pat", name, 4)) { - return NGHTTP2_TOKEN__PATH; - } - break; - case 'w': - if (lstreq("allo", name, 4)) { - return NGHTTP2_TOKEN_ALLOW; - } - break; - } - break; - case 6: - switch (name[5]) { - case 'e': - if (lstreq("cooki", name, 5)) { - return NGHTTP2_TOKEN_COOKIE; - } - break; - case 'r': - if (lstreq("serve", name, 5)) { - return NGHTTP2_TOKEN_SERVER; - } - break; - case 't': - if (lstreq("accep", name, 5)) { - return NGHTTP2_TOKEN_ACCEPT; - } - if (lstreq("expec", name, 5)) { - return NGHTTP2_TOKEN_EXPECT; - } - break; - } - break; - case 7: - switch (name[6]) { - case 'd': - if (lstreq(":metho", name, 6)) { - return NGHTTP2_TOKEN__METHOD; - } - if (lstreq(":metho", name, 6)) { - return NGHTTP2_TOKEN__METHOD; - } - break; - case 'e': - if (lstreq(":schem", name, 6)) { - return NGHTTP2_TOKEN__SCHEME; - } - if (lstreq(":schem", name, 6)) { - return NGHTTP2_TOKEN__SCHEME; - } - if (lstreq("upgrad", name, 6)) { - return NGHTTP2_TOKEN_UPGRADE; - } - break; - case 'h': - if (lstreq("refres", name, 6)) { - return NGHTTP2_TOKEN_REFRESH; - } - break; - case 'r': - if (lstreq("refere", name, 6)) { - return NGHTTP2_TOKEN_REFERER; - } - break; - case 's': - if (lstreq(":statu", name, 6)) { - return NGHTTP2_TOKEN__STATUS; - } - if (lstreq(":statu", name, 6)) { - return NGHTTP2_TOKEN__STATUS; - } - if (lstreq(":statu", name, 6)) { - return NGHTTP2_TOKEN__STATUS; - } - if (lstreq(":statu", name, 6)) { - return NGHTTP2_TOKEN__STATUS; - } - if (lstreq(":statu", name, 6)) { - return NGHTTP2_TOKEN__STATUS; - } - if (lstreq(":statu", name, 6)) { - return NGHTTP2_TOKEN__STATUS; - } - if (lstreq(":statu", name, 6)) { - return NGHTTP2_TOKEN__STATUS; - } - if (lstreq("expire", name, 6)) { - return NGHTTP2_TOKEN_EXPIRES; - } - break; - } - break; - case 8: - switch (name[7]) { - case 'e': - if (lstreq("if-rang", name, 7)) { - return NGHTTP2_TOKEN_IF_RANGE; - } - break; - case 'h': - if (lstreq("if-matc", name, 7)) { - return NGHTTP2_TOKEN_IF_MATCH; - } - break; - case 'n': - if (lstreq("locatio", name, 7)) { - return NGHTTP2_TOKEN_LOCATION; - } - break; - } - break; - case 10: - switch (name[9]) { - case 'e': - if (lstreq("keep-aliv", name, 9)) { - return NGHTTP2_TOKEN_KEEP_ALIVE; - } - if (lstreq("set-cooki", name, 9)) { - return NGHTTP2_TOKEN_SET_COOKIE; - } - break; - case 'n': - if (lstreq("connectio", name, 9)) { - return NGHTTP2_TOKEN_CONNECTION; - } - break; - case 't': - if (lstreq("user-agen", name, 9)) { - return NGHTTP2_TOKEN_USER_AGENT; - } - break; - case 'y': - if (lstreq(":authorit", name, 9)) { - return NGHTTP2_TOKEN__AUTHORITY; - } - break; - } - break; - case 11: - switch (name[10]) { - case 'r': - if (lstreq("retry-afte", name, 10)) { - return NGHTTP2_TOKEN_RETRY_AFTER; - } - break; - } - break; - case 12: - switch (name[11]) { - case 'e': - if (lstreq("content-typ", name, 11)) { - return NGHTTP2_TOKEN_CONTENT_TYPE; - } - break; - case 's': - if (lstreq("max-forward", name, 11)) { - return NGHTTP2_TOKEN_MAX_FORWARDS; - } - break; - } - break; - case 13: - switch (name[12]) { - case 'd': - if (lstreq("last-modifie", name, 12)) { - return NGHTTP2_TOKEN_LAST_MODIFIED; - } - break; - case 'e': - if (lstreq("content-rang", name, 12)) { - return NGHTTP2_TOKEN_CONTENT_RANGE; - } - break; - case 'h': - if (lstreq("if-none-matc", name, 12)) { - return NGHTTP2_TOKEN_IF_NONE_MATCH; - } - break; - case 'l': - if (lstreq("cache-contro", name, 12)) { - return NGHTTP2_TOKEN_CACHE_CONTROL; - } - break; - case 'n': - if (lstreq("authorizatio", name, 12)) { - return NGHTTP2_TOKEN_AUTHORIZATION; - } - break; - case 's': - if (lstreq("accept-range", name, 12)) { - return NGHTTP2_TOKEN_ACCEPT_RANGES; - } - break; - } - break; - case 14: - switch (name[13]) { - case 'h': - if (lstreq("content-lengt", name, 13)) { - return NGHTTP2_TOKEN_CONTENT_LENGTH; - } - break; - case 't': - if (lstreq("accept-charse", name, 13)) { - return NGHTTP2_TOKEN_ACCEPT_CHARSET; - } - break; - } - break; - case 15: - switch (name[14]) { - case 'e': - if (lstreq("accept-languag", name, 14)) { - return NGHTTP2_TOKEN_ACCEPT_LANGUAGE; - } - break; - case 'g': - if (lstreq("accept-encodin", name, 14)) { - return NGHTTP2_TOKEN_ACCEPT_ENCODING; - } - break; - } - break; - case 16: - switch (name[15]) { - case 'e': - if (lstreq("content-languag", name, 15)) { - return NGHTTP2_TOKEN_CONTENT_LANGUAGE; - } - if (lstreq("www-authenticat", name, 15)) { - return NGHTTP2_TOKEN_WWW_AUTHENTICATE; - } - break; - case 'g': - if (lstreq("content-encodin", name, 15)) { - return NGHTTP2_TOKEN_CONTENT_ENCODING; - } - break; - case 'n': - if (lstreq("content-locatio", name, 15)) { - return NGHTTP2_TOKEN_CONTENT_LOCATION; - } - if (lstreq("proxy-connectio", name, 15)) { - return NGHTTP2_TOKEN_PROXY_CONNECTION; - } - break; - } - break; - case 17: - switch (name[16]) { - case 'e': - if (lstreq("if-modified-sinc", name, 16)) { - return NGHTTP2_TOKEN_IF_MODIFIED_SINCE; - } - break; - case 'g': - if (lstreq("transfer-encodin", name, 16)) { - return NGHTTP2_TOKEN_TRANSFER_ENCODING; - } - break; - } - break; - case 18: - switch (name[17]) { - case 'e': - if (lstreq("proxy-authenticat", name, 17)) { - return NGHTTP2_TOKEN_PROXY_AUTHENTICATE; - } - break; - } - break; - case 19: - switch (name[18]) { - case 'e': - if (lstreq("if-unmodified-sinc", name, 18)) { - return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE; - } - break; - case 'n': - if (lstreq("content-dispositio", name, 18)) { - return NGHTTP2_TOKEN_CONTENT_DISPOSITION; - } - if (lstreq("proxy-authorizatio", name, 18)) { - return NGHTTP2_TOKEN_PROXY_AUTHORIZATION; - } - break; - } - break; - case 25: - switch (name[24]) { - case 'y': - if (lstreq("strict-transport-securit", name, 24)) { - return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY; - } - break; - } - break; - case 27: - switch (name[26]) { - case 'n': - if (lstreq("access-control-allow-origi", name, 26)) { - return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN; - } - break; - } - break; - } - return -1; -} - -void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) { - ent->nv = *nv; - ent->cnv.name = nv->name->base; - ent->cnv.namelen = nv->name->len; - ent->cnv.value = nv->value->base; - ent->cnv.valuelen = nv->value->len; - ent->cnv.flags = nv->flags; - ent->next = NULL; - ent->hash = 0; - - nghttp2_rcbuf_incref(ent->nv.name); - nghttp2_rcbuf_incref(ent->nv.value); -} - -void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) { - nghttp2_rcbuf_decref(ent->nv.value); - nghttp2_rcbuf_decref(ent->nv.name); -} +const size_t NGHTTP2_STATIC_TABLE_LENGTH = + sizeof(static_table) / sizeof(static_table[0]); -static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) { - return a->name->len == b->namelen && - memeq(a->name->base, b->name, b->namelen); -} - -static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) { - return a->value->len == b->valuelen && - memeq(a->value->base, b->value, b->valuelen); +static int memeq(const void *s1, const void *s2, size_t n) { + const uint8_t *a = (const uint8_t *)s1, *b = (const uint8_t *)s2; + uint8_t c = 0; + while (n > 0) { + c |= (*a++) ^ (*b++); + --n; + } + return c == 0; } -static uint32_t name_hash(const nghttp2_nv *nv) { - /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */ - uint32_t h = 2166136261u; - size_t i; - - for (i = 0; i < nv->namelen; ++i) { - h ^= nv->name[i]; - h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24); +static uint32_t hash(const uint8_t *s, size_t n) { + uint32_t h = 0; + while (n > 0) { + h = h * 31 + *s++; + --n; } - return h; } -static void hd_map_init(nghttp2_hd_map *map) { - memset(map, 0, sizeof(nghttp2_hd_map)); -} - -static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) { - nghttp2_hd_entry **bucket; - - bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)]; +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) { + int rv = 0; - if (*bucket == NULL) { - *bucket = ent; - return; + /* Since nghttp2_hd_entry is used for indexing, ent->nv.flags always + NGHTTP2_NV_FLAG_NONE */ + ent->nv.flags = NGHTTP2_NV_FLAG_NONE; + + if ((flags & NGHTTP2_HD_FLAG_NAME_ALLOC) && + (flags & NGHTTP2_HD_FLAG_NAME_GIFT) == 0) { + if (namelen == 0) { + /* We should not allow empty header field name */ + ent->nv.name = NULL; + } else { + ent->nv.name = nghttp2_memdup(name, namelen); + if (ent->nv.name == NULL) { + rv = NGHTTP2_ERR_NOMEM; + goto fail; + } + } + } else { + ent->nv.name = name; } - - /* lower index is linked near the root */ - ent->next = *bucket; - *bucket = ent; -} - -static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match, - const nghttp2_nv *nv, int32_t token, - uint32_t hash) { - nghttp2_hd_entry *p; - nghttp2_hd_entry *res = NULL; - - *exact_match = 0; - - for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) { - if (token != p->nv.token || - (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) { - continue; - } - if (!res) { - res = p; - } - if (value_eq(&p->nv, nv)) { - res = p; - *exact_match = 1; - break; + if ((flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) && + (flags & NGHTTP2_HD_FLAG_VALUE_GIFT) == 0) { + if (valuelen == 0) { + ent->nv.value = NULL; + } else { + ent->nv.value = nghttp2_memdup(value, valuelen); + if (ent->nv.value == NULL) { + rv = NGHTTP2_ERR_NOMEM; + goto fail2; + } } + } else { + ent->nv.value = value; } + ent->nv.namelen = namelen; + ent->nv.valuelen = valuelen; + ent->ref = 1; + ent->flags = flags; - return res; -} - -static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) { - nghttp2_hd_entry **dst; + ent->name_hash = name_hash; + ent->value_hash = value_hash; - dst = &map->table[ent->hash & (HD_MAP_SIZE - 1)]; + return 0; - for (; *dst; dst = &(*dst)->next) { - if (*dst != ent) { - continue; - } +fail2: + if (flags & NGHTTP2_HD_FLAG_NAME_ALLOC) { + free(ent->nv.name); + } +fail: + return rv; +} - *dst = ent->next; - ent->next = NULL; - return; +void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) { + assert(ent->ref == 0); + if (ent->flags & NGHTTP2_HD_FLAG_NAME_ALLOC) { + free(ent->nv.name); + } + if (ent->flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) { + free(ent->nv.value); } } -static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize, - nghttp2_mem *mem) { +static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize) { size_t size; for (size = 1; size < bufsize; size <<= 1) ; - ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size); + ringbuf->buffer = malloc(sizeof(nghttp2_hd_entry *) * size); if (ringbuf->buffer == NULL) { return NGHTTP2_ERR_NOMEM; } @@ -620,8 +225,7 @@ return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask]; } -static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize, - nghttp2_mem *mem) { +static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize) { size_t i; size_t size; nghttp2_hd_entry **buffer; @@ -631,39 +235,39 @@ } for (size = 1; size < bufsize; size <<= 1) ; - buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size); + buffer = malloc(sizeof(nghttp2_hd_entry *) * size); if (buffer == NULL) { return NGHTTP2_ERR_NOMEM; } for (i = 0; i < ringbuf->len; ++i) { buffer[i] = hd_ringbuf_get(ringbuf, i); } - nghttp2_mem_free(mem, ringbuf->buffer); + free(ringbuf->buffer); ringbuf->buffer = buffer; ringbuf->mask = size - 1; ringbuf->first = 0; return 0; } -static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) { +static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf) { size_t i; if (ringbuf == NULL) { return; } for (i = 0; i < ringbuf->len; ++i) { nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i); - + --ent->ref; nghttp2_hd_entry_free(ent); - nghttp2_mem_free(mem, ent); + free(ent); } - nghttp2_mem_free(mem, ringbuf->buffer); + free(ringbuf->buffer); } static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf, - nghttp2_hd_entry *ent, nghttp2_mem *mem) { + nghttp2_hd_entry *ent) { int rv; - rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem); + rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1); if (rv != 0) { return rv; @@ -680,44 +284,37 @@ --ringbuf->len; } -static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) { +static int hd_context_init(nghttp2_hd_context *context) { int rv; - context->mem = mem; context->bad = 0; context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE; rv = hd_ringbuf_init(&context->hd_table, context->hd_table_bufsize_max / - NGHTTP2_HD_ENTRY_OVERHEAD, - mem); + NGHTTP2_HD_ENTRY_OVERHEAD); if (rv != 0) { return rv; } context->hd_table_bufsize = 0; - context->next_seq = 0; - return 0; } static void hd_context_free(nghttp2_hd_context *context) { - hd_ringbuf_free(&context->hd_table, context->mem); + hd_ringbuf_free(&context->hd_table); } -int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) { - return nghttp2_hd_deflate_init2( - deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem); +int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater) { + return nghttp2_hd_deflate_init2(deflater, + NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE); } int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater, - size_t deflate_hd_table_bufsize_max, - nghttp2_mem *mem) { + size_t deflate_hd_table_bufsize_max) { int rv; - rv = hd_context_init(&deflater->ctx, mem); + rv = hd_context_init(&deflater->ctx); if (rv != 0) { return rv; } - hd_map_init(&deflater->map); - if (deflate_hd_table_bufsize_max < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) { deflater->notify_table_size_change = 1; deflater->ctx.hd_table_bufsize_max = deflate_hd_table_bufsize_max; @@ -731,48 +328,55 @@ return 0; } -int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) { +int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater) { int rv; - rv = hd_context_init(&inflater->ctx, mem); + rv = hd_context_init(&inflater->ctx); if (rv != 0) { goto fail; } inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE; - inflater->min_hd_table_bufsize_max = UINT32_MAX; - inflater->nv_name_keep = NULL; - inflater->nv_value_keep = NULL; + inflater->ent_keep = NULL; + inflater->nv_keep = NULL; inflater->opcode = NGHTTP2_HD_OPCODE_NONE; - inflater->state = NGHTTP2_HD_STATE_INFLATE_START; + inflater->state = NGHTTP2_HD_STATE_OPCODE; - nghttp2_buf_init(&inflater->namebuf); - nghttp2_buf_init(&inflater->valuebuf); + rv = nghttp2_bufs_init3(&inflater->nvbufs, NGHTTP2_HD_MAX_NV / 8, 8, 1, 0); - inflater->namercbuf = NULL; - inflater->valuercbuf = NULL; + if (rv != 0) { + goto nvbufs_fail; + } inflater->huffman_encoded = 0; inflater->index = 0; inflater->left = 0; inflater->shift = 0; + inflater->newnamelen = 0; inflater->index_required = 0; inflater->no_index = 0; return 0; +nvbufs_fail: + hd_context_free(&inflater->ctx); fail: return rv; } static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) { - nghttp2_rcbuf_decref(inflater->nv_value_keep); - nghttp2_rcbuf_decref(inflater->nv_name_keep); + if (inflater->ent_keep) { + if (inflater->ent_keep->ref == 0) { + nghttp2_hd_entry_free(inflater->ent_keep); + free(inflater->ent_keep); + } + inflater->ent_keep = NULL; + } - inflater->nv_value_keep = NULL; - inflater->nv_name_keep = NULL; + free(inflater->nv_keep); + inflater->nv_keep = NULL; } void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) { @@ -781,10 +385,7 @@ void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) { hd_inflate_keep_free(inflater); - - nghttp2_rcbuf_decref(inflater->valuercbuf); - nghttp2_rcbuf_decref(inflater->namercbuf); - + nghttp2_bufs_free(&inflater->nvbufs); hd_context_free(&inflater->ctx); } @@ -792,18 +393,30 @@ return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen; } -static int emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) { - DEBUGF(fprintf(stderr, "inflatehd: header emission: %s: %s\n", nv->name->base, - nv->value->base)); +static int emit_indexed_header(nghttp2_nv *nv_out, nghttp2_hd_entry *ent) { + DEBUGF(fprintf(stderr, "inflatehd: header emission: ")); + DEBUGF(fwrite(ent->nv.name, ent->nv.namelen, 1, stderr)); + DEBUGF(fprintf(stderr, ": ")); + DEBUGF(fwrite(ent->nv.value, ent->nv.valuelen, 1, stderr)); + DEBUGF(fprintf(stderr, "\n")); /* ent->ref may be 0. This happens if the encoder emits literal block larger than header table capacity with indexing. */ - *nv_out = *nv; + *nv_out = ent->nv; + return 0; +} +static int emit_literal_header(nghttp2_nv *nv_out, nghttp2_nv *nv) { + DEBUGF(fprintf(stderr, "inflatehd: header emission: ")); + DEBUGF(fwrite(nv->name, nv->namelen, 1, stderr)); + DEBUGF(fprintf(stderr, ": ")); + DEBUGF(fwrite(nv->value, nv->valuelen, 1, stderr)); + DEBUGF(fprintf(stderr, "\n")); + *nv_out = *nv; return 0; } static size_t count_encoded_length(size_t n, size_t prefix) { - size_t k = (size_t)((1 << prefix) - 1); + size_t k = (1 << prefix) - 1; size_t len = 0; if (n < k) { @@ -820,23 +433,21 @@ } static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) { - size_t k = (size_t)((1 << prefix) - 1); + size_t k = (1 << prefix) - 1; uint8_t *begin = buf; - *buf = (uint8_t)(*buf & ~k); + *buf &= ~k; if (n < k) { - *buf = (uint8_t)(*buf | n); + *buf |= n; return 1; } - *buf = (uint8_t)(*buf | k); - ++buf; - + *buf++ |= k; n -= k; for (; n >= 128; n >>= 7) { - *buf++ = (uint8_t)((1 << 7) | (n & 0x7f)); + *buf++ = (1 << 7) | (n & 0x7f); } *buf++ = (uint8_t)n; @@ -862,11 +473,11 @@ * of bytes processed, or returns -1, indicating decoding error. */ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *final, - uint32_t initial, size_t shift, const uint8_t *in, - const uint8_t *last, size_t prefix) { - uint32_t k = (uint8_t)((1 << prefix) - 1); + uint32_t initial, size_t shift, uint8_t *in, + uint8_t *last, size_t prefix) { + uint32_t k = (1 << prefix) - 1; uint32_t n = initial; - const uint8_t *start = in; + uint8_t *start = in; *shift_ptr = 0; *final = 0; @@ -994,7 +605,7 @@ blocklen = count_encoded_length(enclen, 7); DEBUGF(fprintf(stderr, "deflatehd: emit string str=")); - DEBUGF(fwrite(str, 1, len, stderr)); + DEBUGF(fwrite(str, len, 1, stderr)); DEBUGF(fprintf(stderr, ", length=%zu, huffman=%d, encoded_length=%zu\n", len, huffman, enclen)); @@ -1021,39 +632,38 @@ return rv; } -static uint8_t pack_first_byte(int indexing_mode) { - switch (indexing_mode) { - case NGHTTP2_HD_WITH_INDEXING: +static uint8_t pack_first_byte(int inc_indexing, int no_index) { + if (inc_indexing) { return 0x40u; - case NGHTTP2_HD_WITHOUT_INDEXING: - return 0; - case NGHTTP2_HD_NEVER_INDEXING: + } + + if (no_index) { return 0x10u; - default: - assert(0); } - /* This is required to compile with android NDK r10d + - --enable-werror */ + return 0; } static int emit_indname_block(nghttp2_bufs *bufs, size_t idx, - const nghttp2_nv *nv, int indexing_mode) { + const nghttp2_nv *nv, int inc_indexing) { int rv; uint8_t *bufp; size_t blocklen; uint8_t sb[16]; size_t prefixlen; + int no_index; - if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) { + no_index = (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0; + + if (inc_indexing) { prefixlen = 6; } else { prefixlen = 4; } DEBUGF(fprintf(stderr, "deflatehd: emit indname index=%zu, valuelen=%zu, " - "indexing_mode=%d\n", - idx, nv->valuelen, indexing_mode)); + "indexing=%d, no_index=%d\n", + idx, nv->valuelen, inc_indexing, no_index)); blocklen = count_encoded_length(idx + 1, prefixlen); @@ -1063,7 +673,7 @@ bufp = sb; - *bufp = pack_first_byte(indexing_mode); + *bufp = pack_first_byte(inc_indexing, no_index); encode_length(bufp, idx + 1, prefixlen); @@ -1081,14 +691,17 @@ } static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv, - int indexing_mode) { + int inc_indexing) { int rv; + int no_index; + + no_index = (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0; DEBUGF(fprintf(stderr, "deflatehd: emit newname namelen=%zu, valuelen=%zu, " - "indexing_mode=%d\n", - nv->namelen, nv->valuelen, indexing_mode)); + "indexing=%d, no_index=%d\n", + nv->namelen, nv->valuelen, inc_indexing, no_index)); - rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode)); + rv = nghttp2_bufs_addb(bufs, pack_first_byte(inc_indexing, no_index)); if (rv != 0) { return rv; } @@ -1106,16 +719,16 @@ return 0; } -static int add_hd_table_incremental(nghttp2_hd_context *context, - nghttp2_hd_nv *nv, nghttp2_hd_map *map, - uint32_t hash) { +static nghttp2_hd_entry *add_hd_table_incremental(nghttp2_hd_context *context, + const nghttp2_nv *nv, + uint32_t name_hash, + uint32_t value_hash, + uint8_t entry_flags) { int rv; nghttp2_hd_entry *new_ent; size_t room; - nghttp2_mem *mem; - mem = context->mem; - room = entry_room(nv->name->len, nv->value->len); + room = entry_room(nv->namelen, nv->valuelen); while (context->hd_table_bufsize + room > context->hd_table_bufsize_max && context->hd_table.len > 0) { @@ -1123,53 +736,65 @@ size_t idx = context->hd_table.len - 1; nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx); - context->hd_table_bufsize -= - entry_room(ent->nv.name->len, ent->nv.value->len); - - DEBUGF(fprintf(stderr, "hpack: remove item from header table: %s: %s\n", - (char *)ent->nv.name->base, (char *)ent->nv.value->base)); + context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen); + DEBUGF(fprintf(stderr, "hpack: remove item from header table: ")); + DEBUGF(fwrite(ent->nv.name, ent->nv.namelen, 1, stderr)); + DEBUGF(fprintf(stderr, ": ")); + DEBUGF(fwrite(ent->nv.value, ent->nv.valuelen, 1, stderr)); + DEBUGF(fprintf(stderr, "\n")); hd_ringbuf_pop_back(&context->hd_table); - if (map) { - hd_map_remove(map, ent); + if (--ent->ref == 0) { + nghttp2_hd_entry_free(ent); + free(ent); } - - nghttp2_hd_entry_free(ent); - nghttp2_mem_free(mem, ent); } - if (room > context->hd_table_bufsize_max) { - /* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is - immediately evicted. So we don't allocate memory for it. */ - return 0; + new_ent = malloc(sizeof(nghttp2_hd_entry)); + if (new_ent == NULL) { + return NULL; } - new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry)); - if (new_ent == NULL) { - return NGHTTP2_ERR_NOMEM; + rv = nghttp2_hd_entry_init(new_ent, entry_flags, nv->name, nv->namelen, + nv->value, nv->valuelen, name_hash, value_hash); + if (rv != 0) { + free(new_ent); + return NULL; } - nghttp2_hd_entry_init(new_ent, nv); + if (room > context->hd_table_bufsize_max) { + /* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is + immediately evicted. */ + --new_ent->ref; + } else { + rv = hd_ringbuf_push_front(&context->hd_table, new_ent); - rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem); + if (rv != 0) { + --new_ent->ref; - if (rv != 0) { - nghttp2_hd_entry_free(new_ent); - nghttp2_mem_free(mem, new_ent); + /* nv->name and nv->value are managed by caller. */ + new_ent->nv.name = NULL; + new_ent->nv.namelen = 0; + new_ent->nv.value = NULL; + new_ent->nv.valuelen = 0; - return rv; - } + nghttp2_hd_entry_free(new_ent); + free(new_ent); - new_ent->seq = context->next_seq++; - new_ent->hash = hash; + return NULL; + } - if (map) { - hd_map_insert(map, new_ent); + context->hd_table_bufsize += room; } + return new_ent; +} - context->hd_table_bufsize += room; +static int name_eq(const nghttp2_nv *a, const nghttp2_nv *b) { + return a->namelen == b->namelen && memeq(a->name, b->name, a->namelen); +} - return 0; +static int value_eq(const nghttp2_nv *a, const nghttp2_nv *b) { + return a->valuelen == b->valuelen && memeq(a->value, b->value, a->valuelen); } typedef struct { @@ -1178,84 +803,78 @@ uint8_t name_value_match; } search_result; -static search_result search_static_table(const nghttp2_nv *nv, int32_t token, - int indexing_mode) { - search_result res = {token, 0}; - int i; - nghttp2_hd_static_entry *ent; - - if (indexing_mode == NGHTTP2_HD_NEVER_INDEXING) { - return res; - } - - for (i = token; - i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token; - ++i) { - ent = &static_table[i]; - if (ent->value.len == nv->valuelen && - memcmp(ent->value.base, nv->value, nv->valuelen) == 0) { - res.index = i; - res.name_value_match = 1; - return res; - } - } - return res; -} - static search_result search_hd_table(nghttp2_hd_context *context, - const nghttp2_nv *nv, int32_t token, - int indexing_mode, nghttp2_hd_map *map, - uint32_t hash) { + const nghttp2_nv *nv, uint32_t name_hash, + uint32_t value_hash) { + ssize_t left = -1, right = (ssize_t)STATIC_TABLE_LENGTH; search_result res = {-1, 0}; - nghttp2_hd_entry *ent; - int exact_match; + size_t i; + int use_index = (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) == 0; - if (token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) { - res = search_static_table(nv, token, indexing_mode); - if (res.name_value_match) { - return res; - } - } + /* Search dynamic table first, so that we can find recently used + entry first */ + if (use_index) { + for (i = 0; i < context->hd_table.len; ++i) { + nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, i); + if (ent->name_hash != name_hash || !name_eq(&ent->nv, nv)) { + continue; + } + + if (res.index == -1) { + res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH); + } - exact_match = 0; - ent = hd_map_find(map, &exact_match, nv, token, hash); - if (ent == NULL) { - return res; + if (ent->value_hash == value_hash && value_eq(&ent->nv, nv)) { + res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH); + res.name_value_match = 1; + return res; + } + } } - if (res.index != -1 && !exact_match) { - return res; + while (right - left > 1) { + ssize_t mid = (left + right) / 2; + nghttp2_hd_entry *ent = &static_table[mid].ent; + if (ent->name_hash < name_hash) { + left = mid; + } else { + right = mid; + } } - res.index = - (ssize_t)(context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH); + for (i = right; i < STATIC_TABLE_LENGTH; ++i) { + nghttp2_hd_entry *ent = &static_table[i].ent; + if (ent->name_hash != name_hash) { + break; + } - if (exact_match) { - res.name_value_match = 1; + if (name_eq(&ent->nv, nv)) { + if (res.index == -1) { + res.index = (ssize_t)(static_table[i].index); + } + if (use_index && ent->value_hash == value_hash && + value_eq(&ent->nv, nv)) { + res.index = (ssize_t)(static_table[i].index); + res.name_value_match = 1; + return res; + } + } } return res; } -static void hd_context_shrink_table_size(nghttp2_hd_context *context, - nghttp2_hd_map *map) { - nghttp2_mem *mem; - - mem = context->mem; - +static void hd_context_shrink_table_size(nghttp2_hd_context *context) { while (context->hd_table_bufsize > context->hd_table_bufsize_max && context->hd_table.len > 0) { size_t idx = context->hd_table.len - 1; nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx); - context->hd_table_bufsize -= - entry_room(ent->nv.name->len, ent->nv.value->len); + context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen); hd_ringbuf_pop_back(&context->hd_table); - if (map) { - hd_map_remove(map, ent); + if (--ent->ref == 0) { + nghttp2_hd_entry_free(ent); + free(ent); } - - nghttp2_hd_entry_free(ent); - nghttp2_mem_free(mem, ent); } } @@ -1271,39 +890,15 @@ deflater->notify_table_size_change = 1; - hd_context_shrink_table_size(&deflater->ctx, &deflater->map); + hd_context_shrink_table_size(&deflater->ctx); return 0; } int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater, size_t settings_hd_table_bufsize_max) { - switch (inflater->state) { - case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE: - case NGHTTP2_HD_STATE_INFLATE_START: - break; - default: - return NGHTTP2_ERR_INVALID_STATE; - } - - /* It seems that encoder is not required to send dynamic table size - update if the table size is not changed after applying - SETTINGS_HEADER_TABLE_SIZE. RFC 7541 is ambiguous here, but this - is the intention of the editor. If new maximum table size is - strictly smaller than the current negotiated maximum size, - encoder must send dynamic table size update. In other cases, we - cannot expect it to do so. */ - if (inflater->ctx.hd_table_bufsize_max > settings_hd_table_bufsize_max) { - inflater->state = NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE; - /* Remember minimum value, and validate that encoder sends the - value less than or equal to this. */ - inflater->min_hd_table_bufsize_max = settings_hd_table_bufsize_max; - } - inflater->settings_hd_table_bufsize_max = settings_hd_table_bufsize_max; - inflater->ctx.hd_table_bufsize_max = settings_hd_table_bufsize_max; - - hd_context_shrink_table_size(&inflater->ctx, NULL); + hd_context_shrink_table_size(&inflater->ctx); return 0; } @@ -1314,43 +909,36 @@ return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH - 1; } -nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) { +nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context, + size_t idx) { assert(INDEX_RANGE_VALID(context, idx)); if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) { - return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH) - ->nv; + return hd_ringbuf_get(&context->hd_table, + idx - NGHTTP2_STATIC_TABLE_LENGTH); } else { - nghttp2_hd_static_entry *ent = &static_table[idx]; - nghttp2_hd_nv nv = {&ent->name, &ent->value, ent->token, - NGHTTP2_NV_FLAG_NONE}; - return nv; + return &static_table[static_table_index[idx]].ent; } } -static const nghttp2_nv *nghttp2_hd_table_get2(nghttp2_hd_context *context, - size_t idx) { - assert(INDEX_RANGE_VALID(context, idx)); - if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) { - return &hd_ringbuf_get(&context->hd_table, - idx - NGHTTP2_STATIC_TABLE_LENGTH)->cnv; - } - - return &static_table[idx].cnv; -} +#define name_match(NV, NAME) \ + (nv->namelen == sizeof(NAME) - 1 && memeq(nv->name, NAME, sizeof(NAME) - 1)) -static int hd_deflate_decide_indexing(nghttp2_hd_deflater *deflater, - const nghttp2_nv *nv, int32_t token) { - if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE || - token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG || - token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE || - token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION || - token == NGHTTP2_TOKEN_SET_COOKIE || +static int hd_deflate_should_indexing(nghttp2_hd_deflater *deflater, + const nghttp2_nv *nv) { + if ((nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) || entry_room(nv->namelen, nv->valuelen) > deflater->ctx.hd_table_bufsize_max * 3 / 4) { - return NGHTTP2_HD_WITHOUT_INDEXING; + return 0; } - - return NGHTTP2_HD_WITH_INDEXING; +#ifdef NGHTTP2_XHD + return !name_match(nv, NGHTTP2_XHD); +#else /* !NGHTTP2_XHD */ + return !name_match(nv, ":path") && !name_match(nv, "content-length") && + !name_match(nv, "set-cookie") && !name_match(nv, "etag") && + !name_match(nv, "if-modified-since") && + !name_match(nv, "if-none-match") && !name_match(nv, "location") && + !name_match(nv, "age"); +#endif /* !NGHTTP2_XHD */ } static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, @@ -1358,36 +946,17 @@ int rv; search_result res; ssize_t idx; - int indexing_mode; - int32_t token; - nghttp2_mem *mem; - uint32_t hash = 0; - - DEBUGF(fprintf(stderr, "deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen, - nv->name, (int)nv->valuelen, nv->value)); - - mem = deflater->ctx.mem; - - token = lookup_token(nv->name, nv->namelen); - if (token == -1) { - hash = name_hash(nv); - } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) { - hash = static_table[token].hash; - } - - /* Don't index authorization header field since it may contain low - entropy secret data (e.g., id/password). Also cookie header - field with less than 20 bytes value is also never indexed. This - is the same criteria used in Firefox codebase. */ - indexing_mode = - token == NGHTTP2_TOKEN_AUTHORIZATION || - (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) || - (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) - ? NGHTTP2_HD_NEVER_INDEXING - : hd_deflate_decide_indexing(deflater, nv, token); + int incidx = 0; + uint32_t name_hash = hash(nv->name, nv->namelen); + uint32_t value_hash = hash(nv->value, nv->valuelen); + + DEBUGF(fprintf(stderr, "deflatehd: deflating ")); + DEBUGF(fwrite(nv->name, nv->namelen, 1, stderr)); + DEBUGF(fprintf(stderr, ": ")); + DEBUGF(fwrite(nv->value, nv->valuelen, 1, stderr)); + DEBUGF(fprintf(stderr, "\n")); - res = search_hd_table(&deflater->ctx, nv, token, indexing_mode, - &deflater->map, hash); + res = search_hd_table(&deflater->ctx, nv, name_hash, value_hash); idx = res.index; @@ -1395,7 +964,7 @@ DEBUGF(fprintf(stderr, "deflatehd: name/value match index=%zd\n", idx)); - rv = emit_indexed_block(bufs, (size_t)idx); + rv = emit_indexed_block(bufs, idx); if (rv != 0) { return rv; } @@ -1407,42 +976,33 @@ DEBUGF(fprintf(stderr, "deflatehd: name match index=%zd\n", res.index)); } - if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) { - nghttp2_hd_nv hd_nv; - + if (hd_deflate_should_indexing(deflater, nv)) { + nghttp2_hd_entry *new_ent; if (idx != -1 && idx < (ssize_t)NGHTTP2_STATIC_TABLE_LENGTH) { - hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name; - nghttp2_rcbuf_incref(hd_nv.name); + nghttp2_nv nv_indname; + nv_indname = *nv; + nv_indname.name = nghttp2_hd_table_get(&deflater->ctx, idx)->nv.name; + new_ent = + add_hd_table_incremental(&deflater->ctx, &nv_indname, name_hash, + value_hash, NGHTTP2_HD_FLAG_VALUE_ALLOC); } else { - rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem); - if (rv != 0) { - return rv; - } - } - - rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem); - - if (rv != 0) { - nghttp2_rcbuf_decref(hd_nv.name); - return rv; + new_ent = add_hd_table_incremental( + &deflater->ctx, nv, name_hash, value_hash, + NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_VALUE_ALLOC); } - - hd_nv.token = token; - hd_nv.flags = NGHTTP2_NV_FLAG_NONE; - - rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash); - - nghttp2_rcbuf_decref(hd_nv.value); - nghttp2_rcbuf_decref(hd_nv.name); - - if (rv != 0) { + if (!new_ent) { return NGHTTP2_ERR_HEADER_COMP; } + if (new_ent->ref == 0) { + nghttp2_hd_entry_free(new_ent); + free(new_ent); + } + incidx = 1; } if (idx == -1) { - rv = emit_newname_block(bufs, nv, indexing_mode); + rv = emit_newname_block(bufs, nv, incidx); } else { - rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode); + rv = emit_indname_block(bufs, idx, nv, incidx); } if (rv != 0) { return rv; @@ -1508,11 +1068,8 @@ size_t nvlen) { nghttp2_bufs bufs; int rv; - nghttp2_mem *mem; - mem = deflater->ctx.mem; - - rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen, mem); + rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen); if (rv != 0) { return rv; @@ -1563,30 +1120,19 @@ int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, size_t deflate_hd_table_bufsize_max) { - return nghttp2_hd_deflate_new2(deflater_ptr, deflate_hd_table_bufsize_max, - NULL); -} - -int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr, - size_t deflate_hd_table_bufsize_max, - nghttp2_mem *mem) { int rv; nghttp2_hd_deflater *deflater; - if (mem == NULL) { - mem = nghttp2_mem_default(); - } - - deflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_deflater)); + deflater = malloc(sizeof(nghttp2_hd_deflater)); if (deflater == NULL) { return NGHTTP2_ERR_NOMEM; } - rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max, mem); + rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max); if (rv != 0) { - nghttp2_mem_free(mem, deflater); + free(deflater); return rv; } @@ -1597,13 +1143,9 @@ } void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) { - nghttp2_mem *mem; - - mem = deflater->ctx.mem; - nghttp2_hd_deflate_free(deflater); - nghttp2_mem_free(mem, deflater); + free(deflater); } static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater, @@ -1625,8 +1167,8 @@ * Integer decoding failed */ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin, - const uint8_t *in, const uint8_t *last, - size_t prefix, size_t maxlen) { + uint8_t *in, uint8_t *last, size_t prefix, + size_t maxlen) { ssize_t rv; uint32_t out; @@ -1665,18 +1207,20 @@ * Out of memory * NGHTTP2_ERR_HEADER_COMP * Huffman decoding failed + * NGHTTP2_ERR_BUFFER_ERROR + * Out of buffer space. */ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater, - nghttp2_buf *buf, const uint8_t *in, - const uint8_t *last) { + nghttp2_bufs *bufs, uint8_t *in, + uint8_t *last) { ssize_t readlen; int final = 0; if ((size_t)(last - in) >= inflater->left) { last = in + inflater->left; final = 1; } - readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in, - (size_t)(last - in), final); + readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, bufs, in, + last - in, final); if (readlen < 0) { DEBUGF(fprintf(stderr, "inflatehd: huffman decoding failed\n")); @@ -1697,13 +1241,17 @@ * Out of memory * NGHTTP2_ERR_HEADER_COMP * Header decompression failed + * NGHTTP2_ERR_BUFFER_ERROR + * Out of buffer space. */ -static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf, - const uint8_t *in, const uint8_t *last) { +static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, + nghttp2_bufs *bufs, uint8_t *in, uint8_t *last) { + int rv; size_t len = nghttp2_min((size_t)(last - in), inflater->left); - - buf->last = nghttp2_cpymem(buf->last, in, len); - + rv = nghttp2_bufs_add(bufs, in, len); + if (rv != 0) { + return rv; + } inflater->left -= len; return (ssize_t)len; } @@ -1720,10 +1268,65 @@ * Out of memory */ static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater, - nghttp2_hd_nv *nv_out) { - nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index); + nghttp2_nv *nv_out) { + nghttp2_hd_entry *ent = nghttp2_hd_table_get(&inflater->ctx, inflater->index); - emit_header(nv_out, &nv); + emit_indexed_header(nv_out, ent); + + return 0; +} + +static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater, nghttp2_nv *nv, + int value_only) { + ssize_t rv; + size_t buflen; + uint8_t *buf; + nghttp2_buf *pbuf; + + if (inflater->index_required || + inflater->nvbufs.head != inflater->nvbufs.cur) { + + rv = nghttp2_bufs_remove(&inflater->nvbufs, &buf); + + if (rv < 0) { + return NGHTTP2_ERR_NOMEM; + } + + buflen = rv; + + if (value_only) { + nv->name = NULL; + nv->namelen = 0; + } else { + nv->name = buf; + nv->namelen = inflater->newnamelen; + } + + nv->value = buf + nv->namelen; + nv->valuelen = buflen - nv->namelen; + + return 0; + } + + /* If we are not going to store header in header table and + name/value are in first chunk, we just refer them from nv, + instead of mallocing another memory. */ + + pbuf = &inflater->nvbufs.head->buf; + + if (value_only) { + nv->name = NULL; + nv->namelen = 0; + } else { + nv->name = pbuf->pos; + nv->namelen = inflater->newnamelen; + } + + nv->value = pbuf->pos + nv->namelen; + nv->valuelen = nghttp2_buf_len(pbuf) - nv->namelen; + + /* Resetting does not change the content of first buffer */ + nghttp2_bufs_reset(&inflater->nvbufs); return 0; } @@ -1740,9 +1343,14 @@ * Out of memory */ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater, - nghttp2_hd_nv *nv_out) { - nghttp2_hd_nv nv; + nghttp2_nv *nv_out) { int rv; + nghttp2_nv nv; + + rv = hd_inflate_remove_bufs(inflater, &nv, 0 /* name and value */); + if (rv != 0) { + return NGHTTP2_ERR_NOMEM; + } if (inflater->no_index) { nv.flags = NGHTTP2_NV_FLAG_NO_INDEX; @@ -1750,25 +1358,36 @@ nv.flags = NGHTTP2_NV_FLAG_NONE; } - nv.name = inflater->namercbuf; - nv.value = inflater->valuercbuf; - nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len); - if (inflater->index_required) { - rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0); + nghttp2_hd_entry *new_ent; + uint8_t ent_flags; - if (rv != 0) { - return rv; + /* nv->value points to the middle of the buffer pointed by + nv->name. So we just need to keep track of nv->name for memory + management. */ + ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT; + + new_ent = + add_hd_table_incremental(&inflater->ctx, &nv, hash(nv.name, nv.namelen), + hash(nv.value, nv.valuelen), ent_flags); + + if (new_ent) { + emit_indexed_header(nv_out, new_ent); + inflater->ent_keep = new_ent; + + return 0; } - } - emit_header(nv_out, &nv); + free(nv.name); + + return NGHTTP2_ERR_NOMEM; + } - inflater->nv_name_keep = nv.name; - inflater->nv_value_keep = nv.value; + emit_literal_header(nv_out, &nv); - inflater->namercbuf = NULL; - inflater->valuercbuf = NULL; + if (nv.name != inflater->nvbufs.head->buf.pos) { + inflater->nv_keep = nv.name; + } return 0; } @@ -1785,11 +1404,15 @@ * Out of memory */ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater, - nghttp2_hd_nv *nv_out) { - nghttp2_hd_nv nv; + nghttp2_nv *nv_out) { int rv; + nghttp2_nv nv; + nghttp2_hd_entry *ent_name; - nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index); + rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */); + if (rv != 0) { + return NGHTTP2_ERR_NOMEM; + } if (inflater->no_index) { nv.flags = NGHTTP2_NV_FLAG_NO_INDEX; @@ -1797,73 +1420,63 @@ nv.flags = NGHTTP2_NV_FLAG_NONE; } - nghttp2_rcbuf_incref(nv.name); + ent_name = nghttp2_hd_table_get(&inflater->ctx, inflater->index); - nv.value = inflater->valuercbuf; + nv.name = ent_name->nv.name; + nv.namelen = ent_name->nv.namelen; if (inflater->index_required) { - rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0); - if (rv != 0) { - nghttp2_rcbuf_decref(nv.name); - return NGHTTP2_ERR_NOMEM; - } - } + nghttp2_hd_entry *new_ent; + uint8_t ent_flags; + int static_name; - emit_header(nv_out, &nv); + ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT; + static_name = inflater->index < NGHTTP2_STATIC_TABLE_LENGTH; - inflater->nv_name_keep = nv.name; - inflater->nv_value_keep = nv.value; + if (!static_name) { + ent_flags |= NGHTTP2_HD_FLAG_NAME_ALLOC; + /* For entry in static table, we must not touch ref, because it + is shared by threads */ + ++ent_name->ref; + } - inflater->valuercbuf = NULL; + new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_name->name_hash, + hash(nv.value, nv.valuelen), ent_flags); - return 0; -} + if (!static_name && --ent_name->ref == 0) { + nghttp2_hd_entry_free(ent_name); + free(ent_name); + } -ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, - int *inflate_flags, uint8_t *in, size_t inlen, - int in_final) { - return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, in, inlen, - in_final); -} + if (new_ent) { + emit_indexed_header(nv_out, new_ent); -ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, - nghttp2_nv *nv_out, int *inflate_flags, - const uint8_t *in, size_t inlen, int in_final) { - ssize_t rv; - nghttp2_hd_nv hd_nv; + inflater->ent_keep = new_ent; - rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen, - in_final); + return 0; + } - if (rv < 0) { - return rv; - } + free(nv.value); - if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { - nv_out->name = hd_nv.name->base; - nv_out->namelen = hd_nv.name->len; + return NGHTTP2_ERR_NOMEM; + } - nv_out->value = hd_nv.value->base; - nv_out->valuelen = hd_nv.value->len; + emit_literal_header(nv_out, &nv); - nv_out->flags = hd_nv.flags; + if (nv.value != inflater->nvbufs.head->buf.pos) { + inflater->nv_keep = nv.value; } - return rv; + return 0; } -ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, - nghttp2_hd_nv *nv_out, int *inflate_flags, - const uint8_t *in, size_t inlen, - int in_final) { +ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, + int *inflate_flags, uint8_t *in, size_t inlen, + int in_final) { ssize_t rv = 0; - const uint8_t *first = in; - const uint8_t *last = in + inlen; + uint8_t *first = in; + uint8_t *last = in + inlen; int rfin = 0; - int busy = 0; - nghttp2_mem *mem; - - mem = inflater->ctx.mem; if (inflater->ctx.bad) { return NGHTTP2_ERR_HEADER_COMP; @@ -1872,28 +1485,11 @@ DEBUGF(fprintf(stderr, "inflatehd: start state=%d\n", inflater->state)); hd_inflate_keep_free(inflater); *inflate_flags = NGHTTP2_HD_INFLATE_NONE; - for (; in != last || busy;) { - busy = 0; + for (; in != last;) { switch (inflater->state) { - case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE: - if ((*in & 0xe0u) != 0x20u) { - DEBUGF(fprintf(stderr, "inflatehd: header table size change was " - "expected, but saw 0x%02x as first byte", - *in)); - rv = NGHTTP2_ERR_HEADER_COMP; - goto fail; - } - /* fall through */ - case NGHTTP2_HD_STATE_INFLATE_START: case NGHTTP2_HD_STATE_OPCODE: if ((*in & 0xe0u) == 0x20u) { DEBUGF(fprintf(stderr, "inflatehd: header table size change\n")); - if (inflater->state == NGHTTP2_HD_STATE_OPCODE) { - DEBUGF(fprintf(stderr, "inflatehd: header table size change must " - "appear at the head of header block\n")); - rv = NGHTTP2_ERR_HEADER_COMP; - goto fail; - } inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED; inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE; } else if (*in & 0x80u) { @@ -1925,10 +1521,8 @@ break; case NGHTTP2_HD_STATE_READ_TABLE_SIZE: rfin = 0; - rv = hd_inflate_read_len( - inflater, &rfin, in, last, 5, - nghttp2_min(inflater->min_hd_table_bufsize_max, - inflater->settings_hd_table_bufsize_max)); + rv = hd_inflate_read_len(inflater, &rfin, in, last, 5, + inflater->settings_hd_table_bufsize_max); if (rv < 0) { goto fail; } @@ -1937,10 +1531,9 @@ goto almost_ok; } DEBUGF(fprintf(stderr, "inflatehd: table_size=%zu\n", inflater->left)); - inflater->min_hd_table_bufsize_max = UINT32_MAX; inflater->ctx.hd_table_bufsize_max = inflater->left; - hd_context_shrink_table_size(&inflater->ctx, NULL); - inflater->state = NGHTTP2_HD_STATE_INFLATE_START; + hd_context_shrink_table_size(&inflater->ctx); + inflater->state = NGHTTP2_HD_STATE_OPCODE; break; case NGHTTP2_HD_STATE_READ_INDEX: { size_t prefixlen; @@ -2021,24 +1614,12 @@ nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx); inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF; - - rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1, - mem); } else { inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME; - rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem); } - - if (rv != 0) { - goto fail; - } - - nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base, - inflater->namercbuf->len); - break; case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF: - rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last); + rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last); if (rv < 0) { goto fail; } @@ -2054,14 +1635,13 @@ goto almost_ok; } - *inflater->namebuf.last = '\0'; - inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf); + inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs); inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN; break; case NGHTTP2_HD_STATE_NEWNAME_READ_NAME: - rv = hd_inflate_read(inflater, &inflater->namebuf, in, last); + rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last); if (rv < 0) { goto fail; } @@ -2076,8 +1656,7 @@ goto almost_ok; } - *inflater->namebuf.last = '\0'; - inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf); + inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs); inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN; @@ -2104,32 +1683,30 @@ } DEBUGF(fprintf(stderr, "inflatehd: valuelen=%zu\n", inflater->left)); + if (inflater->left == 0) { + if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) { + rv = hd_inflate_commit_newname(inflater, nv_out); + } else { + rv = hd_inflate_commit_indname(inflater, nv_out); + } + if (rv != 0) { + goto fail; + } + inflater->state = NGHTTP2_HD_STATE_OPCODE; + *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT; + return (ssize_t)(in - first); + } if (inflater->huffman_encoded) { nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx); inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF; - - rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1, - mem); } else { inflater->state = NGHTTP2_HD_STATE_READ_VALUE; - - rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem); - } - - if (rv != 0) { - goto fail; } - - nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base, - inflater->valuercbuf->len); - - busy = 1; - break; case NGHTTP2_HD_STATE_READ_VALUEHUFF: - rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last); + rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last); if (rv < 0) { goto fail; } @@ -2145,9 +1722,6 @@ goto almost_ok; } - *inflater->valuebuf.last = '\0'; - inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf); - if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) { rv = hd_inflate_commit_newname(inflater, nv_out); } else { @@ -2163,7 +1737,7 @@ return (ssize_t)(in - first); case NGHTTP2_HD_STATE_READ_VALUE: - rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last); + rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last); if (rv < 0) { DEBUGF(fprintf(stderr, "inflatehd: value read failure %zd: %s\n", rv, nghttp2_strerror((int)rv))); @@ -2180,9 +1754,6 @@ goto almost_ok; } - *inflater->valuebuf.last = '\0'; - inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf); - if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) { rv = hd_inflate_commit_newname(inflater, nv_out); } else { @@ -2207,8 +1778,7 @@ if (in_final) { DEBUGF(fprintf(stderr, "inflatehd: in_final set\n")); - if (inflater->state != NGHTTP2_HD_STATE_OPCODE && - inflater->state != NGHTTP2_HD_STATE_INFLATE_START) { + if (inflater->state != NGHTTP2_HD_STATE_OPCODE) { DEBUGF(fprintf(stderr, "inflatehd: unacceptable state=%d\n", inflater->state)); rv = NGHTTP2_ERR_HEADER_COMP; @@ -2220,7 +1790,7 @@ return (ssize_t)(in - first); almost_ok: - if (in_final) { + if (in_final && inflater->state != NGHTTP2_HD_STATE_OPCODE) { DEBUGF(fprintf(stderr, "inflatehd: input ended prematurely\n")); rv = NGHTTP2_ERR_HEADER_COMP; @@ -2238,33 +1808,23 @@ int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) { hd_inflate_keep_free(inflater); - inflater->state = NGHTTP2_HD_STATE_INFLATE_START; return 0; } int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr) { - return nghttp2_hd_inflate_new2(inflater_ptr, NULL); -} - -int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr, - nghttp2_mem *mem) { int rv; nghttp2_hd_inflater *inflater; - if (mem == NULL) { - mem = nghttp2_mem_default(); - } - - inflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_inflater)); + inflater = malloc(sizeof(nghttp2_hd_inflater)); if (inflater == NULL) { return NGHTTP2_ERR_NOMEM; } - rv = nghttp2_hd_inflate_init(inflater, mem); + rv = nghttp2_hd_inflate_init(inflater); if (rv != 0) { - nghttp2_mem_free(mem, inflater); + free(inflater); return rv; } @@ -2275,23 +1835,20 @@ } void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater) { - nghttp2_mem *mem; - - mem = inflater->ctx.mem; nghttp2_hd_inflate_free(inflater); - nghttp2_mem_free(mem, inflater); + free(inflater); } int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t idx, - nghttp2_nv *nv, int indexing_mode) { + nghttp2_nv *nv, int inc_indexing) { - return emit_indname_block(bufs, idx, nv, indexing_mode); + return emit_indname_block(bufs, idx, nv, inc_indexing); } int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv, - int indexing_mode) { - return emit_newname_block(bufs, nv, indexing_mode); + int inc_indexing) { + return emit_newname_block(bufs, nv, inc_indexing); } int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) { @@ -2303,60 +1860,3 @@ uint8_t *last, size_t prefix) { return decode_length(res, shift_ptr, final, initial, shift, in, last, prefix); } - -static size_t hd_get_num_table_entries(nghttp2_hd_context *context) { - return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH; -} - -static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context, - size_t idx) { - if (idx == 0) { - return NULL; - } - - --idx; - - if (!INDEX_RANGE_VALID(context, idx)) { - return NULL; - } - - return nghttp2_hd_table_get2(context, idx); -} - -size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater) { - return hd_get_num_table_entries(&deflater->ctx); -} - -const nghttp2_nv * -nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx) { - return hd_get_table_entry(&deflater->ctx, idx); -} - -size_t -nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater) { - return deflater->ctx.hd_table_bufsize; -} - -size_t -nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater) { - return deflater->ctx.hd_table_bufsize_max; -} - -size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater) { - return hd_get_num_table_entries(&inflater->ctx); -} - -const nghttp2_nv * -nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx) { - return hd_get_table_entry(&inflater->ctx, idx); -} - -size_t -nghttp2_hd_inflate_get_dynamic_table_size(nghttp2_hd_inflater *inflater) { - return inflater->ctx.hd_table_bufsize; -} - -size_t -nghttp2_hd_inflate_get_max_dynamic_table_size(nghttp2_hd_inflater *inflater) { - return inflater->ctx.hd_table_bufsize_max; -} diff -Nru nghttp2-1.13.0/lib/nghttp2_hd.h nghttp2-0.6.7/lib/nghttp2_hd.h --- nghttp2-1.13.0/lib/nghttp2_hd.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_hd.h 2014-11-30 14:15:07.000000000 +0000 @@ -33,8 +33,6 @@ #include "nghttp2_hd_huffman.h" #include "nghttp2_buf.h" -#include "nghttp2_mem.h" -#include "nghttp2_rcbuf.h" #define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE #define NGHTTP2_HD_ENTRY_OVERHEAD 32 @@ -50,108 +48,34 @@ #define NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE (1 << 12) /* Exported for unit test */ -#define NGHTTP2_STATIC_TABLE_LENGTH 61 +extern const size_t NGHTTP2_STATIC_TABLE_LENGTH; -/* 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; - -struct nghttp2_hd_entry; -typedef struct nghttp2_hd_entry nghttp2_hd_entry; + NGHTTP2_HD_FLAG_NONE = 0, + /* Indicates name was dynamically allocated and must be freed */ + NGHTTP2_HD_FLAG_NAME_ALLOC = 1, + /* Indicates value was dynamically allocated and must be freed */ + NGHTTP2_HD_FLAG_VALUE_ALLOC = 1 << 1, + /* Indicates that the name was gifted to the entry and no copying + necessary. */ + NGHTTP2_HD_FLAG_NAME_GIFT = 1 << 2, + /* Indicates that the value was gifted to the entry and no copying + necessary. */ + NGHTTP2_HD_FLAG_VALUE_GIFT = 1 << 3 +} nghttp2_hd_flags; typedef struct { - /* The buffer containing header field name. NULL-termination is - guaranteed. */ - nghttp2_rcbuf *name; - /* The buffer containing header field value. NULL-termination is - guaranteed. */ - nghttp2_rcbuf *value; - /* nghttp2_token value for name. It could be -1 if we have no token - for that header field name. */ - int32_t token; - /* Bitwise OR of one or more of nghttp2_nv_flag. */ + nghttp2_nv nv; + uint32_t name_hash; + uint32_t value_hash; + /* Reference count */ + uint8_t ref; uint8_t flags; -} nghttp2_hd_nv; - -struct nghttp2_hd_entry { - /* The header field name/value pair */ - nghttp2_hd_nv nv; - /* This is solely for nghttp2_hd_{deflate,inflate}_get_table_entry - APIs to keep backward compatibility. */ - nghttp2_nv cnv; - /* The next entry which shares same bucket in hash table. */ - nghttp2_hd_entry *next; - /* The sequence number. We will increment it by one whenever we - store nghttp2_hd_entry to dynamic header table. */ - uint32_t seq; - /* The hash value for header name (nv.name). */ - uint32_t hash; -}; +} nghttp2_hd_entry; -/* The entry used for static header table. */ typedef struct { - nghttp2_rcbuf name; - nghttp2_rcbuf value; - nghttp2_nv cnv; - int32_t token; - uint32_t hash; + nghttp2_hd_entry ent; + size_t index; } nghttp2_hd_static_entry; typedef struct { @@ -169,8 +93,6 @@ } nghttp2_hd_opcode; typedef enum { - NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE, - NGHTTP2_HD_STATE_INFLATE_START, NGHTTP2_HD_STATE_OPCODE, NGHTTP2_HD_STATE_READ_TABLE_SIZE, NGHTTP2_HD_STATE_READ_INDEX, @@ -184,38 +106,23 @@ 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; - /* Memory allocator */ - nghttp2_mem *mem; /* Abstract buffer size of hd_table as described in the spec. This is the sum of length of name/value in hd_table + NGHTTP2_HD_ENTRY_OVERHEAD bytes overhead per each entry. */ size_t hd_table_bufsize; /* The effective header table size. */ size_t hd_table_bufsize_max; - /* Next sequence number for nghttp2_hd_entry */ - uint32_t next_seq; /* If inflate/deflate error occurred, this value is set to 1 and further invocation of inflate/deflate will fail with NGHTTP2_ERR_HEADER_COMP. */ uint8_t bad; } nghttp2_hd_context; -#define HD_MAP_SIZE 128 - -typedef struct { nghttp2_hd_entry *table[HD_MAP_SIZE]; } nghttp2_hd_map; - struct nghttp2_hd_deflater { nghttp2_hd_context ctx; - nghttp2_hd_map map; /* The upper limit of the header table size the deflater accepts. */ size_t deflate_hd_table_bufsize_max; /* Minimum header table size notified in the next context update */ @@ -227,23 +134,27 @@ struct nghttp2_hd_inflater { nghttp2_hd_context ctx; + /* header buffer */ + nghttp2_bufs nvbufs; /* Stores current state of huffman decoding */ nghttp2_hd_huff_decode_context huff_decode_ctx; - /* header buffer */ - nghttp2_buf namebuf, valuebuf; - nghttp2_rcbuf *namercbuf, *valuercbuf; - /* Pointer to the name/value pair which are used in the current - header emission. */ - nghttp2_rcbuf *nv_name_keep, *nv_value_keep; + /* Pointer to the nghttp2_hd_entry which is used current header + emission. This is required because in some cases the + ent_keep->ref == 0 and we have to keep track of it. */ + nghttp2_hd_entry *ent_keep; + /* Pointer to the name/value pair buffer which is used in the + current header emission. */ + uint8_t *nv_keep; /* The number of bytes to read */ size_t left; /* The index in indexed repr or indexed name */ size_t index; + /* The length of new name encoded in literal. For huffman encoded + string, this is the length after it is decoded. */ + size_t newnamelen; /* The maximum header table size the inflater supports. This is the same value transmitted in SETTINGS_HEADER_TABLE_SIZE */ size_t settings_hd_table_bufsize_max; - /* Minimum header table size set by nghttp2_hd_inflate_change_table_size */ - size_t min_hd_table_bufsize_max; /* The number of next shift to decode integer */ size_t shift; nghttp2_hd_opcode opcode; @@ -258,15 +169,24 @@ }; /* - * Initializes the |ent| members. The reference counts of nv->name - * and nv->value are increased by one for each. + * Initializes the |ent| members. If NGHTTP2_HD_FLAG_NAME_ALLOC bit + * 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. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. */ -void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv); +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); -/* - * This function decreases the reference counts of nv->name and - * nv->value. - */ void nghttp2_hd_entry_free(nghttp2_hd_entry *ent); /* @@ -283,7 +203,7 @@ * NGHTTP2_ERR_NOMEM * Out of memory. */ -int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem); +int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater); /* * Initializes |deflater| for deflating name/values pairs. @@ -299,8 +219,7 @@ * Out of memory. */ int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater, - size_t deflate_hd_table_bufsize_max, - nghttp2_mem *mem); + size_t deflate_hd_table_bufsize_max); /* * Deallocates any resources allocated for |deflater|. @@ -340,36 +259,27 @@ * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem); +int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater); /* * Deallocates any resources allocated for |inflater|. */ void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater); -/* - * Similar to nghttp2_hd_inflate_hd(), but this takes nghttp2_hd_nv - * instead of nghttp2_nv as output parameter |nv_out|. Other than - * that return values and semantics are the same as - * nghttp2_hd_inflate_hd(). - */ -ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater, - nghttp2_hd_nv *nv_out, int *inflate_flags, - const 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 indexing_mode); + nghttp2_nv *nv, int inc_indexing); /* For unittesting purpose */ int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv, - int indexing_mode); + int inc_indexing); /* For unittesting purpose */ int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size); /* For unittesting purpose */ -nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index); +nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context, + size_t index); /* For unittesting purpose */ ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *final, @@ -405,10 +315,12 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx); /* - * Decodes the given data |src| with length |srclen|. The |ctx| must + * Decodes the given data |src| with length |srclen|. The |ctx| must * be initialized by nghttp2_hd_huff_decode_context_init(). The result - * will be written to |buf|. This function assumes that |buf| has the - * enough room to store the decoded byte string. + * will be added to |dest|. This function may expand |dest| as + * needed. The caller is responsible to release the memory of |dest| + * by calling nghttp2_bufs_free() or export its content using + * nghttp2_bufs_remove(). * * The caller must set the |final| to nonzero if the given input is * the final block. @@ -420,11 +332,13 @@ * * NGHTTP2_ERR_NOMEM * Out of memory. + * NGHTTP2_ERR_BUFFER_ERROR + * Maximum buffer capacity size exceeded. * NGHTTP2_ERR_HEADER_COMP * Decoding process has failed. */ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, - nghttp2_buf *buf, const uint8_t *src, + nghttp2_bufs *bufs, const uint8_t *src, size_t srclen, int final); #endif /* NGHTTP2_HD_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_hd_huffman.c nghttp2-0.6.7/lib/nghttp2_hd_huffman.c --- nghttp2-1.13.0/lib/nghttp2_hd_huffman.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_hd_huffman.c 2014-11-30 14:15:07.000000000 +0000 @@ -30,6 +30,9 @@ #include "nghttp2_hd.h" +extern const nghttp2_huff_sym huff_sym_table[]; +extern const nghttp2_huff_decode huff_decode_table[][16]; + /* * Encodes huffman code |sym| into |*dest_ptr|, whose least |rembits| * bits are not filled yet. The |rembits| must be in range [1, 8], @@ -41,72 +44,56 @@ size_t rembits, const nghttp2_huff_sym *sym) { int rv; size_t nbits = sym->nbits; - uint32_t code = sym->code; - /* We assume that sym->nbits <= 32 */ - if (rembits > nbits) { - nghttp2_bufs_fast_orb_hold(bufs, (uint8_t)(code << (rembits - nbits))); - return (ssize_t)(rembits - nbits); - } + for (;;) { + if (rembits > nbits) { + if (*avail_ptr) { + nghttp2_bufs_fast_orb_hold(bufs, sym->code << (rembits - nbits)); + } else { + rv = nghttp2_bufs_orb_hold(bufs, sym->code << (rembits - nbits)); + if (rv != 0) { + return rv; + } - if (rembits == nbits) { - nghttp2_bufs_fast_orb(bufs, (uint8_t)code); - --*avail_ptr; - return 8; - } + *avail_ptr = nghttp2_bufs_cur_avail(bufs); + } - nghttp2_bufs_fast_orb(bufs, (uint8_t)(code >> (nbits - rembits))); - --*avail_ptr; + rembits -= nbits; - nbits -= rembits; - if (nbits & 0x7) { - /* align code to MSB byte boundary */ - code <<= 8 - (nbits & 0x7); - } + break; + } - /* we lose at most 3 bytes, but it is not critical in practice */ - if (*avail_ptr < (nbits + 7) / 8) { - rv = nghttp2_bufs_advance(bufs); - if (rv != 0) { - return rv; - } - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - /* we assume that we at least 3 buffer space available */ - assert(*avail_ptr >= 3); - } + if (*avail_ptr) { + nghttp2_bufs_fast_orb(bufs, sym->code >> (nbits - rembits)); + --*avail_ptr; + } else { + rv = nghttp2_bufs_orb(bufs, sym->code >> (nbits - rembits)); + if (rv != 0) { + return rv; + } - /* fast path, since most code is less than 8 */ - if (nbits < 8) { - nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code); - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - return (ssize_t)(8 - nbits); - } + *avail_ptr = nghttp2_bufs_cur_avail(bufs); + } - /* handle longer code path */ - if (nbits > 24) { - nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 24)); - nbits -= 8; - } + nbits -= rembits; + rembits = 8; - if (nbits > 16) { - nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 16)); - nbits -= 8; - } + if (nbits == 0) { + break; + } - if (nbits > 8) { - nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 8)); - nbits -= 8; - } + if (*avail_ptr) { + nghttp2_bufs_fast_addb_hold(bufs, 0); + } else { + rv = nghttp2_bufs_addb_hold(bufs, 0); + if (rv != 0) { + return rv; + } - if (nbits == 8) { - nghttp2_bufs_fast_addb(bufs, (uint8_t)code); - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - return 8; + *avail_ptr = nghttp2_bufs_cur_avail(bufs); + } } - - nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code); - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - return (ssize_t)(8 - nbits); + return (ssize_t)rembits; } size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) { @@ -142,20 +129,24 @@ avail = nghttp2_bufs_cur_avail(bufs); } } - rembits = huff_encode_sym(bufs, &avail, (size_t)rembits, sym); + rembits = huff_encode_sym(bufs, &avail, rembits, sym); if (rembits < 0) { return (int)rembits; } } /* 256 is special terminal symbol, pad with its prefix */ if (rembits < 8) { - /* if rembits < 8, we should have at least 1 buffer space - available */ const nghttp2_huff_sym *sym = &huff_sym_table[256]; - assert(avail); + /* Caution we no longer adjust avail here */ - nghttp2_bufs_fast_orb( - bufs, (uint8_t)(sym->code >> (sym->nbits - (size_t)rembits))); + if (avail) { + nghttp2_bufs_fast_orb(bufs, sym->code >> (sym->nbits - rembits)); + } else { + rv = nghttp2_bufs_orb(bufs, sym->code >> (sym->nbits - rembits)); + if (rv != 0) { + return rv; + } + } } return 0; @@ -167,33 +158,41 @@ } ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, - nghttp2_buf *buf, const uint8_t *src, + nghttp2_bufs *bufs, const uint8_t *src, size_t srclen, int final) { - size_t i; + size_t i, j; + int rv; + size_t avail; + + avail = nghttp2_bufs_cur_avail(bufs); /* We use the decoding algorithm described in http://graphics.ics.uci.edu/pub/Prefix.pdf */ for (i = 0; i < srclen; ++i) { - const nghttp2_huff_decode *t; - - 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) { - *buf->last++ = t->sym; - } - - 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) { - *buf->last++ = t->sym; + uint8_t in = src[i] >> 4; + for (j = 0; j < 2; ++j) { + 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; } - - ctx->state = t->state; - ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0; } if (final && !ctx->accept) { return NGHTTP2_ERR_HEADER_COMP; diff -Nru nghttp2-1.13.0/lib/nghttp2_hd_huffman.h nghttp2-0.6.7/lib/nghttp2_hd_huffman.h --- nghttp2-1.13.0/lib/nghttp2_hd_huffman.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_hd_huffman.h 2014-11-30 14:15:07.000000000 +0000 @@ -71,7 +71,4 @@ uint32_t code; } nghttp2_huff_sym; -extern const nghttp2_huff_sym huff_sym_table[]; -extern const nghttp2_huff_decode huff_decode_table[][16]; - #endif /* NGHTTP2_HD_HUFFMAN_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_helper.c nghttp2-0.6.7/lib/nghttp2_helper.c --- nghttp2-1.13.0/lib/nghttp2_helper.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_helper.c 2014-11-30 14:15:07.000000000 +0000 @@ -51,8 +51,23 @@ return ntohl(n); } +void *nghttp2_memdup(const void *src, size_t n) { + void *dest; + + if (n == 0) { + return NULL; + } + + dest = malloc(n); + if (dest == NULL) { + return NULL; + } + memcpy(dest, src, n); + return dest; +} + /* Generated by gendowncasetbl.py */ -static const uint8_t DOWNCASE_TBL[] = { +static const int DOWNCASE_TBL[] = { 0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */, 4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */, 8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */, @@ -157,97 +172,60 @@ int32_t *recv_reduction_ptr, int32_t *delta_ptr) { if (*delta_ptr > 0) { - int32_t recv_reduction_delta; - int32_t delta; int32_t new_recv_window_size = nghttp2_max(0, *recv_window_size_ptr) - *delta_ptr; - - if (new_recv_window_size >= 0) { + if (new_recv_window_size < 0) { + /* The delta size is strictly more than received bytes. Increase + local_window_size by that difference. */ + int32_t recv_reduction_diff; + if (*local_window_size_ptr > + NGHTTP2_MAX_WINDOW_SIZE + new_recv_window_size) { + return NGHTTP2_ERR_FLOW_CONTROL; + } + *local_window_size_ptr -= new_recv_window_size; + /* If there is recv_reduction due to earlier window_size + reduction, we have to adjust it too. */ + recv_reduction_diff = + nghttp2_min(*recv_reduction_ptr, -new_recv_window_size); + *recv_reduction_ptr -= recv_reduction_diff; + if (*recv_window_size_ptr < 0) { + *recv_window_size_ptr += recv_reduction_diff; + } else { + /* If *recv_window_size_ptr > 0, then those bytes are going to + be backed to the remote peer (by WINDOW_UPDATE with the + adjusted *delta_ptr), so it is effectively 0 now. We set + to *recv_reduction_diff, because caller does not take into + account it in *delta_ptr. */ + *recv_window_size_ptr = recv_reduction_diff; + } + /* recv_reduction_diff must be paied from *delta_ptr, since it + was added in window size reduction (see below). */ + *delta_ptr -= recv_reduction_diff; + } else { *recv_window_size_ptr = new_recv_window_size; - return 0; } - - delta = -new_recv_window_size; - - /* The delta size is strictly more than received bytes. Increase - local_window_size by that difference |delta|. */ - if (*local_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta) { + return 0; + } else { + if (*local_window_size_ptr + *delta_ptr < 0 || + *recv_window_size_ptr < INT32_MIN - *delta_ptr || + *recv_reduction_ptr > INT32_MAX + *delta_ptr) { return NGHTTP2_ERR_FLOW_CONTROL; } - *local_window_size_ptr += delta; - /* If there is recv_reduction due to earlier window_size - reduction, we have to adjust it too. */ - recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta); - *recv_reduction_ptr -= recv_reduction_delta; - if (*recv_window_size_ptr < 0) { - *recv_window_size_ptr += recv_reduction_delta; - } else { - /* If *recv_window_size_ptr > 0, then those bytes are going to - be returned to the remote peer (by WINDOW_UPDATE with the - adjusted *delta_ptr), so it is effectively 0 now. We set to - *recv_reduction_delta, because caller does not take into - account it in *delta_ptr. */ - *recv_window_size_ptr = recv_reduction_delta; - } - /* recv_reduction_delta must be paied from *delta_ptr, since it - was added in window size reduction (see below). */ - *delta_ptr -= recv_reduction_delta; - - return 0; + /* Decreasing local window size. Note that we achieve this without + noticing to the remote peer. To do this, we cut + recv_window_size by -delta. This means that we don't send + WINDOW_UPDATE for -delta bytes. */ + *local_window_size_ptr += *delta_ptr; + *recv_window_size_ptr += *delta_ptr; + *recv_reduction_ptr -= *delta_ptr; + *delta_ptr = 0; } - - if (*local_window_size_ptr + *delta_ptr < 0 || - *recv_window_size_ptr < INT32_MIN - *delta_ptr || - *recv_reduction_ptr > INT32_MAX + *delta_ptr) { - return NGHTTP2_ERR_FLOW_CONTROL; - } - /* Decreasing local window size. Note that we achieve this without - noticing to the remote peer. To do this, we cut - recv_window_size by -delta. This means that we don't send - WINDOW_UPDATE for -delta bytes. */ - *local_window_size_ptr += *delta_ptr; - *recv_window_size_ptr += *delta_ptr; - *recv_reduction_ptr -= *delta_ptr; - *delta_ptr = 0; - - return 0; -} - -int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr, - int32_t *recv_window_size_ptr, - int32_t *recv_reduction_ptr, - int32_t *delta_ptr) { - int32_t recv_reduction_delta; - int32_t delta; - - delta = *delta_ptr; - - assert(delta >= 0); - - /* The delta size is strictly more than received bytes. Increase - local_window_size by that difference |delta|. */ - if (*local_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta) { - return NGHTTP2_ERR_FLOW_CONTROL; - } - - *local_window_size_ptr += delta; - /* If there is recv_reduction due to earlier window_size - reduction, we have to adjust it too. */ - recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta); - *recv_reduction_ptr -= recv_reduction_delta; - - *recv_window_size_ptr += recv_reduction_delta; - - /* recv_reduction_delta must be paied from *delta_ptr, since it was - added in window size reduction (see below). */ - *delta_ptr -= recv_reduction_delta; - return 0; } int nghttp2_should_send_window_update(int32_t local_window_size, int32_t recv_window_size) { - return recv_window_size > 0 && recv_window_size >= local_window_size / 2; + return recv_window_size >= local_window_size / 2; } const char *nghttp2_strerror(int error_code) { @@ -309,33 +287,20 @@ case NGHTTP2_ERR_PUSH_DISABLED: return "Server push is disabled by peer"; case NGHTTP2_ERR_DATA_EXIST: - return "DATA or HEADERS frame has already been submitted for the stream"; - case NGHTTP2_ERR_SESSION_CLOSING: - 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_CANCEL: - return "Cancel"; + return "DATA frame already exists"; case NGHTTP2_ERR_NOMEM: return "Out of memory"; case NGHTTP2_ERR_CALLBACK_FAILURE: return "The user callback function failed"; - case NGHTTP2_ERR_BAD_CLIENT_MAGIC: - return "Received bad client magic byte string"; - case NGHTTP2_ERR_FLOODED: - return "Flooding was detected in this HTTP/2 session, and it must be " - "closed"; + case NGHTTP2_ERR_BAD_PREFACE: + return "Received bad connection preface"; default: return "Unknown error code"; } } +void nghttp2_free(void *ptr) { free(ptr); } + /* Generated by gennmchartbl.py */ static int VALID_HD_NAME_CHARS[] = { 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, @@ -483,38 +448,3 @@ return dest + len; } - -const char *nghttp2_http2_strerror(uint32_t error_code) { - switch (error_code) { - case NGHTTP2_NO_ERROR: - return "NO_ERROR"; - case NGHTTP2_PROTOCOL_ERROR: - return "PROTOCOL_ERROR"; - case NGHTTP2_INTERNAL_ERROR: - return "INTERNAL_ERROR"; - case NGHTTP2_FLOW_CONTROL_ERROR: - return "FLOW_CONTROL_ERROR"; - case NGHTTP2_SETTINGS_TIMEOUT: - return "SETTINGS_TIMEOUT"; - case NGHTTP2_STREAM_CLOSED: - return "STREAM_CLOSED"; - case NGHTTP2_FRAME_SIZE_ERROR: - return "FRAME_SIZE_ERROR"; - case NGHTTP2_REFUSED_STREAM: - return "REFUSED_STREAM"; - case NGHTTP2_CANCEL: - return "CANCEL"; - case NGHTTP2_COMPRESSION_ERROR: - return "COMPRESSION_ERROR"; - case NGHTTP2_CONNECT_ERROR: - return "CONNECT_ERROR"; - case NGHTTP2_ENHANCE_YOUR_CALM: - return "ENHANCE_YOUR_CALM"; - case NGHTTP2_INADEQUATE_SECURITY: - return "INADEQUATE_SECURITY"; - case NGHTTP2_HTTP_1_1_REQUIRED: - return "HTTP_1_1_REQUIRED"; - default: - return "unknown"; - } -} diff -Nru nghttp2-1.13.0/lib/nghttp2_helper.h nghttp2-0.6.7/lib/nghttp2_helper.h --- nghttp2-1.13.0/lib/nghttp2_helper.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_helper.h 2014-11-30 14:15:07.000000000 +0000 @@ -29,20 +29,11 @@ #include #endif /* HAVE_CONFIG_H */ -#include -#include - #include -#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) - -#define nghttp2_struct_of(ptr, type, member) \ - ((type *)(void *)((char *)(ptr)-offsetof(type, member))) - /* * Copies 2 byte unsigned integer |n| in host byte order to |buf| in * network byte order. @@ -67,6 +58,18 @@ */ uint32_t nghttp2_get_uint32(const uint8_t *data); +/* + * Allocates |n| bytes of memory and copy the memory region pointed by + * |src| with the length |n| bytes into it. Returns the allocated memory. + * + * This function returns pointer to allocated memory, or one of the + * following negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +void *nghttp2_memdup(const void *src, size_t n); + void nghttp2_downcase(uint8_t *s, size_t len); /* @@ -90,22 +93,6 @@ int32_t *delta_ptr); /* - * This function works like nghttp2_adjust_local_window_size(). The - * difference is that this function assumes *delta_ptr >= 0, and - * *recv_window_size_ptr is not decreased by *delta_ptr. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGHTTP2_ERR_FLOW_CONTROL - * local_window_size overflow or gets negative. - */ -int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr, - int32_t *recv_window_size_ptr, - int32_t *recv_reduction_ptr, - int32_t *delta_ptr); - -/* * Returns non-zero if the function decided that WINDOW_UPDATE should * be sent. */ @@ -113,6 +100,14 @@ int32_t recv_window_size); /* + * Deallocates memory space pointed by |ptr|. This function exists for + * the application to free the memory space allocated by the library + * functions. Currently this function is hidden from the public API, + * but may be exposed as public API. + */ +void nghttp2_free(void *ptr); + +/* * Copies the buffer |src| of length |len| to the destination pointed * by the |dest|, assuming that the |dest| is at lest |len| bytes long * . Returns dest + len. diff -Nru nghttp2-1.13.0/lib/nghttp2_http.c nghttp2-0.6.7/lib/nghttp2_http.c --- nghttp2-1.13.0/lib/nghttp2_http.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_http.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,563 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "nghttp2_http.h" - -#include -#include -#include - -#include "nghttp2_hd.h" -#include "nghttp2_helper.h" - -static uint8_t downcase(uint8_t c) { - return 'A' <= c && c <= 'Z' ? (uint8_t)(c - 'A' + 'a') : c; -} - -static int memieq(const void *a, const void *b, size_t n) { - size_t i; - const uint8_t *aa = a, *bb = b; - - for (i = 0; i < n; ++i) { - if (downcase(aa[i]) != downcase(bb[i])) { - return 0; - } - } - 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; - size_t i; - if (len == 0) { - return -1; - } - for (i = 0; i < len; ++i) { - if ('0' <= s[i] && s[i] <= '9') { - if (n > INT64_MAX / 10) { - return -1; - } - n *= 10; - if (n > INT64_MAX - (s[i] - '0')) { - return -1; - } - n += s[i] - '0'; - continue; - } - return -1; - } - return n; -} - -static int lws(const uint8_t *s, size_t n) { - size_t i; - for (i = 0; i < n; ++i) { - if (s[i] != ' ' && s[i] != '\t') { - return 0; - } - } - return 1; -} - -static int check_pseudo_header(nghttp2_stream *stream, const nghttp2_hd_nv *nv, - int flag) { - if (stream->http_flags & flag) { - return 0; - } - if (lws(nv->value->base, nv->value->len)) { - return 0; - } - stream->http_flags = (uint16_t)(stream->http_flags | flag); - return 1; -} - -static int expect_response_body(nghttp2_stream *stream) { - return (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_HEAD) == 0 && - stream->status_code / 100 != 1 && stream->status_code != 304 && - stream->status_code != 204; -} - -/* For "http" or "https" URIs, OPTIONS request may have "*" in :path - header field to represent system-wide OPTIONS request. Otherwise, - :path header field value must start with "/". This function must - be called after ":method" header field was received. This function - returns nonzero if path is valid.*/ -static int check_path(nghttp2_stream *stream) { - return (stream->http_flags & NGHTTP2_HTTP_FLAG_SCHEME_HTTP) == 0 || - ((stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_REGULAR) || - ((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_OPTIONS) && - (stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_ASTERISK))); -} - -static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv, - int trailer) { - if (nv->name->base[0] == ':') { - if (trailer || - (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - } - - switch (nv->token) { - case NGHTTP2_TOKEN__AUTHORITY: - if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__AUTHORITY)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - break; - case NGHTTP2_TOKEN__METHOD: - if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__METHOD)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - switch (nv->value->len) { - case 4: - if (lstreq("HEAD", nv->value->base, nv->value->len)) { - stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD; - } - break; - case 7: - switch (nv->value->base[6]) { - case 'T': - if (lstreq("CONNECT", nv->value->base, nv->value->len)) { - if (stream->stream_id % 2 == 0) { - /* we won't allow CONNECT for push */ - return NGHTTP2_ERR_HTTP_HEADER; - } - stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT; - if (stream->http_flags & - (NGHTTP2_HTTP_FLAG__PATH | NGHTTP2_HTTP_FLAG__SCHEME)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - } - break; - case 'S': - if (lstreq("OPTIONS", nv->value->base, nv->value->len)) { - stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_OPTIONS; - } - break; - } - break; - } - break; - case NGHTTP2_TOKEN__PATH: - if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) { - return NGHTTP2_ERR_HTTP_HEADER; - } - if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - if (nv->value->base[0] == '/') { - stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_REGULAR; - } else if (nv->value->len == 1 && nv->value->base[0] == '*') { - stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_ASTERISK; - } - break; - case NGHTTP2_TOKEN__SCHEME: - if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) { - return NGHTTP2_ERR_HTTP_HEADER; - } - if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - if ((nv->value->len == 4 && memieq("http", nv->value->base, 4)) || - (nv->value->len == 5 && memieq("https", nv->value->base, 5))) { - stream->http_flags |= NGHTTP2_HTTP_FLAG_SCHEME_HTTP; - } - break; - case NGHTTP2_TOKEN_HOST: - if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - break; - case NGHTTP2_TOKEN_CONTENT_LENGTH: { - if (stream->content_length != -1) { - return NGHTTP2_ERR_HTTP_HEADER; - } - stream->content_length = parse_uint(nv->value->base, nv->value->len); - if (stream->content_length == -1) { - return NGHTTP2_ERR_HTTP_HEADER; - } - break; - } - /* disallowed header fields */ - case NGHTTP2_TOKEN_CONNECTION: - case NGHTTP2_TOKEN_KEEP_ALIVE: - case NGHTTP2_TOKEN_PROXY_CONNECTION: - case NGHTTP2_TOKEN_TRANSFER_ENCODING: - case NGHTTP2_TOKEN_UPGRADE: - return NGHTTP2_ERR_HTTP_HEADER; - case NGHTTP2_TOKEN_TE: - if (!lstrieq("trailers", nv->value->base, nv->value->len)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - break; - default: - if (nv->name->base[0] == ':') { - return NGHTTP2_ERR_HTTP_HEADER; - } - } - - if (nv->name->base[0] != ':') { - stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED; - } - - return 0; -} - -static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv, - int trailer) { - if (nv->name->base[0] == ':') { - if (trailer || - (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - } - - switch (nv->token) { - case NGHTTP2_TOKEN__STATUS: { - if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__STATUS)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - if (nv->value->len != 3) { - return NGHTTP2_ERR_HTTP_HEADER; - } - stream->status_code = (int16_t)parse_uint(nv->value->base, nv->value->len); - if (stream->status_code == -1) { - return NGHTTP2_ERR_HTTP_HEADER; - } - break; - } - case NGHTTP2_TOKEN_CONTENT_LENGTH: { - if (stream->content_length != -1) { - return NGHTTP2_ERR_HTTP_HEADER; - } - stream->content_length = parse_uint(nv->value->base, nv->value->len); - if (stream->content_length == -1) { - return NGHTTP2_ERR_HTTP_HEADER; - } - break; - } - /* disallowed header fields */ - case NGHTTP2_TOKEN_CONNECTION: - case NGHTTP2_TOKEN_KEEP_ALIVE: - case NGHTTP2_TOKEN_PROXY_CONNECTION: - case NGHTTP2_TOKEN_TRANSFER_ENCODING: - case NGHTTP2_TOKEN_UPGRADE: - return NGHTTP2_ERR_HTTP_HEADER; - case NGHTTP2_TOKEN_TE: - if (!lstrieq("trailers", nv->value->base, nv->value->len)) { - return NGHTTP2_ERR_HTTP_HEADER; - } - break; - default: - if (nv->name->base[0] == ':') { - return NGHTTP2_ERR_HTTP_HEADER; - } - } - - if (nv->name->base[0] != ':') { - stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED; - } - - return 0; -} - -/* Generated by genauthroitychartbl.py */ -static char VALID_AUTHORITY_CHARS[] = { - 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, - 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */, - 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */, - 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, - 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */, - 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */, - 0 /* RS */, 0 /* US */, 0 /* SPC */, 1 /* ! */, 0 /* " */, - 0 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */, - 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* , */, - 1 /* - */, 1 /* . */, 0 /* / */, 1 /* 0 */, 1 /* 1 */, - 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, - 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */, - 0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */, 1 /* @ */, - 1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */, - 1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */, - 1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */, - 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */, - 1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */, - 1 /* Z */, 1 /* [ */, 0 /* \ */, 1 /* ] */, 0 /* ^ */, - 1 /* _ */, 0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, - 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */, - 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */, - 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */, - 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, - 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 0 /* | */, - 0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */, - 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, - 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, - 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */, - 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */, - 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, - 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, - 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */, - 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */, - 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, - 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, - 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */, - 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */, - 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, - 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, - 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */, - 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */, - 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, - 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */, - 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */, - 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */, - 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, - 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */, - 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */, - 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */, - 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, - 0 /* 0xff */ -}; - -static int check_authority(const uint8_t *value, size_t len) { - const uint8_t *last; - for (last = value + len; value != last; ++value) { - if (!VALID_AUTHORITY_CHARS[*value]) { - return 0; - } - } - return 1; -} - -static int check_scheme(const uint8_t *value, size_t len) { - const uint8_t *last; - if (len == 0) { - return 0; - } - - if (!(('A' <= *value && *value <= 'Z') || ('a' <= *value && *value <= 'z'))) { - return 0; - } - - last = value + len; - ++value; - - for (; value != last; ++value) { - if (!(('A' <= *value && *value <= 'Z') || - ('a' <= *value && *value <= 'z') || - ('0' <= *value && *value <= '9') || *value == '+' || *value == '-' || - *value == '.')) { - return 0; - } - } - return 1; -} - -int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream, - nghttp2_frame *frame, nghttp2_hd_nv *nv, - int trailer) { - int rv; - - /* 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 - headers floating around and if we kill the stream because of - this, we may disrupt many web sites and/or libraries. So we - become conservative here, and just ignore those illegal regular - headers. */ - if (!nghttp2_check_header_name(nv->name->base, nv->name->len)) { - size_t i; - if (nv->name->len > 0 && nv->name->base[0] == ':') { - return NGHTTP2_ERR_HTTP_HEADER; - } - /* header field name must be lower-cased without exception */ - for (i = 0; i < nv->name->len; ++i) { - uint8_t c = nv->name->base[i]; - if ('A' <= c && c <= 'Z') { - return NGHTTP2_ERR_HTTP_HEADER; - } - } - /* When ignoring regular headers, we set this flag so that we - still enforce header field ordering rule for pseudo header - fields. */ - stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED; - return NGHTTP2_ERR_IGN_HTTP_HEADER; - } - - if (nv->token == NGHTTP2_TOKEN__AUTHORITY || - nv->token == NGHTTP2_TOKEN_HOST) { - rv = check_authority(nv->value->base, nv->value->len); - } else if (nv->token == NGHTTP2_TOKEN__SCHEME) { - rv = check_scheme(nv->value->base, nv->value->len); - } else { - rv = nghttp2_check_header_value(nv->value->base, nv->value->len); - } - - if (rv == 0) { - assert(nv->name->len > 0); - if (nv->name->base[0] == ':') { - return NGHTTP2_ERR_HTTP_HEADER; - } - /* When ignoring regular headers, we set this flag so that we - still enforce header field ordering rule for pseudo header - fields. */ - stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED; - return NGHTTP2_ERR_IGN_HTTP_HEADER; - } - - if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) { - return http_request_on_header(stream, nv, trailer); - } - - return http_response_on_header(stream, nv, trailer); -} - -int nghttp2_http_on_request_headers(nghttp2_stream *stream, - nghttp2_frame *frame) { - if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) { - if ((stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0) { - return -1; - } - stream->content_length = -1; - } else { - if ((stream->http_flags & NGHTTP2_HTTP_FLAG_REQ_HEADERS) != - NGHTTP2_HTTP_FLAG_REQ_HEADERS || - (stream->http_flags & - (NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) { - return -1; - } - if (!check_path(stream)) { - return -1; - } - } - - if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { - /* we are going to reuse data fields for upcoming response. Clear - them now, except for method flags. */ - stream->http_flags &= NGHTTP2_HTTP_FLAG_METH_ALL; - stream->content_length = -1; - } - - return 0; -} - -int nghttp2_http_on_response_headers(nghttp2_stream *stream) { - if ((stream->http_flags & NGHTTP2_HTTP_FLAG__STATUS) == 0) { - return -1; - } - - if (stream->status_code / 100 == 1) { - /* non-final response */ - stream->http_flags = - (uint16_t)((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_ALL) | - NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE); - stream->content_length = -1; - stream->status_code = -1; - return 0; - } - - stream->http_flags = - (uint16_t)(stream->http_flags & ~NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE); - - if (!expect_response_body(stream)) { - stream->content_length = 0; - } else if (stream->http_flags & (NGHTTP2_HTTP_FLAG_METH_CONNECT | - NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND)) { - stream->content_length = -1; - } - - return 0; -} - -int nghttp2_http_on_trailer_headers(nghttp2_stream *stream _U_, - nghttp2_frame *frame) { - if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { - return -1; - } - - return 0; -} - -int nghttp2_http_on_remote_end_stream(nghttp2_stream *stream) { - if (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) { - return -1; - } - - if (stream->content_length != -1 && - stream->content_length != stream->recv_content_length) { - return -1; - } - - return 0; -} - -int nghttp2_http_on_data_chunk(nghttp2_stream *stream, size_t n) { - stream->recv_content_length += (int64_t)n; - - if ((stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) || - (stream->content_length != -1 && - stream->recv_content_length > stream->content_length)) { - return -1; - } - - return 0; -} - -void nghttp2_http_record_request_method(nghttp2_stream *stream, - nghttp2_frame *frame) { - const nghttp2_nv *nva; - size_t nvlen; - size_t i; - - switch (frame->hd.type) { - case NGHTTP2_HEADERS: - nva = frame->headers.nva; - nvlen = frame->headers.nvlen; - break; - case NGHTTP2_PUSH_PROMISE: - nva = frame->push_promise.nva; - nvlen = frame->push_promise.nvlen; - break; - default: - return; - } - - /* TODO we should do this strictly. */ - for (i = 0; i < nvlen; ++i) { - const nghttp2_nv *nv = &nva[i]; - if (!(nv->namelen == 7 && nv->name[6] == 'd' && - memcmp(":metho", nv->name, nv->namelen - 1) == 0)) { - continue; - } - if (lstreq("CONNECT", nv->value, nv->valuelen)) { - stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT; - return; - } - if (lstreq("HEAD", nv->value, nv->valuelen)) { - stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD; - return; - } - return; - } -} diff -Nru nghttp2-1.13.0/lib/nghttp2_http.h nghttp2-0.6.7/lib/nghttp2_http.h --- nghttp2-1.13.0/lib/nghttp2_http.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_http.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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_HTTP_H -#define NGHTTP2_HTTP_H - -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - -#include -#include "nghttp2_session.h" -#include "nghttp2_stream.h" - -/* - * 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. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGHTTP2_ERR_HTTP_HEADER - * Invalid HTTP header field was received. - * NGHTTP2_ERR_IGN_HTTP_HEADER - * Invalid HTTP header field was received but it can be treated as - * if it was not received because of compatibility reasons. - */ -int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream, - nghttp2_frame *frame, nghttp2_hd_nv *nv, - int trailer); - -/* - * This function is called when request header is received. This - * function performs validation and returns 0 if it succeeds, or -1. - */ -int nghttp2_http_on_request_headers(nghttp2_stream *stream, - nghttp2_frame *frame); - -/* - * This function is called when response header is received. This - * function performs validation and returns 0 if it succeeds, or -1. - */ -int nghttp2_http_on_response_headers(nghttp2_stream *stream); - -/* - * This function is called trailer header (for both request and - * response) is received. This function performs validation and - * returns 0 if it succeeds, or -1. - */ -int nghttp2_http_on_trailer_headers(nghttp2_stream *stream, - nghttp2_frame *frame); - -/* - * This function is called when END_STREAM flag is seen in incoming - * frame. This function performs validation and returns 0 if it - * succeeds, or -1. - */ -int nghttp2_http_on_remote_end_stream(nghttp2_stream *stream); - -/* - * This function is called when chunk of data is received. This - * function performs validation and returns 0 if it succeeds, or -1. - */ -int nghttp2_http_on_data_chunk(nghttp2_stream *stream, size_t n); - -/* - * This function inspects header field in |frame| and records its - * method in stream->http_flags. If frame->hd.type is neither - * NGHTTP2_HEADERS nor NGHTTP2_PUSH_PROMISE, this function does - * nothing. - */ -void nghttp2_http_record_request_method(nghttp2_stream *stream, - nghttp2_frame *frame); - -#endif /* NGHTTP2_HTTP_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_int.h nghttp2-0.6.7/lib/nghttp2_int.h --- nghttp2-1.13.0/lib/nghttp2_int.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_int.h 2014-11-30 14:15:07.000000000 +0000 @@ -39,20 +39,14 @@ } while (0) #endif -/* "less" function, return nonzero if |lhs| is less than |rhs|. */ -typedef int (*nghttp2_less)(const void *lhs, const void *rhs); +typedef int (*nghttp2_compar)(const void *lhs, const void *rhs); /* Internal error code. They must be in the range [-499, -100], inclusive. */ typedef enum { NGHTTP2_ERR_CREDENTIAL_PENDING = -101, NGHTTP2_ERR_IGN_HEADER_BLOCK = -103, - NGHTTP2_ERR_IGN_PAYLOAD = -104, - /* - * 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_PAYLOAD = -104 } nghttp2_internal_error; #endif /* NGHTTP2_INT_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_map.c nghttp2-0.6.7/lib/nghttp2_map.c --- nghttp2-1.13.0/lib/nghttp2_map.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_map.c 2014-11-30 14:15:07.000000000 +0000 @@ -28,11 +28,9 @@ #define INITIAL_TABLE_LENGTH 256 -int nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem) { - map->mem = mem; +int nghttp2_map_init(nghttp2_map *map) { map->tablelen = INITIAL_TABLE_LENGTH; - map->table = - nghttp2_mem_calloc(mem, map->tablelen, sizeof(nghttp2_map_entry *)); + map->table = calloc(map->tablelen, sizeof(nghttp2_map_entry *)); if (map->table == NULL) { return NGHTTP2_ERR_NOMEM; } @@ -42,14 +40,12 @@ return 0; } -void nghttp2_map_free(nghttp2_map *map) { - nghttp2_mem_free(map->mem, map->table); -} +void nghttp2_map_free(nghttp2_map *map) { free(map->table); } void nghttp2_map_each_free(nghttp2_map *map, int (*func)(nghttp2_map_entry *entry, void *ptr), void *ptr) { - uint32_t i; + size_t i; for (i = 0; i < map->tablelen; ++i) { nghttp2_map_entry *entry; for (entry = map->table[i]; entry;) { @@ -65,7 +61,7 @@ int (*func)(nghttp2_map_entry *entry, void *ptr), void *ptr) { int rv; - uint32_t i; + size_t i; for (i = 0; i < map->tablelen; ++i) { nghttp2_map_entry *entry; for (entry = map->table[i]; entry; entry = entry->next) { @@ -85,16 +81,15 @@ /* Same hash function in android HashMap source code. */ /* The |mod| must be power of 2 */ -static uint32_t hash(int32_t key, uint32_t mod) { - uint32_t h = (uint32_t)key; +static int32_t hash(int32_t h, size_t mod) { h ^= (h >> 20) ^ (h >> 12); h ^= (h >> 7) ^ (h >> 4); return h & (mod - 1); } -static int insert(nghttp2_map_entry **table, uint32_t tablelen, +static int insert(nghttp2_map_entry **table, size_t tablelen, nghttp2_map_entry *entry) { - uint32_t h = hash(entry->key, tablelen); + int32_t h = hash(entry->key, tablelen); if (table[h] == NULL) { table[h] = entry; } else { @@ -112,12 +107,10 @@ } /* new_tablelen must be power of 2 */ -static int resize(nghttp2_map *map, uint32_t new_tablelen) { - uint32_t i; +static int resize(nghttp2_map *map, size_t new_tablelen) { + size_t i; nghttp2_map_entry **new_table; - - new_table = - nghttp2_mem_calloc(map->mem, new_tablelen, sizeof(nghttp2_map_entry *)); + new_table = calloc(new_tablelen, sizeof(nghttp2_map_entry *)); if (new_table == NULL) { return NGHTTP2_ERR_NOMEM; } @@ -132,7 +125,7 @@ entry = next; } } - nghttp2_mem_free(map->mem, map->table); + free(map->table); map->tablelen = new_tablelen; map->table = new_table; @@ -157,7 +150,7 @@ } nghttp2_map_entry *nghttp2_map_find(nghttp2_map *map, key_type key) { - uint32_t h; + int32_t h; nghttp2_map_entry *entry; h = hash(key, map->tablelen); for (entry = map->table[h]; entry; entry = entry->next) { @@ -169,19 +162,21 @@ } int nghttp2_map_remove(nghttp2_map *map, key_type key) { - uint32_t h; - nghttp2_map_entry **dst; - + int32_t h; + nghttp2_map_entry *entry, *prev; h = hash(key, map->tablelen); - - for (dst = &map->table[h]; *dst; dst = &(*dst)->next) { - if ((*dst)->key != key) { - continue; + prev = NULL; + for (entry = map->table[h]; entry; entry = entry->next) { + if (entry->key == key) { + if (prev == NULL) { + map->table[h] = entry->next; + } else { + prev->next = entry->next; + } + --map->size; + return 0; } - - *dst = (*dst)->next; - --map->size; - return 0; + prev = entry; } return NGHTTP2_ERR_INVALID_ARGUMENT; } diff -Nru nghttp2-1.13.0/lib/nghttp2_map.h nghttp2-0.6.7/lib/nghttp2_map.h --- nghttp2-1.13.0/lib/nghttp2_map.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_map.h 2014-11-30 14:15:07.000000000 +0000 @@ -31,26 +31,20 @@ #include #include "nghttp2_int.h" -#include "nghttp2_mem.h" /* Implementation of unordered map */ -typedef int32_t key_type; +typedef uint32_t key_type; typedef struct nghttp2_map_entry { struct nghttp2_map_entry *next; key_type key; -#if SIZEOF_INT_P == 4 - /* we requires 8 bytes aligment */ - int64_t pad; -#endif } nghttp2_map_entry; typedef struct { nghttp2_map_entry **table; - nghttp2_mem *mem; + size_t tablelen; size_t size; - uint32_t tablelen; } nghttp2_map; /* @@ -62,7 +56,7 @@ * NGHTTP2_ERR_NOMEM * Out of memory */ -int nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem); +int nghttp2_map_init(nghttp2_map *map); /* * Deallocates any resources allocated for |map|. The stored entries diff -Nru nghttp2-1.13.0/lib/nghttp2_mem.c nghttp2-0.6.7/lib/nghttp2_mem.c --- nghttp2-1.13.0/lib/nghttp2_mem.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_mem.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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. - */ -#include "nghttp2_mem.h" - -static void *default_malloc(size_t size, void *mem_user_data _U_) { - return malloc(size); -} - -static void default_free(void *ptr, void *mem_user_data _U_) { free(ptr); } - -static void *default_calloc(size_t nmemb, size_t size, - void *mem_user_data _U_) { - return calloc(nmemb, size); -} - -static void *default_realloc(void *ptr, size_t size, void *mem_user_data _U_) { - return realloc(ptr, size); -} - -static nghttp2_mem mem_default = {NULL, default_malloc, default_free, - default_calloc, default_realloc}; - -nghttp2_mem *nghttp2_mem_default(void) { return &mem_default; } - -void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size) { - return mem->malloc(size, mem->mem_user_data); -} - -void nghttp2_mem_free(nghttp2_mem *mem, void *ptr) { - mem->free(ptr, mem->mem_user_data); -} - -void nghttp2_mem_free2(nghttp2_free free_func, void *ptr, void *mem_user_data) { - free_func(ptr, mem_user_data); -} - -void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size) { - return mem->calloc(nmemb, size, mem->mem_user_data); -} - -void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size) { - return mem->realloc(ptr, size, mem->mem_user_data); -} diff -Nru nghttp2-1.13.0/lib/nghttp2_mem.h nghttp2-0.6.7/lib/nghttp2_mem.h --- nghttp2-1.13.0/lib/nghttp2_mem.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_mem.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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_MEM_H -#define NGHTTP2_MEM_H - -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - -#include - -/* The default, system standard memory allocator */ -nghttp2_mem *nghttp2_mem_default(void); - -/* Convenient wrapper functions to call allocator function in - |mem|. */ -void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size); -void nghttp2_mem_free(nghttp2_mem *mem, void *ptr); -void nghttp2_mem_free2(nghttp2_free free_func, void *ptr, void *mem_user_data); -void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size); -void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size); - -#endif /* NGHTTP2_MEM_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_net.h nghttp2-0.6.7/lib/nghttp2_net.h --- nghttp2-1.13.0/lib/nghttp2_net.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_net.h 2014-11-30 14:15:07.000000000 +0000 @@ -37,55 +37,8 @@ #include #endif /* HAVE_NETINET_IN_H */ -#include - -#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 */ +#ifdef HAVE_WINSOCK2_H +#include +#endif /* HAVE_WINSOCK2_H */ #endif /* NGHTTP2_NET_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_npn.c nghttp2-0.6.7/lib/nghttp2_npn.c --- nghttp2-1.13.0/lib/nghttp2_npn.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_npn.c 2014-11-30 14:15:07.000000000 +0000 @@ -26,32 +26,29 @@ #include -static int select_next_protocol(unsigned char **out, unsigned char *outlen, - const unsigned char *in, unsigned int inlen, - const char *key, unsigned int keylen) { - unsigned int i; - for (i = 0; i + keylen <= inlen; i += (unsigned int)(in [i] + 1)) { - if (memcmp(&in[i], key, keylen) == 0) { +int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen) { + int http_selected = 0; + unsigned int i = 0; + for (; i < inlen; i += in [i] + 1) { + if (in[i] == NGHTTP2_PROTO_VERSION_ID_LEN && i + 1 + in[i] <= inlen && + memcmp(&in[i + 1], NGHTTP2_PROTO_VERSION_ID, in[i]) == 0) { *out = (unsigned char *)&in[i + 1]; *outlen = in[i]; - return 0; + return 1; + } + if (in[i] == 8 && i + 1 + in[i] <= inlen && + memcmp(&in[i + 1], "http/1.1", in[i]) == 0) { + http_selected = 1; + *out = (unsigned char *)&in[i + 1]; + *outlen = in[i]; + /* Go through to the next iteration, because "HTTP/2" may be + there */ } } - return -1; -} - -#define NGHTTP2_HTTP_1_1_ALPN "\x8http/1.1" -#define NGHTTP2_HTTP_1_1_ALPN_LEN (sizeof(NGHTTP2_HTTP_1_1_ALPN) - 1) - -int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen, - const unsigned char *in, unsigned int inlen) { - if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_ALPN, - NGHTTP2_PROTO_ALPN_LEN) == 0) { - return 1; - } - if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_HTTP_1_1_ALPN, - NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) { + if (http_selected) { return 0; + } else { + return -1; } - return -1; } diff -Nru nghttp2-1.13.0/lib/nghttp2_npn.h nghttp2-0.6.7/lib/nghttp2_npn.h --- nghttp2-1.13.0/lib/nghttp2_npn.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_npn.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,9 +25,9 @@ #ifndef NGHTTP2_NPN_H #define NGHTTP2_NPN_H -#ifdef HAVE_CONFIG_H +#ifdef HAVE_CONFIG #include -#endif /* HAVE_CONFIG_H */ +#endif /* HAVE_CONFIG */ #include diff -Nru nghttp2-1.13.0/lib/nghttp2_option.c nghttp2-0.6.7/lib/nghttp2_option.c --- nghttp2-1.13.0/lib/nghttp2_option.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_option.c 2014-11-30 14:15:07.000000000 +0000 @@ -24,8 +24,6 @@ */ #include "nghttp2_option.h" -#include "nghttp2_session.h" - int nghttp2_option_new(nghttp2_option **option_ptr) { *option_ptr = calloc(1, sizeof(nghttp2_option)); @@ -49,55 +47,7 @@ option->peer_max_concurrent_streams = 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) { - option->opt_set_mask |= NGHTTP2_OPT_NO_HTTP_MESSAGING; - option->no_http_messaging = val; -} - -void nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option, - uint32_t val) { - option->opt_set_mask |= NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS; - option->max_reserved_remote_streams = val; -} - -static void set_ext_type(uint8_t *ext_types, uint8_t type) { - ext_types[type / 8] = (uint8_t)(ext_types[type / 8] | (1 << (type & 0x7))); -} - -void nghttp2_option_set_user_recv_extension_type(nghttp2_option *option, - uint8_t type) { - if (type < 10) { - return; - } - - option->opt_set_mask |= NGHTTP2_OPT_USER_RECV_EXT_TYPES; - set_ext_type(option->user_recv_ext_types, type); -} - -void nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option, - uint8_t type) { - switch (type) { - case NGHTTP2_ALTSVC: - option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES; - option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ALTSVC; - return; - default: - return; - } -} - -void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option, int val) { - option->opt_set_mask |= NGHTTP2_OPT_NO_AUTO_PING_ACK; - option->no_auto_ping_ack = val; -} - -void nghttp2_option_set_max_send_header_block_length(nghttp2_option *option, - size_t val) { - option->opt_set_mask |= NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH; - option->max_send_header_block_length = 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; } diff -Nru nghttp2-1.13.0/lib/nghttp2_option.h nghttp2-0.6.7/lib/nghttp2_option.h --- nghttp2-1.13.0/lib/nghttp2_option.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_option.h 2014-11-30 14:15:07.000000000 +0000 @@ -57,13 +57,7 @@ * SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint. */ NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1, - NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC = 1 << 2, - NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3, - NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS = 1 << 4, - NGHTTP2_OPT_USER_RECV_EXT_TYPES = 1 << 5, - NGHTTP2_OPT_NO_AUTO_PING_ACK = 1 << 6, - NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES = 1 << 7, - NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH = 1 << 8, + NGHTTP2_OPT_RECV_CLIENT_PREFACE = 1 << 2, } nghttp2_option_flag; /** @@ -71,10 +65,6 @@ */ struct nghttp2_option { /** - * NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH - */ - size_t max_send_header_block_length; - /** * Bitwise OR of nghttp2_option_flag to determine that which fields * are specified. */ @@ -84,33 +74,13 @@ */ uint32_t peer_max_concurrent_streams; /** - * NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS - */ - uint32_t max_reserved_remote_streams; - /** - * NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES - */ - uint32_t builtin_recv_ext_types; - /** * NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE */ - int no_auto_window_update; - /** - * NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC - */ - int no_recv_client_magic; - /** - * NGHTTP2_OPT_NO_HTTP_MESSAGING - */ - int no_http_messaging; - /** - * NGHTTP2_OPT_NO_AUTO_PING_ACK - */ - int no_auto_ping_ack; + uint8_t no_auto_window_update; /** - * NGHTTP2_OPT_USER_RECV_EXT_TYPES + * NGHTTP2_OPT_RECV_CLIENT_PREFACE */ - uint8_t user_recv_ext_types[32]; + uint8_t recv_client_preface; }; #endif /* NGHTTP2_OPTION_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_outbound_item.c nghttp2-0.6.7/lib/nghttp2_outbound_item.c --- nghttp2-1.13.0/lib/nghttp2_outbound_item.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_outbound_item.c 2014-11-30 14:15:07.000000000 +0000 @@ -25,17 +25,8 @@ #include "nghttp2_outbound_item.h" #include -#include -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) { +void nghttp2_outbound_item_free(nghttp2_outbound_item *item) { nghttp2_frame *frame; if (item == NULL) { @@ -49,7 +40,7 @@ nghttp2_frame_data_free(&frame->data); break; case NGHTTP2_HEADERS: - nghttp2_frame_headers_free(&frame->headers, mem); + nghttp2_frame_headers_free(&frame->headers); break; case NGHTTP2_PRIORITY: nghttp2_frame_priority_free(&frame->priority); @@ -58,67 +49,23 @@ nghttp2_frame_rst_stream_free(&frame->rst_stream); break; case NGHTTP2_SETTINGS: - nghttp2_frame_settings_free(&frame->settings, mem); + nghttp2_frame_settings_free(&frame->settings); break; case NGHTTP2_PUSH_PROMISE: - nghttp2_frame_push_promise_free(&frame->push_promise, mem); + nghttp2_frame_push_promise_free(&frame->push_promise); break; case NGHTTP2_PING: nghttp2_frame_ping_free(&frame->ping); break; case NGHTTP2_GOAWAY: - nghttp2_frame_goaway_free(&frame->goaway, mem); + nghttp2_frame_goaway_free(&frame->goaway); break; case NGHTTP2_WINDOW_UPDATE: nghttp2_frame_window_update_free(&frame->window_update); break; - default: { - nghttp2_ext_aux_data *aux_data; - - aux_data = &item->aux_data.ext; - - if (aux_data->builtin == 0) { - nghttp2_frame_extension_free(&frame->ext); - break; - } - - switch (frame->hd.type) { - case NGHTTP2_ALTSVC: - nghttp2_frame_altsvc_free(&frame->ext, mem); - break; - default: - assert(0); - 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; + case NGHTTP2_EXT_ALTSVC: + nghttp2_frame_altsvc_free(&frame->ext); + free(frame->ext.payload); + break; } - --q->n; } diff -Nru nghttp2-1.13.0/lib/nghttp2_outbound_item.h nghttp2-0.6.7/lib/nghttp2_outbound_item.h --- nghttp2-1.13.0/lib/nghttp2_outbound_item.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_outbound_item.h 2014-11-30 14:15:07.000000000 +0000 @@ -31,18 +31,21 @@ #include #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; void *stream_user_data; - /* error code when request HEADERS is canceled by RST_STREAM while - it is in queue. */ - uint32_t error_code; - /* nonzero if request HEADERS is canceled. The error code is stored - in |error_code|. */ - uint8_t canceled; + /* nonzero if this item should be attached to stream object to make + it under priority control */ + uint8_t attach_stream; } nghttp2_headers_aux_data; /* struct used for DATA frame */ @@ -64,103 +67,40 @@ * |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 { - NGHTTP2_GOAWAY_AUX_NONE = 0x0, - /* indicates that session should be terminated after the - transmission of this frame. */ - NGHTTP2_GOAWAY_AUX_TERM_ON_SEND = 0x1, - /* 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_flag; - /* struct used for GOAWAY frame */ typedef struct { - /* bitwise-OR of one or more of nghttp2_goaway_aux_flag. */ - uint8_t flags; + /* nonzero if session should be terminated after the transmission of + this frame. */ + int terminate_on_send; } nghttp2_goaway_aux_data; -/* struct used for extension frame */ -typedef struct { - /* nonzero if this extension frame is serialized by library - function, instead of user-defined callbacks. */ - uint8_t builtin; -} nghttp2_ext_aux_data; - /* Additional data which cannot be stored in nghttp2_frame struct */ typedef union { nghttp2_data_aux_data data; nghttp2_headers_aux_data headers; nghttp2_goaway_aux_data goaway; - nghttp2_ext_aux_data ext; } nghttp2_aux_data; -struct nghttp2_outbound_item; -typedef struct nghttp2_outbound_item nghttp2_outbound_item; - -struct nghttp2_outbound_item { +typedef struct { nghttp2_frame frame; - /* Storage for extension frame payload. frame->ext.payload points - to this structure to avoid frequent memory allocation. */ - nghttp2_ext_frame_payload ext_frame_payload; nghttp2_aux_data aux_data; - /* 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). */ + int64_t seq; + /* Reset count of weight. See comment for last_cycle in + nghttp2_session.h */ uint64_t cycle; - nghttp2_outbound_item *qnext; - /* nonzero if this object is queued, except for DATA or HEADERS - which are attached to stream as item. */ + /* The priority used in priority comparion. Larger is served + ealier. */ + int32_t weight; + /* nonzero if this object is queued. */ uint8_t queued; -}; - -/* - * 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); +} nghttp2_outbound_item; /* * Deallocates resource for |item|. If |item| is NULL, this function * does nothing. */ -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) +void nghttp2_outbound_item_free(nghttp2_outbound_item *item); #endif /* NGHTTP2_OUTBOUND_ITEM_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_pq.c nghttp2-0.6.7/lib/nghttp2_pq.c --- nghttp2-1.13.0/lib/nghttp2_pq.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_pq.c 2014-11-30 14:15:07.000000000 +0000 @@ -24,70 +24,57 @@ */ #include "nghttp2_pq.h" -#include -#include - -#include "nghttp2_helper.h" - -int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem) { - pq->mem = mem; - pq->capacity = 0; - pq->q = NULL; +int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_compar compar) { + pq->capacity = 128; + pq->q = malloc(pq->capacity * sizeof(void *)); + if (pq->q == NULL) { + return NGHTTP2_ERR_NOMEM; + } pq->length = 0; - pq->less = less; + pq->compar = compar; return 0; } void nghttp2_pq_free(nghttp2_pq *pq) { - nghttp2_mem_free(pq->mem, pq->q); + free(pq->q); pq->q = NULL; } static void swap(nghttp2_pq *pq, size_t i, size_t j) { - nghttp2_pq_entry *a = pq->q[i]; - nghttp2_pq_entry *b = pq->q[j]; - - pq->q[i] = b; - b->index = i; - pq->q[j] = a; - a->index = j; + void *t = pq->q[i]; + pq->q[i] = pq->q[j]; + pq->q[j] = t; } static void bubble_up(nghttp2_pq *pq, size_t index) { - size_t parent; - while (index != 0) { - parent = (index - 1) / 2; - if (!pq->less(pq->q[index], pq->q[parent])) { - return; + if (index == 0) { + return; + } else { + size_t parent = (index - 1) / 2; + if (pq->compar(pq->q[parent], pq->q[index]) > 0) { + swap(pq, parent, index); + bubble_up(pq, parent); } - swap(pq, parent, index); - index = parent; } } -int nghttp2_pq_push(nghttp2_pq *pq, nghttp2_pq_entry *item) { +int nghttp2_pq_push(nghttp2_pq *pq, void *item) { if (pq->capacity <= pq->length) { void *nq; - size_t ncapacity; - - ncapacity = nghttp2_max(4, (pq->capacity * 2)); - - nq = nghttp2_mem_realloc(pq->mem, pq->q, - ncapacity * sizeof(nghttp2_pq_entry *)); + nq = realloc(pq->q, (pq->capacity * 2) * sizeof(void *)); if (nq == NULL) { return NGHTTP2_ERR_NOMEM; } - pq->capacity = ncapacity; + pq->capacity *= 2; pq->q = nq; } pq->q[pq->length] = item; - item->index = pq->length; ++pq->length; bubble_up(pq, pq->length - 1); return 0; } -nghttp2_pq_entry *nghttp2_pq_top(nghttp2_pq *pq) { +void *nghttp2_pq_top(nghttp2_pq *pq) { if (pq->length == 0) { return NULL; } else { @@ -96,59 +83,32 @@ } static void bubble_down(nghttp2_pq *pq, size_t index) { - size_t i, j, minindex; - for (;;) { - j = index * 2 + 1; - minindex = index; - for (i = 0; i < 2; ++i, ++j) { - if (j >= pq->length) { - break; - } - if (pq->less(pq->q[j], pq->q[minindex])) { - minindex = j; - } + size_t lchild = index * 2 + 1; + size_t minindex = index; + size_t i, j; + for (i = 0; i < 2; ++i) { + j = lchild + i; + if (j >= pq->length) { + break; } - if (minindex == index) { - return; + if (pq->compar(pq->q[minindex], pq->q[j]) > 0) { + minindex = j; } + } + if (minindex != index) { swap(pq, index, minindex); - index = minindex; + bubble_down(pq, minindex); } } void nghttp2_pq_pop(nghttp2_pq *pq) { if (pq->length > 0) { pq->q[0] = pq->q[pq->length - 1]; - pq->q[0]->index = 0; --pq->length; bubble_down(pq, 0); } } -void nghttp2_pq_remove(nghttp2_pq *pq, nghttp2_pq_entry *item) { - assert(pq->q[item->index] == item); - - if (item->index == 0) { - nghttp2_pq_pop(pq); - return; - } - - if (item->index == pq->length - 1) { - --pq->length; - return; - } - - pq->q[item->index] = pq->q[pq->length - 1]; - pq->q[item->index]->index = item->index; - --pq->length; - - if (pq->less(item, pq->q[item->index])) { - bubble_down(pq, item->index); - } else { - bubble_up(pq, item->index); - } -} - int nghttp2_pq_empty(nghttp2_pq *pq) { return pq->length == 0; } size_t nghttp2_pq_size(nghttp2_pq *pq) { return pq->length; } @@ -168,17 +128,3 @@ } } } - -int nghttp2_pq_each(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg) { - size_t i; - - if (pq->length == 0) { - return 0; - } - for (i = 0; i < pq->length; ++i) { - if ((*fun)(pq->q[i], arg)) { - return 1; - } - } - return 0; -} diff -Nru nghttp2-1.13.0/lib/nghttp2_pq.h nghttp2-0.6.7/lib/nghttp2_pq.h --- nghttp2-1.13.0/lib/nghttp2_pq.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_pq.h 2014-11-30 14:15:07.000000000 +0000 @@ -31,24 +31,19 @@ #include #include "nghttp2_int.h" -#include "nghttp2_mem.h" /* Implementation of priority queue */ -typedef struct { size_t index; } nghttp2_pq_entry; - typedef struct { /* The pointer to the pointer to the item stored */ - nghttp2_pq_entry **q; - /* Memory allocator */ - nghttp2_mem *mem; + void **q; /* The number of items sotred */ size_t length; /* The maximum number of items this pq can store. This is automatically extended when length is reached to this value. */ size_t capacity; - /* The less function between items */ - nghttp2_less less; + /* The compare function between items */ + nghttp2_compar compar; } nghttp2_pq; /* @@ -60,7 +55,7 @@ * NGHTTP2_ERR_NOMEM * Out of memory. */ -int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem); +int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_compar cmp); /* * Deallocates any resources allocated for |pq|. The stored items are @@ -77,13 +72,13 @@ * NGHTTP2_ERR_NOMEM * Out of memory. */ -int nghttp2_pq_push(nghttp2_pq *pq, nghttp2_pq_entry *item); +int nghttp2_pq_push(nghttp2_pq *pq, void *item); /* * Returns item at the top of the queue |pq|. If the queue is empty, * this function returns NULL. */ -nghttp2_pq_entry *nghttp2_pq_top(nghttp2_pq *pq); +void *nghttp2_pq_top(nghttp2_pq *pq); /* * Pops item at the top of the queue |pq|. The popped item is not @@ -101,7 +96,7 @@ */ size_t nghttp2_pq_size(nghttp2_pq *pq); -typedef int (*nghttp2_pq_item_cb)(nghttp2_pq_entry *item, void *arg); +typedef int (*nghttp2_pq_item_cb)(void *item, void *arg); /* * Updates each item in |pq| using function |fun| and re-construct @@ -111,18 +106,4 @@ */ void nghttp2_pq_update(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg); -/* - * Applys |fun| to each item in |pq|. The |arg| is passed as arg - * parameter to callback function. This function must not change the - * ordering key. If the return value from callback is nonzero, this - * function returns 1 immediately without iterating remaining items. - * Otherwise this function returns 0. - */ -int nghttp2_pq_each(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg); - -/* - * Removes |item| from priority queue. - */ -void nghttp2_pq_remove(nghttp2_pq *pq, nghttp2_pq_entry *item); - #endif /* NGHTTP2_PQ_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_priority_spec.c nghttp2-0.6.7/lib/nghttp2_priority_spec.c --- nghttp2-1.13.0/lib/nghttp2_priority_spec.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_priority_spec.c 2014-11-30 14:15:07.000000000 +0000 @@ -42,11 +42,3 @@ return pri_spec->stream_id == 0 && pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT && pri_spec->exclusive == 0; } - -void nghttp2_priority_spec_normalize_weight(nghttp2_priority_spec *pri_spec) { - if (pri_spec->weight < NGHTTP2_MIN_WEIGHT) { - pri_spec->weight = NGHTTP2_MIN_WEIGHT; - } else if (pri_spec->weight > NGHTTP2_MAX_WEIGHT) { - pri_spec->weight = NGHTTP2_MAX_WEIGHT; - } -} diff -Nru nghttp2-1.13.0/lib/nghttp2_priority_spec.h nghttp2-0.6.7/lib/nghttp2_priority_spec.h --- nghttp2-1.13.0/lib/nghttp2_priority_spec.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_priority_spec.h 2014-11-30 14:15:07.000000000 +0000 @@ -31,12 +31,4 @@ #include -/* - * This function normalizes pri_spec->weight if it is out of range. - * If pri_spec->weight is less than NGHTTP2_MIN_WEIGHT, it is set to - * NGHTTP2_MIN_WEIGHT. If pri_spec->weight is larger than - * NGHTTP2_MAX_WEIGHT, it is set to NGHTTP2_MAX_WEIGHT. - */ -void nghttp2_priority_spec_normalize_weight(nghttp2_priority_spec *pri_spec); - #endif /* NGHTTP2_PRIORITY_SPEC_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_rcbuf.c nghttp2-0.6.7/lib/nghttp2_rcbuf.c --- nghttp2-1.13.0/lib/nghttp2_rcbuf.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_rcbuf.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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. - */ -#include "nghttp2_rcbuf.h" - -#include -#include - -#include "nghttp2_mem.h" - -int nghttp2_rcbuf_new(nghttp2_rcbuf **rcbuf_ptr, size_t size, - nghttp2_mem *mem) { - uint8_t *p; - - p = nghttp2_mem_malloc(mem, sizeof(nghttp2_rcbuf) + size); - if (p == NULL) { - return NGHTTP2_ERR_NOMEM; - } - - *rcbuf_ptr = (void *)p; - - (*rcbuf_ptr)->mem_user_data = mem->mem_user_data; - (*rcbuf_ptr)->free = mem->free; - (*rcbuf_ptr)->base = p + sizeof(nghttp2_rcbuf); - (*rcbuf_ptr)->len = size; - (*rcbuf_ptr)->ref = 1; - - return 0; -} - -int nghttp2_rcbuf_new2(nghttp2_rcbuf **rcbuf_ptr, const uint8_t *src, - size_t srclen, nghttp2_mem *mem) { - int rv; - - rv = nghttp2_rcbuf_new(rcbuf_ptr, srclen + 1, mem); - if (rv != 0) { - return rv; - } - - memcpy((*rcbuf_ptr)->base, src, srclen); - - (*rcbuf_ptr)->len = srclen; - (*rcbuf_ptr)->base[srclen] = '\0'; - - return 0; -} - -/* - * Frees |rcbuf| itself, regardless of its reference cout. - */ -void nghttp2_rcbuf_del(nghttp2_rcbuf *rcbuf) { - nghttp2_mem_free2(rcbuf->free, rcbuf, rcbuf->mem_user_data); -} - -void nghttp2_rcbuf_incref(nghttp2_rcbuf *rcbuf) { - if (rcbuf->ref == -1) { - return; - } - - ++rcbuf->ref; -} - -void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf) { - if (rcbuf == NULL || rcbuf->ref == -1) { - return; - } - - assert(rcbuf->ref > 0); - - if (--rcbuf->ref == 0) { - nghttp2_rcbuf_del(rcbuf); - } -} - -nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf) { - nghttp2_vec res = {rcbuf->base, rcbuf->len}; - return res; -} diff -Nru nghttp2-1.13.0/lib/nghttp2_rcbuf.h nghttp2-0.6.7/lib/nghttp2_rcbuf.h --- nghttp2-1.13.0/lib/nghttp2_rcbuf.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_rcbuf.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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_RCBUF_H -#define NGHTTP2_RCBUF_H - -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - -#include - -struct nghttp2_rcbuf { - /* custom memory allocator belongs to the mem parameter when - creating this object. */ - void *mem_user_data; - nghttp2_free free; - /* The pointer to the underlying buffer */ - uint8_t *base; - /* Size of buffer pointed by |base|. */ - size_t len; - /* Reference count */ - int32_t ref; -}; - -/* - * Allocates nghttp2_rcbuf object with |size| as initial buffer size. - * When the function succeeds, the reference count becomes 1. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGHTTP2_ERR_NOMEM: - * Out of memory. - */ -int nghttp2_rcbuf_new(nghttp2_rcbuf **rcbuf_ptr, size_t size, nghttp2_mem *mem); - -/* - * Like nghttp2_rcbuf_new(), but initializes the buffer with |src| of - * length |srclen|. This function allocates additional byte at the - * end and puts '\0' into it, so that the resulting buffer could be - * used as NULL-terminated string. Still (*rcbuf_ptr)->len equals to - * |srclen|. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGHTTP2_ERR_NOMEM: - * Out of memory. - */ -int nghttp2_rcbuf_new2(nghttp2_rcbuf **rcbuf_ptr, const uint8_t *src, - size_t srclen, nghttp2_mem *mem); - -/* - * Frees |rcbuf| itself, regardless of its reference cout. - */ -void nghttp2_rcbuf_del(nghttp2_rcbuf *rcbuf); - -#endif /* NGHTTP2_RCBUF_H */ diff -Nru nghttp2-1.13.0/lib/nghttp2_session.c nghttp2-0.6.7/lib/nghttp2_session.c --- nghttp2-1.13.0/lib/nghttp2_session.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_session.c 2014-11-30 14:15:07.000000000 +0000 @@ -28,14 +28,11 @@ #include #include #include -#include #include "nghttp2_helper.h" #include "nghttp2_net.h" #include "nghttp2_priority_spec.h" #include "nghttp2_option.h" -#include "nghttp2_http.h" -#include "nghttp2_pq.h" /* * Returns non-zero if the number of outgoing opened streams is larger @@ -73,34 +70,11 @@ /* * Returns non-zero if |lib_error| is non-fatal error. */ -static int is_non_fatal(int lib_error_code) { - return lib_error_code < 0 && lib_error_code > NGHTTP2_ERR_FATAL; +static int is_non_fatal(int lib_error) { + return lib_error < 0 && lib_error > NGHTTP2_ERR_FATAL; } -int nghttp2_is_fatal(int lib_error_code) { - return lib_error_code < NGHTTP2_ERR_FATAL; -} - -static int session_enforce_http_messaging(nghttp2_session *session) { - return (session->opt_flags & NGHTTP2_OPTMASK_NO_HTTP_MESSAGING) == 0; -} - -/* - * Returns nonzero if |frame| is trailer headers. - */ -static int session_trailer_headers(nghttp2_session *session, - nghttp2_stream *stream, - nghttp2_frame *frame) { - if (!stream || frame->hd.type != NGHTTP2_HEADERS) { - return 0; - } - if (session->server) { - return frame->headers.cat == NGHTTP2_HCAT_HEADERS; - } - - return frame->headers.cat == NGHTTP2_HCAT_HEADERS && - (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) == 0; -} +int nghttp2_is_fatal(int lib_error) { return lib_error < NGHTTP2_ERR_FATAL; } /* Returns nonzero if the |stream| is in reserved(remote) state */ static int state_reserved_remote(nghttp2_session *session, @@ -131,7 +105,7 @@ int32_t stream_id) { /* Assume that stream object with stream_id does not exist */ if (nghttp2_session_is_my_stream_id(session, stream_id)) { - if (session->last_sent_stream_id < stream_id) { + if (session->next_stream_id <= (uint32_t)stream_id) { return 1; } return 0; @@ -142,66 +116,6 @@ return 0; } -static int check_ext_type_set(const uint8_t *ext_types, uint8_t type) { - return (ext_types[type / 8] & (1 << (type & 0x7))) > 0; -} - -static int session_call_error_callback(nghttp2_session *session, - const char *fmt, ...) { - size_t bufsize; - va_list ap; - char *buf; - int rv; - nghttp2_mem *mem; - - if (!session->callbacks.error_callback) { - return 0; - } - - mem = &session->mem; - - va_start(ap, fmt); - rv = vsnprintf(NULL, 0, fmt, ap); - va_end(ap); - - if (rv < 0) { - return NGHTTP2_ERR_NOMEM; - } - - bufsize = (size_t)(rv + 1); - - buf = nghttp2_mem_malloc(mem, bufsize); - if (buf == NULL) { - return NGHTTP2_ERR_NOMEM; - } - - va_start(ap, fmt); - rv = vsnprintf(buf, bufsize, fmt, ap); - va_end(ap); - - if (rv < 0) { - nghttp2_mem_free(mem, buf); - /* vsnprintf may return error because of various things we can - imagine, but typically we don't want to drop session just for - debug callback. */ - DEBUGF(fprintf(stderr, - "error_callback: vsnprintf failed. The template was %s\n", - fmt)); - return 0; - } - - rv = session->callbacks.error_callback(session, buf, (size_t)rv, - session->user_data); - - nghttp2_mem_free(mem, buf); - - if (rv != 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - - return 0; -} - static int session_terminate_session(nghttp2_session *session, int32_t last_stream_id, uint32_t error_code, const char *reason) { @@ -222,8 +136,7 @@ } rv = nghttp2_session_add_goaway(session, last_stream_id, error_code, - debug_data, debug_datalen, - NGHTTP2_GOAWAY_AUX_TERM_ON_SEND); + debug_data, debug_datalen, 1); if (rv != 0) { return rv; @@ -285,17 +198,32 @@ return (nghttp2_stream *)nghttp2_map_find(&session->streams, stream_id); } +static int outbound_item_compar(const void *lhsx, const void *rhsx) { + const nghttp2_outbound_item *lhs, *rhs; + + lhs = (const nghttp2_outbound_item *)lhsx; + rhs = (const nghttp2_outbound_item *)rhsx; + + if (lhs->cycle == rhs->cycle) { + if (lhs->weight == rhs->weight) { + return (lhs->seq < rhs->seq) ? -1 : ((lhs->seq > rhs->seq) ? 1 : 0); + } + + /* Larger weight has higher precedence */ + return rhs->weight - lhs->weight; + } + + return (lhs->cycle < rhs->cycle) ? -1 : 1; +} + static void session_inbound_frame_reset(nghttp2_session *session) { nghttp2_inbound_frame *iframe = &session->iframe; - nghttp2_mem *mem = &session->mem; /* A bit risky code, since if this function is called from nghttp2_session_new(), we rely on the fact that iframe->frame.hd.type is 0, so that no free is performed. */ switch (iframe->frame.hd.type) { - case NGHTTP2_DATA: - break; case NGHTTP2_HEADERS: - nghttp2_frame_headers_free(&iframe->frame.headers, mem); + nghttp2_frame_headers_free(&iframe->frame.headers); break; case NGHTTP2_PRIORITY: nghttp2_frame_priority_free(&iframe->frame.priority); @@ -304,43 +232,22 @@ nghttp2_frame_rst_stream_free(&iframe->frame.rst_stream); break; case NGHTTP2_SETTINGS: - nghttp2_frame_settings_free(&iframe->frame.settings, mem); - - nghttp2_mem_free(mem, iframe->iv); - - iframe->iv = NULL; - iframe->niv = 0; - iframe->max_niv = 0; - + nghttp2_frame_settings_free(&iframe->frame.settings); break; case NGHTTP2_PUSH_PROMISE: - nghttp2_frame_push_promise_free(&iframe->frame.push_promise, mem); + nghttp2_frame_push_promise_free(&iframe->frame.push_promise); break; case NGHTTP2_PING: nghttp2_frame_ping_free(&iframe->frame.ping); break; case NGHTTP2_GOAWAY: - nghttp2_frame_goaway_free(&iframe->frame.goaway, mem); + nghttp2_frame_goaway_free(&iframe->frame.goaway); break; case NGHTTP2_WINDOW_UPDATE: nghttp2_frame_window_update_free(&iframe->frame.window_update); break; - default: - /* extension frame */ - if (check_ext_type_set(session->user_recv_ext_types, - iframe->frame.hd.type)) { - nghttp2_frame_extension_free(&iframe->frame.ext); - } else { - switch (iframe->frame.hd.type) { - case NGHTTP2_ALTSVC: - if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ALTSVC) == 0) { - break; - } - nghttp2_frame_altsvc_free(&iframe->frame.ext, mem); - break; - } - } - + case NGHTTP2_EXT_ALTSVC: + nghttp2_frame_altsvc_free(&iframe->frame.ext); break; } @@ -353,13 +260,15 @@ sizeof(iframe->raw_sbuf)); iframe->sbuf.mark += NGHTTP2_FRAME_HDLEN; - nghttp2_buf_free(&iframe->lbuf, mem); + nghttp2_buf_free(&iframe->lbuf); nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0); - iframe->raw_lbuf = NULL; - + iframe->niv = 0; iframe->payloadleft = 0; iframe->padlen = 0; + iframe->iv[NGHTTP2_INBOUND_NUM_IV - 1].settings_id = + NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; + iframe->iv[NGHTTP2_INBOUND_NUM_IV - 1].value = UINT32_MAX; } static void init_settings(nghttp2_settings_storage *settings) { @@ -371,58 +280,65 @@ settings->max_header_list_size = UINT32_MAX; } -static void active_outbound_item_reset(nghttp2_active_outbound_item *aob, - nghttp2_mem *mem) { +static void active_outbound_item_reset(nghttp2_active_outbound_item *aob) { DEBUGF(fprintf(stderr, "send: reset nghttp2_active_outbound_item\n")); DEBUGF(fprintf(stderr, "send: aob->item = %p\n", aob->item)); - nghttp2_outbound_item_free(aob->item, mem); - nghttp2_mem_free(mem, aob->item); + nghttp2_outbound_item_free(aob->item); + free(aob->item); aob->item = NULL; nghttp2_bufs_reset(&aob->framebufs); aob->state = NGHTTP2_OB_POP_ITEM; } -int nghttp2_enable_strict_preface = 1; +/* This global variable exists for tests where we want to disable this + check. */ +int nghttp2_enable_strict_first_settings_check = 1; static int session_new(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data, int server, - const nghttp2_option *option, nghttp2_mem *mem) { + const nghttp2_option *option) { int rv; - size_t nbuffer; - - if (mem == NULL) { - mem = nghttp2_mem_default(); - } - *session_ptr = nghttp2_mem_calloc(mem, 1, sizeof(nghttp2_session)); + *session_ptr = calloc(1, sizeof(nghttp2_session)); if (*session_ptr == NULL) { rv = NGHTTP2_ERR_NOMEM; goto fail_session; } - (*session_ptr)->mem = *mem; - mem = &(*session_ptr)->mem; - /* next_stream_id is initialized in either nghttp2_session_client_new2 or nghttp2_session_server_new2 */ - rv = nghttp2_hd_deflate_init(&(*session_ptr)->hd_deflater, mem); + rv = nghttp2_pq_init(&(*session_ptr)->ob_pq, outbound_item_compar); + if (rv != 0) { + goto fail_ob_pq; + } + rv = nghttp2_pq_init(&(*session_ptr)->ob_ss_pq, outbound_item_compar); + if (rv != 0) { + goto fail_ob_ss_pq; + } + rv = nghttp2_pq_init(&(*session_ptr)->ob_da_pq, outbound_item_compar); + if (rv != 0) { + goto fail_ob_da_pq; + } + + rv = nghttp2_hd_deflate_init(&(*session_ptr)->hd_deflater); if (rv != 0) { goto fail_hd_deflater; } - rv = nghttp2_hd_inflate_init(&(*session_ptr)->hd_inflater, mem); + rv = nghttp2_hd_inflate_init(&(*session_ptr)->hd_inflater); if (rv != 0) { goto fail_hd_inflater; } - rv = nghttp2_map_init(&(*session_ptr)->streams, mem); + rv = nghttp2_map_init(&(*session_ptr)->streams); if (rv != 0) { goto fail_map; } - nghttp2_stream_init(&(*session_ptr)->root, 0, NGHTTP2_STREAM_FLAG_NONE, - NGHTTP2_STREAM_IDLE, NGHTTP2_DEFAULT_WEIGHT, 0, 0, NULL, - mem); + nghttp2_stream_roots_init(&(*session_ptr)->roots); + + (*session_ptr)->next_seq = 0; + (*session_ptr)->last_cycle = 1; (*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; (*session_ptr)->recv_window_size = 0; @@ -434,24 +350,27 @@ (*session_ptr)->local_last_stream_id = (1u << 31) - 1; (*session_ptr)->remote_last_stream_id = (1u << 31) - 1; + (*session_ptr)->inflight_niv = -1; + (*session_ptr)->pending_local_max_concurrent_stream = NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS; - (*session_ptr)->pending_enable_push = 1; if (server) { (*session_ptr)->server = 1; } - init_settings(&(*session_ptr)->remote_settings); - init_settings(&(*session_ptr)->local_settings); - - (*session_ptr)->max_incoming_reserved_streams = - NGHTTP2_MAX_INCOMING_RESERVED_STREAMS; + /* 1 for Pad Field. */ + rv = nghttp2_bufs_init3(&(*session_ptr)->aob.framebufs, + NGHTTP2_FRAMEBUF_CHUNKLEN, NGHTTP2_FRAMEBUF_MAX_NUM, + 1, NGHTTP2_FRAME_HDLEN + 1); + if (rv != 0) { + goto fail_aob_framebuf; + } - /* Limit max outgoing concurrent streams to sensible value */ - (*session_ptr)->remote_settings.max_concurrent_streams = 100; + active_outbound_item_reset(&(*session_ptr)->aob); - (*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN; + init_settings(&(*session_ptr)->remote_settings); + init_settings(&(*session_ptr)->local_settings); if (option) { if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) && @@ -466,84 +385,28 @@ option->peer_max_concurrent_streams; } - if (option->opt_set_mask & NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS) { - - (*session_ptr)->max_incoming_reserved_streams = - option->max_reserved_remote_streams; - } - - if ((option->opt_set_mask & NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC) && - option->no_recv_client_magic) { - - (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC; - } - - if ((option->opt_set_mask & NGHTTP2_OPT_NO_HTTP_MESSAGING) && - option->no_http_messaging) { - - (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING; - } - - if (option->opt_set_mask & NGHTTP2_OPT_USER_RECV_EXT_TYPES) { - memcpy((*session_ptr)->user_recv_ext_types, option->user_recv_ext_types, - sizeof((*session_ptr)->user_recv_ext_types)); - } - - if (option->opt_set_mask & NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES) { - (*session_ptr)->builtin_recv_ext_types = option->builtin_recv_ext_types; - } - - if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_PING_ACK) && - option->no_auto_ping_ack) { - (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_AUTO_PING_ACK; - } + if (option->opt_set_mask & NGHTTP2_OPT_RECV_CLIENT_PREFACE) { - if (option->opt_set_mask & NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH) { - (*session_ptr)->max_send_header_block_length = - option->max_send_header_block_length; + (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_RECV_CLIENT_PREFACE; } } - nbuffer = ((*session_ptr)->max_send_header_block_length + - NGHTTP2_FRAMEBUF_CHUNKLEN - 1) / - NGHTTP2_FRAMEBUF_CHUNKLEN; - - if (nbuffer == 0) { - nbuffer = 1; - } - - /* 1 for Pad Field. */ - rv = nghttp2_bufs_init3(&(*session_ptr)->aob.framebufs, - NGHTTP2_FRAMEBUF_CHUNKLEN, nbuffer, 1, - NGHTTP2_FRAME_HDLEN + 1, mem); - if (rv != 0) { - goto fail_aob_framebuf; - } - - active_outbound_item_reset(&(*session_ptr)->aob, mem); - (*session_ptr)->callbacks = *callbacks; (*session_ptr)->user_data = user_data; session_inbound_frame_reset(*session_ptr); - if (nghttp2_enable_strict_preface) { + if (server && + ((*session_ptr)->opt_flags & NGHTTP2_OPTMASK_RECV_CLIENT_PREFACE)) { + nghttp2_inbound_frame *iframe = &(*session_ptr)->iframe; - if (server && - ((*session_ptr)->opt_flags & NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC) == - 0) { - iframe->state = NGHTTP2_IB_READ_CLIENT_MAGIC; - iframe->payloadleft = NGHTTP2_CLIENT_MAGIC_LEN; - } else { - iframe->state = NGHTTP2_IB_READ_FIRST_SETTINGS; - } + iframe->state = NGHTTP2_IB_READ_CLIENT_PREFACE; + iframe->payloadleft = NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN; + } else if (nghttp2_enable_strict_first_settings_check) { + nghttp2_inbound_frame *iframe = &(*session_ptr)->iframe; - if (!server) { - (*session_ptr)->aob.state = NGHTTP2_OB_SEND_CLIENT_MAGIC; - nghttp2_bufs_add(&(*session_ptr)->aob.framebufs, NGHTTP2_CLIENT_MAGIC, - NGHTTP2_CLIENT_MAGIC_LEN); - } + iframe->state = NGHTTP2_IB_READ_FIRST_SETTINGS; } return 0; @@ -555,7 +418,13 @@ fail_hd_inflater: nghttp2_hd_deflate_free(&(*session_ptr)->hd_deflater); fail_hd_deflater: - nghttp2_mem_free(mem, *session_ptr); + nghttp2_pq_free(&(*session_ptr)->ob_da_pq); +fail_ob_da_pq: + nghttp2_pq_free(&(*session_ptr)->ob_ss_pq); +fail_ob_ss_pq: + nghttp2_pq_free(&(*session_ptr)->ob_pq); +fail_ob_pq: + free(*session_ptr); fail_session: return rv; } @@ -563,25 +432,16 @@ int nghttp2_session_client_new(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data) { - return nghttp2_session_client_new3(session_ptr, callbacks, user_data, NULL, - NULL); + return nghttp2_session_client_new2(session_ptr, callbacks, user_data, NULL); } int nghttp2_session_client_new2(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data, const nghttp2_option *option) { - return nghttp2_session_client_new3(session_ptr, callbacks, user_data, option, - NULL); -} - -int nghttp2_session_client_new3(nghttp2_session **session_ptr, - const nghttp2_session_callbacks *callbacks, - void *user_data, const nghttp2_option *option, - nghttp2_mem *mem) { int rv; nghttp2_session *session; - rv = session_new(&session, callbacks, user_data, 0, option, mem); + rv = session_new(&session, callbacks, user_data, 0, option); if (rv != 0) { return rv; @@ -597,25 +457,16 @@ int nghttp2_session_server_new(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data) { - return nghttp2_session_server_new3(session_ptr, callbacks, user_data, NULL, - NULL); + return nghttp2_session_server_new2(session_ptr, callbacks, user_data, NULL); } int nghttp2_session_server_new2(nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks, void *user_data, const nghttp2_option *option) { - return nghttp2_session_server_new3(session_ptr, callbacks, user_data, option, - NULL); -} - -int nghttp2_session_server_new3(nghttp2_session **session_ptr, - const nghttp2_session_callbacks *callbacks, - void *user_data, const nghttp2_option *option, - nghttp2_mem *mem) { int rv; nghttp2_session *session; - rv = session_new(&session, callbacks, user_data, 1, option, mem); + rv = session_new(&session, callbacks, user_data, 1, option); if (rv != 0) { return rv; @@ -632,130 +483,95 @@ nghttp2_session *session; nghttp2_stream *stream; nghttp2_outbound_item *item; - nghttp2_mem *mem; session = (nghttp2_session *)ptr; - mem = &session->mem; stream = (nghttp2_stream *)entry; - item = stream->item; + item = stream->data_item; if (item && !item->queued && item != session->aob.item) { - nghttp2_outbound_item_free(item, mem); - nghttp2_mem_free(mem, item); + nghttp2_outbound_item_free(item); + free(item); } nghttp2_stream_free(stream); - nghttp2_mem_free(mem, stream); - - return 0; -} - -static void ob_q_free(nghttp2_outbound_queue *q, nghttp2_mem *mem) { - nghttp2_outbound_item *item, *next; - for (item = q->head; item;) { - next = item->qnext; - nghttp2_outbound_item_free(item, mem); - nghttp2_mem_free(mem, item); - item = next; - } -} - -static int inflight_settings_new(nghttp2_inflight_settings **settings_ptr, - const nghttp2_settings_entry *iv, size_t niv, - nghttp2_mem *mem) { - *settings_ptr = nghttp2_mem_malloc(mem, sizeof(nghttp2_inflight_settings)); - if (!*settings_ptr) { - return NGHTTP2_ERR_NOMEM; - } - - if (niv > 0) { - (*settings_ptr)->iv = nghttp2_frame_iv_copy(iv, niv, mem); - if (!(*settings_ptr)->iv) { - return NGHTTP2_ERR_NOMEM; - } - } else { - (*settings_ptr)->iv = NULL; - } - - (*settings_ptr)->niv = niv; - (*settings_ptr)->next = NULL; + free(stream); return 0; } -static void inflight_settings_del(nghttp2_inflight_settings *settings, - nghttp2_mem *mem) { - if (!settings) { - return; +static void ob_pq_free(nghttp2_pq *pq) { + while (!nghttp2_pq_empty(pq)) { + nghttp2_outbound_item *item = (nghttp2_outbound_item *)nghttp2_pq_top(pq); + nghttp2_outbound_item_free(item); + free(item); + nghttp2_pq_pop(pq); } - - nghttp2_mem_free(mem, settings->iv); - nghttp2_mem_free(mem, settings); + nghttp2_pq_free(pq); } void nghttp2_session_del(nghttp2_session *session) { - nghttp2_mem *mem; - nghttp2_inflight_settings *settings; - if (session == NULL) { return; } + free(session->inflight_iv); - mem = &session->mem; - - for (settings = session->inflight_settings_head; settings;) { - nghttp2_inflight_settings *next = settings->next; - inflight_settings_del(settings, mem); - settings = next; - } - - nghttp2_stream_free(&session->root); + nghttp2_stream_roots_free(&session->roots); /* Have to free streams first, so that we can check - stream->item->queued */ + stream->data_item->queued */ nghttp2_map_each_free(&session->streams, free_streams, session); nghttp2_map_free(&session->streams); - ob_q_free(&session->ob_urgent, mem); - ob_q_free(&session->ob_reg, mem); - ob_q_free(&session->ob_syn, mem); - - active_outbound_item_reset(&session->aob, mem); + ob_pq_free(&session->ob_pq); + ob_pq_free(&session->ob_ss_pq); + ob_pq_free(&session->ob_da_pq); + active_outbound_item_reset(&session->aob); session_inbound_frame_reset(session); nghttp2_hd_deflate_free(&session->hd_deflater); nghttp2_hd_inflate_free(&session->hd_inflater); nghttp2_bufs_free(&session->aob.framebufs); - nghttp2_mem_free(mem, session); + free(session); } -int nghttp2_session_reprioritize_stream( - nghttp2_session *session, nghttp2_stream *stream, - const nghttp2_priority_spec *pri_spec_in) { +int +nghttp2_session_reprioritize_stream(nghttp2_session *session, + nghttp2_stream *stream, + const nghttp2_priority_spec *pri_spec_in) { int rv; nghttp2_stream *dep_stream = NULL; + nghttp2_stream *root_stream; nghttp2_priority_spec pri_spec_default; const nghttp2_priority_spec *pri_spec = pri_spec_in; - assert(pri_spec->stream_id != stream->stream_id); - if (!nghttp2_stream_in_dep_tree(stream)) { return 0; } + if (pri_spec->stream_id == stream->stream_id) { + return nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, "depend on itself"); + } + if (pri_spec->stream_id != 0) { dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id); - if (!dep_stream && + if (session->server && !dep_stream && session_detect_idle_stream(session, pri_spec->stream_id)) { + nghttp2_session_adjust_closed_stream(session, 1); nghttp2_priority_spec_default_init(&pri_spec_default); - dep_stream = nghttp2_session_open_stream( - session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default, - NGHTTP2_STREAM_IDLE, NULL); + if (nghttp2_session_can_add_closed_stream(session, 1)) { - if (dep_stream == NULL) { - return NGHTTP2_ERR_NOMEM; + dep_stream = nghttp2_session_open_stream( + session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default, + NGHTTP2_STREAM_IDLE, NULL); + + if (dep_stream == NULL) { + return NGHTTP2_ERR_NOMEM; + } + } else { + pri_spec = &pri_spec_default; } } else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) { nghttp2_priority_spec_default_init(&pri_spec_default); @@ -764,27 +580,32 @@ } if (pri_spec->stream_id == 0) { - dep_stream = &session->root; - } else if (nghttp2_stream_dep_find_ancestor(dep_stream, stream)) { - DEBUGF(fprintf(stderr, "stream: cycle detected, dep_stream(%p)=%d " - "stream(%p)=%d\n", - dep_stream, dep_stream->stream_id, stream, - stream->stream_id)); + nghttp2_stream_dep_remove_subtree(stream); - nghttp2_stream_dep_remove_subtree(dep_stream); - rv = nghttp2_stream_dep_add_subtree(&session->root, dep_stream); - if (rv != 0) { - return rv; + /* We have to update weight after removing stream from tree */ + stream->weight = pri_spec->weight; + + if (pri_spec->exclusive && + session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) { + + rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us(stream, session); + } else { + rv = nghttp2_stream_dep_make_root(stream, session); } + + return rv; } assert(dep_stream); - if (dep_stream == stream->dep_prev && !pri_spec->exclusive) { - /* This is minor optimization when just weight is changed. */ - nghttp2_stream_change_weight(stream, pri_spec->weight); + if (nghttp2_stream_dep_subtree_find(stream, dep_stream)) { + DEBUGF(fprintf(stderr, "stream: cycle detected, dep_stream(%p)=%d " + "stream(%p)=%d\n", + dep_stream, dep_stream->stream_id, stream, + stream->stream_id)); - return 0; + nghttp2_stream_dep_remove_subtree(dep_stream); + nghttp2_stream_dep_make_root(dep_stream, session); } nghttp2_stream_dep_remove_subtree(stream); @@ -792,10 +613,19 @@ /* We have to update weight after removing stream from tree */ stream->weight = pri_spec->weight; - if (pri_spec->exclusive) { - rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream); + root_stream = nghttp2_stream_get_dep_root(dep_stream); + + if (root_stream->num_substreams + stream->num_substreams > + NGHTTP2_MAX_DEP_TREE_LENGTH) { + stream->weight = NGHTTP2_DEFAULT_WEIGHT; + + rv = nghttp2_stream_dep_make_root(stream, session); } else { - rv = nghttp2_stream_dep_add_subtree(dep_stream, stream); + if (pri_spec->exclusive) { + rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream, session); + } else { + rv = nghttp2_stream_dep_add_subtree(dep_stream, stream, session); + } } if (rv != 0) { @@ -805,6 +635,17 @@ return 0; } +void nghttp2_session_outbound_item_init(nghttp2_session *session, + nghttp2_outbound_item *item) { + item->seq = session->next_seq++; + /* We use cycle for DATA only */ + item->cycle = 0; + item->weight = NGHTTP2_OB_EX_WEIGHT; + item->queued = 0; + + memset(&item->aux_data, 0, sizeof(nghttp2_aux_data)); +} + int nghttp2_session_add_item(nghttp2_session *session, nghttp2_outbound_item *item) { /* TODO Return error if stream is not found for the frame requiring @@ -819,75 +660,75 @@ if (frame->hd.type != NGHTTP2_DATA) { switch (frame->hd.type) { - case NGHTTP2_HEADERS: - /* We push request HEADERS and push response HEADERS to - dedicated queue because their transmission is affected by - SETTINGS_MAX_CONCURRENT_STREAMS */ - /* TODO If 2 HEADERS are submitted for reserved stream, then - both of them are queued into ob_syn, which is not - desirable. */ - if (frame->headers.cat == NGHTTP2_HCAT_REQUEST || - (stream && stream->state == NGHTTP2_STREAM_RESERVED)) { - nghttp2_outbound_queue_push(&session->ob_syn, item); - item->queued = 1; - break; + case NGHTTP2_RST_STREAM: + if (stream) { + /* We rely on the stream state to decide whether number of + streams should be decremented or not. For purly reserved or + idle streams, they are not counted to those numbers and we + must keep this state in order not to decrement the number. + We don't check against NGHTTP2_STREAM_IDLE because + nghttp2_session_get_stream() does not return such + stream. */ + if (stream->state != NGHTTP2_STREAM_RESERVED) { + stream->state = NGHTTP2_STREAM_CLOSING; + } } - nghttp2_outbound_queue_push(&session->ob_reg, item); - item->queued = 1; break; case NGHTTP2_SETTINGS: + item->weight = NGHTTP2_OB_SETTINGS_WEIGHT; + + break; case NGHTTP2_PING: - nghttp2_outbound_queue_push(&session->ob_urgent, item); - item->queued = 1; + /* Ping has highest priority. */ + item->weight = NGHTTP2_OB_PING_WEIGHT; + break; - case NGHTTP2_RST_STREAM: - if (stream) { - stream->state = NGHTTP2_STREAM_CLOSING; - } - nghttp2_outbound_queue_push(&session->ob_reg, item); - item->queued = 1; + default: break; - case NGHTTP2_PUSH_PROMISE: { - nghttp2_headers_aux_data *aux_data; - nghttp2_priority_spec pri_spec; + } - aux_data = &item->aux_data.headers; + if (frame->hd.type == NGHTTP2_HEADERS) { + /* We push request HEADERS and push response HEADERS to + dedicated queue because their transmission is affected by + SETTINGS_MAX_CONCURRENT_STREAMS */ + /* TODO If 2 HEADERS are submitted for reserved stream, then + both of them are queued into ob_ss_pq, which is not + desirable. */ + if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { + rv = nghttp2_pq_push(&session->ob_ss_pq, item); - if (!stream) { - return NGHTTP2_ERR_STREAM_CLOSED; - } + if (rv != 0) { + return rv; + } - nghttp2_priority_spec_init(&pri_spec, stream->stream_id, - NGHTTP2_DEFAULT_WEIGHT, 0); + item->queued = 1; + } else if (stream && (stream->state == NGHTTP2_STREAM_RESERVED || + item->aux_data.headers.attach_stream)) { + item->weight = stream->effective_weight; + item->cycle = session->last_cycle; - if (!nghttp2_session_open_stream( - session, frame->push_promise.promised_stream_id, - NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_RESERVED, - aux_data->stream_user_data)) { - return NGHTTP2_ERR_NOMEM; - } + rv = nghttp2_stream_attach_data(stream, item, session); - /* We don't have to call nghttp2_session_adjust_closed_stream() - here, since stream->stream_id is local stream_id, and it does - not affect closed stream count. */ + if (rv != 0) { + return rv; + } + } else { + rv = nghttp2_pq_push(&session->ob_pq, item); - nghttp2_outbound_queue_push(&session->ob_reg, item); - item->queued = 1; + if (rv != 0) { + return rv; + } - break; - } - case NGHTTP2_WINDOW_UPDATE: - if (stream) { - stream->window_update_queued = 1; - } else if (frame->hd.stream_id == 0) { - session->window_update_queued = 1; + item->queued = 1; } - nghttp2_outbound_queue_push(&session->ob_reg, item); - item->queued = 1; - break; - default: - nghttp2_outbound_queue_push(&session->ob_reg, item); + } else { + rv = nghttp2_pq_push(&session->ob_pq, item); + + if (rv != 0) { + return rv; + } + item->queued = 1; } @@ -898,11 +739,14 @@ return NGHTTP2_ERR_STREAM_CLOSED; } - if (stream->item) { + if (stream->data_item) { return NGHTTP2_ERR_DATA_EXIST; } - rv = nghttp2_stream_attach_item(stream, item); + item->weight = stream->effective_weight; + item->cycle = session->last_cycle; + + rv = nghttp2_stream_attach_data(stream, item, session); if (rv != 0) { return rv; @@ -917,62 +761,26 @@ nghttp2_outbound_item *item; nghttp2_frame *frame; nghttp2_stream *stream; - nghttp2_mem *mem; - mem = &session->mem; stream = nghttp2_session_get_stream(session, stream_id); if (stream && stream->state == NGHTTP2_STREAM_CLOSING) { return 0; } - /* Cancel pending request HEADERS in ob_syn if this RST_STREAM - refers to that stream. */ - if (!session->server && nghttp2_session_is_my_stream_id(session, stream_id) && - nghttp2_outbound_queue_top(&session->ob_syn)) { - nghttp2_headers_aux_data *aux_data; - nghttp2_frame *headers_frame; - - headers_frame = &nghttp2_outbound_queue_top(&session->ob_syn)->frame; - assert(headers_frame->hd.type == NGHTTP2_HEADERS); - - if (headers_frame->hd.stream_id <= stream_id && - (uint32_t)stream_id < session->next_stream_id) { + item = malloc(sizeof(nghttp2_outbound_item)); + if (item == NULL) { + return NGHTTP2_ERR_NOMEM; + } - for (item = session->ob_syn.head; item; item = item->qnext) { - aux_data = &item->aux_data.headers; + nghttp2_session_outbound_item_init(session, item); - if (item->frame.hd.stream_id < stream_id) { - continue; - } - - /* stream_id in ob_syn queue must be strictly increasing. If - we found larger ID, then we can break here. */ - if (item->frame.hd.stream_id > stream_id || aux_data->canceled) { - break; - } - - aux_data->error_code = error_code; - aux_data->canceled = 1; - - return 0; - } - } - } - - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); - if (item == NULL) { - return NGHTTP2_ERR_NOMEM; - } - - nghttp2_outbound_item_init(item); - - frame = &item->frame; + frame = &item->frame; nghttp2_frame_rst_stream_init(&frame->rst_stream, stream_id, error_code); rv = nghttp2_session_add_item(session, item); if (rv != 0) { nghttp2_frame_rst_stream_free(&frame->rst_stream); - nghttp2_mem_free(mem, item); + free(item); return rv; } return 0; @@ -986,24 +794,28 @@ int rv; nghttp2_stream *stream; nghttp2_stream *dep_stream = NULL; + nghttp2_stream *root_stream; int stream_alloc = 0; nghttp2_priority_spec pri_spec_default; nghttp2_priority_spec *pri_spec = pri_spec_in; - nghttp2_mem *mem; + ssize_t num_adjust_closed = 0; - mem = &session->mem; stream = nghttp2_session_get_stream_raw(session, stream_id); if (stream) { assert(stream->state == NGHTTP2_STREAM_IDLE); assert(nghttp2_stream_in_dep_tree(stream)); - nghttp2_session_detach_idle_stream(session, stream); - rv = nghttp2_stream_dep_remove(stream); - if (rv != 0) { - return NULL; - } + nghttp2_session_detach_closed_stream(session, stream); + nghttp2_stream_dep_remove(stream); } else { - stream = nghttp2_mem_malloc(mem, sizeof(nghttp2_stream)); + if (session->server && + (!nghttp2_session_is_my_stream_id(session, stream_id) || + initial_state == NGHTTP2_STREAM_IDLE)) { + num_adjust_closed = 1; + nghttp2_session_adjust_closed_stream(session, 1); + } + + stream = malloc(sizeof(nghttp2_stream)); if (stream == NULL) { return NULL; } @@ -1014,51 +826,46 @@ if (pri_spec->stream_id != 0) { dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id); - if (!dep_stream && + if (session->server && !dep_stream && session_detect_idle_stream(session, pri_spec->stream_id)) { - /* Depends on idle stream, which does not exist in memory. - Assign default priority for it. */ + ++num_adjust_closed; + nghttp2_session_adjust_closed_stream(session, num_adjust_closed); + nghttp2_priority_spec_default_init(&pri_spec_default); - dep_stream = nghttp2_session_open_stream( - session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default, - NGHTTP2_STREAM_IDLE, NULL); - - if (dep_stream == NULL) { - if (stream_alloc) { - nghttp2_mem_free(mem, stream); - } + if (nghttp2_session_can_add_closed_stream(session, num_adjust_closed)) { - return NULL; + dep_stream = nghttp2_session_open_stream( + session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default, + NGHTTP2_STREAM_IDLE, NULL); + + if (dep_stream == NULL) { + if (stream_alloc) { + free(stream); + } + + return NULL; + } + } else { + pri_spec = &pri_spec_default; } } else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) { /* If dep_stream is not part of dependency tree, stream will get - default priority. This handles the case when - pri_spec->stream_id == stream_id. This happens because we - don't check pri_spec->stream_id against new stream ID in - nghttp2_submit_request. This also handles the case when idle - stream created by PRIORITY frame was opened. Somehow we - first remove the idle stream from dependency tree. This is - done to simplify code base, but ideally we should retain old - dependency. But I'm not sure this adds values. */ + default priority. */ nghttp2_priority_spec_default_init(&pri_spec_default); pri_spec = &pri_spec_default; } } - if (initial_state == NGHTTP2_STREAM_RESERVED) { - flags |= NGHTTP2_STREAM_FLAG_PUSH; - } - - nghttp2_stream_init(stream, stream_id, flags, initial_state, pri_spec->weight, - (int32_t)session->remote_settings.initial_window_size, - (int32_t)session->local_settings.initial_window_size, - stream_user_data, mem); + nghttp2_stream_init( + stream, stream_id, flags, initial_state, pri_spec->weight, + &session->roots, session->remote_settings.initial_window_size, + session->local_settings.initial_window_size, stream_user_data); if (stream_alloc) { rv = nghttp2_map_insert(&session->streams, &stream->map_entry); if (rv != 0) { - nghttp2_mem_free(mem, stream); + free(stream); return NULL; } } @@ -1066,12 +873,11 @@ switch (initial_state) { case NGHTTP2_STREAM_RESERVED: if (nghttp2_session_is_my_stream_id(session, stream_id)) { - /* reserved (local) */ + /* half closed (remote) */ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); } else { - /* reserved (remote) */ + /* half closed (local) */ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); - ++session->num_incoming_reserved_streams; } /* Reserved stream does not count in the concurrent streams limit. That is one of the DOS vector. */ @@ -1079,7 +885,8 @@ case NGHTTP2_STREAM_IDLE: /* Idle stream does not count toward the concurrent streams limit. This is used as anchor node in dependency tree. */ - nghttp2_session_keep_idle_stream(session, stream); + assert(session->server); + nghttp2_session_keep_closed_stream(session, stream); break; default: if (nghttp2_session_is_my_stream_id(session, stream_id)) { @@ -1089,19 +896,47 @@ } } + /* We don't have to track dependency of received reserved stream */ + if (stream->shut_flags & NGHTTP2_SHUT_WR) { + return stream; + } + if (pri_spec->stream_id == 0) { - dep_stream = &session->root; + + ++session->roots.num_streams; + + if (pri_spec->exclusive && + session->roots.num_streams <= NGHTTP2_MAX_DEP_TREE_LENGTH) { + rv = nghttp2_stream_dep_all_your_stream_are_belong_to_us(stream, session); + + /* Since no dpri is changed in dependency tree, the above + function call never fail. */ + assert(rv == 0); + } else { + nghttp2_stream_roots_add(&session->roots, stream); + } + + return stream; } + /* TODO Client does not have to track dependencies of streams except + for those which have upload data. Currently, we just track + everything. */ + assert(dep_stream); - if (pri_spec->exclusive) { - rv = nghttp2_stream_dep_insert(dep_stream, stream); - if (rv != 0) { - return NULL; + root_stream = nghttp2_stream_get_dep_root(dep_stream); + + if (root_stream->num_substreams < NGHTTP2_MAX_DEP_TREE_LENGTH) { + if (pri_spec->exclusive) { + nghttp2_stream_dep_insert(dep_stream, stream); + } else { + nghttp2_stream_dep_add(dep_stream, stream); } } else { - nghttp2_stream_dep_add(dep_stream, stream); + stream->weight = NGHTTP2_DEFAULT_WEIGHT; + + nghttp2_stream_roots_add(&session->roots, stream); } return stream; @@ -1111,10 +946,7 @@ uint32_t error_code) { int rv; nghttp2_stream *stream; - nghttp2_mem *mem; - int is_my_stream_id; - mem = &session->mem; stream = nghttp2_session_get_stream(session, stream_id); if (!stream) { @@ -1124,12 +956,12 @@ DEBUGF(fprintf(stderr, "stream: stream(%p)=%d close\n", stream, stream->stream_id)); - if (stream->item) { + if (stream->data_item) { nghttp2_outbound_item *item; - item = stream->item; + item = stream->data_item; - rv = nghttp2_stream_detach_item(stream); + rv = nghttp2_stream_detach_data(stream, session); if (rv != 0) { return rv; @@ -1140,8 +972,8 @@ points to this item, let active_outbound_item_reset() free the item. */ if (!item->queued && item != session->aob.item) { - nghttp2_outbound_item_free(item, mem); - nghttp2_mem_free(mem, item); + nghttp2_outbound_item_free(item); + free(item); } } @@ -1152,7 +984,8 @@ hang the stream in a local endpoint. */ - if (session->callbacks.on_stream_close_callback) { + if (stream->state != NGHTTP2_STREAM_IDLE && + session->callbacks.on_stream_close_callback) { if (session->callbacks.on_stream_close_callback( session, stream_id, error_code, session->user_data) != 0) { @@ -1160,16 +993,12 @@ } } - is_my_stream_id = nghttp2_session_is_my_stream_id(session, stream_id); - - /* pushed streams which is not opened yet is not counted toward max - concurrent limits */ - if ((stream->flags & NGHTTP2_STREAM_FLAG_PUSH)) { - if (!is_my_stream_id) { - --session->num_incoming_reserved_streams; - } - } else { - if (is_my_stream_id) { + switch (stream->state) { + case NGHTTP2_STREAM_RESERVED: + case NGHTTP2_STREAM_IDLE: + break; + default: + if (nghttp2_session_is_my_stream_id(session, stream_id)) { --session->num_outgoing_streams; } else { --session->num_incoming_streams; @@ -1179,46 +1008,28 @@ /* Closes both directions just in case they are not closed yet */ stream->flags |= NGHTTP2_STREAM_FLAG_CLOSED; - if (session->server && !is_my_stream_id && - nghttp2_stream_in_dep_tree(stream)) { + if (session->server && nghttp2_stream_in_dep_tree(stream)) { /* On server side, retain stream at most MAX_CONCURRENT_STREAMS combined with the current active incoming streams to make dependency tree work better. */ nghttp2_session_keep_closed_stream(session, stream); - - rv = nghttp2_session_adjust_closed_stream(session); } else { - rv = nghttp2_session_destroy_stream(session, stream); - } - if (rv != 0) { - return rv; + nghttp2_session_destroy_stream(session, stream); } return 0; } -int nghttp2_session_destroy_stream(nghttp2_session *session, - nghttp2_stream *stream) { - nghttp2_mem *mem; - int rv; - +void nghttp2_session_destroy_stream(nghttp2_session *session, + nghttp2_stream *stream) { DEBUGF(fprintf(stderr, "stream: destroy closed stream(%p)=%d\n", stream, stream->stream_id)); - mem = &session->mem; - - if (nghttp2_stream_in_dep_tree(stream)) { - rv = nghttp2_stream_dep_remove(stream); - if (rv != 0) { - return rv; - } - } + nghttp2_stream_dep_remove(stream); nghttp2_map_remove(&session->streams, stream->stream_id); nghttp2_stream_free(stream); - nghttp2_mem_free(mem, stream); - - return 0; + free(stream); } void nghttp2_session_keep_closed_stream(nghttp2_session *session, @@ -1235,29 +1046,15 @@ session->closed_stream_tail = stream; ++session->num_closed_streams; -} - -void nghttp2_session_keep_idle_stream(nghttp2_session *session, - nghttp2_stream *stream) { - DEBUGF(fprintf(stderr, "stream: keep idle stream(%p)=%d, state=%d\n", stream, - stream->stream_id, stream->state)); - - if (session->idle_stream_tail) { - session->idle_stream_tail->closed_next = stream; - stream->closed_prev = session->idle_stream_tail; - } else { - session->idle_stream_head = stream; - } - session->idle_stream_tail = stream; - ++session->num_idle_streams; + nghttp2_session_adjust_closed_stream(session, 0); } -void nghttp2_session_detach_idle_stream(nghttp2_session *session, - nghttp2_stream *stream) { +void nghttp2_session_detach_closed_stream(nghttp2_session *session, + nghttp2_stream *stream) { nghttp2_stream *prev_stream, *next_stream; - DEBUGF(fprintf(stderr, "stream: detach idle stream(%p)=%d, state=%d\n", + DEBUGF(fprintf(stderr, "stream: detach closed stream(%p)=%d, state=%d\n", stream, stream->stream_id, stream->state)); prev_stream = stream->closed_prev; @@ -1266,24 +1063,34 @@ if (prev_stream) { prev_stream->closed_next = next_stream; } else { - session->idle_stream_head = next_stream; + session->closed_stream_head = next_stream; } if (next_stream) { next_stream->closed_prev = prev_stream; } else { - session->idle_stream_tail = prev_stream; + session->closed_stream_tail = prev_stream; } stream->closed_prev = NULL; stream->closed_next = NULL; - --session->num_idle_streams; + --session->num_closed_streams; } -int nghttp2_session_adjust_closed_stream(nghttp2_session *session) { +int nghttp2_session_can_add_closed_stream(nghttp2_session *session, + ssize_t offset) { + size_t num_stream_max; + + num_stream_max = nghttp2_min(session->local_settings.max_concurrent_streams, + session->pending_local_max_concurrent_stream); + + return offset + session->num_incoming_streams <= num_stream_max; +} + +void nghttp2_session_adjust_closed_stream(nghttp2_session *session, + ssize_t offset) { size_t num_stream_max; - int rv; num_stream_max = nghttp2_min(session->local_settings.max_concurrent_streams, session->pending_local_max_concurrent_stream); @@ -1295,25 +1102,15 @@ num_stream_max)); while (session->num_closed_streams > 0 && - session->num_closed_streams + session->num_incoming_streams > + session->num_closed_streams + session->num_incoming_streams + offset > num_stream_max) { nghttp2_stream *head_stream; - nghttp2_stream *next; head_stream = session->closed_stream_head; assert(head_stream); - next = head_stream->closed_next; - - rv = nghttp2_session_destroy_stream(session, head_stream); - if (rv != 0) { - return rv; - } - - /* head_stream is now freed */ - - session->closed_stream_head = next; + session->closed_stream_head = head_stream->closed_next; if (session->closed_stream_head) { session->closed_stream_head->closed_prev = NULL; @@ -1321,55 +1118,10 @@ session->closed_stream_tail = NULL; } + nghttp2_session_destroy_stream(session, head_stream); + /* head_stream is now freed */ --session->num_closed_streams; } - - return 0; -} - -int nghttp2_session_adjust_idle_stream(nghttp2_session *session) { - size_t max; - int rv; - - /* Make minimum number of idle streams 16, and maximum 100, which - are arbitrary chosen numbers. */ - max = nghttp2_min( - 100, nghttp2_max( - 16, nghttp2_min(session->local_settings.max_concurrent_streams, - session->pending_local_max_concurrent_stream))); - - DEBUGF(fprintf(stderr, "stream: adjusting kept idle streams " - "num_idle_streams=%zu, max=%zu\n", - session->num_idle_streams, max)); - - while (session->num_idle_streams > max) { - nghttp2_stream *head; - nghttp2_stream *next; - - head = session->idle_stream_head; - assert(head); - - next = head->closed_next; - - rv = nghttp2_session_destroy_stream(session, head); - if (rv != 0) { - return rv; - } - - /* head is now destroyed */ - - session->idle_stream_head = next; - - if (session->idle_stream_head) { - session->idle_stream_head->closed_prev = NULL; - } else { - session->idle_stream_tail = NULL; - } - - --session->num_idle_streams; - } - - return 0; } /* @@ -1395,24 +1147,6 @@ } /* - * Returns nonzero if local endpoint allows reception of new stream - * from remote. - */ -static int session_allow_incoming_new_stream(nghttp2_session *session) { - return (session->goaway_flags & - (NGHTTP2_GOAWAY_TERM_ON_SEND | NGHTTP2_GOAWAY_SENT)) == 0; -} - -/* - * This function returns nonzero if session is closing. - */ -static int session_is_closing(nghttp2_session *session) { - return (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) != 0 || - (nghttp2_session_want_read(session) == 0 && - nghttp2_session_want_write(session) == 0); -} - -/* * Check that we can send a frame to the |stream|. This function * returns 0 if we can send a frame to the |frame|, or one of the * following negative error codes: @@ -1421,31 +1155,19 @@ * The stream is already closed. * NGHTTP2_ERR_STREAM_SHUT_WR * The stream is half-closed for transmission. - * NGHTTP2_ERR_SESSION_CLOSING - * This session is closing. */ -static int session_predicate_for_stream_send(nghttp2_session *session, - nghttp2_stream *stream) { +static int stream_predicate_for_send(nghttp2_stream *stream) { if (stream == NULL) { return NGHTTP2_ERR_STREAM_CLOSED; } - if (session_is_closing(session)) { - return NGHTTP2_ERR_SESSION_CLOSING; - } if (stream->shut_flags & NGHTTP2_SHUT_WR) { return NGHTTP2_ERR_STREAM_SHUT_WR; } return 0; } -int nghttp2_session_check_request_allowed(nghttp2_session *session) { - return !session->server && session->next_stream_id <= INT32_MAX && - (session->goaway_flags & NGHTTP2_GOAWAY_RECV) == 0 && - !session_is_closing(session); -} - /* - * This function checks request HEADERS frame, which opens stream, can + * This function checks HEADERS frame |frame|, which opens stream, can * be sent at this time. * * This function returns 0 if it succeeds, or one of the following @@ -1455,19 +1177,14 @@ * New stream cannot be created because of GOAWAY: session is * going down or received last_stream_id is strictly less than * frame->hd.stream_id. - * NGHTTP2_ERR_STREAM_CLOSING - * request HEADERS was canceled by RST_STREAM while it is in queue. */ static int session_predicate_request_headers_send(nghttp2_session *session, - nghttp2_outbound_item *item) { - if (item->aux_data.headers.canceled) { - return NGHTTP2_ERR_STREAM_CLOSING; - } - /* If we are terminating session (NGHTTP2_GOAWAY_TERM_ON_SEND), - GOAWAY was received from peer, or session is about to close, new - request is not allowed. */ - if ((session->goaway_flags & NGHTTP2_GOAWAY_RECV) || - session_is_closing(session)) { + nghttp2_headers *frame) { + /* If we are terminating session (session->goaway_flag is nonzero), + we don't send new request. Also if received last_stream_id is + strictly less than new stream ID, cancel its transmission. */ + if (session->goaway_flags || + session->remote_last_stream_id < frame->hd.stream_id) { return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED; } return 0; @@ -1492,22 +1209,15 @@ * RST_STREAM was queued for this stream. * NGHTTP2_ERR_INVALID_STREAM_STATE * The state of the stream is not valid. - * NGHTTP2_ERR_SESSION_CLOSING - * This session is closing. - * NGHTTP2_ERR_PROTO - * Client side attempted to send response. */ static int session_predicate_response_headers_send(nghttp2_session *session, nghttp2_stream *stream) { int rv; - rv = session_predicate_for_stream_send(session, stream); + rv = stream_predicate_for_send(stream); if (rv != 0) { return rv; } assert(stream); - if (!session->server) { - return NGHTTP2_ERR_PROTO; - } if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) { return NGHTTP2_ERR_INVALID_STREAM_ID; } @@ -1536,42 +1246,28 @@ * The stream is not reserved state * NGHTTP2_ERR_STREAM_CLOSED * RST_STREAM was queued for this stream. - * NGHTTP2_ERR_SESSION_CLOSING - * This session is closing. - * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED - * New stream cannot be created because GOAWAY is already sent or - * received. - * NGHTTP2_ERR_PROTO - * Client side attempted to send push response. */ static int -session_predicate_push_response_headers_send(nghttp2_session *session, +session_predicate_push_response_headers_send(nghttp2_session *session _U_, nghttp2_stream *stream) { int rv; /* TODO Should disallow HEADERS if GOAWAY has already been issued? */ - rv = session_predicate_for_stream_send(session, stream); + rv = stream_predicate_for_send(stream); if (rv != 0) { return rv; } assert(stream); - if (!session->server) { - return NGHTTP2_ERR_PROTO; - } if (stream->state != NGHTTP2_STREAM_RESERVED) { return NGHTTP2_ERR_PROTO; } if (stream->state == NGHTTP2_STREAM_CLOSING) { return NGHTTP2_ERR_STREAM_CLOSING; } - if (session->goaway_flags & NGHTTP2_GOAWAY_RECV) { - return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED; - } return 0; } /* - * This function checks HEADERS, which is neither stream-opening nor - * first response header, with the |stream| can be sent at this time. + * This function checks frames belongs to the |stream| can be sent. * The |stream| can be NULL. * * This function returns 0 if it succeeds, or one of the following @@ -1586,13 +1282,11 @@ * RST_STREAM was queued for this stream. * NGHTTP2_ERR_INVALID_STREAM_STATE * The state of the stream is not valid. - * NGHTTP2_ERR_SESSION_CLOSING - * This session is closing. */ -static int session_predicate_headers_send(nghttp2_session *session, - nghttp2_stream *stream) { +static int session_predicate_stream_frame_send(nghttp2_session *session, + nghttp2_stream *stream) { int rv; - rv = session_predicate_for_stream_send(session, stream); + rv = stream_predicate_for_send(stream); if (rv != 0) { return rv; } @@ -1613,6 +1307,16 @@ } /* + * This function checks HEADERS, which is neither stream-opening nor + * first response header, with the |stream| can be sent at this time. + * The |stream| can be NULL. + */ +static int session_predicate_headers_send(nghttp2_session *session, + nghttp2_stream *stream) { + return session_predicate_stream_frame_send(session, stream); +} + +/* * This function checks PUSH_PROMISE frame |frame| with the |stream| * can be sent at this time. The |stream| can be NULL. * @@ -1634,18 +1338,17 @@ * with END_STREAM flag set has already sent) * NGHTTP2_ERR_PUSH_DISABLED * The remote peer disabled reception of PUSH_PROMISE. - * NGHTTP2_ERR_SESSION_CLOSING - * This session is closing. */ static int session_predicate_push_promise_send(nghttp2_session *session, - nghttp2_stream *stream) { + nghttp2_stream *stream, + int32_t promised_stream_id) { int rv; if (!session->server) { return NGHTTP2_ERR_PROTO; } - rv = session_predicate_for_stream_send(session, stream); + rv = stream_predicate_for_send(stream); if (rv != 0) { return rv; } @@ -1658,7 +1361,7 @@ if (stream->state == NGHTTP2_STREAM_CLOSING) { return NGHTTP2_ERR_STREAM_CLOSING; } - if (session->goaway_flags & NGHTTP2_GOAWAY_RECV) { + if (session->remote_last_stream_id < promised_stream_id) { return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED; } return 0; @@ -1678,17 +1381,10 @@ * RST_STREAM was queued for this stream. * NGHTTP2_ERR_INVALID_STREAM_STATE * The state of the stream is not valid. - * NGHTTP2_ERR_SESSION_CLOSING - * This session is closing. */ static int session_predicate_window_update_send(nghttp2_session *session, int32_t stream_id) { nghttp2_stream *stream; - - if (session_is_closing(session)) { - return NGHTTP2_ERR_SESSION_CLOSING; - } - if (stream_id == 0) { /* Connection-level window update */ return 0; @@ -1706,22 +1402,33 @@ return 0; } +/* + * This function checks ALTSVC with the stream ID |stream_id| can be + * sent at this time. If |stream_id| is 0, ATLSVC frame is always + * allowed to send. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_STREAM_CLOSED + * The stream is already closed or does not exist. + * NGHTTP2_ERR_STREAM_CLOSING + * RST_STREAM was queued for this stream. + */ static int session_predicate_altsvc_send(nghttp2_session *session, int32_t stream_id) { nghttp2_stream *stream; - if (session_is_closing(session)) { - return NGHTTP2_ERR_SESSION_CLOSING; - } - if (stream_id == 0) { return 0; } stream = nghttp2_session_get_stream(session, stream_id); + if (stream == NULL) { return NGHTTP2_ERR_STREAM_CLOSED; } + if (stream->state == NGHTTP2_STREAM_CLOSING) { return NGHTTP2_ERR_STREAM_CLOSING; } @@ -1729,6 +1436,16 @@ return 0; } +/* + * This function checks SETTINGS can be sent at this time. + * + * Currently this function always returns 0. + */ +static int nghttp2_session_predicate_settings_send(nghttp2_session *session _U_, + nghttp2_frame *frame _U_) { + return 0; +} + /* Take into account settings max frame size and both connection-level flow control here */ static ssize_t @@ -1781,13 +1498,11 @@ * RST_STREAM was queued for this stream. * NGHTTP2_ERR_INVALID_STREAM_STATE * The state of the stream is not valid. - * NGHTTP2_ERR_SESSION_CLOSING - * This session is closing. */ static int nghttp2_session_predicate_data_send(nghttp2_session *session, nghttp2_stream *stream) { int rv; - rv = session_predicate_for_stream_send(session, stream); + rv = stream_predicate_for_send(stream); if (rv != 0) { return rv; } @@ -1821,7 +1536,7 @@ ssize_t rv; if (frame->hd.length >= max_payloadlen) { - return (ssize_t)frame->hd.length; + return frame->hd.length; } if (session->callbacks.select_padding_callback) { @@ -1837,7 +1552,7 @@ } return rv; } - return (ssize_t)frame->hd.length; + return frame->hd.length; } /* Add padding to HEADERS or PUSH_PROMISE. We use @@ -1865,12 +1580,12 @@ return (int)padded_payloadlen; } - padlen = (size_t)padded_payloadlen - frame->hd.length; + padlen = padded_payloadlen - frame->hd.length; DEBUGF(fprintf(stderr, "send: padding selected: payloadlen=%zd, padlen=%zu\n", padded_payloadlen, padlen)); - rv = nghttp2_frame_add_pad(framebufs, &frame->hd, padlen, 0); + rv = nghttp2_frame_add_pad(framebufs, &frame->hd, padlen); if (rv != 0) { return rv; @@ -1889,41 +1604,6 @@ additional; } -static int session_pack_extension(nghttp2_session *session, nghttp2_bufs *bufs, - nghttp2_frame *frame) { - ssize_t rv; - nghttp2_buf *buf; - size_t buflen; - size_t framelen; - - assert(session->callbacks.pack_extension_callback); - - buf = &bufs->head->buf; - buflen = nghttp2_min(nghttp2_buf_avail(buf), NGHTTP2_MAX_PAYLOADLEN); - - rv = session->callbacks.pack_extension_callback(session, buf->last, buflen, - frame, session->user_data); - if (rv == NGHTTP2_ERR_CANCEL) { - return (int)rv; - } - - if (rv < 0 || (size_t)rv > buflen) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - - framelen = (size_t)rv; - - frame->hd.length = framelen; - - assert(buf->pos == buf->last); - buf->last += framelen; - buf->pos -= NGHTTP2_FRAME_HDLEN; - - nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); - - return 0; -} - /* * This function serializes frame for transmission. * @@ -1932,11 +1612,10 @@ */ static int session_prep_frame(nghttp2_session *session, nghttp2_outbound_item *item) { + int framerv = 0; int rv; nghttp2_frame *frame; - nghttp2_mem *mem; - mem = &session->mem; frame = &item->frame; if (frame->hd.type != NGHTTP2_DATA) { @@ -1947,10 +1626,23 @@ aux_data = &item->aux_data.headers; + estimated_payloadlen = session_estimate_headers_payload( + session, frame->headers.nva, frame->headers.nvlen, + NGHTTP2_PRIORITY_SPECLEN); + + if (estimated_payloadlen > NGHTTP2_MAX_HEADERSLEN) { + return NGHTTP2_ERR_FRAME_SIZE_ERROR; + } + if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { - /* initial HEADERS, which opens stream */ nghttp2_stream *stream; + /* initial HEADERS, which opens stream */ + rv = session_predicate_request_headers_send(session, &frame->headers); + if (rv != 0) { + return rv; + } + stream = nghttp2_session_open_stream( session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE, &frame->headers.pri_spec, NGHTTP2_STREAM_INITIAL, @@ -1960,110 +1652,86 @@ return NGHTTP2_ERR_NOMEM; } - /* We don't call nghttp2_session_adjust_closed_stream() here, - since we don't keep closed stream in client side */ - - estimated_payloadlen = session_estimate_headers_payload( - session, frame->headers.nva, frame->headers.nvlen, - NGHTTP2_PRIORITY_SPECLEN); - - if (estimated_payloadlen > session->max_send_header_block_length) { - return NGHTTP2_ERR_FRAME_SIZE_ERROR; - } - - rv = session_predicate_request_headers_send(session, item); - if (rv != 0) { - return rv; - } - - if (session_enforce_http_messaging(session)) { - nghttp2_http_record_request_method(stream, frame); - } } else { nghttp2_stream *stream; - estimated_payloadlen = session_estimate_headers_payload( - session, frame->headers.nva, frame->headers.nvlen, - NGHTTP2_PRIORITY_SPECLEN); - - if (estimated_payloadlen > session->max_send_header_block_length) { - return NGHTTP2_ERR_FRAME_SIZE_ERROR; - } - stream = nghttp2_session_get_stream(session, frame->hd.stream_id); - if (stream && stream->state == NGHTTP2_STREAM_RESERVED) { - rv = session_predicate_push_response_headers_send(session, stream); - if (rv == 0) { - frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE; + if (session_predicate_push_response_headers_send(session, stream) == + 0) { + frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE; - if (aux_data->stream_user_data) { - stream->stream_user_data = aux_data->stream_user_data; - } + if (aux_data->stream_user_data) { + stream->stream_user_data = aux_data->stream_user_data; } } else if (session_predicate_response_headers_send(session, stream) == 0) { frame->headers.cat = NGHTTP2_HCAT_RESPONSE; - rv = 0; } else { frame->headers.cat = NGHTTP2_HCAT_HEADERS; rv = session_predicate_headers_send(session, stream); - } - if (rv != 0) { - // If stream was already closed, nghttp2_session_get_stream() - // returns NULL, but item is still attached to the stream. - // Search stream including closed again. - stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); - if (stream && stream->item == item) { - int rv2; + if (rv != 0) { + if (stream && stream->data_item == item) { + int rv2; - rv2 = nghttp2_stream_detach_item(stream); + rv2 = nghttp2_stream_detach_data(stream, session); - if (nghttp2_is_fatal(rv2)) { - return rv2; + if (nghttp2_is_fatal(rv2)) { + return rv2; + } } - } - return rv; + return rv; + } } } - rv = nghttp2_frame_pack_headers(&session->aob.framebufs, &frame->headers, - &session->hd_deflater); + framerv = nghttp2_frame_pack_headers( + &session->aob.framebufs, &frame->headers, &session->hd_deflater); - if (rv != 0) { - return rv; + if (framerv < 0) { + goto close_stream_return; } DEBUGF(fprintf(stderr, "send: before padding, HEADERS serialized in %zd bytes\n", nghttp2_bufs_len(&session->aob.framebufs))); - rv = session_headers_add_pad(session, frame); + framerv = session_headers_add_pad(session, frame); - if (rv != 0) { - return rv; + if (framerv < 0) { + goto close_stream_return; } DEBUGF(fprintf(stderr, "send: HEADERS finally serialized in %zd bytes\n", nghttp2_bufs_len(&session->aob.framebufs))); - if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { - assert(session->last_sent_stream_id < frame->hd.stream_id); - session->last_sent_stream_id = frame->hd.stream_id; + break; + + close_stream_return: + + if (frame->headers.cat == NGHTTP2_HCAT_REQUEST && + !nghttp2_is_fatal(framerv)) { + rv = nghttp2_session_close_stream(session, frame->hd.stream_id, + NGHTTP2_NO_ERROR); + + if (nghttp2_is_fatal(rv)) { + return rv; + } } - break; + return framerv; } case NGHTTP2_PRIORITY: { - if (session_is_closing(session)) { - return NGHTTP2_ERR_SESSION_CLOSING; - } /* PRIORITY frame can be sent at any time and to any stream ID. */ - nghttp2_frame_pack_priority(&session->aob.framebufs, &frame->priority); + framerv = nghttp2_frame_pack_priority(&session->aob.framebufs, + &frame->priority); + if (framerv < 0) { + return framerv; + } /* Peer can send PRIORITY frame against idle stream to create "anchor" in dependency tree. Only client can do this in @@ -2072,140 +1740,114 @@ break; } case NGHTTP2_RST_STREAM: - if (session_is_closing(session)) { - return NGHTTP2_ERR_SESSION_CLOSING; + framerv = nghttp2_frame_pack_rst_stream(&session->aob.framebufs, + &frame->rst_stream); + if (framerv < 0) { + return framerv; } - nghttp2_frame_pack_rst_stream(&session->aob.framebufs, - &frame->rst_stream); break; case NGHTTP2_SETTINGS: { - if (frame->hd.flags & NGHTTP2_FLAG_ACK) { - assert(session->obq_flood_counter_ > 0); - --session->obq_flood_counter_; - /* When session is about to close, don't send SETTINGS ACK. - We are required to send SETTINGS without ACK though; for - example, we have to send SETTINGS as a part of connection - preface. */ - if (session_is_closing(session)) { - return NGHTTP2_ERR_SESSION_CLOSING; - } - } - - rv = nghttp2_frame_pack_settings(&session->aob.framebufs, - &frame->settings); + rv = nghttp2_session_predicate_settings_send(session, frame); if (rv != 0) { return rv; } + framerv = nghttp2_frame_pack_settings(&session->aob.framebufs, + &frame->settings); + if (framerv < 0) { + return framerv; + } break; } case NGHTTP2_PUSH_PROMISE: { nghttp2_stream *stream; + nghttp2_headers_aux_data *aux_data; + nghttp2_priority_spec pri_spec; size_t estimated_payloadlen; + aux_data = &item->aux_data.headers; + estimated_payloadlen = session_estimate_headers_payload( session, frame->push_promise.nva, frame->push_promise.nvlen, 0); - if (estimated_payloadlen > session->max_send_header_block_length) { + if (estimated_payloadlen > NGHTTP2_MAX_HEADERSLEN) { return NGHTTP2_ERR_FRAME_SIZE_ERROR; } - /* stream could be NULL if associated stream was already - closed. */ stream = nghttp2_session_get_stream(session, frame->hd.stream_id); - /* predicte should fail if stream is NULL. */ - rv = session_predicate_push_promise_send(session, stream); + rv = session_predicate_push_promise_send( + session, stream, frame->push_promise.promised_stream_id); if (rv != 0) { return rv; } assert(stream); - rv = nghttp2_frame_pack_push_promise( + framerv = nghttp2_frame_pack_push_promise( &session->aob.framebufs, &frame->push_promise, &session->hd_deflater); - if (rv != 0) { - return rv; + if (framerv < 0) { + return framerv; } - rv = session_headers_add_pad(session, frame); - if (rv != 0) { - return rv; + framerv = session_headers_add_pad(session, frame); + if (framerv < 0) { + return framerv; } - assert(session->last_sent_stream_id + 2 <= - frame->push_promise.promised_stream_id); - session->last_sent_stream_id = frame->push_promise.promised_stream_id; + /* TODO It is unclear reserved stream dpeneds on associated + stream with or without exclusive flag set */ + nghttp2_priority_spec_init(&pri_spec, stream->stream_id, + NGHTTP2_DEFAULT_WEIGHT, 0); + if (!nghttp2_session_open_stream( + session, frame->push_promise.promised_stream_id, + NGHTTP2_STREAM_FLAG_PUSH, &pri_spec, NGHTTP2_STREAM_RESERVED, + aux_data->stream_user_data)) { + return NGHTTP2_ERR_NOMEM; + } break; } case NGHTTP2_PING: - if (frame->hd.flags & NGHTTP2_FLAG_ACK) { - assert(session->obq_flood_counter_ > 0); - --session->obq_flood_counter_; - } - - if (session_is_closing(session)) { - return NGHTTP2_ERR_SESSION_CLOSING; + framerv = nghttp2_frame_pack_ping(&session->aob.framebufs, &frame->ping); + if (framerv < 0) { + return framerv; } - nghttp2_frame_pack_ping(&session->aob.framebufs, &frame->ping); break; - case NGHTTP2_GOAWAY: - rv = nghttp2_frame_pack_goaway(&session->aob.framebufs, &frame->goaway); + case NGHTTP2_WINDOW_UPDATE: { + rv = session_predicate_window_update_send(session, frame->hd.stream_id); if (rv != 0) { return rv; } + framerv = nghttp2_frame_pack_window_update(&session->aob.framebufs, + &frame->window_update); + if (framerv < 0) { + return framerv; + } + break; + } + case NGHTTP2_GOAWAY: + framerv = + nghttp2_frame_pack_goaway(&session->aob.framebufs, &frame->goaway); + if (framerv < 0) { + return framerv; + } session->local_last_stream_id = frame->goaway.last_stream_id; break; - case NGHTTP2_WINDOW_UPDATE: - rv = session_predicate_window_update_send(session, frame->hd.stream_id); + case NGHTTP2_EXT_ALTSVC: + rv = session_predicate_altsvc_send(session, frame->hd.stream_id); if (rv != 0) { return rv; } - nghttp2_frame_pack_window_update(&session->aob.framebufs, - &frame->window_update); - break; - case NGHTTP2_CONTINUATION: - /* We never handle CONTINUATION here. */ - assert(0); - break; - default: { - nghttp2_ext_aux_data *aux_data; - - /* extension frame */ - - aux_data = &item->aux_data.ext; - - if (aux_data->builtin == 0) { - if (session_is_closing(session)) { - return NGHTTP2_ERR_SESSION_CLOSING; - } - - rv = session_pack_extension(session, &session->aob.framebufs, frame); - if (rv != 0) { - return rv; - } - - break; - } - - switch (frame->hd.type) { - case NGHTTP2_ALTSVC: - rv = session_predicate_altsvc_send(session, frame->hd.stream_id); - if (rv != 0) { - return rv; - } - nghttp2_frame_pack_altsvc(&session->aob.framebufs, &frame->ext); + framerv = nghttp2_frame_pack_altsvc(&session->aob.framebufs, &frame->ext); - break; - default: - /* Unreachable here */ - assert(0); - break; + if (framerv < 0) { + return framerv; } break; - } + default: + return NGHTTP2_ERR_INVALID_ARGUMENT; } return 0; } else { @@ -2215,19 +1857,15 @@ stream = nghttp2_session_get_stream(session, frame->hd.stream_id); if (stream) { - assert(stream->item == item); + assert(stream->data_item == item); } rv = nghttp2_session_predicate_data_send(session, stream); if (rv != 0) { - // If stream was already closed, nghttp2_session_get_stream() - // returns NULL, but item is still attached to the stream. - // Search stream including closed again. - stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); if (stream) { int rv2; - rv2 = nghttp2_stream_detach_item(stream); + rv2 = nghttp2_stream_detach_data(stream, session); if (nghttp2_is_fatal(rv2)) { return rv2; @@ -2246,34 +1884,35 @@ queue when session->remote_window_size > 0 */ assert(session->remote_window_size > 0); - rv = nghttp2_stream_defer_item(stream, - NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); + rv = nghttp2_stream_defer_data( + stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, session); if (nghttp2_is_fatal(rv)) { return rv; } session->aob.item = NULL; - active_outbound_item_reset(&session->aob, mem); + active_outbound_item_reset(&session->aob); return NGHTTP2_ERR_DEFERRED; } - rv = nghttp2_session_pack_data(session, &session->aob.framebufs, - next_readmax, frame, &item->aux_data.data, - stream); - if (rv == NGHTTP2_ERR_DEFERRED) { - rv = nghttp2_stream_defer_item(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER); + framerv = + nghttp2_session_pack_data(session, &session->aob.framebufs, + next_readmax, frame, &item->aux_data.data); + if (framerv == NGHTTP2_ERR_DEFERRED) { + rv = nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER, + session); if (nghttp2_is_fatal(rv)) { return rv; } session->aob.item = NULL; - active_outbound_item_reset(&session->aob, mem); + active_outbound_item_reset(&session->aob); return NGHTTP2_ERR_DEFERRED; } - if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_stream_detach_item(stream); + if (framerv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + rv = nghttp2_stream_detach_data(stream, session); if (nghttp2_is_fatal(rv)) { return rv; @@ -2281,81 +1920,143 @@ rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id, NGHTTP2_INTERNAL_ERROR); - if (nghttp2_is_fatal(rv)) { + if (rv != 0) { return rv; } - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + return framerv; } - if (rv != 0) { - int rv2; + if (framerv < 0) { + rv = nghttp2_stream_detach_data(stream, session); - rv2 = nghttp2_stream_detach_item(stream); - - if (nghttp2_is_fatal(rv2)) { - return rv2; + if (nghttp2_is_fatal(rv)) { + return rv; } - return rv; + return framerv; } return 0; } } +/* Used only for tests */ +nghttp2_outbound_item *nghttp2_session_get_ob_pq_top(nghttp2_session *session) { + return (nghttp2_outbound_item *)nghttp2_pq_top(&session->ob_pq); +} + nghttp2_outbound_item * nghttp2_session_get_next_ob_item(nghttp2_session *session) { - if (nghttp2_outbound_queue_top(&session->ob_urgent)) { - return nghttp2_outbound_queue_top(&session->ob_urgent); - } + nghttp2_outbound_item *item, *headers_item; - if (nghttp2_outbound_queue_top(&session->ob_reg)) { - return nghttp2_outbound_queue_top(&session->ob_reg); - } + if (nghttp2_pq_empty(&session->ob_pq)) { + if (nghttp2_pq_empty(&session->ob_ss_pq)) { + if (session->remote_window_size == 0 || + nghttp2_pq_empty(&session->ob_da_pq)) { + return NULL; + } + + return nghttp2_pq_top(&session->ob_da_pq); + } + + /* Return item only when concurrent connection limit is not + reached */ + if (session_is_outgoing_concurrent_streams_max(session)) { + if (session->remote_window_size == 0 || + nghttp2_pq_empty(&session->ob_da_pq)) { + return NULL; + } - if (!session_is_outgoing_concurrent_streams_max(session)) { - if (nghttp2_outbound_queue_top(&session->ob_syn)) { - return nghttp2_outbound_queue_top(&session->ob_syn); + return nghttp2_pq_top(&session->ob_da_pq); } + + return nghttp2_pq_top(&session->ob_ss_pq); + } + + if (nghttp2_pq_empty(&session->ob_ss_pq)) { + return nghttp2_pq_top(&session->ob_pq); } - if (session->remote_window_size > 0) { - return nghttp2_stream_next_outbound_item(&session->root); + item = nghttp2_pq_top(&session->ob_pq); + headers_item = nghttp2_pq_top(&session->ob_ss_pq); + + if (session_is_outgoing_concurrent_streams_max(session) || + item->weight > headers_item->weight || + (item->weight == headers_item->weight && item->seq < headers_item->seq)) { + return item; } - return NULL; + return headers_item; } nghttp2_outbound_item * nghttp2_session_pop_next_ob_item(nghttp2_session *session) { - nghttp2_outbound_item *item; + nghttp2_outbound_item *item, *headers_item; + + if (nghttp2_pq_empty(&session->ob_pq)) { + if (nghttp2_pq_empty(&session->ob_ss_pq)) { + if (session->remote_window_size == 0 || + nghttp2_pq_empty(&session->ob_da_pq)) { + return NULL; + } + + item = nghttp2_pq_top(&session->ob_da_pq); + nghttp2_pq_pop(&session->ob_da_pq); + + item->queued = 0; + + return item; + } + + /* Pop item only when concurrent connection limit is not + reached */ + if (session_is_outgoing_concurrent_streams_max(session)) { + if (session->remote_window_size == 0 || + nghttp2_pq_empty(&session->ob_da_pq)) { + return NULL; + } + + item = nghttp2_pq_top(&session->ob_da_pq); + nghttp2_pq_pop(&session->ob_da_pq); + + item->queued = 0; + + return item; + } + + item = nghttp2_pq_top(&session->ob_ss_pq); + nghttp2_pq_pop(&session->ob_ss_pq); - item = nghttp2_outbound_queue_top(&session->ob_urgent); - if (item) { - nghttp2_outbound_queue_pop(&session->ob_urgent); item->queued = 0; + return item; } - item = nghttp2_outbound_queue_top(&session->ob_reg); - if (item) { - nghttp2_outbound_queue_pop(&session->ob_reg); + if (nghttp2_pq_empty(&session->ob_ss_pq)) { + item = nghttp2_pq_top(&session->ob_pq); + nghttp2_pq_pop(&session->ob_pq); + item->queued = 0; + return item; } - if (!session_is_outgoing_concurrent_streams_max(session)) { - item = nghttp2_outbound_queue_top(&session->ob_syn); - if (item) { - nghttp2_outbound_queue_pop(&session->ob_syn); - item->queued = 0; - return item; - } - } + item = nghttp2_pq_top(&session->ob_pq); + headers_item = nghttp2_pq_top(&session->ob_ss_pq); + + if (session_is_outgoing_concurrent_streams_max(session) || + item->weight > headers_item->weight || + (item->weight == headers_item->weight && item->seq < headers_item->seq)) { + nghttp2_pq_pop(&session->ob_pq); + + item->queued = 0; - if (session->remote_window_size > 0) { - return nghttp2_stream_next_outbound_item(&session->root); + return item; } - return NULL; + nghttp2_pq_pop(&session->ob_ss_pq); + + headers_item->queued = 0; + + return headers_item; } static int session_call_before_frame_send(nghttp2_session *session, @@ -2364,10 +2065,6 @@ if (session->callbacks.before_frame_send_callback) { rv = session->callbacks.before_frame_send_callback(session, frame, session->user_data); - if (rv == NGHTTP2_ERR_CANCEL) { - return rv; - } - if (rv != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; } @@ -2433,19 +2130,16 @@ nghttp2_stream *stream, *next_stream; nghttp2_close_stream_on_goaway_arg arg = {session, NULL, last_stream_id, incoming}; - uint32_t error_code; rv = nghttp2_map_each(&session->streams, find_stream_on_goaway_func, &arg); assert(rv == 0); - error_code = - session->server && incoming ? NGHTTP2_REFUSED_STREAM : NGHTTP2_CANCEL; - stream = arg.head; while (stream) { next_stream = stream->closed_next; stream->closed_next = NULL; - rv = nghttp2_session_close_stream(session, stream->stream_id, error_code); + rv = nghttp2_session_close_stream(session, stream->stream_id, + NGHTTP2_REFUSED_STREAM); /* stream may be deleted here */ @@ -2465,32 +2159,25 @@ return 0; } -static void reschedule_stream(nghttp2_stream *stream) { - stream->last_writelen = stream->item->frame.hd.length; - - nghttp2_stream_reschedule(stream); -} - -static int session_update_stream_consumed_size(nghttp2_session *session, - nghttp2_stream *stream, - size_t delta_size); - -static int session_update_connection_consumed_size(nghttp2_session *session, - size_t delta_size); +static void session_outbound_item_cycle_weight(nghttp2_session *session, + nghttp2_outbound_item *item, + int32_t ini_weight) { + if (item->weight == NGHTTP2_MIN_WEIGHT || item->weight > ini_weight) { -static int session_update_recv_connection_window_size(nghttp2_session *session, - size_t delta_size); + item->weight = ini_weight; -static int session_update_recv_stream_window_size(nghttp2_session *session, - nghttp2_stream *stream, - size_t delta_size, - int send_window_update); + if (item->cycle == session->last_cycle) { + item->cycle = ++session->last_cycle; + } else { + item->cycle = session->last_cycle; + } + } else { + --item->weight; + } +} /* - * Called after a frame is sent. This function runs - * on_frame_send_callback and handles stream closure upon END_STREAM - * or RST_STREAM. This function does not reset session->aob. It is a - * responsibility of session_after_frame_sent2. + * Called after a frame is sent. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -2500,7 +2187,7 @@ * NGHTTP2_ERR_CALLBACK_FAILURE * The callback function failed. */ -static int session_after_frame_sent1(nghttp2_session *session) { +static int session_after_frame_sent(nghttp2_session *session) { int rv; nghttp2_active_outbound_item *aob = &session->aob; nghttp2_outbound_item *item = aob->item; @@ -2515,7 +2202,11 @@ frame->hd.type == NGHTTP2_PUSH_PROMISE) { if (nghttp2_bufs_next_present(framebufs)) { - DEBUGF(fprintf(stderr, "send: CONTINUATION exists, just return\n")); + framebufs->cur = framebufs->cur->next; + + DEBUGF(fprintf(stderr, "send: next CONTINUATION frame, %zu bytes\n", + nghttp2_buf_len(&framebufs->cur->buf))); + return 0; } } @@ -2526,15 +2217,14 @@ switch (frame->hd.type) { case NGHTTP2_HEADERS: { nghttp2_headers_aux_data *aux_data; - nghttp2_stream *stream; - - stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + nghttp2_stream *stream = + nghttp2_session_get_stream(session, frame->hd.stream_id); if (!stream) { break; } - if (stream->item == item) { - rv = nghttp2_stream_detach_item(stream); + if (stream->data_item == item) { + rv = nghttp2_stream_detach_data(stream, session); if (nghttp2_is_fatal(rv)) { return rv; @@ -2566,7 +2256,6 @@ break; } case NGHTTP2_HCAT_PUSH_RESPONSE: - stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH); ++session->num_outgoing_streams; /* Fall through */ case NGHTTP2_HCAT_RESPONSE: @@ -2605,25 +2294,11 @@ stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); if (!stream) { - if (!session_detect_idle_stream(session, frame->hd.stream_id)) { - break; - } - - stream = nghttp2_session_open_stream( - session, frame->hd.stream_id, NGHTTP2_FLAG_NONE, - &frame->priority.pri_spec, NGHTTP2_STREAM_IDLE, NULL); - if (!stream) { - return NGHTTP2_ERR_NOMEM; - } - } else { - rv = nghttp2_session_reprioritize_stream(session, stream, - &frame->priority.pri_spec); - if (nghttp2_is_fatal(rv)) { - return rv; - } + break; } - rv = nghttp2_session_adjust_idle_stream(session); + rv = nghttp2_session_reprioritize_stream(session, stream, + &frame->priority.pri_spec); if (nghttp2_is_fatal(rv)) { return rv; @@ -2643,66 +2318,26 @@ aux_data = &item->aux_data.goaway; - if ((aux_data->flags & NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE) == 0) { - - if (aux_data->flags & NGHTTP2_GOAWAY_AUX_TERM_ON_SEND) { - session->goaway_flags |= NGHTTP2_GOAWAY_TERM_SENT; - } - - session->goaway_flags |= NGHTTP2_GOAWAY_SENT; - - rv = session_close_stream_on_goaway(session, - frame->goaway.last_stream_id, 1); - - if (nghttp2_is_fatal(rv)) { - return rv; - } + if (aux_data->terminate_on_send) { + session->goaway_flags |= NGHTTP2_GOAWAY_TERM_SENT; } - break; - } - case NGHTTP2_WINDOW_UPDATE: - if (frame->hd.stream_id == 0) { - session->window_update_queued = 0; - if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { - rv = session_update_connection_consumed_size(session, 0); - } else { - rv = session_update_recv_connection_window_size(session, 0); - } - } else { - nghttp2_stream *stream; - - stream = nghttp2_session_get_stream(session, frame->hd.stream_id); - if (!stream) { - break; - } - - stream->window_update_queued = 0; - - /* We don't have to send WINDOW_UPDATE if END_STREAM from peer - is seen. */ - if (stream->shut_flags & NGHTTP2_SHUT_RD) { - break; - } - - if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { - rv = session_update_stream_consumed_size(session, stream, 0); - } else { - rv = session_update_recv_stream_window_size(session, stream, 0, 1); - } - } + rv = session_close_stream_on_goaway(session, frame->goaway.last_stream_id, + 1); if (nghttp2_is_fatal(rv)) { return rv; } break; + } default: break; } - + active_outbound_item_reset(&session->aob); return 0; } else { + nghttp2_outbound_item *next_item; nghttp2_stream *stream; nghttp2_data_aux_data *aux_data; @@ -2712,20 +2347,20 @@ /* We update flow control window after a frame was completely sent. This is possible because we choose payload length not to exceed the window */ - session->remote_window_size -= (int32_t)frame->hd.length; + session->remote_window_size -= frame->hd.length; if (stream) { - stream->remote_window_size -= (int32_t)frame->hd.length; + stream->remote_window_size -= frame->hd.length; } if (stream && aux_data->eof) { - rv = nghttp2_stream_detach_item(stream); + rv = nghttp2_stream_detach_data(stream, session); if (nghttp2_is_fatal(rv)) { return rv; } /* Call on_frame_send_callback after - nghttp2_stream_detach_item(), so that application can issue + nghttp2_stream_detach_data(), so that application can issue nghttp2_submit_data() in the callback. */ if (session->callbacks.on_frame_send_callback) { rv = session_call_on_frame_send(session, frame); @@ -2752,10 +2387,7 @@ stream = NULL; } } - return 0; - } - - if (session->callbacks.on_frame_send_callback) { + } else if (session->callbacks.on_frame_send_callback) { rv = session_call_on_frame_send(session, frame); if (nghttp2_is_fatal(rv)) { @@ -2763,148 +2395,154 @@ } } - return 0; - } - /* Unreachable */ - assert(0); - return 0; -} + /* On EOF, we have already detached data if stream is not NULL. + If stream is NULL, we cannot detach data. Please note that + application may issue nghttp2_submit_data() in + on_frame_send_callback, which attach data to stream. We don't + want to detach it. */ + if (aux_data->eof) { + active_outbound_item_reset(aob); -/* - * Called after a frame is sent and session_after_frame_sent1. This - * function is responsible to reset session->aob. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGHTTP2_ERR_NOMEM - * Out of memory. - * NGHTTP2_ERR_CALLBACK_FAILURE - * The callback function failed. - */ -static int session_after_frame_sent2(nghttp2_session *session) { - int rv; - nghttp2_active_outbound_item *aob = &session->aob; - nghttp2_outbound_item *item = aob->item; - nghttp2_bufs *framebufs = &aob->framebufs; - nghttp2_frame *frame; - nghttp2_mem *mem; - nghttp2_stream *stream; - nghttp2_data_aux_data *aux_data; + return 0; + } - mem = &session->mem; - frame = &item->frame; + /* If session is closed or RST_STREAM was queued, we won't send + further data. */ + if (nghttp2_session_predicate_data_send(session, stream) != 0) { + if (stream) { + rv = nghttp2_stream_detach_data(stream, session); - if (frame->hd.type != NGHTTP2_DATA) { + if (nghttp2_is_fatal(rv)) { + return rv; + } + } - if (frame->hd.type == NGHTTP2_HEADERS || - frame->hd.type == NGHTTP2_PUSH_PROMISE) { + active_outbound_item_reset(aob); - if (nghttp2_bufs_next_present(framebufs)) { - framebufs->cur = framebufs->cur->next; + return 0; + } - DEBUGF(fprintf(stderr, "send: next CONTINUATION frame, %zu bytes\n", - nghttp2_buf_len(&framebufs->cur->buf))); + /* Assuming stream is not NULL */ + assert(stream); + next_item = nghttp2_session_get_next_ob_item(session); - return 0; - } - } + session_outbound_item_cycle_weight(session, aob->item, + stream->effective_weight); - active_outbound_item_reset(&session->aob, mem); + /* If priority of this stream is higher or equal to other stream + waiting at the top of the queue, we continue to send this + data. */ + if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP && + (next_item == NULL || outbound_item_compar(item, next_item) < 0)) { + size_t next_readmax; - return 0; - } + next_readmax = nghttp2_session_next_data_read(session, stream); - /* DATA frame */ + if (next_readmax == 0) { - aux_data = &item->aux_data.data; + if (session->remote_window_size == 0 && + stream->remote_window_size > 0) { - /* On EOF, we have already detached data. Please note that - application may issue nghttp2_submit_data() in - on_frame_send_callback (call from session_after_frame_sent1), - which attach data to stream. We don't want to detach it. */ - if (aux_data->eof) { - active_outbound_item_reset(aob, mem); + /* If DATA cannot be sent solely due to connection level + window size, just push item to queue again. We never pop + DATA item while connection level window size is 0. */ + rv = nghttp2_pq_push(&session->ob_da_pq, aob->item); - return 0; - } + if (nghttp2_is_fatal(rv)) { + return rv; + } - /* Reset no_copy here because next write may not use this. */ - aux_data->no_copy = 0; + aob->item->queued = 1; + } else { + rv = nghttp2_stream_defer_data( + stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, session); - stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (nghttp2_is_fatal(rv)) { + return rv; + } + } - /* If session is closed or RST_STREAM was queued, we won't send - further data. */ - if (nghttp2_session_predicate_data_send(session, stream) != 0) { - if (stream) { - rv = nghttp2_stream_detach_item(stream); + aob->item = NULL; + active_outbound_item_reset(aob); + + return 0; + } + nghttp2_bufs_reset(framebufs); + + rv = nghttp2_session_pack_data(session, framebufs, next_readmax, frame, + aux_data); if (nghttp2_is_fatal(rv)) { return rv; } - } + if (rv == NGHTTP2_ERR_DEFERRED) { + rv = nghttp2_stream_defer_data( + stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER, session); - active_outbound_item_reset(aob, mem); + if (nghttp2_is_fatal(rv)) { + return rv; + } - return 0; - } + aob->item = NULL; + active_outbound_item_reset(aob); - aob->item = NULL; - active_outbound_item_reset(&session->aob, mem); + return 0; + } + if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { + /* Stop DATA frame chain and issue RST_STREAM to close the + stream. We don't return + NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE intentionally. */ + rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id, + NGHTTP2_INTERNAL_ERROR); - return 0; -} + if (nghttp2_is_fatal(rv)) { + return rv; + } -static int session_call_send_data(nghttp2_session *session, - nghttp2_outbound_item *item, - nghttp2_bufs *framebufs) { - int rv; - nghttp2_buf *buf; - size_t length; - nghttp2_frame *frame; - nghttp2_data_aux_data *aux_data; + rv = nghttp2_stream_detach_data(stream, session); - buf = &framebufs->cur->buf; - frame = &item->frame; - length = frame->hd.length - frame->data.padlen; - aux_data = &item->aux_data.data; + if (nghttp2_is_fatal(rv)) { + return rv; + } - rv = session->callbacks.send_data_callback(session, frame, buf->pos, length, - &aux_data->data_prd.source, - session->user_data); - - switch (rv) { - case 0: - case NGHTTP2_ERR_WOULDBLOCK: - case NGHTTP2_ERR_PAUSE: - case NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE: - return rv; - default: - return NGHTTP2_ERR_CALLBACK_FAILURE; + active_outbound_item_reset(aob); + + return 0; + } + assert(rv == 0); + + return 0; + } + + if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) { + rv = nghttp2_pq_push(&session->ob_da_pq, aob->item); + + if (nghttp2_is_fatal(rv)) { + return rv; + } + + aob->item->queued = 1; + } + + aob->item = NULL; + active_outbound_item_reset(&session->aob); + return 0; } + /* Unreachable */ + assert(0); + return 0; } -static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, - const uint8_t **data_ptr, - int fast_cb) { +ssize_t nghttp2_session_mem_send(nghttp2_session *session, + const uint8_t **data_ptr) { int rv; nghttp2_active_outbound_item *aob; nghttp2_bufs *framebufs; - nghttp2_mem *mem; - mem = &session->mem; aob = &session->aob; framebufs = &aob->framebufs; - /* We may have idle streams more than we expect (e.g., - nghttp2_session_change_stream_priority() or - nghttp2_session_create_idle_stream()). Adjust them here. */ - rv = nghttp2_session_adjust_idle_stream(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - + *data_ptr = NULL; for (;;) { switch (aob->state) { case NGHTTP2_OB_POP_ITEM: { @@ -2915,15 +2553,28 @@ return 0; } + if (item->frame.hd.type == NGHTTP2_DATA || + item->frame.hd.type == NGHTTP2_HEADERS) { + nghttp2_frame *frame; + nghttp2_stream *stream; + + frame = &item->frame; + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + + if (stream && item == stream->data_item && + stream->dpri != NGHTTP2_STREAM_DPRI_TOP) { + /* We have DATA with higher priority in queue within the + same dependency tree. */ + break; + } + } + rv = session_prep_frame(session, item); if (rv == NGHTTP2_ERR_DEFERRED) { DEBUGF(fprintf(stderr, "send: frame transmission deferred\n")); break; } if (rv < 0) { - int32_t opened_stream_id = 0; - uint32_t error_code = NGHTTP2_INTERNAL_ERROR; - DEBUGF(fprintf(stderr, "send: frame preparation failed with %s\n", nghttp2_strerror(rv))); /* TODO If the error comes from compressor, the connection @@ -2934,49 +2585,20 @@ /* The library is responsible for the transmission of WINDOW_UPDATE frame, so we don't call error callback for it. */ - if (frame->hd.type != NGHTTP2_WINDOW_UPDATE && - session->callbacks.on_frame_not_send_callback( - session, frame, rv, session->user_data) != 0) { + if (frame->hd.type != NGHTTP2_WINDOW_UPDATE) { + if (session->callbacks.on_frame_not_send_callback( + session, frame, rv, session->user_data) != 0) { - nghttp2_outbound_item_free(item, mem); - nghttp2_mem_free(mem, item); + nghttp2_outbound_item_free(item); + free(item); - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - } - /* We have to close stream opened by failed request HEADERS - or PUSH_PROMISE. */ - switch (item->frame.hd.type) { - case NGHTTP2_HEADERS: - if (item->frame.headers.cat == NGHTTP2_HCAT_REQUEST) { - opened_stream_id = item->frame.hd.stream_id; - if (item->aux_data.headers.canceled) { - error_code = item->aux_data.headers.error_code; - } else { - /* Set error_code to REFUSED_STREAM so that application - can send request again. */ - error_code = NGHTTP2_REFUSED_STREAM; + return NGHTTP2_ERR_CALLBACK_FAILURE; } } - break; - case NGHTTP2_PUSH_PROMISE: - opened_stream_id = item->frame.push_promise.promised_stream_id; - break; - } - if (opened_stream_id) { - /* careful not to override rv */ - int rv2; - rv2 = nghttp2_session_close_stream(session, opened_stream_id, - error_code); - - if (nghttp2_is_fatal(rv2)) { - return rv2; - } } - - nghttp2_outbound_item_free(item, mem); - nghttp2_mem_free(mem, item); - active_outbound_item_reset(aob, mem); + nghttp2_outbound_item_free(item); + free(item); + active_outbound_item_reset(aob); if (rv == NGHTTP2_ERR_HEADER_COMP) { /* If header compression error occurred, should terminiate @@ -3008,63 +2630,13 @@ if (nghttp2_is_fatal(rv)) { return rv; } - - if (rv == NGHTTP2_ERR_CANCEL) { - int32_t opened_stream_id = 0; - uint32_t error_code = NGHTTP2_INTERNAL_ERROR; - - if (session->callbacks.on_frame_not_send_callback) { - if (session->callbacks.on_frame_not_send_callback( - session, frame, rv, session->user_data) != 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - } - - /* We have to close stream opened by canceled request - HEADERS or PUSH_PROMISE. */ - switch (item->frame.hd.type) { - case NGHTTP2_HEADERS: - if (item->frame.headers.cat == NGHTTP2_HCAT_REQUEST) { - opened_stream_id = item->frame.hd.stream_id; - /* We don't have to check - item->aux_data.headers.canceled since it has already - been checked. */ - /* Set error_code to REFUSED_STREAM so that application - can send request again. */ - error_code = NGHTTP2_REFUSED_STREAM; - } - break; - case NGHTTP2_PUSH_PROMISE: - opened_stream_id = item->frame.push_promise.promised_stream_id; - break; - } - if (opened_stream_id) { - /* careful not to override rv */ - int rv2; - rv2 = nghttp2_session_close_stream(session, opened_stream_id, - error_code); - - if (nghttp2_is_fatal(rv2)) { - return rv2; - } - } - - active_outbound_item_reset(aob, mem); - - break; - } } else { DEBUGF(fprintf(stderr, "send: next frame: DATA\n")); - - if (item->aux_data.data.no_copy) { - aob->state = NGHTTP2_OB_SEND_NO_COPY; - break; - } } DEBUGF(fprintf(stderr, "send: start transmitting frame type=%u, length=%zd\n", - framebufs->cur->buf.pos[3], + framebufs->cur->buf.pos[2], framebufs->cur->buf.last - framebufs->cur->buf.pos)); aob->state = NGHTTP2_OB_SEND_DATA; @@ -3081,17 +2653,7 @@ DEBUGF(fprintf(stderr, "send: end transmission of a frame\n")); /* Frame has completely sent */ - if (fast_cb) { - rv = session_after_frame_sent2(session); - } else { - rv = session_after_frame_sent1(session); - if (rv < 0) { - /* FATAL */ - assert(nghttp2_is_fatal(rv)); - return rv; - } - rv = session_after_frame_sent2(session); - } + rv = session_after_frame_sent(session); if (rv < 0) { /* FATAL */ assert(nghttp2_is_fatal(rv)); @@ -3108,128 +2670,14 @@ everything, we will adjust it. */ buf->pos += datalen; - return (ssize_t)datalen; + return datalen; } - case NGHTTP2_OB_SEND_NO_COPY: { - nghttp2_stream *stream; - nghttp2_frame *frame; - int pause; - - DEBUGF(fprintf(stderr, "send: no copy DATA\n")); - - frame = &aob->item->frame; - - stream = nghttp2_session_get_stream(session, frame->hd.stream_id); - if (stream == NULL) { - DEBUGF(fprintf( - stderr, - "send: no copy DATA cancelled because stream was closed\n")); - - active_outbound_item_reset(aob, mem); - - break; - } - - rv = session_call_send_data(session, aob->item, framebufs); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_stream_detach_item(stream); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id, - NGHTTP2_INTERNAL_ERROR); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - active_outbound_item_reset(aob, mem); - - break; - } - - if (rv == NGHTTP2_ERR_WOULDBLOCK) { - return 0; - } - - pause = (rv == NGHTTP2_ERR_PAUSE); - - rv = session_after_frame_sent1(session); - if (rv < 0) { - assert(nghttp2_is_fatal(rv)); - return rv; - } - rv = session_after_frame_sent2(session); - if (rv < 0) { - assert(nghttp2_is_fatal(rv)); - return rv; - } - - /* We have already adjusted the next state */ - - if (pause) { - return 0; - } - - break; - } - case NGHTTP2_OB_SEND_CLIENT_MAGIC: { - size_t datalen; - nghttp2_buf *buf; - - buf = &framebufs->cur->buf; - - if (buf->pos == buf->last) { - DEBUGF(fprintf(stderr, "send: end transmission of client magic\n")); - active_outbound_item_reset(aob, mem); - break; - } - - *data_ptr = buf->pos; - datalen = nghttp2_buf_len(buf); - - buf->pos += datalen; - - return (ssize_t)datalen; - } - } - } -} - -ssize_t nghttp2_session_mem_send(nghttp2_session *session, - const uint8_t **data_ptr) { - int rv; - ssize_t len; - - *data_ptr = NULL; - - len = nghttp2_session_mem_send_internal(session, data_ptr, 1); - if (len <= 0) { - return len; - } - - if (session->aob.item) { - /* We have to call session_after_frame_sent1 here to handle stream - closure upon transmission of frames. Otherwise, END_STREAM may - be reached to client before we call nghttp2_session_mem_send - again and we may get exceeding number of incoming streams. */ - rv = session_after_frame_sent1(session); - if (rv < 0) { - assert(nghttp2_is_fatal(rv)); - return (ssize_t)rv; } } - - return len; } int nghttp2_session_send(nghttp2_session *session) { - const uint8_t *data = NULL; + const uint8_t *data; ssize_t datalen; ssize_t sentlen; nghttp2_bufs *framebufs; @@ -3237,12 +2685,12 @@ framebufs = &session->aob.framebufs; for (;;) { - datalen = nghttp2_session_mem_send_internal(session, &data, 0); + datalen = nghttp2_session_mem_send(session, &data); if (datalen <= 0) { return (int)datalen; } - sentlen = session->callbacks.send_callback(session, data, (size_t)datalen, - 0, session->user_data); + sentlen = session->callbacks.send_callback(session, data, datalen, 0, + session->user_data); if (sentlen < 0) { if (sentlen == NGHTTP2_ERR_WOULDBLOCK) { /* Transmission canceled. Rewind the offset */ @@ -3310,9 +2758,6 @@ if (session->callbacks.on_begin_headers_callback) { rv = session->callbacks.on_begin_headers_callback(session, frame, session->user_data); - if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - return rv; - } if (rv != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; } @@ -3322,65 +2767,20 @@ static int session_call_on_header(nghttp2_session *session, const nghttp2_frame *frame, - const nghttp2_hd_nv *nv) { - int rv = 0; - if (session->callbacks.on_header_callback2) { - rv = session->callbacks.on_header_callback2( - session, frame, nv->name, nv->value, nv->flags, session->user_data); - } else if (session->callbacks.on_header_callback) { - rv = session->callbacks.on_header_callback( - session, frame, nv->name->base, nv->name->len, nv->value->base, - nv->value->len, nv->flags, session->user_data); - } - - if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - return rv; - } - if (rv != 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - - return 0; -} - -static int -session_call_on_extension_chunk_recv_callback(nghttp2_session *session, - const uint8_t *data, size_t len) { + const nghttp2_nv *nv) { int rv; - nghttp2_inbound_frame *iframe = &session->iframe; - nghttp2_frame *frame = &iframe->frame; - - if (session->callbacks.on_extension_chunk_recv_callback) { - rv = session->callbacks.on_extension_chunk_recv_callback( - session, &frame->hd, data, len, session->user_data); - if (rv == NGHTTP2_ERR_CANCEL) { + if (session->callbacks.on_header_callback) { + rv = session->callbacks.on_header_callback( + session, frame, nv->name, nv->namelen, nv->value, nv->valuelen, + nv->flags, session->user_data); + if (rv == NGHTTP2_ERR_PAUSE || + rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { return rv; } if (rv != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; } } - - return 0; -} - -static int session_call_unpack_extension_callback(nghttp2_session *session) { - int rv; - nghttp2_inbound_frame *iframe = &session->iframe; - nghttp2_frame *frame = &iframe->frame; - void *payload = NULL; - - rv = session->callbacks.unpack_extension_callback( - session, &payload, &frame->hd, session->user_data); - if (rv == NGHTTP2_ERR_CANCEL) { - return rv; - } - if (rv != 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - - frame->ext.payload = payload; - return 0; } @@ -3400,58 +2800,28 @@ return nghttp2_session_terminate_session(session, NGHTTP2_FRAME_SIZE_ERROR); } -static uint32_t get_error_code_from_lib_error_code(int lib_error_code) { - switch (lib_error_code) { - case NGHTTP2_ERR_STREAM_CLOSED: - return NGHTTP2_STREAM_CLOSED; - case NGHTTP2_ERR_HEADER_COMP: - return NGHTTP2_COMPRESSION_ERROR; - case NGHTTP2_ERR_FRAME_SIZE_ERROR: - return NGHTTP2_FRAME_SIZE_ERROR; - case NGHTTP2_ERR_FLOW_CONTROL: - return NGHTTP2_FLOW_CONTROL_ERROR; - case NGHTTP2_ERR_REFUSED_STREAM: - return NGHTTP2_REFUSED_STREAM; - case NGHTTP2_ERR_PROTO: - case NGHTTP2_ERR_HTTP_HEADER: - case NGHTTP2_ERR_HTTP_MESSAGING: - return NGHTTP2_PROTOCOL_ERROR; - default: - return NGHTTP2_INTERNAL_ERROR; - } -} - -static int session_handle_invalid_stream2(nghttp2_session *session, - int32_t stream_id, - nghttp2_frame *frame, - int lib_error_code) { +static int session_handle_invalid_stream(nghttp2_session *session, + nghttp2_frame *frame, + uint32_t error_code) { int rv; - rv = nghttp2_session_add_rst_stream( - session, stream_id, get_error_code_from_lib_error_code(lib_error_code)); + rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id, error_code); if (rv != 0) { return rv; } if (session->callbacks.on_invalid_frame_recv_callback) { if (session->callbacks.on_invalid_frame_recv_callback( - session, frame, lib_error_code, session->user_data) != 0) { + session, frame, error_code, session->user_data) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; } } return 0; } -static int session_handle_invalid_stream(nghttp2_session *session, - nghttp2_frame *frame, - int lib_error_code) { - return session_handle_invalid_stream2(session, frame->hd.stream_id, frame, - lib_error_code); -} - static int session_inflate_handle_invalid_stream(nghttp2_session *session, nghttp2_frame *frame, - int lib_error_code) { + uint32_t error_code) { int rv; - rv = session_handle_invalid_stream(session, frame, lib_error_code); + rv = session_handle_invalid_stream(session, frame, error_code); if (nghttp2_is_fatal(rv)) { return rv; } @@ -3463,25 +2833,24 @@ */ static int session_handle_invalid_connection(nghttp2_session *session, nghttp2_frame *frame, - int lib_error_code, + uint32_t error_code, const char *reason) { if (session->callbacks.on_invalid_frame_recv_callback) { if (session->callbacks.on_invalid_frame_recv_callback( - session, frame, lib_error_code, session->user_data) != 0) { + session, frame, error_code, session->user_data) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; } } - return nghttp2_session_terminate_session_with_reason( - session, get_error_code_from_lib_error_code(lib_error_code), reason); + return nghttp2_session_terminate_session_with_reason(session, error_code, + reason); } static int session_inflate_handle_invalid_connection(nghttp2_session *session, nghttp2_frame *frame, - int lib_error_code, + uint32_t error_code, const char *reason) { int rv; - rv = - session_handle_invalid_connection(session, frame, lib_error_code, reason); + rv = session_handle_invalid_connection(session, frame, error_code, reason); if (nghttp2_is_fatal(rv)) { return rv; } @@ -3521,38 +2890,29 @@ ssize_t proclen; int rv; int inflate_flags; - nghttp2_hd_nv nv; + nghttp2_nv nv; nghttp2_stream *stream; - nghttp2_stream *subject_stream; - int trailer = 0; *readlen_ptr = 0; - stream = nghttp2_session_get_stream(session, frame->hd.stream_id); - - if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { - subject_stream = nghttp2_session_get_stream( - session, frame->push_promise.promised_stream_id); - } else { - subject_stream = stream; - trailer = session_trailer_headers(session, stream, frame); - } DEBUGF(fprintf(stderr, "recv: decoding header block %zu bytes\n", inlen)); for (;;) { inflate_flags = 0; - proclen = nghttp2_hd_inflate_hd_nv(&session->hd_inflater, &nv, - &inflate_flags, in, inlen, final); + proclen = nghttp2_hd_inflate_hd(&session->hd_inflater, &nv, &inflate_flags, + in, inlen, final); if (nghttp2_is_fatal((int)proclen)) { return (int)proclen; } if (proclen < 0) { if (session->iframe.state == NGHTTP2_IB_READ_HEADER_BLOCK) { - if (subject_stream && subject_stream->state != NGHTTP2_STREAM_CLOSING) { + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + + if (stream && stream->state != NGHTTP2_STREAM_CLOSING) { /* Adding RST_STREAM here is very important. It prevents from invoking subsequent callbacks for the same stream ID. */ - rv = nghttp2_session_add_rst_stream( - session, subject_stream->stream_id, NGHTTP2_COMPRESSION_ERROR); + rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id, + NGHTTP2_COMPRESSION_ERROR); if (nghttp2_is_fatal(rv)) { return rv; @@ -3568,56 +2928,17 @@ return NGHTTP2_ERR_HEADER_COMP; } in += proclen; - inlen -= (size_t)proclen; - *readlen_ptr += (size_t)proclen; + inlen -= proclen; + *readlen_ptr += proclen; DEBUGF(fprintf(stderr, "recv: proclen=%zd\n", proclen)); if (call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) { - rv = 0; - if (subject_stream && session_enforce_http_messaging(session)) { - rv = nghttp2_http_on_header(session, subject_stream, frame, &nv, - trailer); - if (rv == NGHTTP2_ERR_HTTP_HEADER) { - DEBUGF(fprintf( - stderr, "recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n", - frame->hd.type, subject_stream->stream_id, (int)nv.name->len, - nv.name->base, (int)nv.value->len, nv.value->base)); - - rv = session_call_error_callback( - session, "Invalid HTTP header field was received: frame type: " - "%u, stream: %d, name: [%.*s], value: [%.*s]", - frame->hd.type, frame->hd.stream_id, (int)nv.name->len, - nv.name->base, (int)nv.value->len, nv.value->base); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - rv = - session_handle_invalid_stream2(session, subject_stream->stream_id, - frame, NGHTTP2_ERR_HTTP_HEADER); - if (nghttp2_is_fatal(rv)) { - return rv; - } - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - - if (rv == NGHTTP2_ERR_IGN_HTTP_HEADER) { - /* header is ignored */ - DEBUGF(fprintf( - stderr, "recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s\n", - frame->hd.type, subject_stream->stream_id, (int)nv.name->len, - nv.name->base, (int)nv.value->len, nv.value->base)); - } - } - if (rv == 0) { - rv = session_call_on_header(session, frame, &nv); - /* This handles NGHTTP2_ERR_PAUSE and - NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */ - if (rv != 0) { - return rv; - } + rv = session_call_on_header(session, frame, &nv); + /* This handles NGHTTP2_ERR_PAUSE and + NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */ + if (rv != 0) { + return rv; } } if (inflate_flags & NGHTTP2_HD_INFLATE_FINAL) { @@ -3632,7 +2953,9 @@ } /* - * Call this function when HEADERS frame was completely received. + * Decompress header blocks of incoming request HEADERS and also call + * additional callbacks. This function can be called again if this + * function returns NGHTTP2_ERR_PAUSE. * * This function returns 0 if it succeeds, or one of negative error * codes: @@ -3642,101 +2965,108 @@ * NGHTTP2_ERR_NOMEM * Out of memory. */ -static int session_end_stream_headers_received(nghttp2_session *session, - nghttp2_frame *frame, - nghttp2_stream *stream) { - int rv; - if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { - return 0; - } - - nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); - rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream); - if (nghttp2_is_fatal(rv)) { - return rv; +int nghttp2_session_end_request_headers_received(nghttp2_session *session _U_, + nghttp2_frame *frame, + nghttp2_stream *stream) { + if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); } - + /* Here we assume that stream is not shutdown in NGHTTP2_SHUT_WR */ return 0; } -static int session_after_header_block_received(nghttp2_session *session) { - int rv = 0; - int call_cb = 1; - nghttp2_frame *frame = &session->iframe.frame; - nghttp2_stream *stream; - - /* We don't call on_frame_recv_callback if stream has been closed - already or being closed. */ - stream = nghttp2_session_get_stream(session, frame->hd.stream_id); - if (!stream || stream->state == NGHTTP2_STREAM_CLOSING) { - return 0; - } - - if (session_enforce_http_messaging(session)) { - if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { - nghttp2_stream *subject_stream; - - subject_stream = nghttp2_session_get_stream( - session, frame->push_promise.promised_stream_id); - if (subject_stream) { - rv = nghttp2_http_on_request_headers(subject_stream, frame); - } - } else { - assert(frame->hd.type == NGHTTP2_HEADERS); - switch (frame->headers.cat) { - case NGHTTP2_HCAT_REQUEST: - rv = nghttp2_http_on_request_headers(stream, frame); - break; - case NGHTTP2_HCAT_RESPONSE: - case NGHTTP2_HCAT_PUSH_RESPONSE: - rv = nghttp2_http_on_response_headers(stream); - break; - case NGHTTP2_HCAT_HEADERS: - if (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) { - assert(!session->server); - rv = nghttp2_http_on_response_headers(stream); - } else { - rv = nghttp2_http_on_trailer_headers(stream, frame); - } - break; - default: - assert(0); - } - if (rv == 0 && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { - rv = nghttp2_http_on_remote_end_stream(stream); - } +/* + * Decompress header blocks of incoming (push-)response HEADERS and + * also call additional callbacks. This function can be called again + * if this function returns NGHTTP2_ERR_PAUSE. + * + * This function returns 0 if it succeeds, or one of negative error + * codes: + * + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +int nghttp2_session_end_response_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream) { + int rv; + if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + /* This is the last frame of this stream, so disallow + further receptions. */ + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream); + if (nghttp2_is_fatal(rv)) { + return rv; } - if (rv != 0) { - int32_t stream_id; - - if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { - stream_id = frame->push_promise.promised_stream_id; - } else { - stream_id = frame->hd.stream_id; - } - - call_cb = 0; + } + return 0; +} - rv = session_handle_invalid_stream2(session, stream_id, frame, - NGHTTP2_ERR_HTTP_MESSAGING); - if (nghttp2_is_fatal(rv)) { - return rv; - } +/* + * Decompress header blocks of incoming HEADERS and also call + * additional callbacks. This function can be called again if this + * function returns NGHTTP2_ERR_PAUSE. + * + * This function returns 0 if it succeeds, or one of negative error + * codes: + * + * NGHTTP2_ERR_CALLBACK_FAILURE + * The callback function failed. + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +int nghttp2_session_end_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream) { + int rv; + if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + if (!nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { } - } - - if (call_cb) { - rv = session_call_on_frame_received(session, frame); + nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream); if (nghttp2_is_fatal(rv)) { return rv; } } + return 0; +} + +static int session_after_header_block_received(nghttp2_session *session) { + int rv; + nghttp2_frame *frame = &session->iframe.frame; + nghttp2_stream *stream; + + /* We don't call on_frame_recv_callback if stream has been closed + already or being closed. */ + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (!stream || stream->state == NGHTTP2_STREAM_CLOSING) { + return 0; + } + + rv = session_call_on_frame_received(session, frame); + if (nghttp2_is_fatal(rv)) { + return rv; + } if (frame->hd.type != NGHTTP2_HEADERS) { return 0; } - return session_end_stream_headers_received(session, frame, stream); + switch (frame->headers.cat) { + case NGHTTP2_HCAT_REQUEST: + return nghttp2_session_end_request_headers_received(session, frame, stream); + case NGHTTP2_HCAT_RESPONSE: + case NGHTTP2_HCAT_PUSH_RESPONSE: + return nghttp2_session_end_response_headers_received(session, frame, + stream); + case NGHTTP2_HCAT_HEADERS: + return nghttp2_session_end_headers_received(session, frame, stream); + default: + assert(0); + } + return 0; } int nghttp2_session_on_request_headers_received(nghttp2_session *session, @@ -3745,7 +3075,8 @@ nghttp2_stream *stream; if (frame->hd.stream_id == 0) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: stream_id == 0"); + session, frame, NGHTTP2_PROTOCOL_ERROR, + "request HEADERS: stream_id == 0"); } /* If client recieves idle stream from server, it is invalid @@ -3754,59 +3085,51 @@ if (!session->server) { if (session_detect_idle_stream(session, frame->hd.stream_id)) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, + session, frame, NGHTTP2_PROTOCOL_ERROR, "request HEADERS: client received request"); } return NGHTTP2_ERR_IGN_HEADER_BLOCK; } - assert(session->server); - if (!session_is_new_peer_stream_id(session, frame->hd.stream_id)) { /* The spec says if an endpoint receives a HEADERS with invalid stream ID, it MUST issue connection error with error code PROTOCOL_ERROR. But we could get trailer HEADERS after we have sent RST_STREAM to this stream and peer have not received it. Then connection error is too harsh. It means that we only use - connection error if stream ID refers idle stream. Therwise we + connection error if stream ID refers idle stream. OTherwise we just ignore HEADERS for now. */ - if (frame->hd.stream_id == 0 || - nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { + if (session_detect_idle_stream(session, frame->hd.stream_id)) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, + session, frame, NGHTTP2_PROTOCOL_ERROR, "request HEADERS: invalid stream_id"); } - stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id); - if (stream && (stream->shut_flags & NGHTTP2_SHUT_RD)) { - return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed"); - } - return NGHTTP2_ERR_IGN_HEADER_BLOCK; } session->last_recv_stream_id = frame->hd.stream_id; + if (session->local_last_stream_id < frame->hd.stream_id) { + /* We just ignore stream rather than local_last_stream_id */ + return NGHTTP2_ERR_IGN_HEADER_BLOCK; + } + if (session_is_incoming_concurrent_streams_max(session)) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, + session, frame, NGHTTP2_ENHANCE_YOUR_CALM, "request HEADERS: max concurrent streams exceeded"); } - if (!session_allow_incoming_new_stream(session)) { - /* We just ignore stream after GOAWAY was sent */ - return NGHTTP2_ERR_IGN_HEADER_BLOCK; - } - if (frame->headers.pri_spec.stream_id == frame->hd.stream_id) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: depend on itself"); + session, frame, NGHTTP2_PROTOCOL_ERROR, + "request HEADERS: depend on itself"); } if (session_is_incoming_concurrent_streams_pending_max(session)) { return session_inflate_handle_invalid_stream(session, frame, - NGHTTP2_ERR_REFUSED_STREAM); + NGHTTP2_REFUSED_STREAM); } stream = nghttp2_session_open_stream( @@ -3815,14 +3138,7 @@ if (!stream) { return NGHTTP2_ERR_NOMEM; } - - rv = nghttp2_session_adjust_closed_stream(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - session->last_proc_stream_id = session->last_recv_stream_id; - rv = session_call_on_begin_headers(session, frame); if (rv != 0) { return rv; @@ -3840,7 +3156,8 @@ nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)); if (frame->hd.stream_id == 0) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "response HEADERS: stream_id == 0"); + session, frame, NGHTTP2_PROTOCOL_ERROR, + "response HEADERS: stream_id == 0"); } if (stream->shut_flags & NGHTTP2_SHUT_RD) { /* half closed (remote): from the spec: @@ -3848,11 +3165,9 @@ If an endpoint receives additional frames for a stream that is in this state it MUST respond with a stream error (Section 5.4.2) of type STREAM_CLOSED. - - We go further, and make it connection error. */ - return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed"); + return session_inflate_handle_invalid_stream(session, frame, + NGHTTP2_STREAM_CLOSED); } stream->state = NGHTTP2_STREAM_OPENED; rv = session_call_on_begin_headers(session, frame); @@ -3869,36 +3184,25 @@ assert(stream->state == NGHTTP2_STREAM_RESERVED); if (frame->hd.stream_id == 0) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, + session, frame, NGHTTP2_PROTOCOL_ERROR, "push response HEADERS: stream_id == 0"); } - - if (session->server) { - return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, - "HEADERS: no HEADERS allowed from client in reserved state"); + if (session->goaway_flags) { + /* We don't accept new stream after GOAWAY is sent or received. */ + return NGHTTP2_ERR_IGN_HEADER_BLOCK; } if (session_is_incoming_concurrent_streams_max(session)) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, + session, frame, NGHTTP2_ENHANCE_YOUR_CALM, "push response HEADERS: max concurrent streams exceeded"); } - - if (!session_allow_incoming_new_stream(session)) { - /* We don't accept new stream after GOAWAY was sent. */ - return NGHTTP2_ERR_IGN_HEADER_BLOCK; - } - if (session_is_incoming_concurrent_streams_pending_max(session)) { return session_inflate_handle_invalid_stream(session, frame, - NGHTTP2_ERR_REFUSED_STREAM); + NGHTTP2_REFUSED_STREAM); } nghttp2_stream_promise_fulfilled(stream); - if (!nghttp2_session_is_my_stream_id(session, stream->stream_id)) { - --session->num_incoming_reserved_streams; - } ++session->num_incoming_streams; rv = session_call_on_begin_headers(session, frame); if (rv != 0) { @@ -3913,7 +3217,15 @@ int rv = 0; if (frame->hd.stream_id == 0) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "HEADERS: stream_id == 0"); + session, frame, NGHTTP2_PROTOCOL_ERROR, "HEADERS: stream_id == 0"); + } + if (stream->state == NGHTTP2_STREAM_RESERVED) { + /* reserved. The valid push response HEADERS is processed by + nghttp2_session_on_push_response_headers_received(). This + generic HEADERS is called invalid cases for HEADERS against + reserved state. */ + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_PROTOCOL_ERROR, "HEADERS: stream in reserved"); } if ((stream->shut_flags & NGHTTP2_SHUT_RD)) { /* half closed (remote): from the spec: @@ -3921,11 +3233,9 @@ If an endpoint receives additional frames for a stream that is in this state it MUST respond with a stream error (Section 5.4.2) of type STREAM_CLOSED. - - we go further, and make it connection error. */ - return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed"); + return session_inflate_handle_invalid_stream(session, frame, + NGHTTP2_STREAM_CLOSED); } if (nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { if (stream->state == NGHTTP2_STREAM_OPENED) { @@ -3934,9 +3244,15 @@ return rv; } return 0; + } else if (stream->state == NGHTTP2_STREAM_CLOSING) { + /* This is race condition. NGHTTP2_STREAM_CLOSING indicates + that we queued RST_STREAM but it has not been sent. It will + eventually sent, so we just ignore this frame. */ + return NGHTTP2_ERR_IGN_HEADER_BLOCK; + } else { + return session_inflate_handle_invalid_stream(session, frame, + NGHTTP2_PROTOCOL_ERROR); } - - return NGHTTP2_ERR_IGN_HEADER_BLOCK; } /* If this is remote peer initiated stream, it is OK unless it has sent END_STREAM frame already. But if stream is in @@ -3971,18 +3287,20 @@ return nghttp2_session_on_request_headers_received(session, frame); } + if (nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { + if (stream->state == NGHTTP2_STREAM_OPENING) { + frame->headers.cat = NGHTTP2_HCAT_RESPONSE; + return nghttp2_session_on_response_headers_received(session, frame, + stream); + } + frame->headers.cat = NGHTTP2_HCAT_HEADERS; + return nghttp2_session_on_headers_received(session, frame, stream); + } if (stream->state == NGHTTP2_STREAM_RESERVED) { frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE; return nghttp2_session_on_push_response_headers_received(session, frame, stream); } - - if (stream->state == NGHTTP2_STREAM_OPENING && - nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { - frame->headers.cat = NGHTTP2_HCAT_RESPONSE; - return nghttp2_session_on_response_headers_received(session, frame, stream); - } - frame->headers.cat = NGHTTP2_HCAT_HEADERS; return nghttp2_session_on_headers_received(session, frame, stream); } @@ -3993,13 +3311,8 @@ nghttp2_stream *stream; if (frame->hd.stream_id == 0) { - return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, - "PRIORITY: stream_id == 0"); - } - - if (frame->priority.pri_spec.stream_id == frame->hd.stream_id) { - return nghttp2_session_terminate_session_with_reason( - session, NGHTTP2_PROTOCOL_ERROR, "depend on itself"); + return session_handle_invalid_connection( + session, frame, NGHTTP2_PROTOCOL_ERROR, "PRIORITY: stream_id == 0"); } if (!session->server) { @@ -4012,7 +3325,8 @@ if (!stream) { /* PRIORITY against idle stream can create anchor node in dependency tree. */ - if (!session_detect_idle_stream(session, frame->hd.stream_id)) { + if (!session_detect_idle_stream(session, frame->hd.stream_id) || + !nghttp2_session_can_add_closed_stream(session, 1)) { return 0; } @@ -4023,11 +3337,6 @@ if (stream == NULL) { return NGHTTP2_ERR_NOMEM; } - - rv = nghttp2_session_adjust_idle_stream(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } } else { rv = nghttp2_session_reprioritize_stream(session, stream, &frame->priority.pri_spec); @@ -4035,11 +3344,6 @@ if (nghttp2_is_fatal(rv)) { return rv; } - - rv = nghttp2_session_adjust_idle_stream(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } } return session_call_on_frame_received(session, frame); @@ -4060,19 +3364,15 @@ int rv; nghttp2_stream *stream; if (frame->hd.stream_id == 0) { - return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, - "RST_STREAM: stream_id == 0"); - } - - if (session_detect_idle_stream(session, frame->hd.stream_id)) { - return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, - "RST_STREAM: stream in idle"); + return session_handle_invalid_connection( + session, frame, NGHTTP2_PROTOCOL_ERROR, "RST_STREAM: stream_id == 0"); } - stream = nghttp2_session_get_stream(session, frame->hd.stream_id); - if (stream) { - /* We may use stream->shut_flags for strict error checking. */ - nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + if (!stream) { + if (session_detect_idle_stream(session, frame->hd.stream_id)) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_PROTOCOL_ERROR, "RST_STREAM: stream in idle"); + } } rv = session_call_on_frame_received(session, frame); @@ -4109,8 +3409,8 @@ rv = nghttp2_stream_update_remote_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return nghttp2_session_terminate_session(arg->session, + NGHTTP2_FLOW_CONTROL_ERROR); } /* If window size gets positive, push deferred DATA frame to @@ -4118,8 +3418,8 @@ if (stream->remote_window_size > 0 && nghttp2_stream_check_deferred_by_flow_control(stream)) { - rv = nghttp2_stream_resume_deferred_item( - stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); + rv = nghttp2_stream_resume_deferred_data( + stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, arg->session); if (nghttp2_is_fatal(rv)) { return rv; @@ -4145,7 +3445,7 @@ arg.session = session; arg.new_window_size = new_initial_window_size; - arg.old_window_size = (int32_t)session->remote_settings.initial_window_size; + arg.old_window_size = session->remote_settings.initial_window_size; return nghttp2_map_each(&session->streams, update_remote_initial_window_size_func, &arg); @@ -4161,22 +3461,22 @@ rv = nghttp2_stream_update_local_initial_window_size( stream, arg->new_window_size, arg->old_window_size); if (rv != 0) { - return nghttp2_session_add_rst_stream(arg->session, stream->stream_id, - NGHTTP2_FLOW_CONTROL_ERROR); + return nghttp2_session_terminate_session(arg->session, + NGHTTP2_FLOW_CONTROL_ERROR); } - if (!(arg->session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) && - stream->window_update_queued == 0 && - nghttp2_should_send_window_update(stream->local_window_size, - stream->recv_window_size)) { - - rv = nghttp2_session_add_window_update(arg->session, NGHTTP2_FLAG_NONE, - stream->stream_id, - stream->recv_window_size); - if (rv != 0) { - return rv; - } + if (!(arg->session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) { - stream->recv_window_size = 0; + if (nghttp2_should_send_window_update(stream->local_window_size, + stream->recv_window_size)) { + + rv = nghttp2_session_add_window_update(arg->session, NGHTTP2_FLAG_NONE, + stream->stream_id, + stream->recv_window_size); + if (rv != 0) { + return rv; + } + stream->recv_window_size = 0; + } } return 0; } @@ -4222,33 +3522,21 @@ int rv; size_t i; int32_t new_initial_window_size = -1; - uint32_t header_table_size = 0; - uint32_t min_header_table_size = UINT32_MAX; + int32_t header_table_size = -1; uint8_t header_table_size_seen = 0; - /* For NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, use the value last - seen. For NGHTTP2_SETTINGS_HEADER_TABLE_SIZE, use both minimum - value and last seen value. */ + /* Use the value last seen. */ for (i = 0; i < niv; ++i) { switch (iv[i].settings_id) { case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: header_table_size_seen = 1; header_table_size = iv[i].value; - min_header_table_size = nghttp2_min(min_header_table_size, iv[i].value); break; case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: - new_initial_window_size = (int32_t)iv[i].value; + new_initial_window_size = iv[i].value; break; } } if (header_table_size_seen) { - if (min_header_table_size < header_table_size) { - rv = nghttp2_hd_inflate_change_table_size(&session->hd_inflater, - min_header_table_size); - if (rv != 0) { - return rv; - } - } - rv = nghttp2_hd_inflate_change_table_size(&session->hd_inflater, header_table_size); if (rv != 0) { @@ -4258,7 +3546,7 @@ if (new_initial_window_size != -1) { rv = session_update_local_initial_window_size( session, new_initial_window_size, - (int32_t)session->local_settings.initial_window_size); + session->local_settings.initial_window_size); if (rv != 0) { return rv; } @@ -4287,6 +3575,9 @@ } } + session->pending_local_max_concurrent_stream = + NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS; + return 0; } @@ -4294,41 +3585,36 @@ nghttp2_frame *frame, int noack) { int rv; size_t i; - nghttp2_mem *mem; - nghttp2_inflight_settings *settings; - - mem = &session->mem; if (frame->hd.stream_id != 0) { - return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, - "SETTINGS: stream_id != 0"); + return session_handle_invalid_connection( + session, frame, NGHTTP2_PROTOCOL_ERROR, "SETTINGS: stream_id != 0"); } if (frame->hd.flags & NGHTTP2_FLAG_ACK) { if (frame->settings.niv != 0) { return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_FRAME_SIZE_ERROR, + session, frame, NGHTTP2_FRAME_SIZE_ERROR, "SETTINGS: ACK and payload != 0"); } - - settings = session->inflight_settings_head; - - if (!settings) { + if (session->inflight_niv == -1) { return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "SETTINGS: unexpected ACK"); + session, frame, NGHTTP2_PROTOCOL_ERROR, "SETTINGS: unexpected ACK"); } - - rv = nghttp2_session_update_local_settings(session, settings->iv, - settings->niv); - - session->inflight_settings_head = settings->next; - - inflight_settings_del(settings, mem); - + rv = nghttp2_session_update_local_settings(session, session->inflight_iv, + session->inflight_niv); + free(session->inflight_iv); + session->inflight_iv = NULL; + session->inflight_niv = -1; if (rv != 0) { + uint32_t error_code = NGHTTP2_INTERNAL_ERROR; if (nghttp2_is_fatal(rv)) { return rv; } - return session_handle_invalid_connection(session, frame, rv, NULL); + if (rv == NGHTTP2_ERR_HEADER_COMP) { + error_code = NGHTTP2_COMPRESSION_ERROR; + } + return session_handle_invalid_connection(session, frame, error_code, + NULL); } return session_call_on_frame_received(session, frame); } @@ -4339,6 +3625,12 @@ switch (entry->settings_id) { case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: + if (entry->value > NGHTTP2_MAX_HEADER_TABLE_SIZE) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_COMPRESSION_ERROR, + "SETTINGS: too large SETTINGS_HEADER_TABLE_SIZE"); + } + rv = nghttp2_hd_deflate_change_table_size(&session->hd_deflater, entry->value); if (rv != 0) { @@ -4346,7 +3638,7 @@ return rv; } else { return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_HEADER_COMP, NULL); + session, frame, NGHTTP2_COMPRESSION_ERROR, NULL); } } @@ -4357,13 +3649,13 @@ if (entry->value != 0 && entry->value != 1) { return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, + session, frame, NGHTTP2_PROTOCOL_ERROR, "SETTINGS: invalid SETTINGS_ENBLE_PUSH"); } if (!session->server && entry->value != 0) { return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, + session, frame, NGHTTP2_PROTOCOL_ERROR, "SETTINGS: server attempted to enable push"); } @@ -4381,12 +3673,11 @@ /* Check that initial_window_size < (1u << 31) */ if (entry->value > NGHTTP2_MAX_WINDOW_SIZE) { return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_FLOW_CONTROL, + session, frame, NGHTTP2_FLOW_CONTROL_ERROR, "SETTINGS: too large SETTINGS_INITIAL_WINDOW_SIZE"); } - rv = session_update_remote_initial_window_size(session, - (int32_t)entry->value); + rv = session_update_remote_initial_window_size(session, entry->value); if (nghttp2_is_fatal(rv)) { return rv; @@ -4394,7 +3685,7 @@ if (rv != 0) { return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_FLOW_CONTROL, NULL); + session, frame, NGHTTP2_FLOW_CONTROL_ERROR, NULL); } session->remote_settings.initial_window_size = entry->value; @@ -4405,7 +3696,7 @@ if (entry->value < NGHTTP2_MAX_FRAME_SIZE_MIN || entry->value > NGHTTP2_MAX_FRAME_SIZE_MAX) { return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, + session, frame, NGHTTP2_PROTOCOL_ERROR, "SETTINGS: invalid SETTINGS_MAX_FRAME_SIZE"); } @@ -4420,7 +3711,7 @@ } } - if (!noack && !session_is_closing(session)) { + if (!noack) { rv = nghttp2_session_add_settings(session, NGHTTP2_FLAG_ACK, NULL, 0); if (rv != 0) { @@ -4429,7 +3720,7 @@ } return session_handle_invalid_connection(session, frame, - NGHTTP2_ERR_INTERNAL, NULL); + NGHTTP2_INTERNAL_ERROR, NULL); } } @@ -4437,39 +3728,37 @@ } static int session_process_settings_frame(nghttp2_session *session) { + int rv; nghttp2_inbound_frame *iframe = &session->iframe; nghttp2_frame *frame = &iframe->frame; size_t i; nghttp2_settings_entry min_header_size_entry; - if (iframe->max_niv) { - min_header_size_entry = iframe->iv[iframe->max_niv - 1]; + min_header_size_entry = iframe->iv[NGHTTP2_INBOUND_NUM_IV - 1]; - if (min_header_size_entry.value < UINT32_MAX) { - /* If we have less value, then we must have - SETTINGS_HEADER_TABLE_SIZE in i < iframe->niv */ - for (i = 0; i < iframe->niv; ++i) { - if (iframe->iv[i].settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) { - break; - } + if (min_header_size_entry.value < UINT32_MAX) { + /* If we have less value, then we must have + SETTINGS_HEADER_TABLE_SIZE in i < iframe->niv */ + for (i = 0; i < iframe->niv; ++i) { + if (iframe->iv[i].settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) { + break; } + } - assert(i < iframe->niv); + assert(i < iframe->niv); - if (min_header_size_entry.value != iframe->iv[i].value) { - iframe->iv[iframe->niv++] = iframe->iv[i]; - iframe->iv[i] = min_header_size_entry; - } + if (min_header_size_entry.value != iframe->iv[i].value) { + iframe->iv[iframe->niv++] = iframe->iv[i]; + iframe->iv[i] = min_header_size_entry; } } - nghttp2_frame_unpack_settings_payload(&frame->settings, iframe->iv, - iframe->niv); - - iframe->iv = NULL; - iframe->niv = 0; - iframe->max_niv = 0; - + rv = nghttp2_frame_unpack_settings_payload(&frame->settings, iframe->iv, + iframe->niv); + if (rv != 0) { + assert(nghttp2_is_fatal(rv)); + return rv; + } return nghttp2_session_on_settings_received(session, frame, 0 /* ACK */); } @@ -4482,21 +3771,22 @@ if (frame->hd.stream_id == 0) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: stream_id == 0"); + session, frame, NGHTTP2_PROTOCOL_ERROR, "PUSH_PROMISE: stream_id == 0"); } if (session->server || session->local_settings.enable_push == 0) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: push disabled"); + session, frame, NGHTTP2_PROTOCOL_ERROR, "PUSH_PROMISE: push disabled"); + } + if (session->goaway_flags) { + /* We just dicard PUSH_PROMISE after GOAWAY is sent or + received. */ + return NGHTTP2_ERR_IGN_HEADER_BLOCK; } if (!nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: invalid stream_id"); - } - - if (!session_allow_incoming_new_stream(session)) { - /* We just discard PUSH_PROMISE after GOAWAY was sent */ - return NGHTTP2_ERR_IGN_HEADER_BLOCK; + session, frame, NGHTTP2_PROTOCOL_ERROR, + "PUSH_PROMISE: invalid stream_id"); } if (!session_is_new_peer_stream_id(session, @@ -4505,52 +3795,57 @@ illegal stream ID is subject to a connection error of type PROTOCOL_ERROR. */ return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, + session, frame, NGHTTP2_PROTOCOL_ERROR, "PUSH_PROMISE: invalid promised_stream_id"); } - - if (session_detect_idle_stream(session, frame->hd.stream_id)) { - return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: stream in idle"); - } - session->last_recv_stream_id = frame->push_promise.promised_stream_id; stream = nghttp2_session_get_stream(session, frame->hd.stream_id); - if (!stream || stream->state == NGHTTP2_STREAM_CLOSING || - !session->pending_enable_push || - session->num_incoming_reserved_streams >= - session->max_incoming_reserved_streams) { - /* Currently, client does not retain closed stream, so we don't - check NGHTTP2_SHUT_RD condition here. */ - - rv = nghttp2_session_add_rst_stream( - session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL); + if (!stream || stream->state == NGHTTP2_STREAM_CLOSING) { + if (!stream) { + if (session_detect_idle_stream(session, frame->hd.stream_id)) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_PROTOCOL_ERROR, + "PUSH_PROMISE: stream in idle"); + } + } + rv = nghttp2_session_add_rst_stream(session, + frame->push_promise.promised_stream_id, + NGHTTP2_REFUSED_STREAM); if (rv != 0) { return rv; } return NGHTTP2_ERR_IGN_HEADER_BLOCK; } - if (stream->shut_flags & NGHTTP2_SHUT_RD) { - return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_STREAM_CLOSED, - "PUSH_PROMISE: stream closed"); + if (session->callbacks.on_invalid_frame_recv_callback) { + if (session->callbacks.on_invalid_frame_recv_callback( + session, frame, NGHTTP2_PROTOCOL_ERROR, session->user_data) != + 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + } + rv = nghttp2_session_add_rst_stream(session, + frame->push_promise.promised_stream_id, + NGHTTP2_PROTOCOL_ERROR); + if (rv != 0) { + return rv; + } + return NGHTTP2_ERR_IGN_HEADER_BLOCK; } + /* TODO It is unclear reserved stream dpeneds on associated + stream with or without exclusive flag set */ nghttp2_priority_spec_init(&pri_spec, stream->stream_id, NGHTTP2_DEFAULT_WEIGHT, 0); promised_stream = nghttp2_session_open_stream( - session, frame->push_promise.promised_stream_id, NGHTTP2_STREAM_FLAG_NONE, + session, frame->push_promise.promised_stream_id, NGHTTP2_STREAM_FLAG_PUSH, &pri_spec, NGHTTP2_STREAM_RESERVED, NULL); if (!promised_stream) { return NGHTTP2_ERR_NOMEM; } - /* We don't call nghttp2_session_adjust_closed_stream(), since we - don't keep closed stream in client side */ - session->last_proc_stream_id = session->last_recv_stream_id; rv = session_call_on_begin_headers(session, frame); if (rv != 0) { @@ -4579,12 +3874,10 @@ nghttp2_frame *frame) { int rv = 0; if (frame->hd.stream_id != 0) { - return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, - "PING: stream_id != 0"); + return session_handle_invalid_connection( + session, frame, NGHTTP2_PROTOCOL_ERROR, "PING: stream_id != 0"); } - if ((session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK) == 0 && - (frame->hd.flags & NGHTTP2_FLAG_ACK) == 0 && - !session_is_closing(session)) { + if ((frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) { /* Peer sent ping, so ping it back */ rv = nghttp2_session_add_ping(session, NGHTTP2_FLAG_ACK, frame->ping.opaque_data); @@ -4610,8 +3903,8 @@ int rv; if (frame->hd.stream_id != 0) { - return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, - "GOAWAY: stream_id != 0"); + return session_handle_invalid_connection( + session, frame, NGHTTP2_PROTOCOL_ERROR, "GOAWAY: stream_id != 0"); } /* Spec says Endpoints MUST NOT increase the value they send in the last stream identifier. */ @@ -4619,12 +3912,11 @@ !nghttp2_session_is_my_stream_id(session, frame->goaway.last_stream_id)) || session->remote_last_stream_id < frame->goaway.last_stream_id) { - return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + return session_handle_invalid_connection(session, frame, + NGHTTP2_PROTOCOL_ERROR, "GOAWAY: invalid last_stream_id"); } - session->goaway_flags |= NGHTTP2_GOAWAY_RECV; - session->remote_last_stream_id = frame->goaway.last_stream_id; rv = session_call_on_frame_received(session, frame); @@ -4650,20 +3942,49 @@ return nghttp2_session_on_goaway_received(session, frame); } +int nghttp2_session_on_altsvc_received(nghttp2_session *session, + nghttp2_frame *frame) { + /* ALTSVC is exptected to be received by client only. We have + already rejected ALTSVC if it is received by server. */ + if (frame->hd.stream_id != 0 && + !nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_PROTOCOL_ERROR, "ALTSVC: invalid stream_id"); + } + + return session_call_on_frame_received(session, frame); +} + +static int session_process_altsvc_frame(nghttp2_session *session) { + nghttp2_inbound_frame *iframe = &session->iframe; + nghttp2_frame *frame = &iframe->frame; + int rv; + + frame->ext.payload = &iframe->ext_frame_payload; + + rv = nghttp2_frame_unpack_altsvc_payload( + &frame->ext, iframe->sbuf.pos, nghttp2_buf_len(&iframe->sbuf), + iframe->lbuf.pos, nghttp2_buf_len(&iframe->lbuf)); + + if (rv != 0) { + return session_handle_invalid_connection( + session, frame, NGHTTP2_FRAME_SIZE_ERROR, "ALTSVC: could not unpack"); + } + + nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0); + + return nghttp2_session_on_altsvc_received(session, frame); +} + static int session_on_connection_window_update_received(nghttp2_session *session, nghttp2_frame *frame) { /* Handle connection-level flow control */ - if (frame->window_update.window_size_increment == 0) { - return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, - "WINDOW_UPDATE: window_size_increment == 0"); - } - - if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < - session->remote_window_size) { + if (frame->window_update.window_size_increment == 0 || + NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < + session->remote_window_size) { return session_handle_invalid_connection(session, frame, - NGHTTP2_ERR_FLOW_CONTROL, NULL); + NGHTTP2_FLOW_CONTROL_ERROR, NULL); } session->remote_window_size += frame->window_update.window_size_increment; @@ -4674,37 +3995,33 @@ nghttp2_frame *frame) { int rv; nghttp2_stream *stream; - - if (session_detect_idle_stream(session, frame->hd.stream_id)) { - return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, - "WINDOW_UPDATE to idle stream"); - } - stream = nghttp2_session_get_stream(session, frame->hd.stream_id); if (!stream) { + if (session_detect_idle_stream(session, frame->hd.stream_id)) { + return session_handle_invalid_connection(session, frame, + NGHTTP2_PROTOCOL_ERROR, + "WINDOW_UPDATE to idle stream"); + } return 0; } if (state_reserved_remote(session, stream)) { return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "WINDOW_UPADATE to reserved stream"); - } - if (frame->window_update.window_size_increment == 0) { - return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, - "WINDOW_UPDATE: window_size_increment == 0"); + session, frame, NGHTTP2_PROTOCOL_ERROR, + "WINDOW_UPADATE to reserved stream"); } - if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < - stream->remote_window_size) { + if (frame->window_update.window_size_increment == 0 || + NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < + stream->remote_window_size) { return session_handle_invalid_stream(session, frame, - NGHTTP2_ERR_FLOW_CONTROL); + NGHTTP2_FLOW_CONTROL_ERROR); } stream->remote_window_size += frame->window_update.window_size_increment; if (stream->remote_window_size > 0 && nghttp2_stream_check_deferred_by_flow_control(stream)) { - rv = nghttp2_stream_resume_deferred_item( - stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); + rv = nghttp2_stream_resume_deferred_data( + stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, session); if (nghttp2_is_fatal(rv)) { return rv; @@ -4732,74 +4049,21 @@ return nghttp2_session_on_window_update_received(session, frame); } -int nghttp2_session_on_altsvc_received(nghttp2_session *session, - nghttp2_frame *frame) { - nghttp2_ext_altsvc *altsvc; - nghttp2_stream *stream; - - altsvc = frame->ext.payload; - - /* session->server case has been excluded */ - - if (frame->hd.stream_id == 0) { - if (altsvc->origin_len == 0) { - return 0; - } - } else { - if (altsvc->origin_len > 0) { - return 0; - } - - stream = nghttp2_session_get_stream(session, frame->hd.stream_id); - if (!stream) { - return 0; - } - - if (stream->state == NGHTTP2_STREAM_CLOSING) { - return 0; - } - } - - return session_call_on_frame_received(session, frame); -} - -static int session_process_altsvc_frame(nghttp2_session *session) { - nghttp2_inbound_frame *iframe = &session->iframe; - nghttp2_frame *frame = &iframe->frame; - - nghttp2_frame_unpack_altsvc_payload( - &frame->ext, nghttp2_get_uint16(iframe->sbuf.pos), iframe->lbuf.pos, - nghttp2_buf_len(&iframe->lbuf)); - - /* nghttp2_frame_unpack_altsvc_payload steals buffer from - iframe->lbuf */ - nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0); - - return nghttp2_session_on_altsvc_received(session, frame); -} - -static int session_process_extension_frame(nghttp2_session *session) { - int rv; - nghttp2_inbound_frame *iframe = &session->iframe; - nghttp2_frame *frame = &iframe->frame; - - rv = session_call_unpack_extension_callback(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - /* This handles the case where rv == NGHTTP2_ERR_CANCEL as well */ - if (rv != 0) { - return 0; - } - - return session_call_on_frame_received(session, frame); -} +/* static int get_error_code_from_lib_error_code(int lib_error_code) */ +/* { */ +/* switch(lib_error_code) { */ +/* case NGHTTP2_ERR_HEADER_COMP: */ +/* return NGHTTP2_COMPRESSION_ERROR; */ +/* case NGHTTP2_ERR_FRAME_SIZE_ERROR: */ +/* return NGHTTP2_FRAME_SIZE_ERROR; */ +/* default: */ +/* return NGHTTP2_PROTOCOL_ERROR; */ +/* } */ +/* } */ int nghttp2_session_on_data_received(nghttp2_session *session, nghttp2_frame *frame) { int rv = 0; - int call_cb = 1; nghttp2_stream *stream; /* We don't call on_frame_recv_callback if stream has been closed @@ -4812,23 +4076,9 @@ return 0; } - if (session_enforce_http_messaging(session) && - (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { - if (nghttp2_http_on_remote_end_stream(stream) != 0) { - call_cb = 0; - rv = nghttp2_session_add_rst_stream(session, stream->stream_id, - NGHTTP2_PROTOCOL_ERROR); - if (nghttp2_is_fatal(rv)) { - return rv; - } - } - } - - if (call_cb) { - rv = session_call_on_frame_received(session, frame); - if (nghttp2_is_fatal(rv)) { - return rv; - } + rv = session_call_on_frame_received(session, frame); + if (nghttp2_is_fatal(rv)) { + return rv; } if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { @@ -4868,7 +4118,7 @@ *recv_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - (int32_t)delta) { return -1; } - *recv_window_size_ptr += (int32_t)delta; + *recv_window_size_ptr += delta; return 0; } @@ -4897,21 +4147,21 @@ } /* We don't have to send WINDOW_UPDATE if the data received is the last chunk in the incoming stream. */ - /* We have to use local_settings here because it is the constraint - the remote endpoint should honor. */ if (send_window_update && - !(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) && - stream->window_update_queued == 0 && - nghttp2_should_send_window_update(stream->local_window_size, - stream->recv_window_size)) { - rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, - stream->stream_id, - stream->recv_window_size); - if (rv != 0) { - return rv; + !(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) { + /* We have to use local_settings here because it is the constraint + the remote endpoint should honor. */ + if (nghttp2_should_send_window_update(stream->local_window_size, + stream->recv_window_size)) { + rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, + stream->stream_id, + stream->recv_window_size); + if (rv == 0) { + stream->recv_window_size = 0; + } else { + return rv; + } } - - stream->recv_window_size = 0; } return 0; } @@ -4937,19 +4187,20 @@ return nghttp2_session_terminate_session(session, NGHTTP2_FLOW_CONTROL_ERROR); } - if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) && - session->window_update_queued == 0 && - nghttp2_should_send_window_update(session->local_window_size, - session->recv_window_size)) { - /* Use stream ID 0 to update connection-level flow control - window */ - rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, 0, - session->recv_window_size); - if (rv != 0) { - return rv; - } + if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) { + + if (nghttp2_should_send_window_update(session->local_window_size, + session->recv_window_size)) { + /* Use stream ID 0 to update connection-level flow control + window */ + rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, 0, + session->recv_window_size); + if (rv != 0) { + return rv; + } - session->recv_window_size = 0; + session->recv_window_size = 0; + } } return 0; } @@ -4957,7 +4208,6 @@ static int session_update_consumed_size(nghttp2_session *session, int32_t *consumed_size_ptr, int32_t *recv_window_size_ptr, - uint8_t window_update_queued, int32_t stream_id, size_t delta_size, int32_t local_window_size) { int32_t recv_size; @@ -4968,25 +4218,23 @@ NGHTTP2_FLOW_CONTROL_ERROR); } - *consumed_size_ptr += (int32_t)delta_size; + *consumed_size_ptr += delta_size; - if (window_update_queued == 0) { - /* recv_window_size may be smaller than consumed_size, because it - may be decreased by negative value with - nghttp2_submit_window_update(). */ - recv_size = nghttp2_min(*consumed_size_ptr, *recv_window_size_ptr); + /* recv_window_size may be smaller than consumed_size, because it + may be decreased by negative value with + nghttp2_submit_window_update(). */ + recv_size = nghttp2_min(*consumed_size_ptr, *recv_window_size_ptr); - if (nghttp2_should_send_window_update(local_window_size, recv_size)) { - rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, - stream_id, recv_size); - - if (rv != 0) { - return rv; - } + if (nghttp2_should_send_window_update(local_window_size, recv_size)) { + rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, + stream_id, recv_size); - *recv_window_size_ptr -= recv_size; - *consumed_size_ptr -= recv_size; + if (rv != 0) { + return rv; } + + *recv_window_size_ptr -= recv_size; + *consumed_size_ptr -= recv_size; } return 0; @@ -4997,15 +4245,14 @@ size_t delta_size) { return session_update_consumed_size( session, &stream->consumed_size, &stream->recv_window_size, - stream->window_update_queued, stream->stream_id, delta_size, - stream->local_window_size); + stream->stream_id, delta_size, stream->local_window_size); } static int session_update_connection_consumed_size(nghttp2_session *session, size_t delta_size) { - return session_update_consumed_size( - session, &session->consumed_size, &session->recv_window_size, - session->window_update_queued, 0, delta_size, session->local_window_size); + return session_update_consumed_size(session, &session->consumed_size, + &session->recv_window_size, 0, delta_size, + session->local_window_size); } /* @@ -5031,7 +4278,6 @@ nghttp2_inbound_frame *iframe; int32_t stream_id; const char *failure_reason; - uint32_t error_code = NGHTTP2_PROTOCOL_ERROR; iframe = &session->iframe; stream_id = iframe->frame.hd.stream_id; @@ -5043,27 +4289,16 @@ failure_reason = "DATA: stream_id == 0"; goto fail; } - - if (session_detect_idle_stream(session, stream_id)) { - failure_reason = "DATA: stream in idle"; - error_code = NGHTTP2_PROTOCOL_ERROR; - goto fail; - } - stream = nghttp2_session_get_stream(session, stream_id); if (!stream) { - stream = nghttp2_session_get_stream_raw(session, stream_id); - if (stream && (stream->shut_flags & NGHTTP2_SHUT_RD)) { - failure_reason = "DATA: stream closed"; - error_code = NGHTTP2_STREAM_CLOSED; + if (session_detect_idle_stream(session, stream_id)) { + failure_reason = "DATA: stream in idle"; goto fail; } - return NGHTTP2_ERR_IGN_PAYLOAD; } if (stream->shut_flags & NGHTTP2_SHUT_RD) { failure_reason = "DATA: stream in half-closed(remote)"; - error_code = NGHTTP2_STREAM_CLOSED; goto fail; } @@ -5086,8 +4321,8 @@ } return 0; fail: - rv = nghttp2_session_terminate_session_with_reason(session, error_code, - failure_reason); + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, failure_reason); if (nghttp2_is_fatal(rv)) { return rv; } @@ -5112,8 +4347,7 @@ const uint8_t *in, const uint8_t *last) { size_t readlen; - readlen = - nghttp2_min((size_t)(last - in), nghttp2_buf_mark_avail(&iframe->sbuf)); + readlen = nghttp2_min(last - in, nghttp2_buf_mark_avail(&iframe->sbuf)); iframe->sbuf.last = nghttp2_cpymem(iframe->sbuf.last, in, readlen); @@ -5125,7 +4359,6 @@ */ static void inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe) { nghttp2_settings_entry iv; - nghttp2_settings_entry *min_header_table_size_entry; size_t i; nghttp2_frame_unpack_settings_entry(&iv, iframe->sbuf.pos); @@ -5139,11 +4372,8 @@ case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: break; default: - DEBUGF( - fprintf(stderr, "recv: unknown settings id=0x%02x\n", iv.settings_id)); - - iframe->iv[iframe->niv++] = iv; - + DEBUGF(fprintf(stderr, "recv: ignore unknown settings id=0x%02x\n", + iv.settings_id)); return; } @@ -5158,13 +4388,10 @@ iframe->iv[iframe->niv++] = iv; } - if (iv.settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) { - /* Keep track of minimum value of SETTINGS_HEADER_TABLE_SIZE */ - min_header_table_size_entry = &iframe->iv[iframe->max_niv - 1]; + if (iv.settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE && + iv.value < iframe->iv[NGHTTP2_INBOUND_NUM_IV - 1].value) { - if (iv.value < min_header_table_size_entry->value) { - min_header_table_size_entry->value = iv.value; - } + iframe->iv[NGHTTP2_INBOUND_NUM_IV - 1] = iv; } } @@ -5194,7 +4421,7 @@ size_t padlen; /* 1 for Pad Length field */ - padlen = (size_t)(iframe->sbuf.pos[0] + 1); + padlen = iframe->sbuf.pos[0] + 1; DEBUGF(fprintf(stderr, "recv: padlen=%zu\n", padlen)); @@ -5205,7 +4432,7 @@ iframe->padlen = padlen; - return (ssize_t)padlen; + return padlen; } /* @@ -5225,10 +4452,11 @@ padlen = trail_padlen - payloadleft; if (readlen < padlen) { return -1; + } else { + return readlen - padlen; } - return (ssize_t)(readlen - padlen); } - return (ssize_t)(readlen); + return readlen; } ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, @@ -5242,31 +4470,21 @@ nghttp2_frame_hd cont_hd; nghttp2_stream *stream; size_t pri_fieldlen; - nghttp2_mem *mem; DEBUGF(fprintf(stderr, "recv: connection recv_window_size=%d, local_window=%d\n", session->recv_window_size, session->local_window_size)); - mem = &session->mem; - - /* We may have idle streams more than we expect (e.g., - nghttp2_session_change_stream_priority() or - nghttp2_session_create_idle_stream()). Adjust them here. */ - rv = nghttp2_session_adjust_idle_stream(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - for (;;) { switch (iframe->state) { - case NGHTTP2_IB_READ_CLIENT_MAGIC: + case NGHTTP2_IB_READ_CLIENT_PREFACE: readlen = nghttp2_min(inlen, iframe->payloadleft); - if (memcmp(NGHTTP2_CLIENT_MAGIC + NGHTTP2_CLIENT_MAGIC_LEN - + if (memcmp(NGHTTP2_CLIENT_CONNECTION_PREFACE + + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - iframe->payloadleft, in, readlen) != 0) { - return NGHTTP2_ERR_BAD_CLIENT_MAGIC; + return NGHTTP2_ERR_BAD_PREFACE; } iframe->payloadleft -= readlen; @@ -5288,19 +4506,13 @@ return in - first; } - if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS || - (iframe->sbuf.pos[4] & NGHTTP2_FLAG_ACK)) { + if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS) { + nghttp2_frame_unpack_frame_hd(&iframe->frame.hd, iframe->sbuf.pos); + iframe->payloadleft = iframe->frame.hd.length; - iframe->state = NGHTTP2_IB_IGN_ALL; - - rv = session_call_error_callback( - session, "Remote peer returned unexpected data while we expected " - "SETTINGS frame. Perhaps, peer does not support HTTP/2 " - "properly."); + busy = 1; - if (nghttp2_is_fatal(rv)) { - return rv; - } + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; rv = nghttp2_session_terminate_session_with_reason( session, NGHTTP2_PROTOCOL_ERROR, "SETTINGS expected"); @@ -5309,7 +4521,7 @@ return rv; } - return (ssize_t)inlen; + break; } iframe->state = NGHTTP2_IB_READ_HEAD; @@ -5459,16 +4671,6 @@ busy = 1; - if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); - if (nghttp2_is_fatal(rv)) { - return rv; - } - iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; - break; - } - if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) { iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; break; @@ -5537,25 +4739,6 @@ iframe->state = NGHTTP2_IB_READ_SETTINGS; if (iframe->payloadleft) { - nghttp2_settings_entry *min_header_table_size_entry; - - /* We allocate iv with addtional one entry, to store the - minimum header table size. */ - iframe->max_niv = - iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1; - - iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) * - iframe->max_niv); - - if (!iframe->iv) { - return NGHTTP2_ERR_NOMEM; - } - - min_header_table_size_entry = &iframe->iv[iframe->max_niv - 1]; - min_header_table_size_entry->settings_id = - NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; - min_header_table_size_entry->value = UINT32_MAX; - inbound_frame_set_mark(iframe, NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH); break; } @@ -5646,67 +4829,48 @@ iframe->state = NGHTTP2_IB_IGN_PAYLOAD; break; - default: - DEBUGF(fprintf(stderr, "recv: extension frame\n")); - - if (check_ext_type_set(session->user_recv_ext_types, - iframe->frame.hd.type)) { - if (!session->callbacks.unpack_extension_callback) { - /* Silently ignore unknown frame type. */ + case NGHTTP2_EXT_ALTSVC: + DEBUGF(fprintf(stderr, "recv: ALTSVC\n")); - busy = 1; - - iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + iframe->frame.hd.flags = NGHTTP2_FLAG_NONE; - break; + if (session->server) { + rv = nghttp2_session_terminate_session_with_reason( + session, NGHTTP2_PROTOCOL_ERROR, + "ALTSVC: reserved for server only"); + if (nghttp2_is_fatal(rv)) { + return rv; } busy = 1; - iframe->state = NGHTTP2_IB_READ_EXTENSION_PAYLOAD; + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; break; - } else { - switch (iframe->frame.hd.type) { - case NGHTTP2_ALTSVC: - if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ALTSVC) == - 0) { - busy = 1; - iframe->state = NGHTTP2_IB_IGN_PAYLOAD; - break; - } + } - DEBUGF(fprintf(stderr, "recv: ALTSVC\n")); + if (iframe->payloadleft < NGHTTP2_ALTSVC_MINLEN) { + busy = 1; - iframe->frame.hd.flags = NGHTTP2_FLAG_NONE; - iframe->frame.ext.payload = &iframe->ext_frame_payload.altsvc; + iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; - if (session->server) { - busy = 1; - iframe->state = NGHTTP2_IB_IGN_PAYLOAD; - break; - } + break; + } - if (iframe->payloadleft < 2) { - busy = 1; - iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; - break; - } + iframe->state = NGHTTP2_IB_READ_NBYTE; + inbound_frame_set_mark(iframe, NGHTTP2_ALTSVC_FIXED_PARTLEN); - busy = 1; + break; + default: + DEBUGF(fprintf(stderr, "recv: unknown frame\n")); - iframe->state = NGHTTP2_IB_READ_NBYTE; - inbound_frame_set_mark(iframe, 2); + /* Silently ignore unknown frame type. */ - break; - default: - busy = 1; + busy = 1; - iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + iframe->state = NGHTTP2_IB_IGN_PAYLOAD; - break; - } - } + break; } if (!on_begin_frame_called) { @@ -5757,7 +4921,7 @@ iframe->state = NGHTTP2_IB_IGN_PAYLOAD; break; } - iframe->frame.headers.padlen = (size_t)padlen; + iframe->frame.headers.padlen = padlen; pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags); @@ -5783,16 +4947,6 @@ busy = 1; - if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); - if (nghttp2_is_fatal(rv)) { - return rv; - } - iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; - break; - } - if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) { iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; break; @@ -5835,7 +4989,7 @@ break; } - iframe->frame.push_promise.padlen = (size_t)padlen; + iframe->frame.push_promise.padlen = padlen; if (iframe->payloadleft < 4) { busy = 1; @@ -5857,17 +5011,6 @@ busy = 1; - if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.push_promise.promised_stream_id, - NGHTTP2_INTERNAL_ERROR); - if (nghttp2_is_fatal(rv)) { - return rv; - } - iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; - break; - } - if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) { iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK; break; @@ -5892,7 +5035,7 @@ debuglen = iframe->frame.hd.length - 8; if (debuglen > 0) { - iframe->raw_lbuf = nghttp2_mem_malloc(mem, debuglen); + iframe->raw_lbuf = malloc(debuglen); if (iframe->raw_lbuf == NULL) { return NGHTTP2_ERR_NOMEM; @@ -5916,34 +5059,24 @@ session_inbound_frame_reset(session); break; - case NGHTTP2_ALTSVC: { - size_t origin_len; - - origin_len = nghttp2_get_uint16(iframe->sbuf.pos); + case NGHTTP2_EXT_ALTSVC: { + size_t varlen; - DEBUGF(fprintf(stderr, "recv: origin_len=%zu\n", origin_len)); + varlen = iframe->frame.hd.length - NGHTTP2_ALTSVC_FIXED_PARTLEN; - if (2 + origin_len > iframe->payloadleft) { - busy = 1; - iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR; - break; - } - - if (iframe->frame.hd.length > 2) { - iframe->raw_lbuf = - nghttp2_mem_malloc(mem, iframe->frame.hd.length - 2); + if (varlen > 0) { + iframe->raw_lbuf = malloc(varlen); if (iframe->raw_lbuf == NULL) { return NGHTTP2_ERR_NOMEM; } - nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf, - iframe->frame.hd.length); + nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf, varlen); } busy = 1; - iframe->state = NGHTTP2_IB_READ_ALTSVC_PAYLOAD; + iframe->state = NGHTTP2_IB_READ_ALTSVC; break; } @@ -5957,8 +5090,6 @@ case NGHTTP2_IB_READ_HEADER_BLOCK: case NGHTTP2_IB_IGN_HEADER_BLOCK: { ssize_t data_readlen; - size_t trail_padlen; - int final; #ifdef DEBUGBUILD if (iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) { fprintf(stderr, "recv: [IB_READ_HEADER_BLOCK]\n"); @@ -5974,20 +5105,20 @@ data_readlen = inbound_frame_effective_readlen( iframe, iframe->payloadleft - readlen, readlen); - trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen); - - final = (iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) && - iframe->payloadleft - (size_t)data_readlen == trail_padlen; - - if (data_readlen > 0 || (data_readlen == 0 && final)) { + if (data_readlen >= 0) { + size_t trail_padlen; size_t hd_proclen = 0; - - DEBUGF(fprintf(stderr, "recv: block final=%d\n", final)); - - rv = - inflate_header_block(session, &iframe->frame, &hd_proclen, - (uint8_t *)in, (size_t)data_readlen, final, - iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK); + trail_padlen = + nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen); + DEBUGF(fprintf(stderr, "recv: block final=%d\n", + (iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) && + iframe->payloadleft - data_readlen == trail_padlen)); + + rv = inflate_header_block( + session, &iframe->frame, &hd_proclen, (uint8_t *)in, data_readlen, + (iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) && + iframe->payloadleft - data_readlen == trail_padlen, + iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK); if (nghttp2_is_fatal(rv)) { return rv; @@ -6007,12 +5138,8 @@ in += hd_proclen; iframe->payloadleft -= hd_proclen; - /* Use promised stream ID for PUSH_PROMISE */ rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE - ? iframe->frame.push_promise.promised_stream_id - : iframe->frame.hd.stream_id, - NGHTTP2_INTERNAL_ERROR); + session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6138,16 +5265,21 @@ break; case NGHTTP2_IB_READ_GOAWAY_DEBUG: - DEBUGF(fprintf(stderr, "recv: [IB_READ_GOAWAY_DEBUG]\n")); + case NGHTTP2_IB_READ_ALTSVC: +#ifdef DEBUGBUILD + if (iframe->state == NGHTTP2_IB_READ_GOAWAY_DEBUG) { + fprintf(stderr, "recv: [IB_READ_GOAWAY_DEBUG]\n"); + } else { + fprintf(stderr, "recv: [IB_READ_ALTSVC]\n"); + } +#endif /* DEBUGBUILD */ readlen = inbound_frame_payload_readlen(iframe, in, last); - if (readlen > 0) { - iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen); + iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen); - iframe->payloadleft -= readlen; - in += readlen; - } + iframe->payloadleft -= readlen; + in += readlen; DEBUGF(fprintf(stderr, "recv: readlen=%zu, payloadleft=%zu\n", readlen, iframe->payloadleft)); @@ -6158,7 +5290,11 @@ break; } - rv = session_process_goaway_frame(session); + if (iframe->state == NGHTTP2_IB_READ_GOAWAY_DEBUG) { + rv = session_process_goaway_frame(session); + } else { + rv = session_process_altsvc_frame(session); + } if (nghttp2_is_fatal(rv)) { return rv; @@ -6195,7 +5331,7 @@ if (cont_hd.type != NGHTTP2_CONTINUATION || cont_hd.stream_id != iframe->frame.hd.stream_id) { DEBUGF(fprintf(stderr, "recv: expected stream_id=%d, type=%d, but " - "got stream_id=%d, type=%u\n", + "got stream_id=%d, type=%d\n", iframe->frame.hd.stream_id, NGHTTP2_CONTINUATION, cont_hd.stream_id, cont_hd.type)); rv = nghttp2_session_terminate_session_with_reason( @@ -6214,8 +5350,7 @@ /* CONTINUATION won't bear NGHTTP2_PADDED flag */ - iframe->frame.hd.flags = (uint8_t)( - iframe->frame.hd.flags | (cont_hd.flags & NGHTTP2_FLAG_END_HEADERS)); + iframe->frame.hd.flags |= cont_hd.flags & NGHTTP2_FLAG_END_HEADERS; iframe->frame.hd.length += cont_hd.length; busy = 1; @@ -6286,20 +5421,12 @@ break; } - iframe->frame.data.padlen = (size_t)padlen; + iframe->frame.data.padlen = padlen; iframe->state = NGHTTP2_IB_READ_DATA; break; case NGHTTP2_IB_READ_DATA: - stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id); - - if (!stream) { - busy = 1; - iframe->state = NGHTTP2_IB_IGN_DATA; - break; - } - DEBUGF(fprintf(stderr, "recv: [IB_READ_DATA]\n")); readlen = inbound_frame_payload_readlen(iframe, in, last); @@ -6317,155 +5444,55 @@ return rv; } - rv = session_update_recv_stream_window_size( - session, stream, readlen, - iframe->payloadleft || - (iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0); - if (nghttp2_is_fatal(rv)) { - return rv; + stream = + nghttp2_session_get_stream(session, iframe->frame.hd.stream_id); + if (stream) { + rv = session_update_recv_stream_window_size( + session, stream, readlen, + iframe->payloadleft || + (iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0); + if (nghttp2_is_fatal(rv)) { + return rv; + } } data_readlen = inbound_frame_effective_readlen( iframe, iframe->payloadleft, readlen); - if (data_readlen == -1) { - /* everything is padding */ - data_readlen = 0; - } - - padlen = (ssize_t)readlen - data_readlen; + padlen = readlen - data_readlen; if (padlen > 0) { /* Padding is considered as "consumed" immediately */ rv = nghttp2_session_consume(session, iframe->frame.hd.stream_id, - (size_t)padlen); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - } - - DEBUGF(fprintf(stderr, "recv: data_readlen=%zd\n", data_readlen)); - - if (data_readlen > 0) { - if (session_enforce_http_messaging(session)) { - if (nghttp2_http_on_data_chunk(stream, (size_t)data_readlen) != 0) { - if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { - /* Consume all data for connection immediately here */ - rv = session_update_connection_consumed_size( - session, (size_t)data_readlen); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - } - - rv = nghttp2_session_add_rst_stream( - session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR); - if (nghttp2_is_fatal(rv)) { - return rv; - } - busy = 1; - iframe->state = NGHTTP2_IB_IGN_DATA; - break; - } - } - if (session->callbacks.on_data_chunk_recv_callback) { - rv = session->callbacks.on_data_chunk_recv_callback( - session, iframe->frame.hd.flags, iframe->frame.hd.stream_id, - in - readlen, (size_t)data_readlen, session->user_data); - if (rv == NGHTTP2_ERR_PAUSE) { - return in - first; - } - - if (nghttp2_is_fatal(rv)) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - } - } - } - - if (iframe->payloadleft) { - break; - } - - rv = session_process_data_frame(session); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - session_inbound_frame_reset(session); - - break; - case NGHTTP2_IB_IGN_DATA: - DEBUGF(fprintf(stderr, "recv: [IB_IGN_DATA]\n")); - - readlen = inbound_frame_payload_readlen(iframe, in, last); - iframe->payloadleft -= readlen; - in += readlen; - - DEBUGF(fprintf(stderr, "recv: readlen=%zu, payloadleft=%zu\n", readlen, - iframe->payloadleft)); - - if (readlen > 0) { - /* Update connection-level flow control window for ignored - DATA frame too */ - rv = session_update_recv_connection_window_size(session, readlen); - if (nghttp2_is_fatal(rv)) { - return rv; - } - - if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { - - /* Ignored DATA is considered as "consumed" immediately. */ - rv = session_update_connection_consumed_size(session, readlen); + padlen); if (nghttp2_is_fatal(rv)) { return rv; } } - } - - if (iframe->payloadleft) { - break; - } - - session_inbound_frame_reset(session); - - break; - case NGHTTP2_IB_IGN_ALL: - return (ssize_t)inlen; - case NGHTTP2_IB_READ_EXTENSION_PAYLOAD: - DEBUGF(fprintf(stderr, "recv: [IB_READ_EXTENSION_PAYLOAD]\n")); - - readlen = inbound_frame_payload_readlen(iframe, in, last); - iframe->payloadleft -= readlen; - in += readlen; - - DEBUGF(fprintf(stderr, "recv: readlen=%zu, payloadleft=%zu\n", readlen, - iframe->payloadleft)); - - if (readlen > 0) { - rv = session_call_on_extension_chunk_recv_callback( - session, in - readlen, readlen); - if (nghttp2_is_fatal(rv)) { - return rv; - } - if (rv != 0) { - busy = 1; + DEBUGF(fprintf(stderr, "recv: data_readlen=%zd\n", data_readlen)); - iframe->state = NGHTTP2_IB_IGN_PAYLOAD; + if (stream && data_readlen > 0 && + session->callbacks.on_data_chunk_recv_callback) { + rv = session->callbacks.on_data_chunk_recv_callback( + session, iframe->frame.hd.flags, iframe->frame.hd.stream_id, + in - readlen, data_readlen, session->user_data); + if (rv == NGHTTP2_ERR_PAUSE) { + return in - first; + } - break; + if (nghttp2_is_fatal(rv)) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } } } - if (iframe->payloadleft > 0) { + if (iframe->payloadleft) { break; } - rv = session_process_extension_frame(session); + rv = session_process_data_frame(session); if (nghttp2_is_fatal(rv)) { return rv; } @@ -6473,31 +5500,37 @@ session_inbound_frame_reset(session); break; - case NGHTTP2_IB_READ_ALTSVC_PAYLOAD: - DEBUGF(fprintf(stderr, "recv: [IB_READ_ALTSVC_PAYLOAD]\n")); + case NGHTTP2_IB_IGN_DATA: + DEBUGF(fprintf(stderr, "recv: [IB_IGN_DATA]\n")); readlen = inbound_frame_payload_readlen(iframe, in, last); - - if (readlen > 0) { - iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen); - - iframe->payloadleft -= readlen; - in += readlen; - } + iframe->payloadleft -= readlen; + in += readlen; DEBUGF(fprintf(stderr, "recv: readlen=%zu, payloadleft=%zu\n", readlen, iframe->payloadleft)); - if (iframe->payloadleft) { - assert(nghttp2_buf_avail(&iframe->lbuf) > 0); + if (readlen > 0) { + /* Update connection-level flow control window for ignored + DATA frame too */ + rv = session_update_recv_connection_window_size(session, readlen); + if (nghttp2_is_fatal(rv)) { + return rv; + } - break; - } + if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) { - rv = session_process_altsvc_frame(session); + /* Ignored DATA is considered as "consumed" immediately. */ + rv = session_update_connection_consumed_size(session, readlen); - if (nghttp2_is_fatal(rv)) { - return rv; + if (nghttp2_is_fatal(rv)) { + return rv; + } + } + } + + if (iframe->payloadleft) { + break; } session_inbound_frame_reset(session); @@ -6523,7 +5556,7 @@ ssize_t readlen; readlen = session_recv(session, buf, sizeof(buf)); if (readlen > 0) { - ssize_t proclen = nghttp2_session_mem_recv(session, buf, (size_t)readlen); + ssize_t proclen = nghttp2_session_mem_recv(session, buf, readlen); if (proclen < 0) { return (int)proclen; } @@ -6543,16 +5576,16 @@ * reserved state. */ static size_t session_get_num_active_streams(nghttp2_session *session) { - return nghttp2_map_size(&session->streams) - session->num_closed_streams - - session->num_idle_streams; + return nghttp2_map_size(&session->streams) - session->num_closed_streams; } int nghttp2_session_want_read(nghttp2_session *session) { size_t num_active_streams; - /* If this flag is set, we don't want to read. The application + /* If these flags are set, we don't want to read. The application should drop the connection. */ - if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_SENT) { + if ((session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) && + (session->goaway_flags & NGHTTP2_GOAWAY_TERM_SENT)) { return 0; } @@ -6565,19 +5598,31 @@ return 1; } - /* If there is no active streams and GOAWAY has been sent or - received, we are done with this session. */ - return (session->goaway_flags & - (NGHTTP2_GOAWAY_SENT | NGHTTP2_GOAWAY_RECV)) == 0; + /* If there is no active streams, we check last_stream_id peer sent + to us. Here is the asymmetry between server and client. For + server, if client cannot make new request, current conneciton is + no use. Server push might be going, but it is idempotent and can + be safely retried with the new connection. For client side, the + theory is the same. */ + if (session->server) { + return session->local_last_stream_id > session->last_recv_stream_id; + } else { + return (uint32_t)session->remote_last_stream_id >= session->next_stream_id; + } } int nghttp2_session_want_write(nghttp2_session *session) { - /* If these flag is set, we don't want to write any data. The + size_t num_active_streams; + + /* If these flags are set, we don't want to write any data. The application should drop the connection. */ - if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_SENT) { + if ((session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) && + (session->goaway_flags & NGHTTP2_GOAWAY_TERM_SENT)) { return 0; } + num_active_streams = session_get_num_active_streams(session); + /* * Unless termination GOAWAY is sent or received, we want to write * frames if there is pending ones. If pending frame is request/push @@ -6585,20 +5630,29 @@ * want to write them. */ - if (session->aob.item == NULL && - nghttp2_outbound_queue_top(&session->ob_urgent) == NULL && - nghttp2_outbound_queue_top(&session->ob_reg) == NULL && - (nghttp2_pq_empty(&session->root.obq) || + if (session->aob.item == NULL && nghttp2_pq_empty(&session->ob_pq) && + (nghttp2_pq_empty(&session->ob_da_pq) || session->remote_window_size == 0) && - (nghttp2_outbound_queue_top(&session->ob_syn) == NULL || + (nghttp2_pq_empty(&session->ob_ss_pq) || session_is_outgoing_concurrent_streams_max(session))) { return 0; } - /* If there is no active streams and GOAWAY has been sent or - received, we are done with this session. */ - return (session->goaway_flags & - (NGHTTP2_GOAWAY_SENT | NGHTTP2_GOAWAY_RECV)) == 0; + if (num_active_streams > 0) { + return 1; + } + + /* If there is no active streams, we check last_stream_id peer sent + to us. Here is the asymmetry between server and client. For + server, if client cannot make new request, current conneciton is + no use. Server push might be going, but it is idempotent and can + be safely retried with the new connection. For client side, the + theory is the same. */ + if (session->server) { + return session->local_last_stream_id > session->last_recv_stream_id; + } else { + return (uint32_t)session->remote_last_stream_id >= session->next_stream_id; + } } int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags, @@ -6606,21 +5660,13 @@ int rv; nghttp2_outbound_item *item; nghttp2_frame *frame; - nghttp2_mem *mem; - - mem = &session->mem; - if ((flags & NGHTTP2_FLAG_ACK) && - session->obq_flood_counter_ >= NGHTTP2_MAX_OBQ_FLOOD_ITEM) { - return NGHTTP2_ERR_FLOODED; - } - - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + item = malloc(sizeof(nghttp2_outbound_item)); if (item == NULL) { return NGHTTP2_ERR_NOMEM; } - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; @@ -6630,28 +5676,20 @@ if (rv != 0) { nghttp2_frame_ping_free(&frame->ping); - nghttp2_mem_free(mem, item); + free(item); return rv; } - - if (flags & NGHTTP2_FLAG_ACK) { - ++session->obq_flood_counter_; - } - return 0; } int nghttp2_session_add_goaway(nghttp2_session *session, int32_t last_stream_id, uint32_t error_code, const uint8_t *opaque_data, - size_t opaque_data_len, uint8_t aux_flags) { + size_t opaque_data_len, int terminate_on_send) { int rv; nghttp2_outbound_item *item; nghttp2_frame *frame; uint8_t *opaque_data_copy = NULL; nghttp2_goaway_aux_data *aux_data; - nghttp2_mem *mem; - - mem = &session->mem; if (nghttp2_session_is_my_stream_id(session, last_stream_id)) { return NGHTTP2_ERR_INVALID_ARGUMENT; @@ -6661,20 +5699,20 @@ if (opaque_data_len + 8 > NGHTTP2_MAX_PAYLOADLEN) { return NGHTTP2_ERR_INVALID_ARGUMENT; } - opaque_data_copy = nghttp2_mem_malloc(mem, opaque_data_len); + opaque_data_copy = malloc(opaque_data_len); if (opaque_data_copy == NULL) { return NGHTTP2_ERR_NOMEM; } memcpy(opaque_data_copy, opaque_data, opaque_data_len); } - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + item = malloc(sizeof(nghttp2_outbound_item)); if (item == NULL) { - nghttp2_mem_free(mem, opaque_data_copy); + free(opaque_data_copy); return NGHTTP2_ERR_NOMEM; } - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; @@ -6686,12 +5724,12 @@ opaque_data_copy, opaque_data_len); aux_data = &item->aux_data.goaway; - aux_data->flags = aux_flags; + aux_data->terminate_on_send = terminate_on_send; rv = nghttp2_session_add_item(session, item); if (rv != 0) { - nghttp2_frame_goaway_free(&frame->goaway, mem); - nghttp2_mem_free(mem, item); + nghttp2_frame_goaway_free(&frame->goaway); + free(item); return rv; } return 0; @@ -6703,15 +5741,13 @@ int rv; nghttp2_outbound_item *item; nghttp2_frame *frame; - nghttp2_mem *mem; - mem = &session->mem; - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + item = malloc(sizeof(nghttp2_outbound_item)); if (item == NULL) { return NGHTTP2_ERR_NOMEM; } - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; @@ -6722,23 +5758,12 @@ if (rv != 0) { nghttp2_frame_window_update_free(&frame->window_update); - nghttp2_mem_free(mem, item); + free(item); return rv; } return 0; } -static void -session_append_inflight_settings(nghttp2_session *session, - nghttp2_inflight_settings *settings) { - nghttp2_inflight_settings **i; - - for (i = &session->inflight_settings_head; *i; i = &(*i)->next) - ; - - *i = settings; -} - int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags, const nghttp2_settings_entry *iv, size_t niv) { nghttp2_outbound_item *item; @@ -6746,34 +5771,28 @@ nghttp2_settings_entry *iv_copy; size_t i; int rv; - nghttp2_mem *mem; - nghttp2_inflight_settings *inflight_settings = NULL; - - mem = &session->mem; if (flags & NGHTTP2_FLAG_ACK) { if (niv != 0) { return NGHTTP2_ERR_INVALID_ARGUMENT; } - - if (session->obq_flood_counter_ >= NGHTTP2_MAX_OBQ_FLOOD_ITEM) { - return NGHTTP2_ERR_FLOODED; - } + } else if (session->inflight_niv != -1) { + return NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS; } if (!nghttp2_iv_check(iv, niv)) { return NGHTTP2_ERR_INVALID_ARGUMENT; } - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + item = malloc(sizeof(nghttp2_outbound_item)); if (item == NULL) { return NGHTTP2_ERR_NOMEM; } if (niv > 0) { - iv_copy = nghttp2_frame_iv_copy(iv, niv, mem); + iv_copy = nghttp2_frame_iv_copy(iv, niv); if (iv_copy == NULL) { - nghttp2_mem_free(mem, item); + free(item); return NGHTTP2_ERR_NOMEM; } } else { @@ -6781,16 +5800,22 @@ } if ((flags & NGHTTP2_FLAG_ACK) == 0) { - rv = inflight_settings_new(&inflight_settings, iv, niv, mem); - if (rv != 0) { - assert(nghttp2_is_fatal(rv)); - nghttp2_mem_free(mem, iv_copy); - nghttp2_mem_free(mem, item); - return rv; + if (niv > 0) { + session->inflight_iv = nghttp2_frame_iv_copy(iv, niv); + + if (session->inflight_iv == NULL) { + free(iv_copy); + free(item); + return NGHTTP2_ERR_NOMEM; + } + } else { + session->inflight_iv = NULL; } + + session->inflight_niv = niv; } - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; @@ -6800,24 +5825,20 @@ /* The only expected error is fatal one */ assert(nghttp2_is_fatal(rv)); - inflight_settings_del(inflight_settings, mem); + if ((flags & NGHTTP2_FLAG_ACK) == 0) { + free(session->inflight_iv); + session->inflight_iv = NULL; + session->inflight_niv = -1; + } - nghttp2_frame_settings_free(&frame->settings, mem); - nghttp2_mem_free(mem, item); + nghttp2_frame_settings_free(&frame->settings); + free(item); return rv; } - if (flags & NGHTTP2_FLAG_ACK) { - ++session->obq_flood_counter_; - } else { - session_append_inflight_settings(session, inflight_settings); - } - - /* Extract NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS and ENABLE_PUSH - here. We use it to refuse the incoming stream and PUSH_PROMISE - with RST_STREAM. */ - + /* Extract NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS here and use + it to refuse the incoming streams with RST_STREAM. */ for (i = niv; i > 0; --i) { if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS) { session->pending_local_max_concurrent_stream = iv[i - 1].value; @@ -6825,20 +5846,12 @@ } } - for (i = niv; i > 0; --i) { - if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_ENABLE_PUSH) { - session->pending_enable_push = (uint8_t)iv[i - 1].value; - break; - } - } - return 0; } int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, size_t datamax, nghttp2_frame *frame, - nghttp2_data_aux_data *aux_data, - nghttp2_stream *stream) { + nghttp2_data_aux_data *aux_data) { int rv; uint32_t data_flags; ssize_t payloadlen; @@ -6851,6 +5864,12 @@ buf = &bufs->cur->buf; if (session->callbacks.read_length_callback) { + nghttp2_stream *stream; + + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); + if (!stream) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } payloadlen = session->callbacks.read_length_callback( session, frame->hd.type, stream->stream_id, session->remote_window_size, @@ -6870,17 +5889,17 @@ return NGHTTP2_ERR_CALLBACK_FAILURE; } - if ((size_t)payloadlen > nghttp2_buf_avail(buf)) { + if (payloadlen > nghttp2_buf_avail(buf)) { /* Resize the current buffer(s). The reason why we do +1 for buffer size is for possible padding field. */ rv = nghttp2_bufs_realloc(&session->aob.framebufs, - (size_t)(NGHTTP2_FRAME_HDLEN + 1 + payloadlen)); + NGHTTP2_FRAME_HDLEN + 1 + payloadlen); if (rv != 0) { DEBUGF(fprintf(stderr, "send: realloc buffer failed rv=%d", rv)); /* If reallocation failed, old buffers are still in tact. So use safe limit. */ - payloadlen = (ssize_t)datamax; + payloadlen = datamax; DEBUGF( fprintf(stderr, "send: use safe limit payloadlen=%zd", payloadlen)); @@ -6894,7 +5913,7 @@ } /* Current max DATA length is less then buffer chunk size */ - assert(nghttp2_buf_avail(buf) >= datamax); + assert(nghttp2_buf_avail(buf) >= (ssize_t)datamax); data_flags = NGHTTP2_DATA_FLAG_NONE; payloadlen = aux_data->data_prd.read_callback( @@ -6923,26 +5942,12 @@ if (data_flags & NGHTTP2_DATA_FLAG_EOF) { aux_data->eof = 1; - /* If NGHTTP2_DATA_FLAG_NO_END_STREAM is set, don't set - NGHTTP2_FLAG_END_STREAM */ - if ((aux_data->flags & NGHTTP2_FLAG_END_STREAM) && - (data_flags & NGHTTP2_DATA_FLAG_NO_END_STREAM) == 0) { + if (aux_data->flags & NGHTTP2_FLAG_END_STREAM) { frame->hd.flags |= NGHTTP2_FLAG_END_STREAM; } } - if (data_flags & NGHTTP2_DATA_FLAG_NO_COPY) { - if (session->callbacks.send_data_callback == NULL) { - DEBUGF(fprintf( - stderr, - "NGHTTP2_DATA_FLAG_NO_COPY requires send_data_callback set\n")); - - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - aux_data->no_copy = 1; - } - - frame->hd.length = (size_t)payloadlen; + frame->hd.length = payloadlen; frame->data.padlen = 0; max_payloadlen = nghttp2_min(datamax, frame->hd.length + NGHTTP2_MAX_PADLEN); @@ -6954,26 +5959,15 @@ return (int)padded_payloadlen; } - frame->data.padlen = (size_t)(padded_payloadlen - payloadlen); + frame->data.padlen = padded_payloadlen - payloadlen; nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd); - rv = nghttp2_frame_add_pad(bufs, &frame->hd, frame->data.padlen, - aux_data->no_copy); + rv = nghttp2_frame_add_pad(bufs, &frame->hd, frame->data.padlen); if (rv != 0) { return rv; } - reschedule_stream(stream); - - if (frame->hd.length == 0 && (data_flags & NGHTTP2_DATA_FLAG_EOF) && - (data_flags & NGHTTP2_DATA_FLAG_NO_END_STREAM)) { - /* DATA payload length is 0, and DATA frame does not bear - END_STREAM. In this case, there is no point to send 0 length - DATA frame. */ - return NGHTTP2_ERR_CANCEL; - } - return 0; } @@ -7004,12 +5998,12 @@ int rv; nghttp2_stream *stream; stream = nghttp2_session_get_stream(session, stream_id); - if (stream == NULL || !nghttp2_stream_check_deferred_item(stream)) { + if (stream == NULL || !nghttp2_stream_check_deferred_data(stream)) { return NGHTTP2_ERR_INVALID_ARGUMENT; } - rv = nghttp2_stream_resume_deferred_item(stream, - NGHTTP2_STREAM_FLAG_DEFERRED_USER); + rv = nghttp2_stream_resume_deferred_data( + stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER, session); if (nghttp2_is_fatal(rv)) { return rv; @@ -7019,10 +6013,9 @@ } size_t nghttp2_session_get_outbound_queue_size(nghttp2_session *session) { - return nghttp2_outbound_queue_size(&session->ob_urgent) + - nghttp2_outbound_queue_size(&session->ob_reg) + - nghttp2_outbound_queue_size(&session->ob_syn); - /* TODO account for item attached to stream */ + return nghttp2_pq_size(&session->ob_pq) + + nghttp2_pq_size(&session->ob_ss_pq) + + nghttp2_pq_size(&session->ob_da_pq); } int32_t @@ -7095,19 +6088,16 @@ assert(0); } -static int nghttp2_session_upgrade_internal(nghttp2_session *session, - const uint8_t *settings_payload, - size_t settings_payloadlen, - void *stream_user_data) { +int nghttp2_session_upgrade(nghttp2_session *session, + const uint8_t *settings_payload, + size_t settings_payloadlen, + void *stream_user_data) { nghttp2_stream *stream; nghttp2_frame frame; nghttp2_settings_entry *iv; size_t niv; int rv; nghttp2_priority_spec pri_spec; - nghttp2_mem *mem; - - mem = &session->mem; if ((!session->server && session->next_stream_id != 1) || (session->server && session->last_recv_stream_id >= 1)) { @@ -7117,7 +6107,7 @@ return NGHTTP2_ERR_INVALID_ARGUMENT; } rv = nghttp2_frame_unpack_settings_payload2(&iv, &niv, settings_payload, - settings_payloadlen, mem); + settings_payloadlen); if (rv != 0) { return rv; } @@ -7131,7 +6121,7 @@ } else { rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, niv); } - nghttp2_mem_free(mem, iv); + free(iv); if (rv != 0) { return rv; } @@ -7144,74 +6134,17 @@ if (stream == NULL) { return NGHTTP2_ERR_NOMEM; } - - /* We don't call nghttp2_session_adjust_closed_stream(), since this - should be the first stream open. */ - if (session->server) { nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); session->last_recv_stream_id = 1; session->last_proc_stream_id = 1; } else { nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); - session->last_sent_stream_id = 1; session->next_stream_id += 2; } return 0; } -int nghttp2_session_upgrade(nghttp2_session *session, - const uint8_t *settings_payload, - size_t settings_payloadlen, - void *stream_user_data) { - int rv; - nghttp2_stream *stream; - - rv = nghttp2_session_upgrade_internal(session, settings_payload, - settings_payloadlen, stream_user_data); - if (rv != 0) { - return rv; - } - - stream = nghttp2_session_get_stream(session, 1); - assert(stream); - - /* We have no information about request header fields when Upgrade - was happened. So we don't know the request method here. If - request method is HEAD, we have a trouble because we may have - nonzero content-length header field in response headers, and we - will going to check it against the actual DATA frames, but we may - get mismatch because HEAD response body must be empty. Because - of this reason, nghttp2_session_upgrade() was deprecated in favor - of nghttp2_session_upgrade2(), which has |head_request| parameter - to indicate that request method is HEAD or not. */ - stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND; - return 0; -} - -int nghttp2_session_upgrade2(nghttp2_session *session, - const uint8_t *settings_payload, - size_t settings_payloadlen, int head_request, - void *stream_user_data) { - int rv; - nghttp2_stream *stream; - - rv = nghttp2_session_upgrade_internal(session, settings_payload, - settings_payloadlen, stream_user_data); - if (rv != 0) { - return rv; - } - - stream = nghttp2_session_get_stream(session, 1); - assert(stream); - - if (head_request) { - stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD; - } - - return 0; -} - int nghttp2_session_get_stream_local_close(nghttp2_session *session, int32_t stream_id) { nghttp2_stream *stream; @@ -7259,170 +6192,13 @@ stream = nghttp2_session_get_stream(session, stream_id); - if (!stream) { - return 0; - } - - rv = session_update_stream_consumed_size(session, stream, size); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - return 0; -} - -int nghttp2_session_consume_connection(nghttp2_session *session, size_t size) { - int rv; - - if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) { - return NGHTTP2_ERR_INVALID_STATE; - } - - rv = session_update_connection_consumed_size(session, size); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - return 0; -} - -int nghttp2_session_consume_stream(nghttp2_session *session, int32_t stream_id, - size_t size) { - int rv; - nghttp2_stream *stream; - - if (stream_id == 0) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) { - return NGHTTP2_ERR_INVALID_STATE; - } - - stream = nghttp2_session_get_stream(session, stream_id); - - if (!stream) { - return 0; - } - - rv = session_update_stream_consumed_size(session, stream, size); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - return 0; -} - -int nghttp2_session_set_next_stream_id(nghttp2_session *session, - int32_t next_stream_id) { - if (next_stream_id <= 0 || - session->next_stream_id > (uint32_t)next_stream_id) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - if (session->server) { - if (next_stream_id % 2) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - } else if (next_stream_id % 2 == 0) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - session->next_stream_id = (uint32_t)next_stream_id; - return 0; -} - -uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session) { - return session->next_stream_id; -} - -int32_t nghttp2_session_get_last_proc_stream_id(nghttp2_session *session) { - return session->last_proc_stream_id; -} - -nghttp2_stream *nghttp2_session_find_stream(nghttp2_session *session, - int32_t stream_id) { - if (stream_id == 0) { - return &session->root; - } - - return nghttp2_session_get_stream_raw(session, stream_id); -} - -nghttp2_stream *nghttp2_session_get_root_stream(nghttp2_session *session) { - return &session->root; -} - -int nghttp2_session_check_server_session(nghttp2_session *session) { - return session->server; -} - -int nghttp2_session_change_stream_priority( - nghttp2_session *session, int32_t stream_id, - const nghttp2_priority_spec *pri_spec) { - int rv; - nghttp2_stream *stream; - nghttp2_priority_spec pri_spec_copy; - - if (stream_id == 0 || stream_id == pri_spec->stream_id) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - stream = nghttp2_session_get_stream_raw(session, stream_id); - if (!stream) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - pri_spec_copy = *pri_spec; - nghttp2_priority_spec_normalize_weight(&pri_spec_copy); - - rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec_copy); - - if (nghttp2_is_fatal(rv)) { - return rv; - } - - /* We don't intentionally call nghttp2_session_adjust_idle_stream() - so that idle stream created by this function, and existing ones - are kept for application. We will adjust number of idle stream - in nghttp2_session_mem_send or nghttp2_session_mem_recv is - called. */ - return 0; -} - -int nghttp2_session_create_idle_stream(nghttp2_session *session, - int32_t stream_id, - const nghttp2_priority_spec *pri_spec) { - nghttp2_stream *stream; - nghttp2_priority_spec pri_spec_copy; - - if (stream_id == 0 || stream_id == pri_spec->stream_id || - !session_detect_idle_stream(session, stream_id)) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - stream = nghttp2_session_get_stream_raw(session, stream_id); if (stream) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } + rv = session_update_stream_consumed_size(session, stream, size); - pri_spec_copy = *pri_spec; - nghttp2_priority_spec_normalize_weight(&pri_spec_copy); - - stream = - nghttp2_session_open_stream(session, stream_id, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_copy, NGHTTP2_STREAM_IDLE, NULL); - if (!stream) { - return NGHTTP2_ERR_NOMEM; + if (nghttp2_is_fatal(rv)) { + return rv; + } } - /* We don't intentionally call nghttp2_session_adjust_idle_stream() - so that idle stream created by this function, and existing ones - are kept for application. We will adjust number of idle stream - in nghttp2_session_mem_send or nghttp2_session_mem_recv is - called. */ return 0; } diff -Nru nghttp2-1.13.0/lib/nghttp2_session.h nghttp2-0.6.7/lib/nghttp2_session.h --- nghttp2-1.13.0/lib/nghttp2_session.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_session.h 2014-11-30 14:15:07.000000000 +0000 @@ -30,6 +30,7 @@ #endif /* HAVE_CONFIG_H */ #include +#include "nghttp2_pq.h" #include "nghttp2_map.h" #include "nghttp2_frame.h" #include "nghttp2_hd.h" @@ -38,36 +39,18 @@ #include "nghttp2_int.h" #include "nghttp2_buf.h" #include "nghttp2_callbacks.h" -#include "nghttp2_mem.h" - -/* The global variable for tests where we want to disable strict - preface handling. */ -extern int nghttp2_enable_strict_preface; /* * Option flags. */ typedef enum { NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE = 1 << 0, - NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1, - NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2, - NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3 + NGHTTP2_OPTMASK_RECV_CLIENT_PREFACE = 1 << 1, } nghttp2_optmask; -/* - * bitmask for built-in type to enable the default handling for that - * type of the frame. - */ -typedef enum { - NGHTTP2_TYPEMASK_NONE = 0, - NGHTTP2_TYPEMASK_ALTSVC = 1 << 0 -} nghttp2_typemask; - typedef enum { NGHTTP2_OB_POP_ITEM, - NGHTTP2_OB_SEND_DATA, - NGHTTP2_OB_SEND_NO_COPY, - NGHTTP2_OB_SEND_CLIENT_MAGIC + NGHTTP2_OB_SEND_DATA } nghttp2_outbound_state; typedef struct { @@ -80,27 +63,10 @@ nghttp2_session_recv(). */ #define NGHTTP2_INBOUND_BUFFER_LENGTH 16384 -/* The default maximum number of incoming reserved streams */ -#define NGHTTP2_MAX_INCOMING_RESERVED_STREAMS 200 - -/* Even if we have less SETTINGS_MAX_CONCURRENT_STREAMS than this - number, we keep NGHTTP2_MIN_IDLE_STREAMS streams in idle state */ -#define NGHTTP2_MIN_IDLE_STREAMS 16 - -/* The maximum number of items in outbound queue, which is considered - as flooding caused by peer. All frames are not considered here. - We only consider PING + ACK and SETTINGS + ACK. This is because - they both are response to the frame initiated by peer and peer can - send as many of them as they want. If peer does not read network, - response frames are stacked up, which leads to memory exhaustion. - The value selected here is arbitrary, but safe value and if we have - these frames in this number, it is considered suspicious. */ -#define NGHTTP2_MAX_OBQ_FLOOD_ITEM 10000 - /* Internal state when receiving incoming frame */ typedef enum { /* Receiving frame header */ - NGHTTP2_IB_READ_CLIENT_MAGIC, + NGHTTP2_IB_READ_CLIENT_PREFACE, NGHTTP2_IB_READ_FIRST_SETTINGS, NGHTTP2_IB_READ_HEAD, NGHTTP2_IB_READ_NBYTE, @@ -110,26 +76,26 @@ NGHTTP2_IB_FRAME_SIZE_ERROR, NGHTTP2_IB_READ_SETTINGS, NGHTTP2_IB_READ_GOAWAY_DEBUG, + NGHTTP2_IB_READ_ALTSVC, NGHTTP2_IB_EXPECT_CONTINUATION, NGHTTP2_IB_IGN_CONTINUATION, NGHTTP2_IB_READ_PAD_DATA, NGHTTP2_IB_READ_DATA, - NGHTTP2_IB_IGN_DATA, - NGHTTP2_IB_IGN_ALL, - NGHTTP2_IB_READ_ALTSVC_PAYLOAD, - NGHTTP2_IB_READ_EXTENSION_PAYLOAD + NGHTTP2_IB_IGN_DATA } nghttp2_inbound_state; +#define NGHTTP2_INBOUND_NUM_IV 7 + typedef struct { nghttp2_frame frame; /* Storage for extension frame payload. frame->ext.payload points to this structure to avoid frequent memory allocation. */ nghttp2_ext_frame_payload ext_frame_payload; - /* The received SETTINGS entry. For the standard settings entries, - we only keep the last seen value. For - SETTINGS_HEADER_TABLE_SIZE, we also keep minimum value in the - last index. */ - nghttp2_settings_entry *iv; + /* The received SETTINGS entry. The protocol says that we only cares + about the defined settings ID. If unknown ID is received, it is + ignored. We use last entry to hold minimum header table size if + same settings are multiple times. */ + nghttp2_settings_entry iv[NGHTTP2_INBOUND_NUM_IV]; /* buffer pointers to small buffer, raw_sbuf */ nghttp2_buf sbuf; /* buffer pointers to large buffer, raw_lbuf */ @@ -138,8 +104,6 @@ uint8_t *raw_lbuf; /* The number of entry filled in |iv| */ size_t niv; - /* The number of entries |iv| can store. */ - size_t max_niv; /* How many bytes we still need to receive for current frame */ size_t payloadleft; /* padding length for the current frame */ @@ -166,105 +130,68 @@ NGHTTP2_GOAWAY_TERM_ON_SEND = 0x1, /* Flag means GOAWAY to terminate session has been sent */ NGHTTP2_GOAWAY_TERM_SENT = 0x2, - /* Flag means GOAWAY was sent */ - NGHTTP2_GOAWAY_SENT = 0x4, - /* Flag means GOAWAY was received */ - NGHTTP2_GOAWAY_RECV = 0x8 } nghttp2_goaway_flag; -/* nghttp2_inflight_settings stores the SETTINGS entries which local - endpoint has sent to the remote endpoint, and has not received ACK - yet. */ -struct nghttp2_inflight_settings { - struct nghttp2_inflight_settings *next; - nghttp2_settings_entry *iv; - size_t niv; -}; - -typedef struct nghttp2_inflight_settings nghttp2_inflight_settings; - struct nghttp2_session { nghttp2_map /* */ streams; - /* root of dependency tree*/ - nghttp2_stream root; - /* 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; + nghttp2_stream_roots roots; + /* Queue for outbound frames other than stream-creating HEADERS and + DATA */ + nghttp2_pq /* */ ob_pq; + /* Queue for outbound stream-creating HEADERS frame */ + nghttp2_pq /* */ ob_ss_pq; + /* QUeue for DATA frame */ + nghttp2_pq /* */ ob_da_pq; nghttp2_active_outbound_item aob; nghttp2_inbound_frame iframe; nghttp2_hd_deflater hd_deflater; nghttp2_hd_inflater hd_inflater; nghttp2_session_callbacks callbacks; - /* Memory allocator */ - nghttp2_mem mem; - /* Base value when we schedule next DATA frame write. This is - updated when one frame was written. */ + /* 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. */ uint64_t last_cycle; void *user_data; - /* Points to the latest incoming closed stream. NULL if there is no - closed stream. Only used when session is initialized as - server. */ + /* Points to the latest closed stream. NULL if there is no closed + stream. Only used when session is initialized as server. */ nghttp2_stream *closed_stream_head; - /* Points to the oldest incoming closed stream. NULL if there is no - closed stream. Only used when session is initialized as - server. */ + /* Points to the oldest closed stream. NULL if there is no closed + stream. Only used when session is initialized as server. */ nghttp2_stream *closed_stream_tail; - /* Points to the latest idle stream. NULL if there is no idle - stream. Only used when session is initialized as server .*/ - nghttp2_stream *idle_stream_head; - /* Points to the oldest idle stream. NULL if there is no idle - stream. Only used when session is initialized as erver. */ - nghttp2_stream *idle_stream_tail; - /* Queue of In-flight SETTINGS values. SETTINGS bearing ACK is not - considered as in-flight. */ - nghttp2_inflight_settings *inflight_settings_head; + /* In-flight SETTINGS values. NULL does not necessarily mean there + is no in-flight SETTINGS. */ + nghttp2_settings_entry *inflight_iv; + /* The number of entries in |inflight_iv|. -1 if there is no + in-flight SETTINGS. */ + ssize_t inflight_niv; /* The number of outgoing streams. This will be capped by remote_settings.max_concurrent_streams. */ size_t num_outgoing_streams; /* The number of incoming streams. This will be capped by local_settings.max_concurrent_streams. */ size_t num_incoming_streams; - /* The number of incoming reserved streams. This is the number of - streams in reserved (remote) state. RFC 7540 does not limit this - number. nghttp2 offers - nghttp2_option_set_max_reserved_remote_streams() to achieve this. - If it is used, num_incoming_streams is capped by - max_incoming_reserved_streams. Client application should - consider to set this because without that server can send - arbitrary number of PUSH_PROMISE, and exhaust client's memory. */ - size_t num_incoming_reserved_streams; - /* The maximum number of incoming reserved streams (reserved - (remote) state). RST_STREAM will be sent for the pushed stream - which exceeds this limit. */ - size_t max_incoming_reserved_streams; /* The number of closed streams still kept in |streams| hash. The closed streams can be accessed through single linked list |closed_stream_head|. The current implementation only keeps incoming streams and session is initialized as server. */ size_t num_closed_streams; - /* The number of idle streams kept in |streams| hash. The idle - streams can be accessed through doubly linked list - |idle_stream_head|. The current implementation only keeps idle - streams if session is initialized as server. */ - size_t num_idle_streams; /* The number of bytes allocated for nvbuf */ size_t nvbuflen; - /* Counter for detecting flooding in outbound queue */ - size_t obq_flood_counter_; - /* The maximum length of header block to send. Calculated by the - same way as nghttp2_hd_deflate_bound() does. */ - size_t max_send_header_block_length; /* Next Stream ID. Made unsigned int to detect >= (1 << 31). */ uint32_t next_stream_id; - /* The last stream ID this session initiated. For client session, - this is the last stream ID it has sent. For server session, it - is the last promised stream ID sent in PUSH_PROMISE. */ - int32_t last_sent_stream_id; /* The largest stream ID received so far */ int32_t last_recv_stream_id; /* The largest stream ID which has been processed in some way. This @@ -307,28 +234,11 @@ /* Unacked local SETTINGS_MAX_CONCURRENT_STREAMS value. We use this to refuse the incoming stream if it exceeds this value. */ uint32_t pending_local_max_concurrent_stream; - /* The bitwose OR of zero or more of nghttp2_typemask to indicate - that the default handling of extension frame is enabled. */ - uint32_t builtin_recv_ext_types; - /* Unacked local ENABLE_PUSH value. We use this to refuse - PUSH_PROMISE before SETTINGS ACK is received. */ - uint8_t pending_enable_push; /* Nonzero if the session is server side. */ uint8_t server; /* Flags indicating GOAWAY is sent and/or recieved. The flags are composed by bitwise OR-ing nghttp2_goaway_flag. */ uint8_t goaway_flags; - /* This flag is used to reduce excessive queuing of WINDOW_UPDATE to - this session. The nonzero does not necessarily mean - WINDOW_UPDATE is not queued. */ - uint8_t window_update_queued; - /* Bitfield of extension frame types that application is willing to - receive. To designate the bit of given frame type i, use - user_recv_ext_types[i / 8] & (1 << (i & 0x7)). First 10 frame - types are standard frame types and not used in this bitfield. If - bit is set, it indicates that incoming frame with that type is - passed to user defined callbacks, otherwise they are ignored. */ - uint8_t user_recv_ext_types[32]; }; /* Struct used when updating initial window size of each active @@ -359,6 +269,14 @@ 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 * on success. @@ -369,7 +287,7 @@ * NGHTTP2_ERR_NOMEM * Out of memory. * NGHTTP2_ERR_STREAM_CLOSED - * Stream already closed (DATA and PUSH_PROMISE frame only) + * Stream already closed (DATA frame only) */ int nghttp2_session_add_item(nghttp2_session *session, nghttp2_outbound_item *item); @@ -405,9 +323,6 @@ * * NGHTTP2_ERR_NOMEM * Out of memory. - * NGHTTP2_ERR_FLOODED - * There are too many items in outbound queue; this only happens - * if NGHTTP2_FLAG_ACK is set in |flags| */ int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags, const uint8_t *opaque_data); @@ -415,9 +330,7 @@ /* * Adds GOAWAY frame with the last-stream-ID |last_stream_id| and the * error code |error_code|. This is a convenient function built on top - * of nghttp2_session_add_frame() to add GOAWAY easily. The - * |aux_flags| are bitwise-OR of one or more of - * nghttp2_goaway_aux_flag. + * of nghttp2_session_add_frame() to add GOAWAY easily. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -429,7 +342,7 @@ */ int nghttp2_session_add_goaway(nghttp2_session *session, int32_t last_stream_id, uint32_t error_code, const uint8_t *opaque_data, - size_t opaque_data_len, uint8_t aux_flags); + size_t opaque_data_len, int terminate_on_send); /* * Adds WINDOW_UPDATE frame with stream ID |stream_id| and @@ -455,9 +368,6 @@ * * NGHTTP2_ERR_NOMEM * Out of memory. - * NGHTTP2_ERR_FLOODED - * There are too many items in outbound queue; this only happens - * if NGHTTP2_FLAG_ACK is set in |flags| */ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags, const nghttp2_settings_entry *iv, size_t niv); @@ -471,16 +381,8 @@ * is a pointer to the arbitrary user supplied data to be associated * to this stream. * - * If |initial_state| is NGHTTP2_STREAM_RESERVED, this function sets - * NGHTTP2_STREAM_FLAG_PUSH flag set. - * * This function returns a pointer to created new stream object, or * NULL. - * - * This function adjusts neither the number of closed streams or idle - * streams. The caller should manually call - * nghttp2_session_adjust_closed_stream() or - * nghttp2_session_adjust_idle_stream() respectively. */ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session, int32_t stream_id, uint8_t flags, @@ -515,14 +417,9 @@ * Deletes |stream| from memory. After this function returns, stream * cannot be accessed. * - * This function returns 0 if it succeeds, or one the following - * negative error codes: - * - * NGHTTP2_ERR_NOMEM - * Out of memory */ -int nghttp2_session_destroy_stream(nghttp2_session *session, - nghttp2_stream *stream); +void nghttp2_session_destroy_stream(nghttp2_session *session, + nghttp2_stream *stream); /* * Tries to keep incoming closed stream |stream|. Due to the @@ -534,43 +431,27 @@ nghttp2_stream *stream); /* - * Appends |stream| to linked list |session->idle_stream_head|. We - * apply fixed limit for list size. To fit into that limit, one or - * more oldest streams are removed from list as necessary. + * Detaches |stream| from closed streams linked list. */ -void nghttp2_session_keep_idle_stream(nghttp2_session *session, - nghttp2_stream *stream); +void nghttp2_session_detach_closed_stream(nghttp2_session *session, + nghttp2_stream *stream); /* - * Detaches |stream| from idle streams linked list. + * Returns nonzero if |offset| closed stream(s) can be added to closed + * linked list now. */ -void nghttp2_session_detach_idle_stream(nghttp2_session *session, - nghttp2_stream *stream); +int nghttp2_session_can_add_closed_stream(nghttp2_session *session, + ssize_t offset); /* * Deletes closed stream to ensure that number of incoming streams * including active and closed is in the maximum number of allowed - * stream. - * - * This function returns 0 if it succeeds, or one the following - * negative error codes: - * - * NGHTTP2_ERR_NOMEM - * Out of memory - */ -int nghttp2_session_adjust_closed_stream(nghttp2_session *session); - -/* - * Deletes idle stream to ensure that number of idle streams is in - * certain limit. - * - * This function returns 0 if it succeeds, or one the following - * negative error codes: - * - * NGHTTP2_ERR_NOMEM - * Out of memory + * stream. If |offset| is nonzero, it is decreased from the maximum + * number of allowed stream when comparing number of active and closed + * stream and the maximum number. */ -int nghttp2_session_adjust_idle_stream(nghttp2_session *session); +void nghttp2_session_adjust_closed_stream(nghttp2_session *session, + ssize_t offset); /* * If further receptions and transmissions over the stream |stream_id| @@ -585,6 +466,18 @@ int nghttp2_session_close_stream_if_shut_rdwr(nghttp2_session *session, nghttp2_stream *stream); +int nghttp2_session_end_request_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream); + +int nghttp2_session_end_response_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream); + +int nghttp2_session_end_headers_received(nghttp2_session *session, + nghttp2_frame *frame, + nghttp2_stream *stream); + int nghttp2_session_on_request_headers_received(nghttp2_session *session, nghttp2_frame *frame); @@ -659,9 +552,6 @@ * Out of memory * NGHTTP2_ERR_CALLBACK_FAILURE * The read_callback failed - * NGHTTP2_ERR_FLOODED - * There are too many items in outbound queue, and this is most - * likely caused by misbehaviour of peer. */ int nghttp2_session_on_settings_received(nghttp2_session *session, nghttp2_frame *frame, int noack); @@ -695,9 +585,6 @@ * Out of memory. * NGHTTP2_ERR_CALLBACK_FAILURE * The callback function failed. - * NGHTTP2_ERR_FLOODED - * There are too many items in outbound queue, and this is most - * likely caused by misbehaviour of peer. */ int nghttp2_session_on_ping_received(nghttp2_session *session, nghttp2_frame *frame); @@ -733,12 +620,14 @@ nghttp2_frame *frame); /* - * Called when ALTSVC is recieved, assuming |frame| is properly + * Called when ALTSVC is received, assuming |frame| is properly * initialized. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * + * NGHTTP2_ERR_NOMEM + * Out of memory. * NGHTTP2_ERR_CALLBACK_FAILURE * The callback function failed. */ @@ -795,25 +684,30 @@ */ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs, size_t datamax, nghttp2_frame *frame, - nghttp2_data_aux_data *aux_data, - nghttp2_stream *stream); + 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); /* - * Pops and returns next item to send. If there is no such item, + * Pops and returns next item to send. If there is no such item, * returns NULL. This function takes into account max concurrent - * streams. That means if session->ob_syn has item and max concurrent - * streams is reached, the even if other queues contain items, then - * this function returns NULL. + * streams. That means if session->ob_pq is empty but + * session->ob_ss_pq has item and max concurrent streams is reached, + * then this function returns NULL. */ nghttp2_outbound_item * nghttp2_session_pop_next_ob_item(nghttp2_session *session); /* - * Returns next item to send. If there is no such item, this function + * Returns next item to send. If there is no such item, this function * returns NULL. This function takes into account max concurrent - * streams. That means if session->ob_syn has item and max concurrent - * streams is reached, the even if other queues contain items, then - * this function returns NULL. + * streams. That means if session->ob_pq is empty but + * session->ob_ss_pq has item and max concurrent streams is reached, + * then this function returns NULL. */ nghttp2_outbound_item * nghttp2_session_get_next_ob_item(nghttp2_session *session); @@ -840,11 +734,7 @@ /* * Re-prioritize |stream|. The new priority specification is - * |pri_spec|. Caller must ensure that stream->hd.stream_id != - * pri_spec->stream_id. - * - * This function does not adjust the number of idle streams. The - * caller should call nghttp2_session_adjust_idle_stream() later. + * |pri_spec|. * * This function returns 0 if it succeeds, or one of the following * negative error codes: diff -Nru nghttp2-1.13.0/lib/nghttp2_stream.c nghttp2-0.6.7/lib/nghttp2_stream.c --- nghttp2-1.13.0/lib/nghttp2_stream.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_stream.c 2014-11-30 14:15:07.000000000 +0000 @@ -30,54 +30,24 @@ #include "nghttp2_session.h" #include "nghttp2_helper.h" -/* Maximum distance between any two stream's cycle in the same - prirority queue. Imagine stream A's cycle is A, and stream B's - cycle is B, and A < B. The cycle is unsigned 32 bit integer, it - may get overflow. Because of how we calculate the next cycle - value, if B - A is less than or equals to - NGHTTP2_MAX_CYCLE_DISTANCE, A and B are in the same scale, in other - words, B is really greater than or equal to A. Otherwise, A is a - result of overflow, and it is actually A > B if we consider that - fact. */ -#define NGHTTP2_MAX_CYCLE_DISTANCE (16384 * 256 + 255) - -static int stream_less(const void *lhsx, const void *rhsx) { - const nghttp2_stream *lhs, *rhs; - - lhs = nghttp2_struct_of(lhsx, nghttp2_stream, pq_entry); - rhs = nghttp2_struct_of(rhsx, nghttp2_stream, pq_entry); - - if (lhs->cycle == rhs->cycle) { - return lhs->seq < rhs->seq; - } - - if (lhs->cycle < rhs->cycle) { - return rhs->cycle - lhs->cycle <= NGHTTP2_MAX_CYCLE_DISTANCE; - } - - return lhs->cycle - rhs->cycle > NGHTTP2_MAX_CYCLE_DISTANCE; -} - void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id, uint8_t flags, nghttp2_stream_state initial_state, - int32_t weight, int32_t remote_initial_window_size, + int32_t weight, nghttp2_stream_roots *roots, + int32_t remote_initial_window_size, int32_t local_initial_window_size, - void *stream_user_data, nghttp2_mem *mem) { - nghttp2_map_entry_init(&stream->map_entry, (key_type)stream_id); - nghttp2_pq_init(&stream->obq, stream_less, mem); - + void *stream_user_data) { + nghttp2_map_entry_init(&stream->map_entry, stream_id); stream->stream_id = stream_id; stream->flags = flags; stream->state = initial_state; stream->shut_flags = NGHTTP2_SHUT_NONE; stream->stream_user_data = stream_user_data; - stream->item = NULL; + stream->data_item = NULL; stream->remote_window_size = remote_initial_window_size; stream->local_window_size = local_initial_window_size; stream->recv_window_size = 0; stream->consumed_size = 0; stream->recv_reduction = 0; - stream->window_update_queued = 0; stream->dep_prev = NULL; stream->dep_next = NULL; @@ -87,460 +57,431 @@ stream->closed_prev = NULL; stream->closed_next = NULL; + stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA; + stream->num_substreams = 1; stream->weight = weight; + stream->effective_weight = stream->weight; stream->sum_dep_weight = 0; + stream->sum_norest_weight = 0; + stream->sum_top_weight = 0; - stream->http_flags = NGHTTP2_HTTP_FLAG_NONE; - stream->content_length = -1; - stream->recv_content_length = 0; - stream->status_code = -1; - - stream->queued = 0; - stream->descendant_last_cycle = 0; - stream->cycle = 0; - stream->pending_penalty = 0; - stream->descendant_next_seq = 0; - stream->seq = 0; - stream->last_writelen = 0; -} - -void nghttp2_stream_free(nghttp2_stream *stream) { - nghttp2_pq_free(&stream->obq); - /* We don't free stream->item. If it is assigned to aob, then - active_outbound_item_reset() will delete it. Otherwise, - nghttp2_stream_close() or session_del() will delete it. */ + stream->roots = roots; + stream->root_prev = NULL; + stream->root_next = NULL; } -void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) { - stream->shut_flags = (uint8_t)(stream->shut_flags | flag); +void nghttp2_stream_free(nghttp2_stream *stream _U_) { + /* We don't free stream->data_item. If it is assigned to aob, then + active_outbound_item_reset() will delete it. If it is queued, + then it is deleted when pq is deleted in nghttp2_session_del(). + Otherwise, nghttp2_session_del() will delete it. */ } -/* - * Returns nonzero if |stream| is active. This function does not take - * into account its descendants. - */ -static int stream_active(nghttp2_stream *stream) { - return stream->item && - (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0; -} - -/* - * Returns nonzero if |stream| or one of its descendants is active - */ -static int stream_subtree_active(nghttp2_stream *stream) { - return stream_active(stream) || !nghttp2_pq_empty(&stream->obq); +void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) { + stream->shut_flags |= flag; } -/* - * Returns next cycle for |stream|. - */ -static void stream_next_cycle(nghttp2_stream *stream, uint32_t last_cycle) { - uint32_t penalty; - - penalty = (uint32_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT + - stream->pending_penalty; +static int stream_push_data(nghttp2_stream *stream, nghttp2_session *session) { + int rv; + nghttp2_outbound_item *item; - stream->cycle = last_cycle + penalty / (uint32_t)stream->weight; - stream->pending_penalty = penalty % (uint32_t)stream->weight; -} + assert(stream->data_item); + assert(stream->data_item->queued == 0); -static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) { - int rv; + item = stream->data_item; - for (; dep_stream && !stream->queued; - stream = dep_stream, dep_stream = dep_stream->dep_prev) { - stream_next_cycle(stream, dep_stream->descendant_last_cycle); - stream->seq = dep_stream->descendant_next_seq++; + /* If item is now sent, don't push it to the queue. Otherwise, we + may push same item twice. */ + if (session->aob.item == item) { + return 0; + } - DEBUGF(fprintf(stderr, "stream: stream=%d obq push cycle=%d\n", - stream->stream_id, stream->cycle)); + if (item->weight > stream->effective_weight) { + item->weight = stream->effective_weight; + } - DEBUGF(fprintf(stderr, "stream: push stream %d to stream %d\n", - stream->stream_id, dep_stream->stream_id)); + item->cycle = session->last_cycle; - rv = nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); - if (rv != 0) { - return rv; + switch (item->frame.hd.type) { + case NGHTTP2_DATA: + rv = nghttp2_pq_push(&session->ob_da_pq, item); + break; + case NGHTTP2_HEADERS: + if (stream->state == NGHTTP2_STREAM_RESERVED) { + rv = nghttp2_pq_push(&session->ob_ss_pq, item); + } else { + rv = nghttp2_pq_push(&session->ob_pq, item); } - stream->queued = 1; + break; + default: + /* should not reach here */ + assert(0); } + if (rv != 0) { + return rv; + } + + item->queued = 1; + return 0; } -/* - * Removes |stream| from parent's obq. If removal of |stream| makes - * parent's obq empty, and parent is not active, then parent is also - * removed. This process is repeated recursively. - */ -static void stream_obq_remove(nghttp2_stream *stream) { - nghttp2_stream *dep_stream; - - dep_stream = stream->dep_prev; +static nghttp2_stream *stream_first_sib(nghttp2_stream *stream) { + for (; stream->sib_prev; stream = stream->sib_prev) + ; - if (!stream->queued) { - return; - } + return stream; +} - for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) { - DEBUGF(fprintf(stderr, "stream: remove stream %d from stream %d\n", - stream->stream_id, dep_stream->stream_id)); - - nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry); - - assert(stream->queued); - - stream->queued = 0; - stream->cycle = 0; - stream->pending_penalty = 0; - stream->descendant_last_cycle = 0; - stream->last_writelen = 0; +static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) { + for (; stream->sib_next; stream = stream->sib_next) + ; - if (stream_subtree_active(dep_stream)) { - return; - } - } + return stream; } -/* - * Moves |stream| from |src|'s obq to |dest|'s obq. Removal from - * |src|'s obq is just done calling nghttp2_pq_remove(), so it does - * not recursively remove |src| and ancestors, like - * stream_obq_remove(). - */ -static int stream_obq_move(nghttp2_stream *dest, nghttp2_stream *src, - nghttp2_stream *stream) { - if (!stream->queued) { - return 0; - } +static nghttp2_stream *stream_update_dep_length(nghttp2_stream *stream, + ssize_t delta) { + stream->num_substreams += delta; - DEBUGF(fprintf(stderr, "stream: remove stream %d from stream %d (move)\n", - stream->stream_id, src->stream_id)); + stream = stream_first_sib(stream); - nghttp2_pq_remove(&src->obq, &stream->pq_entry); - stream->queued = 0; + if (stream->dep_prev) { + return stream_update_dep_length(stream->dep_prev, delta); + } - return stream_obq_push(dest, stream); + return stream; } -void nghttp2_stream_reschedule(nghttp2_stream *stream) { - nghttp2_stream *dep_stream; - - assert(stream->queued); - - dep_stream = stream->dep_prev; +int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream, + int32_t weight) { + weight = stream->weight * weight / stream->sum_dep_weight; - for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) { - nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry); + return nghttp2_max(1, weight); +} - stream_next_cycle(stream, dep_stream->descendant_last_cycle); - stream->seq = dep_stream->descendant_next_seq++; +int32_t nghttp2_stream_dep_distributed_effective_weight(nghttp2_stream *stream, + int32_t weight) { + if (stream->sum_norest_weight == 0) { + return stream->effective_weight; + } - nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); + weight = stream->effective_weight * weight / stream->sum_norest_weight; - DEBUGF(fprintf(stderr, "stream: stream=%d obq resched cycle=%d\n", - stream->stream_id, stream->cycle)); + return nghttp2_max(1, weight); +} - dep_stream->last_writelen = stream->last_writelen; +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; } -} -void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) { - nghttp2_stream *dep_stream; - uint32_t last_cycle; - int32_t old_weight; - uint32_t wlen_penalty; + weight = stream->effective_weight * weight / stream->sum_top_weight; - if (stream->weight == weight) { - return; - } + return nghttp2_max(1, weight); +} - old_weight = stream->weight; - stream->weight = weight; +static void stream_update_dep_set_rest(nghttp2_stream *stream); - dep_stream = stream->dep_prev; +/* Updates effective_weight of descendant streams in subtree of + |stream|. We assume that stream->effective_weight is already set + right. */ +static void stream_update_dep_effective_weight(nghttp2_stream *stream) { + nghttp2_stream *si; - if (!dep_stream) { + DEBUGF(fprintf(stderr, "stream: update_dep_effective_weight " + "stream(%p)=%d, weight=%d, sum_norest_weight=%d, " + "sum_top_weight=%d\n", + stream, stream->stream_id, stream->weight, + stream->sum_norest_weight, stream->sum_top_weight)); + + /* stream->sum_norest_weight == 0 means there is no + NGHTTP2_STREAM_DPRI_TOP under stream */ + if (stream->dpri != NGHTTP2_STREAM_DPRI_NO_DATA || + stream->sum_norest_weight == 0) { return; } - dep_stream->sum_dep_weight += weight - old_weight; + /* 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); + } - if (!stream->queued) { + stream_update_dep_effective_weight(si); + } return; } - nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry); - - wlen_penalty = (uint32_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT; + /* 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) { + si->effective_weight = + stream_dep_distributed_top_effective_weight(stream, si->weight); - /* Compute old stream->pending_penalty we used to calculate - stream->cycle */ - stream->pending_penalty = - (uint32_t)((stream->pending_penalty + (uint32_t)old_weight - - (wlen_penalty % (uint32_t)old_weight)) % - (uint32_t)old_weight); + DEBUGF(fprintf(stderr, "stream: stream=%d top eweight=%d\n", + si->stream_id, si->effective_weight)); - last_cycle = stream->cycle - - (wlen_penalty + stream->pending_penalty) / (uint32_t)old_weight; + continue; + } - /* Now we have old stream->pending_penalty and new stream->weight in - place */ - stream_next_cycle(stream, last_cycle); + if (si->dpri == NGHTTP2_STREAM_DPRI_NO_DATA) { + DEBUGF(fprintf(stderr, "stream: stream=%d no_data, ignored\n", + si->stream_id)); - if (stream->cycle < dep_stream->descendant_last_cycle && - (dep_stream->descendant_last_cycle - stream->cycle) <= - NGHTTP2_MAX_CYCLE_DISTANCE) { - stream->cycle = dep_stream->descendant_last_cycle; + /* 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)); + } } +} - /* Continue to use same stream->seq */ +static void stream_update_dep_set_rest(nghttp2_stream *stream) { + if (stream == NULL) { + return; + } - nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); + DEBUGF(fprintf(stderr, "stream: stream=%d is rest\n", stream->stream_id)); - DEBUGF(fprintf(stderr, "stream: stream=%d obq resched cycle=%d\n", - stream->stream_id, stream->cycle)); -} + if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) { + return; + } -static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) { - for (; stream->sib_next; stream = stream->sib_next) - ; + if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) { + stream->dpri = NGHTTP2_STREAM_DPRI_REST; - return stream; -} + stream_update_dep_set_rest(stream->sib_next); -int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream, - int32_t weight) { - weight = stream->weight * weight / stream->sum_dep_weight; + return; + } - return nghttp2_max(1, weight); + stream_update_dep_set_rest(stream->sib_next); + stream_update_dep_set_rest(stream->dep_next); } -#ifdef STREAM_DEP_DEBUG - -static void ensure_inactive(nghttp2_stream *stream) { +/* + * Performs dfs starting |stream|, search stream which can become + * NGHTTP2_STREAM_DPRI_TOP and set its dpri. + */ +static void stream_update_dep_set_top(nghttp2_stream *stream) { nghttp2_stream *si; - if (stream->queued) { - fprintf(stderr, "stream(%p)=%d, stream->queued = 1; want 0\n", stream, - stream->stream_id); - assert(0); + if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) { + return; } - if (stream_active(stream)) { - fprintf(stderr, "stream(%p)=%d, stream_active(stream) = 1; want 0\n", - stream, stream->stream_id); - assert(0); - } + if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) { + DEBUGF( + fprintf(stderr, "stream: stream=%d data is top\n", stream->stream_id)); - if (!nghttp2_pq_empty(&stream->obq)) { - fprintf(stderr, "stream(%p)=%d, nghttp2_pq_size() = %zu; want 0\n", stream, - stream->stream_id, nghttp2_pq_size(&stream->obq)); - assert(0); + stream->dpri = NGHTTP2_STREAM_DPRI_TOP; + + return; } for (si = stream->dep_next; si; si = si->sib_next) { - ensure_inactive(si); + stream_update_dep_set_top(si); } } -static void check_queued(nghttp2_stream *stream) { +/* + * Performs dfs starting |stream|, and dueue stream whose dpri is + * NGHTTP2_STREAM_DPRI_TOP and has not been queued yet. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory. + */ +static int stream_update_dep_queue_top(nghttp2_stream *stream, + nghttp2_session *session) { + int rv; nghttp2_stream *si; - int queued; - if (stream->queued) { - if (!stream_subtree_active(stream)) { - fprintf(stderr, - "stream(%p)=%d, stream->queued == 1, but " - "stream_active() == %d and nghttp2_pq_size(&stream->obq) = %zu\n", - stream, stream->stream_id, stream_active(stream), - nghttp2_pq_size(&stream->obq)); - assert(0); - } - if (!stream_active(stream)) { - queued = 0; - for (si = stream->dep_next; si; si = si->sib_next) { - if (si->queued) { - ++queued; - } - } - if (queued == 0) { - fprintf(stderr, "stream(%p)=%d, stream->queued == 1, and " - "!stream_active(), but no descendants is queued\n", - stream, stream->stream_id); - assert(0); + if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) { + return 0; + } + + if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) { + if (!stream->data_item->queued) { + DEBUGF(fprintf(stderr, "stream: stream=%d enqueue\n", stream->stream_id)); + rv = stream_push_data(stream, session); + + if (rv != 0) { + return rv; } } - for (si = stream->dep_next; si; si = si->sib_next) { - check_queued(si); - } - } else { - if (stream_active(stream) || !nghttp2_pq_empty(&stream->obq)) { - fprintf(stderr, "stream(%p) = %d, stream->queued == 0, but " - "stream_active(stream) == %d and " - "nghttp2_pq_size(&stream->obq) = %zu\n", - stream, stream->stream_id, stream_active(stream), - nghttp2_pq_size(&stream->obq)); - assert(0); - } - for (si = stream->dep_next; si; si = si->sib_next) { - ensure_inactive(si); - } + return 0; } -} -static void check_sum_dep(nghttp2_stream *stream) { - nghttp2_stream *si; - int32_t n = 0; - for (si = stream->dep_next; si; si = si->sib_next) { - n += si->weight; - } - if (n != stream->sum_dep_weight) { - fprintf(stderr, "stream(%p)=%d, sum_dep_weight = %d; want %d\n", stream, - stream->stream_id, n, stream->sum_dep_weight); - assert(0); - } for (si = stream->dep_next; si; si = si->sib_next) { - check_sum_dep(si); - } -} + rv = stream_update_dep_queue_top(si, session); -static void check_dep_prev(nghttp2_stream *stream) { - nghttp2_stream *si; - for (si = stream->dep_next; si; si = si->sib_next) { - if (si->dep_prev != stream) { - fprintf(stderr, "si->dep_prev = %p; want %p\n", si->dep_prev, stream); - assert(0); + if (rv != 0) { + return rv; } - check_dep_prev(si); } -} -#endif /* STREAM_DEP_DEBUG */ + return 0; +} -#ifdef STREAM_DEP_DEBUG -static void validate_tree(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_DATA, 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. + */ +static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream) { nghttp2_stream *si; + int rv; - if (!stream) { - return; + stream->sum_norest_weight = 0; + stream->sum_top_weight = 0; + + if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) { + return 1; } - for (; stream->dep_prev; stream = stream->dep_prev) - ; + if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) { + return 0; + } - assert(stream->stream_id == 0); - assert(!stream->queued); + rv = 0; - fprintf(stderr, "checking...\n"); - if (nghttp2_pq_empty(&stream->obq)) { - fprintf(stderr, "root obq empty\n"); - for (si = stream->dep_next; si; si = si->sib_next) { - ensure_inactive(si); + for (si = stream->dep_next; si; si = si->sib_next) { + + if (stream_update_dep_sum_norest_weight(si)) { + rv = 1; + stream->sum_norest_weight += si->weight; } - } else { - for (si = stream->dep_next; si; si = si->sib_next) { - check_queued(si); + + if (si->dpri == NGHTTP2_STREAM_DPRI_TOP) { + stream->sum_top_weight += si->weight; } } - check_sum_dep(stream); - check_dep_prev(stream); + return rv; } -#else /* !STREAM_DEP_DEBUG */ -static void validate_tree(nghttp2_stream *stream _U_) {} -#endif /* !STREAM_DEP_DEBUG*/ -static int stream_update_dep_on_attach_item(nghttp2_stream *stream) { - int rv; +static int stream_update_dep_on_attach_data(nghttp2_stream *stream, + nghttp2_session *session) { + nghttp2_stream *root_stream; - rv = stream_obq_push(stream->dep_prev, stream); - if (rv != 0) { - return rv; - } + stream->dpri = NGHTTP2_STREAM_DPRI_REST; - validate_tree(stream); - return 0; -} + stream_update_dep_set_rest(stream->dep_next); -static int stream_update_dep_on_detach_item(nghttp2_stream *stream) { - if (nghttp2_pq_empty(&stream->obq)) { - stream_obq_remove(stream); - } + root_stream = nghttp2_stream_get_dep_root(stream); - validate_tree(stream); + DEBUGF(fprintf(stderr, "root=%p, stream=%p\n", root_stream, stream)); - return 0; + stream_update_dep_set_top(root_stream); + + stream_update_dep_sum_norest_weight(root_stream); + stream_update_dep_effective_weight(root_stream); + + return stream_update_dep_queue_top(root_stream, session); } -int nghttp2_stream_attach_item(nghttp2_stream *stream, - nghttp2_outbound_item *item) { - int rv; +static int stream_update_dep_on_detach_data(nghttp2_stream *stream, + nghttp2_session *session) { + nghttp2_stream *root_stream; - assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0); - assert(stream->item == NULL); + stream->dpri = NGHTTP2_STREAM_DPRI_NO_DATA; - DEBUGF(fprintf(stderr, "stream: stream=%d attach item=%p\n", - stream->stream_id, item)); + root_stream = nghttp2_stream_get_dep_root(stream); - stream->item = item; + stream_update_dep_set_top(root_stream); - rv = stream_update_dep_on_attach_item(stream); - if (rv != 0) { - /* This may relave stream->queued == 1, but stream->item == NULL. - But only consequence of this error is fatal one, and session - destruction. In that execution path, these inconsistency does - not matter. */ - stream->item = NULL; - return rv; - } + stream_update_dep_sum_norest_weight(root_stream); + stream_update_dep_effective_weight(root_stream); - return 0; + return stream_update_dep_queue_top(root_stream, session); } -int nghttp2_stream_detach_item(nghttp2_stream *stream) { - DEBUGF(fprintf(stderr, "stream: stream=%d detach item=%p\n", - stream->stream_id, stream->item)); +int nghttp2_stream_attach_data(nghttp2_stream *stream, + nghttp2_outbound_item *data_item, + nghttp2_session *session) { + assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0); + assert(stream->data_item == NULL); + + DEBUGF(fprintf(stderr, "stream: stream=%d attach data=%p\n", + stream->stream_id, data_item)); - stream->item = NULL; - stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL); + stream->data_item = data_item; - return stream_update_dep_on_detach_item(stream); + return stream_update_dep_on_attach_data(stream, session); } -int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) { - assert(stream->item); +int nghttp2_stream_detach_data(nghttp2_stream *stream, + nghttp2_session *session) { + DEBUGF(fprintf(stderr, "stream: stream=%d detach data=%p\n", + stream->stream_id, stream->data_item)); - DEBUGF(fprintf(stderr, "stream: stream=%d defer item=%p cause=%02x\n", - stream->stream_id, stream->item, flags)); + stream->data_item = NULL; + stream->flags &= ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL; + + return stream_update_dep_on_detach_data(stream, session); +} + +int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags, + nghttp2_session *session) { + assert(stream->data_item); + + DEBUGF(fprintf(stderr, "stream: stream=%d defer data=%p cause=%02x\n", + stream->stream_id, stream->data_item, flags)); stream->flags |= flags; - return stream_update_dep_on_detach_item(stream); + return stream_update_dep_on_detach_data(stream, session); } -int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) { - assert(stream->item); +int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, uint8_t flags, + nghttp2_session *session) { + assert(stream->data_item); - DEBUGF(fprintf(stderr, "stream: stream=%d resume item=%p flags=%02x\n", - stream->stream_id, stream->item, flags)); + DEBUGF(fprintf(stderr, "stream: stream=%d resume data=%p flags=%02x\n", + stream->stream_id, stream->data_item, flags)); - stream->flags = (uint8_t)(stream->flags & ~flags); + stream->flags &= ~flags; if (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) { return 0; } - return stream_update_dep_on_attach_item(stream); + return stream_update_dep_on_attach_data(stream, session); } -int nghttp2_stream_check_deferred_item(nghttp2_stream *stream) { - return stream->item && (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL); +int nghttp2_stream_check_deferred_data(nghttp2_stream *stream) { + return stream->data_item && + (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL); } int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream) { - return stream->item && + return stream->data_item && (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL); } @@ -575,23 +516,51 @@ void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) { stream->state = NGHTTP2_STREAM_OPENED; - stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH); } -int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream, - nghttp2_stream *target) { - for (; stream; stream = stream->dep_prev) { - if (stream == target) { - return 1; +nghttp2_stream *nghttp2_stream_get_dep_root(nghttp2_stream *stream) { + for (;;) { + if (stream->sib_prev) { + stream = stream->sib_prev; + + continue; } + + if (stream->dep_prev) { + stream = stream->dep_prev; + + continue; + } + + break; } - return 0; + + return stream; } -int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream, - nghttp2_stream *stream) { +int nghttp2_stream_dep_subtree_find(nghttp2_stream *stream, + nghttp2_stream *target) { + if (stream == NULL) { + return 0; + } + + if (stream == target) { + return 1; + } + + if (nghttp2_stream_dep_subtree_find(stream->sib_next, target)) { + return 1; + } + + return nghttp2_stream_dep_subtree_find(stream->dep_next, target); +} + +void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream, + nghttp2_stream *stream) { nghttp2_stream *si; - int rv; + nghttp2_stream *root_stream; + + assert(stream->data_item == NULL); DEBUGF(fprintf(stderr, "stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n", @@ -602,51 +571,32 @@ if (dep_stream->dep_next) { for (si = dep_stream->dep_next; si; si = si->sib_next) { - si->dep_prev = stream; - if (si->queued) { - rv = stream_obq_move(stream, dep_stream, si); - if (rv != 0) { - return rv; - } - } - } - - if (stream_subtree_active(stream)) { - rv = stream_obq_push(dep_stream, stream); - if (rv != 0) { - return rv; - } + stream->num_substreams += si->num_substreams; } stream->dep_next = dep_stream->dep_next; + stream->dep_next->dep_prev = stream; } dep_stream->dep_next = stream; stream->dep_prev = dep_stream; - validate_tree(stream); + root_stream = stream_update_dep_length(dep_stream, 1); - return 0; -} + stream_update_dep_sum_norest_weight(root_stream); + stream_update_dep_effective_weight(root_stream); -static void set_dep_prev(nghttp2_stream *stream, nghttp2_stream *dep) { - for (; stream; stream = stream->sib_next) { - stream->dep_prev = dep; - } + ++stream->roots->num_streams; } static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) { dep_stream->dep_next = stream; - if (stream) { - stream->dep_prev = dep_stream; - } + stream->dep_prev = dep_stream; } -static void link_sib(nghttp2_stream *a, nghttp2_stream *b) { - a->sib_next = b; - if (b) { - b->sib_prev = a; - } +static void link_sib(nghttp2_stream *prev_stream, nghttp2_stream *stream) { + prev_stream->sib_next = stream; + stream->sib_prev = prev_stream; } static void insert_link_dep(nghttp2_stream *dep_stream, @@ -659,6 +609,8 @@ link_sib(stream, sib_next); + sib_next->dep_prev = NULL; + link_dep(dep_stream, stream); } @@ -676,11 +628,10 @@ * | * dep_next */ + dep_next->dep_prev = NULL; link_sib(prev, dep_next); - set_dep_prev(dep_next, stream->dep_prev); - if (stream->sib_next) { link_sib(stream_last_sib(dep_next), stream->sib_next); } @@ -716,12 +667,9 @@ */ link_dep(prev, dep_next); - set_dep_prev(dep_next, stream->dep_prev); - if (stream->sib_next) { link_sib(stream_last_sib(dep_next), stream->sib_next); } - } else if (stream->sib_next) { /* * prev @@ -740,9 +688,15 @@ void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, nghttp2_stream *stream) { + nghttp2_stream *root_stream; + + assert(stream->data_item == NULL); + DEBUGF(fprintf(stderr, "stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream, dep_stream->stream_id, stream, stream->stream_id)); + root_stream = stream_update_dep_length(dep_stream, 1); + dep_stream->sum_dep_weight += stream->weight; if (dep_stream->dep_next == NULL) { @@ -751,13 +705,17 @@ insert_link_dep(dep_stream, stream); } - validate_tree(stream); + stream_update_dep_sum_norest_weight(root_stream); + stream_update_dep_effective_weight(root_stream); + + ++stream->roots->num_streams; } -int nghttp2_stream_dep_remove(nghttp2_stream *stream) { - nghttp2_stream *dep_prev, *si; +void nghttp2_stream_dep_remove(nghttp2_stream *stream) { + nghttp2_stream *prev, *next, *dep_prev, *si, *root_stream; int32_t sum_dep_weight_delta; - int rv; + + root_stream = NULL; DEBUGF(fprintf(stderr, "stream: dep_remove stream(%p)=%d\n", stream, stream->stream_id)); @@ -769,31 +727,50 @@ si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight); sum_dep_weight_delta += si->weight; - - if (si->queued) { - rv = stream_obq_move(stream->dep_prev, stream, si); - if (rv != 0) { - return rv; - } - } } - assert(stream->dep_prev); + prev = stream_first_sib(stream); - dep_prev = stream->dep_prev; + dep_prev = prev->dep_prev; - dep_prev->sum_dep_weight += sum_dep_weight_delta; + if (dep_prev) { + root_stream = stream_update_dep_length(dep_prev, -1); - if (stream->queued) { - stream_obq_remove(stream); + dep_prev->sum_dep_weight += sum_dep_weight_delta; } if (stream->sib_prev) { unlink_sib(stream); - } else { + } else if (stream->dep_prev) { unlink_dep(stream); + } else { + nghttp2_stream_roots_remove(stream->roots, stream); + + /* stream is a root of tree. Removing stream makes its + descendants a root of its own subtree. */ + + for (si = stream->dep_next; si;) { + next = si->sib_next; + + si->dep_prev = NULL; + si->sib_prev = NULL; + si->sib_next = NULL; + + /* We already distributed weight of |stream| to this. */ + si->effective_weight = si->weight; + + nghttp2_stream_roots_add(si->roots, si); + + si = next; + } + } + + if (root_stream) { + stream_update_dep_sum_norest_weight(root_stream); + stream_update_dep_effective_weight(root_stream); } + stream->num_substreams = 1; stream->sum_dep_weight = 0; stream->dep_prev = NULL; @@ -801,207 +778,283 @@ stream->sib_prev = NULL; stream->sib_next = NULL; - validate_tree(dep_prev); - - return 0; + --stream->roots->num_streams; } int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, - nghttp2_stream *stream) { + nghttp2_stream *stream, + nghttp2_session *session) { nghttp2_stream *last_sib; nghttp2_stream *dep_next; - nghttp2_stream *si; - int rv; + nghttp2_stream *root_stream; + size_t delta_substreams; DEBUGF(fprintf(stderr, "stream: dep_insert_subtree dep_stream(%p)=%d " "stream(%p)=%d\n", dep_stream, dep_stream->stream_id, stream, stream->stream_id)); - stream->sum_dep_weight += dep_stream->sum_dep_weight; - dep_stream->sum_dep_weight = stream->weight; + delta_substreams = stream->num_substreams; + + stream_update_dep_set_rest(stream); if (dep_stream->dep_next) { + /* dep_stream->num_substreams includes dep_stream itself */ + stream->num_substreams += dep_stream->num_substreams - 1; + + stream->sum_dep_weight += dep_stream->sum_dep_weight; + dep_stream->sum_dep_weight = stream->weight; + dep_next = dep_stream->dep_next; + stream_update_dep_set_rest(dep_next); + link_dep(dep_stream, stream); if (stream->dep_next) { last_sib = stream_last_sib(stream->dep_next); link_sib(last_sib, dep_next); + + dep_next->dep_prev = NULL; } else { link_dep(stream, dep_next); } - - for (si = dep_next; si; si = si->sib_next) { - si->dep_prev = stream; - if (si->queued) { - rv = stream_obq_move(stream, dep_stream, si); - if (rv != 0) { - return rv; - } - } - } } else { link_dep(dep_stream, stream); - } - if (stream_subtree_active(stream)) { - rv = stream_obq_push(dep_stream, stream); - if (rv != 0) { - return rv; - } + assert(dep_stream->sum_dep_weight == 0); + dep_stream->sum_dep_weight = stream->weight; } - validate_tree(dep_stream); + root_stream = stream_update_dep_length(dep_stream, delta_substreams); - return 0; + stream_update_dep_set_top(root_stream); + + stream_update_dep_sum_norest_weight(root_stream); + stream_update_dep_effective_weight(root_stream); + + return stream_update_dep_queue_top(root_stream, session); } int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream, - nghttp2_stream *stream) { - int rv; + nghttp2_stream *stream, + nghttp2_session *session) { + nghttp2_stream *root_stream; DEBUGF(fprintf(stderr, "stream: dep_add_subtree dep_stream(%p)=%d " "stream(%p)=%d\n", dep_stream, dep_stream->stream_id, stream, stream->stream_id)); - dep_stream->sum_dep_weight += stream->weight; + stream_update_dep_set_rest(stream); if (dep_stream->dep_next) { + dep_stream->sum_dep_weight += stream->weight; + insert_link_dep(dep_stream, stream); } else { link_dep(dep_stream, stream); - } - if (stream_subtree_active(stream)) { - rv = stream_obq_push(dep_stream, stream); - if (rv != 0) { - return rv; - } + assert(dep_stream->sum_dep_weight == 0); + dep_stream->sum_dep_weight = stream->weight; } - validate_tree(dep_stream); + root_stream = stream_update_dep_length(dep_stream, stream->num_substreams); - return 0; + stream_update_dep_set_top(root_stream); + + stream_update_dep_sum_norest_weight(root_stream); + stream_update_dep_effective_weight(root_stream); + + return stream_update_dep_queue_top(root_stream, session); } void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) { - nghttp2_stream *next, *dep_prev; + nghttp2_stream *prev, *next, *dep_prev, *root_stream; DEBUGF(fprintf(stderr, "stream: dep_remove_subtree stream(%p)=%d\n", stream, stream->stream_id)); - assert(stream->dep_prev); + if (stream->sib_prev) { + prev = stream->sib_prev; + + prev->sib_next = stream->sib_next; + if (prev->sib_next) { + prev->sib_next->sib_prev = prev; + } - dep_prev = stream->dep_prev; + prev = stream_first_sib(prev); - if (stream->sib_prev) { - link_sib(stream->sib_prev, stream->sib_next); - } else { + dep_prev = prev->dep_prev; + + } else if (stream->dep_prev) { + dep_prev = stream->dep_prev; next = stream->sib_next; - link_dep(dep_prev, next); + dep_prev->dep_next = next; if (next) { + next->dep_prev = dep_prev; + next->sib_prev = NULL; } - } - dep_prev->sum_dep_weight -= stream->weight; + } else { + nghttp2_stream_roots_remove(stream->roots, stream); - if (stream->queued) { - stream_obq_remove(stream); + dep_prev = NULL; } - validate_tree(dep_prev); + if (dep_prev) { + dep_prev->sum_dep_weight -= stream->weight; + + root_stream = stream_update_dep_length(dep_prev, -stream->num_substreams); + + stream_update_dep_sum_norest_weight(root_stream); + stream_update_dep_effective_weight(root_stream); + } stream->sib_prev = NULL; stream->sib_next = NULL; stream->dep_prev = NULL; } -int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) { - return stream->dep_prev || stream->dep_next || stream->sib_prev || - stream->sib_next; -} +int nghttp2_stream_dep_make_root(nghttp2_stream *stream, + nghttp2_session *session) { + DEBUGF(fprintf(stderr, "stream: dep_make_root stream(%p)=%d\n", stream, + stream->stream_id)); -nghttp2_outbound_item * -nghttp2_stream_next_outbound_item(nghttp2_stream *stream) { - nghttp2_pq_entry *ent; - nghttp2_stream *si; + nghttp2_stream_roots_add(stream->roots, stream); - for (;;) { - if (stream_active(stream)) { - /* Update ascendant's descendant_last_cycle here, so that we can - assure that new stream is scheduled based on it. */ - for (si = stream; si->dep_prev; si = si->dep_prev) { - si->dep_prev->descendant_last_cycle = si->cycle; - } - return stream->item; - } - ent = nghttp2_pq_top(&stream->obq); - if (!ent) { - return NULL; - } - stream = nghttp2_struct_of(ent, nghttp2_stream, pq_entry); - } + stream_update_dep_set_rest(stream); + + stream->effective_weight = stream->weight; + + stream_update_dep_set_top(stream); + + stream_update_dep_sum_norest_weight(stream); + stream_update_dep_effective_weight(stream); + + return stream_update_dep_queue_top(stream, session); } -nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) { - if (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) { - return NGHTTP2_STREAM_STATE_CLOSED; - } +int +nghttp2_stream_dep_all_your_stream_are_belong_to_us(nghttp2_stream *stream, + nghttp2_session *session) { + nghttp2_stream *first, *si; - if (stream->flags & NGHTTP2_STREAM_FLAG_PUSH) { - if (stream->shut_flags & NGHTTP2_SHUT_RD) { - return NGHTTP2_STREAM_STATE_RESERVED_LOCAL; - } + DEBUGF(fprintf(stderr, "stream: ALL YOUR STREAM ARE BELONG TO US " + "stream(%p)=%d\n", + stream, stream->stream_id)); + + first = stream->roots->head; + + /* stream must not be include in stream->roots->head list */ + assert(first != stream); + + if (first) { + nghttp2_stream *prev; + + prev = first; + + DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n", first, + first->stream_id)); + + stream->sum_dep_weight += first->weight; + stream->num_substreams += first->num_substreams; + + for (si = first->root_next; si; si = si->root_next) { + + assert(si != stream); + + DEBUGF( + fprintf(stderr, "stream: root stream(%p)=%d\n", si, si->stream_id)); - if (stream->shut_flags & NGHTTP2_SHUT_WR) { - return NGHTTP2_STREAM_STATE_RESERVED_REMOTE; + stream->sum_dep_weight += si->weight; + stream->num_substreams += si->num_substreams; + + link_sib(prev, si); + + prev = si; } - } - if (stream->shut_flags & NGHTTP2_SHUT_RD) { - return NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE; - } + if (stream->dep_next) { + nghttp2_stream *sib_next; - if (stream->shut_flags & NGHTTP2_SHUT_WR) { - return NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL; - } + sib_next = stream->dep_next; + + sib_next->dep_prev = NULL; - if (stream->state == NGHTTP2_STREAM_IDLE) { - return NGHTTP2_STREAM_STATE_IDLE; + link_sib(first, sib_next); + link_dep(stream, prev); + } else { + link_dep(stream, first); + } } - return NGHTTP2_STREAM_STATE_OPEN; -} + nghttp2_stream_roots_remove_all(stream->roots); -nghttp2_stream *nghttp2_stream_get_parent(nghttp2_stream *stream) { - return stream->dep_prev; + return nghttp2_stream_dep_make_root(stream, session); } -nghttp2_stream *nghttp2_stream_get_next_sibling(nghttp2_stream *stream) { - return stream->sib_next; +int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) { + return stream->dep_prev || stream->dep_next || stream->sib_prev || + stream->sib_next || stream->root_next || stream->root_prev || + stream->roots->head == stream; } -nghttp2_stream *nghttp2_stream_get_previous_sibling(nghttp2_stream *stream) { - return stream->sib_prev; +void nghttp2_stream_roots_init(nghttp2_stream_roots *roots) { + roots->head = NULL; + roots->num_streams = 0; } -nghttp2_stream *nghttp2_stream_get_first_child(nghttp2_stream *stream) { - return stream->dep_next; -} +void nghttp2_stream_roots_free(nghttp2_stream_roots *roots _U_) {} + +void nghttp2_stream_roots_add(nghttp2_stream_roots *roots, + nghttp2_stream *stream) { + if (roots->head) { + stream->root_next = roots->head; + roots->head->root_prev = stream; + } -int32_t nghttp2_stream_get_weight(nghttp2_stream *stream) { - return stream->weight; + roots->head = stream; } -int32_t nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream) { - return stream->sum_dep_weight; +void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots, + nghttp2_stream *stream) { + nghttp2_stream *root_prev, *root_next; + + root_prev = stream->root_prev; + root_next = stream->root_next; + + if (root_prev) { + root_prev->root_next = root_next; + + if (root_next) { + root_next->root_prev = root_prev; + } + } else { + if (root_next) { + root_next->root_prev = NULL; + } + + roots->head = root_next; + } + + stream->root_prev = NULL; + stream->root_next = NULL; } -int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream) { - return stream->stream_id; +void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots) { + nghttp2_stream *si, *next; + + for (si = roots->head; si;) { + next = si->root_next; + + si->root_prev = NULL; + si->root_next = NULL; + + si = next; + } + + roots->head = NULL; } diff -Nru nghttp2-1.13.0/lib/nghttp2_stream.h nghttp2-0.6.7/lib/nghttp2_stream.h --- nghttp2-1.13.0/lib/nghttp2_stream.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_stream.h 2014-11-30 14:15:07.000000000 +0000 @@ -36,6 +36,11 @@ #include "nghttp2_int.h" /* + * Maximum number of streams in one dependency tree. + */ +#define NGHTTP2_MAX_DEP_TREE_LENGTH 100 + +/* * If local peer is stream initiator: * NGHTTP2_STREAM_OPENING : upon sending request HEADERS * NGHTTP2_STREAM_OPENED : upon receiving response HEADERS @@ -79,8 +84,7 @@ typedef enum { NGHTTP2_STREAM_FLAG_NONE = 0, - /* Indicates that this stream is pushed stream and not opened - yet. */ + /* Indicates that this stream is pushed stream */ NGHTTP2_STREAM_FLAG_PUSH = 0x01, /* Indicates that this stream was closed */ NGHTTP2_STREAM_FLAG_CLOSED = 0x02, @@ -94,67 +98,24 @@ } nghttp2_stream_flag; -/* HTTP related flags to enforce HTTP semantics */ typedef enum { - NGHTTP2_HTTP_FLAG_NONE = 0, - /* header field seen so far */ - NGHTTP2_HTTP_FLAG__AUTHORITY = 1, - NGHTTP2_HTTP_FLAG__PATH = 1 << 1, - NGHTTP2_HTTP_FLAG__METHOD = 1 << 2, - NGHTTP2_HTTP_FLAG__SCHEME = 1 << 3, - /* host is not pseudo header, but we require either host or - :authority */ - NGHTTP2_HTTP_FLAG_HOST = 1 << 4, - NGHTTP2_HTTP_FLAG__STATUS = 1 << 5, - /* required header fields for HTTP request except for CONNECT - method. */ - NGHTTP2_HTTP_FLAG_REQ_HEADERS = NGHTTP2_HTTP_FLAG__METHOD | - NGHTTP2_HTTP_FLAG__PATH | - NGHTTP2_HTTP_FLAG__SCHEME, - NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED = 1 << 6, - /* HTTP method flags */ - NGHTTP2_HTTP_FLAG_METH_CONNECT = 1 << 7, - NGHTTP2_HTTP_FLAG_METH_HEAD = 1 << 8, - NGHTTP2_HTTP_FLAG_METH_OPTIONS = 1 << 9, - NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND = 1 << 10, - NGHTTP2_HTTP_FLAG_METH_ALL = NGHTTP2_HTTP_FLAG_METH_CONNECT | - NGHTTP2_HTTP_FLAG_METH_HEAD | - NGHTTP2_HTTP_FLAG_METH_OPTIONS | - NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND, - /* :path category */ - /* path starts with "/" */ - NGHTTP2_HTTP_FLAG_PATH_REGULAR = 1 << 11, - /* path "*" */ - NGHTTP2_HTTP_FLAG_PATH_ASTERISK = 1 << 12, - /* scheme */ - /* "http" or "https" scheme */ - NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 13, - /* set if final response is expected */ - NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14 -} nghttp2_http_flag; + NGHTTP2_STREAM_DPRI_NONE = 0, + NGHTTP2_STREAM_DPRI_NO_DATA = 0x01, + NGHTTP2_STREAM_DPRI_TOP = 0x02, + NGHTTP2_STREAM_DPRI_REST = 0x04 +} nghttp2_stream_dpri; + +struct nghttp2_stream_roots; + +typedef struct nghttp2_stream_roots nghttp2_stream_roots; + +struct nghttp2_stream; + +typedef struct nghttp2_stream nghttp2_stream; struct nghttp2_stream { /* Intrusive Map */ nghttp2_map_entry map_entry; - /* Entry for dep_prev->obq */ - nghttp2_pq_entry pq_entry; - /* Priority Queue storing direct descendant (nghttp2_stream). Only - streams which itself has some data to send, or has a descendant - which has some data to sent. */ - nghttp2_pq obq; - /* Content-Length of request/response body. -1 if unknown. */ - int64_t content_length; - /* Received body so far */ - int64_t recv_content_length; - /* Base last_cycle for direct descendent streams. */ - uint32_t descendant_last_cycle; - /* Next scheduled time to sent item */ - uint32_t cycle; - /* Next seq used for direct descendant streams */ - uint64_t descendant_next_seq; - /* Secondary key for prioritization to break a tie for cycle. This - value is monotonically increased for single parent stream. */ - uint64_t seq; /* 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 @@ -164,19 +125,28 @@ dep_prev and sib_prev are NULL. */ nghttp2_stream *dep_prev, *dep_next; nghttp2_stream *sib_prev, *sib_next; + /* pointers to track dependency tree root streams. This is + doubly-linked list and first element is pointed by + roots->head. */ + nghttp2_stream *root_prev, *root_next; /* When stream is kept after closure, it may be kept in doubly linked list pointed by nghttp2_session closed_stream_head. closed_next points to the next stream object if it is the element of the list. */ nghttp2_stream *closed_prev, *closed_next; + /* pointer to roots, which tracks dependency tree roots */ + nghttp2_stream_roots *roots; /* The arbitrary data provided by user for this stream. */ void *stream_user_data; /* Item to send */ - nghttp2_outbound_item *item; - /* Last written length of frame payload */ - size_t last_writelen; + nghttp2_outbound_item *data_item; /* stream ID */ int32_t stream_id; + /* categorized priority of this stream. Only stream bearing + NGHTTP2_STREAM_DPRI_TOP can send item. */ + nghttp2_stream_dpri dpri; + /* the number of streams in subtree */ + size_t num_substreams; /* Current remote window size. This value is computed against the current initial window size of remote endpoint. */ int32_t remote_window_size; @@ -197,35 +167,30 @@ int32_t local_window_size; /* weight of this stream */ int32_t weight; - /* This is unpaid penalty (offset) when calculating cycle. */ - uint32_t pending_penalty; - /* sum of weight of direct descendants */ + /* effective weight of this stream in belonging dependency tree */ + int32_t effective_weight; + /* sum of weight (not effective_weight) of direct descendants */ int32_t sum_dep_weight; + /* sum of weight of direct descendants which have at least one + 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; - /* 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; - /* Nonzero if this stream has been queued to stream pointed by - dep_prev. We maintain the invariant that if a stream is queued, - then its ancestors, except for root, are also queued. This - invariant may break in fatal error condition. */ - uint8_t queued; - /* This flag is used to reduce excessive queuing of WINDOW_UPDATE to - this stream. The nonzero does not necessarily mean WINDOW_UPDATE - is not queued. */ - uint8_t window_update_queued; }; void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id, uint8_t flags, nghttp2_stream_state initial_state, - int32_t weight, int32_t remote_initial_window_size, + int32_t weight, nghttp2_stream_roots *roots, + int32_t remote_initial_window_size, int32_t local_initial_window_size, - void *stream_user_data, nghttp2_mem *mem); + void *stream_user_data); void nghttp2_stream_free(nghttp2_stream *stream); @@ -236,9 +201,9 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag); /* - * Defer |stream->item|. We won't call this function in the situation - * where |stream->item| == NULL. The |flags| is bitwise OR of zero or - * more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and + * Defer |stream->data_item|. We won't call this function in the + * situation where |stream->data_item| == NULL. If |flags| is bitwise + * OR of zero or more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL. The |flags| indicates * the reason of this action. * @@ -248,7 +213,8 @@ * NGHTTP2_ERR_NOMEM * Out of memory */ -int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags); +int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags, + nghttp2_session *session); /* * Put back deferred data in this stream to active state. The |flags| @@ -257,22 +223,17 @@ * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and given masks are * cleared if they are set. So even if this function is called, if * one of flag is still set, data does not become active. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGHTTP2_ERR_NOMEM - * Out of memory */ -int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags); +int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream, uint8_t flags, + nghttp2_session *session); /* - * Returns nonzero if item is deferred by whatever reason. + * Returns nonzero if data item is deferred by whatever reason. */ -int nghttp2_stream_check_deferred_item(nghttp2_stream *stream); +int nghttp2_stream_check_deferred_data(nghttp2_stream *stream); /* - * Returns nonzero if item is deferred by flow control. + * Returns nonzero if data item is deferred by flow control. */ int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream); @@ -308,47 +269,61 @@ void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream); /* - * Returns nonzero if |target| is an ancestor of |stream|. + * Returns the stream positioned in root of the dependency tree the + * |stream| belongs to. */ -int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream, - nghttp2_stream *target); +nghttp2_stream *nghttp2_stream_get_dep_root(nghttp2_stream *stream); + +/* + * Returns nonzero if |target| is found in subtree of |stream|. + */ +int nghttp2_stream_dep_subtree_find(nghttp2_stream *stream, + nghttp2_stream *target); /* * Computes distributed weight of a stream of the |weight| under the - * |stream| if |stream| is removed from a dependency tree. + * |stream| if |stream| is removed from a dependency tree. The result + * is computed using stream->weight rather than + * stream->effective_weight. */ int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream, int32_t weight); /* + * Computes effective weight of a stream of the |weight| under the + * |stream|. The result is computed using stream->effective_weight + * rather than stream->weight. This function is used to determine + * weight in dependency tree. + */ +int32_t nghttp2_stream_dep_distributed_effective_weight(nghttp2_stream *stream, + int32_t weight); + +/* * Makes the |stream| depend on the |dep_stream|. This dependency is * exclusive. All existing direct descendants of |dep_stream| become * the descendants of the |stream|. This function assumes - * |stream->item| is NULL. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGHTTP2_ERR_NOMEM - * Out of memory + * |stream->data| is NULL and no dpri members are changed in this + * dependency tree. */ -int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream, - nghttp2_stream *stream); +void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream, + nghttp2_stream *stream); /* * Makes the |stream| depend on the |dep_stream|. This dependency is - * not exclusive. This function assumes |stream->item| is NULL. + * not exclusive. This function assumes |stream->data| is NULL and no + * dpri members are changed in this dependency tree. */ void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, nghttp2_stream *stream); /* * Removes the |stream| from the current dependency tree. This - * function assumes |stream->item| is NULL. + * function assumes |stream->data| is NULL. */ -int nghttp2_stream_dep_remove(nghttp2_stream *stream); +void nghttp2_stream_dep_remove(nghttp2_stream *stream); /* - * Attaches |item| to |stream|. + * Attaches |data_item| to |stream|. Updates dpri members in this + * dependency tree. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -356,12 +331,14 @@ * NGHTTP2_ERR_NOMEM * Out of memory */ -int nghttp2_stream_attach_item(nghttp2_stream *stream, - nghttp2_outbound_item *item); +int nghttp2_stream_attach_data(nghttp2_stream *stream, + nghttp2_outbound_item *data_item, + nghttp2_session *session); /* - * Detaches |stream->item|. This function does not free - * |stream->item|. The caller must free it. + * Detaches |stream->data_item|. Updates dpri members in this + * dependency tree. This function does not free |stream->data_item|. + * The caller must free it. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -369,11 +346,12 @@ * NGHTTP2_ERR_NOMEM * Out of memory */ -int nghttp2_stream_detach_item(nghttp2_stream *stream); +int nghttp2_stream_detach_data(nghttp2_stream *stream, + nghttp2_session *session); /* * Makes the |stream| depend on the |dep_stream|. This dependency is - * exclusive. + * exclusive. Updates dpri members in this dependency tree. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -382,11 +360,12 @@ * Out of memory */ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream, - nghttp2_stream *stream); + nghttp2_stream *stream, + nghttp2_session *session); /* * Makes the |stream| depend on the |dep_stream|. This dependency is - * not exclusive. + * not exclusive. Updates dpri members in this dependency tree. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -395,11 +374,13 @@ * Out of memory */ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream, - nghttp2_stream *stream); + nghttp2_stream *stream, + nghttp2_session *session); /* - * Removes subtree whose root stream is |stream|. The - * effective_weight of streams in removed subtree is not updated. + * Removes subtree whose root stream is |stream|. Removing subtree + * does not change dpri values. The effective_weight of streams in + * removed subtree is not updated. * * This function returns 0 if it succeeds, or one of the following * negative error codes: @@ -410,27 +391,53 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream); /* - * Returns nonzero if |stream| is in any dependency tree. + * Makes the |stream| as root. Updates dpri members in this + * dependency tree. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory */ -int nghttp2_stream_in_dep_tree(nghttp2_stream *stream); +int nghttp2_stream_dep_make_root(nghttp2_stream *stream, + nghttp2_session *session); /* - * Schedules transmission of |stream|'s item, assuming stream->item is - * attached, and stream->last_writelen was updated. + * Makes the |stream| as root and all existing root streams become + * direct children of |stream|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGHTTP2_ERR_NOMEM + * Out of memory */ -void nghttp2_stream_reschedule(nghttp2_stream *stream); +int +nghttp2_stream_dep_all_your_stream_are_belong_to_us(nghttp2_stream *stream, + nghttp2_session *session); /* - * Changes |stream|'s weight to |weight|. If |stream| is queued, it - * will be rescheduled based on new weight. + * Returns nonzero if |stream| is in any dependency tree. */ -void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight); +int nghttp2_stream_in_dep_tree(nghttp2_stream *stream); -/* - * Returns a stream which has highest priority, updating - * descendant_last_cycle of selected stream's ancestors. - */ -nghttp2_outbound_item * -nghttp2_stream_next_outbound_item(nghttp2_stream *stream); +struct nghttp2_stream_roots { + nghttp2_stream *head; + + int32_t num_streams; +}; + +void nghttp2_stream_roots_init(nghttp2_stream_roots *roots); + +void nghttp2_stream_roots_free(nghttp2_stream_roots *roots); + +void nghttp2_stream_roots_add(nghttp2_stream_roots *roots, + nghttp2_stream *stream); + +void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots, + nghttp2_stream *stream); + +void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots); #endif /* NGHTTP2_STREAM */ diff -Nru nghttp2-1.13.0/lib/nghttp2_submit.c nghttp2-0.6.7/lib/nghttp2_submit.c --- nghttp2-1.13.0/lib/nghttp2_submit.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/lib/nghttp2_submit.c 2014-11-30 14:15:07.000000000 +0000 @@ -32,35 +32,6 @@ #include "nghttp2_helper.h" #include "nghttp2_priority_spec.h" -/* - * Detects the dependency error, that is stream attempted to depend on - * itself. If |stream_id| is -1, we use session->next_stream_id as - * stream ID. - * - * This function returns 0 if it succeeds, or one of the following - * error codes: - * - * NGHTTP2_ERR_INVALID_ARGUMENT - * Stream attempted to depend on itself. - */ -static int detect_self_dependency(nghttp2_session *session, int32_t stream_id, - const nghttp2_priority_spec *pri_spec) { - assert(pri_spec); - - if (stream_id == -1) { - if ((int32_t)session->next_stream_id == pri_spec->stream_id) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - return 0; - } - - if (stream_id == pri_spec->stream_id) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - return 0; -} - /* This function takes ownership of |nva_copy|. Regardless of the return value, the caller must not free |nva_copy| after this function returns. */ @@ -69,33 +40,36 @@ const nghttp2_priority_spec *pri_spec, nghttp2_nv *nva_copy, size_t nvlen, const nghttp2_data_provider *data_prd, - void *stream_user_data) { + void *stream_user_data, + uint8_t attach_stream) { int rv; uint8_t flags_copy; nghttp2_outbound_item *item = NULL; nghttp2_frame *frame = NULL; nghttp2_headers_category hcat; - nghttp2_mem *mem; - mem = &session->mem; + if (stream_id == 0) { + rv = NGHTTP2_ERR_INVALID_ARGUMENT; + goto fail; + } - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + item = malloc(sizeof(nghttp2_outbound_item)); if (item == NULL) { rv = NGHTTP2_ERR_NOMEM; goto fail; } - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); if (data_prd != NULL && data_prd->read_callback != NULL) { item->aux_data.headers.data_prd = *data_prd; } item->aux_data.headers.stream_user_data = stream_user_data; + item->aux_data.headers.attach_stream = attach_stream; - flags_copy = - (uint8_t)((flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) | - NGHTTP2_FLAG_END_HEADERS); + flags_copy = (flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) | + NGHTTP2_FLAG_END_HEADERS; if (stream_id == -1) { if (session->next_stream_id > INT32_MAX) { @@ -103,7 +77,7 @@ goto fail; } - stream_id = (int32_t)session->next_stream_id; + stream_id = session->next_stream_id; session->next_stream_id += 2; hcat = NGHTTP2_HCAT_REQUEST; @@ -120,7 +94,7 @@ rv = nghttp2_session_add_item(session, item); if (rv != 0) { - nghttp2_frame_headers_free(&frame->headers, mem); + nghttp2_frame_headers_free(&frame->headers); goto fail2; } @@ -132,51 +106,47 @@ fail: /* nghttp2_frame_headers_init() takes ownership of nva_copy. */ - nghttp2_nv_array_del(nva_copy, mem); + nghttp2_nv_array_del(nva_copy); fail2: - nghttp2_mem_free(mem, item); + free(item); return rv; } +static void adjust_priority_spec_weight(nghttp2_priority_spec *pri_spec) { + if (pri_spec->weight < NGHTTP2_MIN_WEIGHT) { + pri_spec->weight = NGHTTP2_MIN_WEIGHT; + } else if (pri_spec->weight > NGHTTP2_MAX_WEIGHT) { + pri_spec->weight = NGHTTP2_MAX_WEIGHT; + } +} + static int32_t submit_headers_shared_nva(nghttp2_session *session, uint8_t flags, int32_t stream_id, const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd, - void *stream_user_data) { + void *stream_user_data, + uint8_t attach_stream) { int rv; nghttp2_nv *nva_copy; nghttp2_priority_spec copy_pri_spec; - nghttp2_mem *mem; - - mem = &session->mem; if (pri_spec) { copy_pri_spec = *pri_spec; - nghttp2_priority_spec_normalize_weight(©_pri_spec); + adjust_priority_spec_weight(©_pri_spec); } else { nghttp2_priority_spec_default_init(©_pri_spec); } - rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen, mem); + rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen); if (rv < 0) { return rv; } return submit_headers_shared(session, flags, stream_id, ©_pri_spec, - nva_copy, nvlen, data_prd, stream_user_data); -} - -int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id, - const nghttp2_nv *nva, size_t nvlen) { - if (stream_id <= 0) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - return (int)submit_headers_shared_nva(session, NGHTTP2_FLAG_END_STREAM, - stream_id, NULL, nva, nvlen, NULL, - NULL); + nva_copy, nvlen, data_prd, stream_user_data, + attach_stream); } int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, @@ -184,37 +154,21 @@ const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, void *stream_user_data) { - int rv; - - if (stream_id == -1) { - if (session->server) { - return NGHTTP2_ERR_PROTO; - } - } else if (stream_id <= 0) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - flags &= NGHTTP2_FLAG_END_STREAM; if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) { - rv = detect_self_dependency(session, stream_id, pri_spec); - if (rv != 0) { - return rv; - } - flags |= NGHTTP2_FLAG_PRIORITY; } else { pri_spec = NULL; } return submit_headers_shared_nva(session, flags, stream_id, pri_spec, nva, - nvlen, NULL, stream_user_data); + nvlen, NULL, stream_user_data, 0); } -int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags, +int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags _U_, const uint8_t *opaque_data) { - flags &= NGHTTP2_FLAG_ACK; - return nghttp2_session_add_ping(session, flags, opaque_data); + return nghttp2_session_add_ping(session, NGHTTP2_FLAG_NONE, opaque_data); } int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_, @@ -224,9 +178,6 @@ nghttp2_outbound_item *item; nghttp2_frame *frame; nghttp2_priority_spec copy_pri_spec; - nghttp2_mem *mem; - - mem = &session->mem; if (stream_id == 0 || pri_spec == NULL) { return NGHTTP2_ERR_INVALID_ARGUMENT; @@ -238,15 +189,15 @@ copy_pri_spec = *pri_spec; - nghttp2_priority_spec_normalize_weight(©_pri_spec); + adjust_priority_spec_weight(©_pri_spec); - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + item = malloc(sizeof(nghttp2_outbound_item)); if (item == NULL) { return NGHTTP2_ERR_NOMEM; } - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; @@ -256,7 +207,7 @@ if (rv != 0) { nghttp2_frame_priority_free(&frame->priority); - nghttp2_mem_free(mem, item); + free(item); return rv; } @@ -276,24 +227,8 @@ int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags _U_, int32_t last_stream_id, uint32_t error_code, const uint8_t *opaque_data, size_t opaque_data_len) { - if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) { - return 0; - } return nghttp2_session_add_goaway(session, last_stream_id, error_code, - opaque_data, opaque_data_len, - NGHTTP2_GOAWAY_AUX_NONE); -} - -int nghttp2_submit_shutdown_notice(nghttp2_session *session) { - if (!session->server) { - return NGHTTP2_ERR_INVALID_STATE; - } - if (session->goaway_flags) { - return 0; - } - return nghttp2_session_add_goaway(session, (1u << 31) - 1, NGHTTP2_NO_ERROR, - NULL, 0, - NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE); + opaque_data, opaque_data_len, 0); } int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags _U_, @@ -311,11 +246,8 @@ uint8_t flags_copy; int32_t promised_stream_id; int rv; - nghttp2_mem *mem; - mem = &session->mem; - - if (stream_id <= 0 || nghttp2_session_is_my_stream_id(session, stream_id)) { + if (stream_id == 0 || nghttp2_session_is_my_stream_id(session, stream_id)) { return NGHTTP2_ERR_INVALID_ARGUMENT; } @@ -328,26 +260,26 @@ return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE; } - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + item = malloc(sizeof(nghttp2_outbound_item)); if (item == NULL) { return NGHTTP2_ERR_NOMEM; } - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); item->aux_data.headers.stream_user_data = promised_stream_user_data; frame = &item->frame; - rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen, mem); + rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen); if (rv < 0) { - nghttp2_mem_free(mem, item); + free(item); return rv; } flags_copy = NGHTTP2_FLAG_END_HEADERS; - promised_stream_id = (int32_t)session->next_stream_id; + promised_stream_id = session->next_stream_id; session->next_stream_id += 2; nghttp2_frame_push_promise_init(&frame->push_promise, flags_copy, stream_id, @@ -356,8 +288,8 @@ rv = nghttp2_session_add_item(session, item); if (rv != 0) { - nghttp2_frame_push_promise_free(&frame->push_promise, mem); - nghttp2_mem_free(mem, item); + nghttp2_frame_push_promise_free(&frame->push_promise); + free(item); return rv; } @@ -410,156 +342,105 @@ return 0; } -int nghttp2_session_set_local_window_size(nghttp2_session *session, - uint8_t flags, int32_t stream_id, - int32_t window_size) { - int32_t window_size_increment; - nghttp2_stream *stream; +int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_, + int32_t stream_id, uint32_t max_age, uint16_t port, + const uint8_t *protocol_id, size_t protocol_id_len, + const uint8_t *host, size_t host_len, + const uint8_t *origin, size_t origin_len) { int rv; + size_t varlen; + uint8_t *var, *varp; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_ext_altsvc *altsvc; + uint8_t *copy_protocol_id, *copy_host, *copy_origin; - if (window_size < 0) { - return NGHTTP2_ERR_INVALID_ARGUMENT; + if (!session->server) { + return NGHTTP2_ERR_PROTO; } - flags = 0; + varlen = protocol_id_len + host_len + origin_len; - if (stream_id == 0) { - window_size_increment = window_size - session->local_window_size; + /* 9 = fixed part 8 bytes + HOST_LEN 1 byte */ + if (varlen + 9 > NGHTTP2_MAX_PAYLOADLEN) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } - if (window_size_increment == 0) { - return 0; - } + altsvc = malloc(sizeof(nghttp2_ext_altsvc)); - if (window_size_increment < 0) { - return nghttp2_adjust_local_window_size( - &session->local_window_size, &session->recv_window_size, - &session->recv_reduction, &window_size_increment); - } + if (altsvc == NULL) { + rv = NGHTTP2_ERR_NOMEM; - rv = nghttp2_increase_local_window_size( - &session->local_window_size, &session->recv_window_size, - &session->recv_reduction, &window_size_increment); + goto fail; + } - if (rv != 0) { - return rv; - } + if (varlen == 0) { + var = NULL; + copy_protocol_id = NULL; + copy_host = NULL; + copy_origin = NULL; } else { - stream = nghttp2_session_get_stream(session, stream_id); + var = malloc(varlen); - if (stream == NULL) { - return 0; - } - - window_size_increment = window_size - stream->local_window_size; - - if (window_size_increment == 0) { - return 0; - } - - if (window_size_increment < 0) { - return nghttp2_adjust_local_window_size( - &stream->local_window_size, &stream->recv_window_size, - &stream->recv_reduction, &window_size_increment); - } - - rv = nghttp2_increase_local_window_size( - &stream->local_window_size, &stream->recv_window_size, - &stream->recv_reduction, &window_size_increment); + if (var == NULL) { + rv = NGHTTP2_ERR_NOMEM; - if (rv != 0) { - return rv; + goto var_alloc_fail; } - } - - if (window_size_increment > 0) { - return nghttp2_session_add_window_update(session, flags, stream_id, - window_size_increment); - } - - return 0; -} - -int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_, - int32_t stream_id, const uint8_t *origin, - size_t origin_len, const uint8_t *field_value, - size_t field_value_len) { - nghttp2_mem *mem; - uint8_t *buf, *p; - uint8_t *origin_copy; - uint8_t *field_value_copy; - nghttp2_outbound_item *item; - nghttp2_frame *frame; - nghttp2_ext_altsvc *altsvc; - int rv; - mem = &session->mem; + varp = var; - if (!session->server) { - return NGHTTP2_ERR_INVALID_STATE; - } + memcpy(varp, protocol_id, protocol_id_len); - if (2 + origin_len + field_value_len > NGHTTP2_MAX_PAYLOADLEN) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } + copy_protocol_id = varp; + varp += protocol_id_len; - if (stream_id == 0) { - if (origin_len == 0) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - } else if (origin_len != 0) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } + memcpy(varp, host, host_len); - buf = nghttp2_mem_malloc(mem, origin_len + field_value_len + 2); - if (buf == NULL) { - return NGHTTP2_ERR_NOMEM; - } + copy_host = varp; + varp += host_len; - p = buf; + memcpy(varp, origin, origin_len); - origin_copy = p; - if (origin_len) { - p = nghttp2_cpymem(p, origin, origin_len); + copy_origin = varp; } - *p++ = '\0'; - field_value_copy = p; - if (field_value_len) { - p = nghttp2_cpymem(p, field_value, field_value_len); - } - *p++ = '\0'; + item = malloc(sizeof(nghttp2_outbound_item)); - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); if (item == NULL) { rv = NGHTTP2_ERR_NOMEM; - goto fail_item_malloc; - } - nghttp2_outbound_item_init(item); - - item->aux_data.ext.builtin = 1; + goto frame_alloc_fail; + } - altsvc = &item->ext_frame_payload.altsvc; + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; frame->ext.payload = altsvc; - nghttp2_frame_altsvc_init(&frame->ext, stream_id, origin_copy, origin_len, - field_value_copy, field_value_len); + nghttp2_frame_altsvc_init(&frame->ext, stream_id, max_age, port, + copy_protocol_id, protocol_id_len, copy_host, + host_len, copy_origin, origin_len); rv = nghttp2_session_add_item(session, item); + if (rv != 0) { - nghttp2_frame_altsvc_free(&frame->ext, mem); - nghttp2_mem_free(mem, item); + nghttp2_frame_altsvc_free(&frame->ext); + free(item); + free(altsvc); return rv; } return 0; -fail_item_malloc: - free(buf); +frame_alloc_fail: + free(var); +var_alloc_fail: + free(altsvc); + +fail: return rv; } @@ -583,25 +464,15 @@ const nghttp2_data_provider *data_prd, void *stream_user_data) { uint8_t flags; - int rv; - if (session->server) { - return NGHTTP2_ERR_PROTO; - } - - if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) { - rv = detect_self_dependency(session, -1, pri_spec); - if (rv != 0) { - return rv; - } - } else { + if (pri_spec && nghttp2_priority_spec_check_default(pri_spec)) { pri_spec = NULL; } flags = set_request_flags(pri_spec, data_prd); return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen, - data_prd, stream_user_data); + data_prd, stream_user_data, 0); } static uint8_t set_response_flags(const nghttp2_data_provider *data_prd) { @@ -615,19 +486,9 @@ int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd) { - uint8_t flags; - - if (stream_id <= 0) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - if (!session->server) { - return NGHTTP2_ERR_PROTO; - } - - flags = set_response_flags(data_prd); + uint8_t flags = set_response_flags(data_prd); return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen, - data_prd, NULL); + data_prd, NULL, 1); } int nghttp2_submit_data(nghttp2_session *session, uint8_t flags, @@ -638,20 +499,17 @@ nghttp2_frame *frame; nghttp2_data_aux_data *aux_data; uint8_t nflags = flags & NGHTTP2_FLAG_END_STREAM; - nghttp2_mem *mem; - - mem = &session->mem; if (stream_id == 0) { return NGHTTP2_ERR_INVALID_ARGUMENT; } - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); + item = malloc(sizeof(nghttp2_outbound_item)); if (item == NULL) { return NGHTTP2_ERR_NOMEM; } - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; aux_data = &item->aux_data.data; @@ -665,7 +523,7 @@ rv = nghttp2_session_add_item(session, item); if (rv != 0) { nghttp2_frame_data_free(&frame->data); - nghttp2_mem_free(mem, item); + free(item); return rv; } return 0; @@ -682,42 +540,5 @@ return NGHTTP2_ERR_INSUFF_BUFSIZE; } - return (ssize_t)nghttp2_frame_pack_settings_payload(buf, iv, niv); -} - -int nghttp2_submit_extension(nghttp2_session *session, uint8_t type, - uint8_t flags, int32_t stream_id, void *payload) { - int rv; - nghttp2_outbound_item *item; - nghttp2_frame *frame; - nghttp2_mem *mem; - - mem = &session->mem; - - if (type <= NGHTTP2_CONTINUATION) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - - if (!session->callbacks.pack_extension_callback) { - return NGHTTP2_ERR_INVALID_STATE; - } - - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); - if (item == NULL) { - return NGHTTP2_ERR_NOMEM; - } - - nghttp2_outbound_item_init(item); - - frame = &item->frame; - nghttp2_frame_extension_init(&frame->ext, type, flags, stream_id, payload); - - rv = nghttp2_session_add_item(session, item); - if (rv != 0) { - nghttp2_frame_extension_free(&frame->ext); - nghttp2_mem_free(mem, item); - return rv; - } - - return 0; + return nghttp2_frame_pack_settings_payload(buf, iv, niv); } diff -Nru nghttp2-1.13.0/ltmain.sh nghttp2-0.6.7/ltmain.sh --- nghttp2-1.13.0/ltmain.sh 2016-07-21 13:47:58.000000000 +0000 +++ nghttp2-0.6.7/ltmain.sh 2014-11-30 14:15:30.000000000 +0000 @@ -1,12 +1,9 @@ -#! /bin/sh -## DO NOT EDIT - This file generated from ./build-aux/ltmain.in -## by inline-source v2014-01-03.01 -# libtool (GNU libtool) 2.4.6 -# Provide generalized library-building support services. +# libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit , 1996 -# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -26,2112 +23,881 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . - - -PROGRAM=libtool -PACKAGE=libtool -VERSION="2.4.6 Debian-2.4.6-0.1" -package_revision=2.4.6 - - -## ------ ## -## Usage. ## -## ------ ## - -# Run './libtool --help' for help with using this script from the -# command line. - - -## ------------------------------- ## -## User overridable command paths. ## -## ------------------------------- ## - -# After configure completes, it has a better idea of some of the -# shell tools we need than the defaults used by the functions shared -# with bootstrap, so set those here where they can still be over- -# ridden by the user, but otherwise take precedence. - -: ${AUTOCONF="autoconf"} -: ${AUTOMAKE="automake"} - - -## -------------------------- ## -## Source external libraries. ## -## -------------------------- ## - -# Much of our low-level functionality needs to be sourced from external -# libraries, which are installed to $pkgauxdir. - -# Set a version string for this script. -scriptversion=2015-01-20.17; # UTC - -# General shell script boiler plate, and helper functions. -# Written by Gary V. Vaughan, 2004 - -# Copyright (C) 2004-2015 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. - -# As a special exception to the GNU General Public License, if you distribute -# this file as part of a program or library that is built using GNU Libtool, -# you may include this file under the same distribution terms that you use -# for the rest of that program. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to gary@gnu.org. +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -## ------ ## -## Usage. ## -## ------ ## - -# Evaluate this file near the top of your script to gain access to -# the functions and variables defined here: +# Usage: $progname [OPTION]... [MODE-ARG]... # -# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# Provide generalized library-building support services. # -# If you need to override any of the default environment variable -# settings, do that before evaluating this file. - +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --no-warn don't display warning messages +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.11 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . +# GNU libtool home page: . +# General help using GNU software: . -## -------------------- ## -## Shell normalisation. ## -## -------------------- ## - -# Some shells need a little help to be as Bourne compatible as possible. -# Before doing anything else, make sure all that help has been provided! +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.2 Debian-2.4.2-1.11" +TIMESTAMP="" +package_revision=1.3337 -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac -fi - -# NLS nuisances: We save the old values in case they are required later. -_G_user_locale= -_G_safe_locale= -for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES -do - eval "if test set = \"\${$_G_var+set}\"; then - save_$_G_var=\$$_G_var - $_G_var=C - export $_G_var - _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" - _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" - fi" -done - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Make sure IFS has a sensible default -sp=' ' -nl=' -' -IFS="$sp $nl" - -# There are apparently some retarded systems that use ';' as a PATH separator! -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh - - -## ------------------------- ## -## Locate command utilities. ## -## ------------------------- ## - - -# func_executable_p FILE -# ---------------------- -# Check that FILE is an executable regular file. -func_executable_p () +# A function that is used when there is no print builtin or printf. +func_fallback_echo () { - test -f "$1" && test -x "$1" -} - - -# func_path_progs PROGS_LIST CHECK_FUNC [PATH] -# -------------------------------------------- -# Search for either a program that responds to --version with output -# containing "GNU", or else returned by CHECK_FUNC otherwise, by -# trying all the directories in PATH with each of the elements of -# PROGS_LIST. -# -# CHECK_FUNC should accept the path to a candidate program, and -# set $func_check_prog_result if it truncates its output less than -# $_G_path_prog_max characters. -func_path_progs () -{ - _G_progs_list=$1 - _G_check_func=$2 - _G_PATH=${3-"$PATH"} - - _G_path_prog_max=0 - _G_path_prog_found=false - _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} - for _G_dir in $_G_PATH; do - IFS=$_G_save_IFS - test -z "$_G_dir" && _G_dir=. - for _G_prog_name in $_G_progs_list; do - for _exeext in '' .EXE; do - _G_path_prog=$_G_dir/$_G_prog_name$_exeext - func_executable_p "$_G_path_prog" || continue - case `"$_G_path_prog" --version 2>&1` in - *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; - *) $_G_check_func $_G_path_prog - func_path_progs_result=$func_check_prog_result - ;; - esac - $_G_path_prog_found && break 3 - done - done - done - IFS=$_G_save_IFS - test -z "$func_path_progs_result" && { - echo "no acceptable sed could be found in \$PATH" >&2 - exit 1 - } -} - - -# We want to be able to use the functions in this file before configure -# has figured out where the best binaries are kept, which means we have -# to search for them ourselves - except when the results are already set -# where we skip the searches. - -# Unless the user overrides by setting SED, search the path for either GNU -# sed, or the sed that truncates its output the least. -test -z "$SED" && { - _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ - for _G_i in 1 2 3 4 5 6 7; do - _G_sed_script=$_G_sed_script$nl$_G_sed_script - done - echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed - _G_sed_script= - - func_check_prog_sed () - { - _G_path_prog=$1 - - _G_count=0 - printf 0123456789 >conftest.in - while : - do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo '' >> conftest.nl - "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break - diff conftest.out conftest.nl >/dev/null 2>&1 || break - _G_count=`expr $_G_count + 1` - if test "$_G_count" -gt "$_G_path_prog_max"; then - # Best one so far, save it but keep looking for a better one - func_check_prog_result=$_G_path_prog - _G_path_prog_max=$_G_count - fi - # 10*(2^10) chars as input seems more than enough - test 10 -lt "$_G_count" && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out - } - - func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin - rm -f conftest.sed - SED=$func_path_progs_result + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' } +# NLS nuisances: We save the old values to restore during execute mode. +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL -# Unless the user overrides by setting GREP, search the path for either GNU -# grep, or the grep that truncates its output the least. -test -z "$GREP" && { - func_check_prog_grep () - { - _G_path_prog=$1 - - _G_count=0 - _G_path_prog_max=0 - printf 0123456789 >conftest.in - while : - do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo 'GREP' >> conftest.nl - "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break - diff conftest.out conftest.nl >/dev/null 2>&1 || break - _G_count=`expr $_G_count + 1` - if test "$_G_count" -gt "$_G_path_prog_max"; then - # Best one so far, save it but keep looking for a better one - func_check_prog_result=$_G_path_prog - _G_path_prog_max=$_G_count - fi - # 10*(2^10) chars as input seems more than enough - test 10 -lt "$_G_count" && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out - } +$lt_unset CDPATH - func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin - GREP=$func_path_progs_result -} +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" -## ------------------------------- ## -## User overridable command paths. ## -## ------------------------------- ## -# All uppercase variable names are used for environment variables. These -# variables can be overridden by the user before calling a script that -# uses them if a suitable command of that name is not already available -# in the command search PATH. : ${CP="cp -f"} -: ${ECHO="printf %s\n"} -: ${EGREP="$GREP -E"} -: ${FGREP="$GREP -F"} -: ${LN_S="ln -s"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. -## -------------------- ## -## Useful sed snippets. ## -## -------------------- ## +exit_status=$EXIT_SUCCESS -sed_dirname='s|/[^/]*$||' -sed_basename='s|^.*/||' +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' +dirname="s,/[^/]*$,," +basename="s,^.*/,," -# Same as above, but do not quote variable references. -sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' -# Sed substitution that converts a w32 file name or path -# that contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation -# Re-'\' parameter expansions in output of sed_double_quote_subst that -# were '\'-ed in input to the same. If an odd number of '\' preceded a -# '$' in input to sed_double_quote_subst, that '$' was protected from -# expansion. Since each input '\' is now two '\'s, look for any number -# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. -_G_bs='\\' -_G_bs2='\\\\' -_G_bs4='\\\\\\\\' -_G_dollar='\$' -sed_double_backslash="\ - s/$_G_bs4/&\\ -/g - s/^$_G_bs2$_G_dollar/$_G_bs&/ - s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g - s/\n//g" + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation -## ----------------- ## -## Global variables. ## -## ----------------- ## - -# Except for the global variables explicitly listed below, the following -# functions in the '^func_' namespace, and the '^require_' namespace -# variables initialised in the 'Resource management' section, sourcing -# this file will not pollute your global namespace with anything -# else. There's no portable way to scope variables in Bourne shell -# though, so actually running these functions will sometimes place -# results into a variable named after the function, and often use -# temporary variables in the '^_G_' namespace. If you are careful to -# avoid using those namespaces casually in your sourcing script, things -# should continue to work as you expect. And, of course, you can freely -# overwrite any of the functions or variables defined here before -# calling anything to customize them. +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. -# Allow overriding, eg assuming that you follow the convention of -# putting '$debug_cmd' at the start of all your functions, you can get -# bash to show function call trace with: -# -# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name -debug_cmd=${debug_cmd-":"} -exit_cmd=: +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' -# By convention, finish your script with: -# -# exit $exit_status -# -# so that you can set exit_status to non-zero if you want to indicate -# something went wrong during execution without actually bailing out at -# the point of failure. -exit_status=$EXIT_SUCCESS +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath=$0 +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} -# The name of this program. -progname=`$ECHO "$progpath" |$SED "$sed_basename"` +# The name of this program: +func_dirname_and_basename "$progpath" +progname=$func_basename_result -# Make sure we have an absolute progpath for reexecution: +# Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) - progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` - progpath=$progdir/$progname + progpath="$progdir/$progname" ;; *) - _G_IFS=$IFS + save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do - IFS=$_G_IFS + IFS="$save_IFS" test -x "$progdir/$progname" && break done - IFS=$_G_IFS + IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` - progpath=$progdir/$progname + progpath="$progdir/$progname" ;; esac +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' -## ----------------- ## -## Standard options. ## -## ----------------- ## - -# The following options affect the operation of the functions defined -# below, and should be set appropriately depending on run-time para- -# meters passed on the command line. +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" +# Standard options: opt_dry_run=false +opt_help=false opt_quiet=false opt_verbose=false +opt_warning=: -# Categories 'all' and 'none' are always available. Append any others -# you will pass as the first argument to func_warning from your own -# code. -warning_categories= - -# By default, display warnings according to 'opt_warning_types'. Set -# 'warning_func' to ':' to elide all warnings, or func_fatal_error to -# treat the next displayed warning as a fatal error. -warning_func=func_warn_and_continue - -# Set to 'all' to display all warnings, 'none' to suppress all -# warnings, or a space delimited list of some subset of -# 'warning_categories' to display only the listed warnings. -opt_warning_types=all - - -## -------------------- ## -## Resource management. ## -## -------------------- ## - -# This section contains definitions for functions that each ensure a -# particular resource (a file, or a non-empty configuration variable for -# example) is available, and if appropriate to extract default values -# from pertinent package files. Call them using their associated -# 'require_*' variable to ensure that they are executed, at most, once. -# -# It's entirely deliberate that calling these functions can set -# variables that don't obey the namespace limitations obeyed by the rest -# of this file, in order that that they be as useful as possible to -# callers. - - -# require_term_colors -# ------------------- -# Allow display of bold text on terminals that support it. -require_term_colors=func_require_term_colors -func_require_term_colors () -{ - $debug_cmd - - test -t 1 && { - # COLORTERM and USE_ANSI_COLORS environment variables take - # precedence, because most terminfo databases neglect to describe - # whether color sequences are supported. - test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} - - if test 1 = "$USE_ANSI_COLORS"; then - # Standard ANSI escape sequences - tc_reset='' - tc_bold=''; tc_standout='' - tc_red=''; tc_green='' - tc_blue=''; tc_cyan='' - else - # Otherwise trust the terminfo database after all. - test -n "`tput sgr0 2>/dev/null`" && { - tc_reset=`tput sgr0` - test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` - tc_standout=$tc_bold - test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` - test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` - test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` - test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` - test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` - } - fi - } - - require_term_colors=: +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} -## ----------------- ## -## Function library. ## -## ----------------- ## - -# This section contains a variety of useful functions to call in your -# scripts. Take note of the portable wrappers for features provided by -# some modern shells, which will fall back to slower equivalents on -# less featureful shells. + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} -# func_append VAR VALUE -# --------------------- -# Append VALUE onto the existing contents of VAR. +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 +} - # We should try to minimise forks, especially on Windows where they are - # unreasonably slow, so skip the feature probes when bash or zsh are - # being used: - if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then - : ${_G_HAVE_ARITH_OP="yes"} - : ${_G_HAVE_XSI_OPS="yes"} - # The += operator was introduced in bash 3.1 - case $BASH_VERSION in - [12].* | 3.0 | 3.0*) ;; - *) - : ${_G_HAVE_PLUSEQ_OP="yes"} - ;; - esac - fi +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 - # _G_HAVE_PLUSEQ_OP - # Can be empty, in which case the shell is probed, "yes" if += is - # useable or anything else if it does not work. - test -z "$_G_HAVE_PLUSEQ_OP" \ - && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ - && _G_HAVE_PLUSEQ_OP=yes - -if test yes = "$_G_HAVE_PLUSEQ_OP" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_append () - { - $debug_cmd + # bash bug again: + : +} - eval "$1+=\$2" - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_append () - { - $debug_cmd +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} - eval "$1=\$$1\$2" - } -fi - - -# func_append_quoted VAR VALUE -# ---------------------------- -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -if test yes = "$_G_HAVE_PLUSEQ_OP"; then - eval 'func_append_quoted () - { - $debug_cmd - - func_quote_for_eval "$2" - eval "$1+=\\ \$func_quote_for_eval_result" - }' -else - func_append_quoted () - { - $debug_cmd - - func_quote_for_eval "$2" - eval "$1=\$$1\\ \$func_quote_for_eval_result" - } -fi - - -# func_append_uniq VAR VALUE -# -------------------------- -# Append unique VALUE onto the existing contents of VAR, assuming -# entries are delimited by the first character of VALUE. For example: -# -# func_append_uniq options " --another-option option-argument" -# -# will only append to $options if " --another-option option-argument " -# is not already present somewhere in $options already (note spaces at -# each end implied by leading space in second argument). -func_append_uniq () -{ - $debug_cmd - - eval _G_current_value='`$ECHO $'$1'`' - _G_delim=`expr "$2" : '\(.\)'` - - case $_G_delim$_G_current_value$_G_delim in - *"$2$_G_delim"*) ;; - *) func_append "$@" ;; - esac -} - - -# func_arith TERM... -# ------------------ -# Set func_arith_result to the result of evaluating TERMs. - test -z "$_G_HAVE_ARITH_OP" \ - && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ - && _G_HAVE_ARITH_OP=yes - -if test yes = "$_G_HAVE_ARITH_OP"; then - eval 'func_arith () - { - $debug_cmd - - func_arith_result=$(( $* )) - }' -else - func_arith () - { - $debug_cmd - - func_arith_result=`expr "$@"` - } -fi - - -# func_basename FILE -# ------------------ -# Set func_basename_result to FILE with everything up to and including -# the last / stripped. -if test yes = "$_G_HAVE_XSI_OPS"; then - # If this shell supports suffix pattern removal, then use it to avoid - # forking. Hide the definitions single quotes in case the shell chokes - # on unsupported syntax... - _b='func_basename_result=${1##*/}' - _d='case $1 in - */*) func_dirname_result=${1%/*}$2 ;; - * ) func_dirname_result=$3 ;; - esac' - -else - # ...otherwise fall back to using sed. - _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' - _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` - if test "X$func_dirname_result" = "X$1"; then - func_dirname_result=$3 - else - func_append func_dirname_result "$2" - fi' -fi - -eval 'func_basename () -{ - $debug_cmd - - '"$_b"' -}' - - -# func_dirname FILE APPEND NONDIR_REPLACEMENT -# ------------------------------------------- -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -eval 'func_dirname () -{ - $debug_cmd - - '"$_d"' -}' - - -# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT -# -------------------------------------------------------- -# Perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# For efficiency, we do not delegate to the functions above but instead -# duplicate the functionality here. -eval 'func_dirname_and_basename () -{ - $debug_cmd - - '"$_b"' - '"$_d"' -}' - - -# func_echo ARG... -# ---------------- -# Echo program name prefixed message. -func_echo () -{ - $debug_cmd - - _G_message=$* - - func_echo_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_IFS - $ECHO "$progname: $_G_line" - done - IFS=$func_echo_IFS -} - - -# func_echo_all ARG... -# -------------------- -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - - -# func_echo_infix_1 INFIX ARG... -# ------------------------------ -# Echo program name, followed by INFIX on the first line, with any -# additional lines not showing INFIX. -func_echo_infix_1 () -{ - $debug_cmd - - $require_term_colors - - _G_infix=$1; shift - _G_indent=$_G_infix - _G_prefix="$progname: $_G_infix: " - _G_message=$* - - # Strip color escape sequences before counting printable length - for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" - do - test -n "$_G_tc" && { - _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` - _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` - } - done - _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes - - func_echo_infix_1_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_infix_1_IFS - $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 - _G_prefix=$_G_indent - done - IFS=$func_echo_infix_1_IFS -} - - -# func_error ARG... -# ----------------- -# Echo program name prefixed message to standard error. -func_error () -{ - $debug_cmd - - $require_term_colors - - func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 -} - - -# func_fatal_error ARG... -# ----------------------- -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () { - $debug_cmd - - func_error "$*" - exit $EXIT_FAILURE + func_error ${1+"$@"} + func_fatal_error "$help" } +help="Try \`$progname --help' for more information." ## default -# func_grep EXPRESSION FILENAME -# ----------------------------- +# func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { - $debug_cmd - $GREP "$1" "$2" >/dev/null 2>&1 } -# func_len STRING -# --------------- -# Set func_len_result to the length of STRING. STRING may not -# start with a hyphen. - test -z "$_G_HAVE_XSI_OPS" \ - && (eval 'x=a/b/c; - test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ - && _G_HAVE_XSI_OPS=yes - -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_len () - { - $debug_cmd - - func_len_result=${#1} - }' -else - func_len () - { - $debug_cmd - - func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` - } -fi - - -# func_mkdir_p DIRECTORY-PATH -# --------------------------- +# func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { - $debug_cmd - - _G_directory_path=$1 - _G_dir_list= + my_directory_path="$1" + my_dir_list= - if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then - # Protect directory names starting with '-' - case $_G_directory_path in - -*) _G_directory_path=./$_G_directory_path ;; + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... - while test ! -d "$_G_directory_path"; do + while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. - _G_dir_list=$_G_directory_path:$_G_dir_list + my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done - case $_G_directory_path in */*) ;; *) break ;; esac + case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop - _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done - _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` - func_mkdir_p_IFS=$IFS; IFS=: - for _G_dir in $_G_dir_list; do - IFS=$func_mkdir_p_IFS - # mkdir can fail with a 'File exist' error if two processes + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! - $MKDIR "$_G_dir" 2>/dev/null || : + $MKDIR "$my_dir" 2>/dev/null || : done - IFS=$func_mkdir_p_IFS + IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. - test -d "$_G_directory_path" || \ - func_fatal_error "Failed to create '$1'" + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" fi } -# func_mktempdir [BASENAME] -# ------------------------- +# func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If -# given, BASENAME is the basename for that directory. +# given, STRING is the basename for that directory. func_mktempdir () { - $debug_cmd + my_template="${TMPDIR-/tmp}/${1-$progname}" - _G_template=${TMPDIR-/tmp}/${1-$progname} - - if test : = "$opt_dry_run"; then + if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode - _G_tmpdir=$_G_template-$$ + my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost - _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` - - if test ! -d "$_G_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - _G_tmpdir=$_G_template-${RANDOM-0}$$ - - func_mktempdir_umask=`umask` - umask 0077 - $MKDIR "$_G_tmpdir" - umask $func_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$_G_tmpdir" || \ - func_fatal_error "cannot create temporary directory '$_G_tmpdir'" - fi - - $ECHO "$_G_tmpdir" -} - - -# func_normal_abspath PATH -# ------------------------ -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -func_normal_abspath () -{ - $debug_cmd - - # These SED scripts presuppose an absolute path with a trailing slash. - _G_pathcar='s|^/\([^/]*\).*$|\1|' - _G_pathcdr='s|^/[^/]*||' - _G_removedotparts=':dotsl - s|/\./|/|g - t dotsl - s|/\.$|/|' - _G_collapseslashes='s|/\{1,\}|/|g' - _G_finalslash='s|/*$|/|' - - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` - while :; do - # Processed it all yet? - if test / = "$func_normal_abspath_tpath"; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result"; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} - - -# func_notquiet ARG... -# -------------------- -# Echo program name prefixed message only when not in quiet mode. -func_notquiet () -{ - $debug_cmd - - $opt_quiet || func_echo ${1+"$@"} - - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" -# func_relative_path SRCDIR DSTDIR -# -------------------------------- -# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. -func_relative_path () -{ - $debug_cmd - - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=$func_dirname_result - if test -z "$func_relative_path_tlibdir"; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done - - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test -n "$func_stripname_result"; then - func_append func_relative_path_result "/$func_stripname_result" - fi - - # Normalisation. If bindir is libdir, return '.' else relative path. - if test -n "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - fi - - test -n "$func_relative_path_result" || func_relative_path_result=. - - : -} - - -# func_quote_for_eval ARG... -# -------------------------- -# Aesthetically quote ARGs to be evaled later. -# This function returns two values: -# i) func_quote_for_eval_result -# double-quoted, suitable for a subsequent eval -# ii) func_quote_for_eval_unquoted_result -# has all characters that are still active within double -# quotes backslashified. -func_quote_for_eval () -{ - $debug_cmd - - func_quote_for_eval_unquoted_result= - func_quote_for_eval_result= - while test 0 -lt $#; do - case $1 in - *[\\\`\"\$]*) - _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; - *) - _G_unquoted_arg=$1 ;; - esac - if test -n "$func_quote_for_eval_unquoted_result"; then - func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" - else - func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" - fi - - case $_G_unquoted_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and variable expansion - # for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_quoted_arg=\"$_G_unquoted_arg\" - ;; - *) - _G_quoted_arg=$_G_unquoted_arg - ;; - esac - - if test -n "$func_quote_for_eval_result"; then - func_append func_quote_for_eval_result " $_G_quoted_arg" - else - func_append func_quote_for_eval_result "$_G_quoted_arg" - fi - shift - done -} - - -# func_quote_for_expand ARG -# ------------------------- -# Aesthetically quote ARG to be evaled later; same as above, -# but do not quote variable references. -func_quote_for_expand () -{ - $debug_cmd - - case $1 in - *[\\\`\"]*) - _G_arg=`$ECHO "$1" | $SED \ - -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; - *) - _G_arg=$1 ;; - esac - - case $_G_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting and command substitution for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_arg=\"$_G_arg\" - ;; - esac - - func_quote_for_expand_result=$_G_arg -} - - -# func_stripname PREFIX SUFFIX NAME -# --------------------------------- -# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_stripname () - { - $debug_cmd - - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary variable first. - func_stripname_result=$3 - func_stripname_result=${func_stripname_result#"$1"} - func_stripname_result=${func_stripname_result%"$2"} - }' -else - func_stripname () - { - $debug_cmd - - case $2 in - .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; - *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; - esac - } -fi - - -# func_show_eval CMD [FAIL_EXP] -# ----------------------------- -# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - $debug_cmd - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - func_quote_for_expand "$_G_cmd" - eval "func_notquiet $func_quote_for_expand_result" - - $opt_dry_run || { - eval "$_G_cmd" - _G_status=$? - if test 0 -ne "$_G_status"; then - eval "(exit $_G_status); $_G_fail_exp" - fi - } -} - - -# func_show_eval_locale CMD [FAIL_EXP] -# ------------------------------------ -# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () -{ - $debug_cmd - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - $opt_quiet || { - func_quote_for_expand "$_G_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - $opt_dry_run || { - eval "$_G_user_locale - $_G_cmd" - _G_status=$? - eval "$_G_safe_locale" - if test 0 -ne "$_G_status"; then - eval "(exit $_G_status); $_G_fail_exp" - fi - } -} - - -# func_tr_sh -# ---------- -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () -{ - $debug_cmd - - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac -} - - -# func_verbose ARG... -# ------------------- -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $debug_cmd - - $opt_verbose && func_echo "$*" - - : -} - - -# func_warn_and_continue ARG... -# ----------------------------- -# Echo program name prefixed warning message to standard error. -func_warn_and_continue () -{ - $debug_cmd - - $require_term_colors - - func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 -} - - -# func_warning CATEGORY ARG... -# ---------------------------- -# Echo program name prefixed warning message to standard error. Warning -# messages can be filtered according to CATEGORY, where this function -# elides messages where CATEGORY is not listed in the global variable -# 'opt_warning_types'. -func_warning () -{ - $debug_cmd - - # CATEGORY must be in the warning_categories list! - case " $warning_categories " in - *" $1 "*) ;; - *) func_internal_error "invalid warning category '$1'" ;; - esac - - _G_category=$1 - shift - - case " $opt_warning_types " in - *" $_G_category "*) $warning_func ${1+"$@"} ;; - esac -} - - -# func_sort_ver VER1 VER2 -# ----------------------- -# 'sort -V' is not generally available. -# Note this deviates from the version comparison in automake -# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a -# but this should suffice as we won't be specifying old -# version formats or redundant trailing .0 in bootstrap.conf. -# If we did want full compatibility then we should probably -# use m4_version_compare from autoconf. -func_sort_ver () -{ - $debug_cmd - - printf '%s\n%s\n' "$1" "$2" \ - | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n -} - -# func_lt_ver PREV CURR -# --------------------- -# Return true if PREV and CURR are in the correct order according to -# func_sort_ver, otherwise false. Use it like this: -# -# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." -func_lt_ver () -{ - $debug_cmd - - test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` -} - - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: -#! /bin/sh - -# Set a version string for this script. -scriptversion=2014-01-07.03; # UTC - -# A portable, pluggable option parser for Bourne shell. -# Written by Gary V. Vaughan, 2010 - -# Copyright (C) 2010-2015 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# This file is a library for parsing options in your shell scripts along -# with assorted other useful supporting features that you can make use -# of too. -# -# For the simplest scripts you might need only: -# -# #!/bin/sh -# . relative/path/to/funclib.sh -# . relative/path/to/options-parser -# scriptversion=1.0 -# func_options ${1+"$@"} -# eval set dummy "$func_options_result"; shift -# ...rest of your script... -# -# In order for the '--version' option to work, you will need to have a -# suitably formatted comment like the one at the top of this file -# starting with '# Written by ' and ending with '# warranty; '. -# -# For '-h' and '--help' to work, you will also need a one line -# description of your script's purpose in a comment directly above the -# '# Written by ' line, like the one at the top of this file. -# -# The default options also support '--debug', which will turn on shell -# execution tracing (see the comment above debug_cmd below for another -# use), and '--verbose' and the func_verbose function to allow your script -# to display verbose messages only when your user has specified -# '--verbose'. -# -# After sourcing this file, you can plug processing for additional -# options by amending the variables from the 'Configuration' section -# below, and following the instructions in the 'Option parsing' -# section further down. - -## -------------- ## -## Configuration. ## -## -------------- ## - -# You should override these variables in your script after sourcing this -# file so that they reflect the customisations you have added to the -# option parser. - -# The usage line for option parsing errors and the start of '-h' and -# '--help' output messages. You can embed shell variables for delayed -# expansion at the time the message is displayed, but you will need to -# quote other shell meta-characters carefully to prevent them being -# expanded when the contents are evaled. -usage='$progpath [OPTION]...' - -# Short help message in response to '-h' and '--help'. Add to this or -# override it after sourcing this library to reflect the full set of -# options your script accepts. -usage_message="\ - --debug enable verbose shell tracing - -W, --warnings=CATEGORY - report the warnings falling in CATEGORY [all] - -v, --verbose verbosely report processing - --version print version information and exit - -h, --help print short or long help message and exit -" - -# Additional text appended to 'usage_message' in response to '--help'. -long_help_message=" -Warning categories include: - 'all' show all warnings - 'none' turn off all the warnings - 'error' warnings are treated as fatal errors" - -# Help message printed before fatal option parsing errors. -fatal_help="Try '\$progname --help' for more information." - - - -## ------------------------- ## -## Hook function management. ## -## ------------------------- ## - -# This section contains functions for adding, removing, and running hooks -# to the main code. A hook is just a named list of of function, that can -# be run in order later on. - -# func_hookable FUNC_NAME -# ----------------------- -# Declare that FUNC_NAME will run hooks added with -# 'func_add_hook FUNC_NAME ...'. -func_hookable () -{ - $debug_cmd - - func_append hookable_fns " $1" -} - - -# func_add_hook FUNC_NAME HOOK_FUNC -# --------------------------------- -# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must -# first have been declared "hookable" by a call to 'func_hookable'. -func_add_hook () -{ - $debug_cmd - - case " $hookable_fns " in - *" $1 "*) ;; - *) func_fatal_error "'$1' does not accept hook functions." ;; - esac - - eval func_append ${1}_hooks '" $2"' -} - - -# func_remove_hook FUNC_NAME HOOK_FUNC -# ------------------------------------ -# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. -func_remove_hook () -{ - $debug_cmd - - eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' -} - - -# func_run_hooks FUNC_NAME [ARG]... -# --------------------------------- -# Run all hook functions registered to FUNC_NAME. -# It is assumed that the list of hook functions contains nothing more -# than a whitespace-delimited list of legal shell function names, and -# no effort is wasted trying to catch shell meta-characters or preserve -# whitespace. -func_run_hooks () -{ - $debug_cmd - - case " $hookable_fns " in - *" $1 "*) ;; - *) func_fatal_error "'$1' does not support hook funcions.n" ;; - esac - - eval _G_hook_fns=\$$1_hooks; shift - - for _G_hook in $_G_hook_fns; do - eval $_G_hook '"$@"' - - # store returned options list back into positional - # parameters for next 'cmd' execution. - eval _G_hook_result=\$${_G_hook}_result - eval set dummy "$_G_hook_result"; shift - done - - func_quote_for_eval ${1+"$@"} - func_run_hooks_result=$func_quote_for_eval_result -} - - - -## --------------- ## -## Option parsing. ## -## --------------- ## - -# In order to add your own option parsing hooks, you must accept the -# full positional parameter list in your hook function, remove any -# options that you action, and then pass back the remaining unprocessed -# options in '_result', escaped suitably for -# 'eval'. Like this: -# -# my_options_prep () -# { -# $debug_cmd -# -# # Extend the existing usage message. -# usage_message=$usage_message' -# -s, --silent don'\''t print informational messages -# ' -# -# func_quote_for_eval ${1+"$@"} -# my_options_prep_result=$func_quote_for_eval_result -# } -# func_add_hook func_options_prep my_options_prep -# -# -# my_silent_option () -# { -# $debug_cmd -# -# # Note that for efficiency, we parse as many options as we can -# # recognise in a loop before passing the remainder back to the -# # caller on the first unrecognised argument we encounter. -# while test $# -gt 0; do -# opt=$1; shift -# case $opt in -# --silent|-s) opt_silent=: ;; -# # Separate non-argument short options: -# -s*) func_split_short_opt "$_G_opt" -# set dummy "$func_split_short_opt_name" \ -# "-$func_split_short_opt_arg" ${1+"$@"} -# shift -# ;; -# *) set dummy "$_G_opt" "$*"; shift; break ;; -# esac -# done -# -# func_quote_for_eval ${1+"$@"} -# my_silent_option_result=$func_quote_for_eval_result -# } -# func_add_hook func_parse_options my_silent_option -# -# -# my_option_validation () -# { -# $debug_cmd -# -# $opt_silent && $opt_verbose && func_fatal_help "\ -# '--silent' and '--verbose' options are mutually exclusive." -# -# func_quote_for_eval ${1+"$@"} -# my_option_validation_result=$func_quote_for_eval_result -# } -# func_add_hook func_validate_options my_option_validation -# -# You'll alse need to manually amend $usage_message to reflect the extra -# options you parse. It's preferable to append if you can, so that -# multiple option parsing hooks can be added safely. - - -# func_options [ARG]... -# --------------------- -# All the functions called inside func_options are hookable. See the -# individual implementations for details. -func_hookable func_options -func_options () -{ - $debug_cmd - - func_options_prep ${1+"$@"} - eval func_parse_options \ - ${func_options_prep_result+"$func_options_prep_result"} - eval func_validate_options \ - ${func_parse_options_result+"$func_parse_options_result"} + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi - eval func_run_hooks func_options \ - ${func_validate_options_result+"$func_validate_options_result"} + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi - # save modified positional parameters for caller - func_options_result=$func_run_hooks_result + $ECHO "$my_tmpdir" } -# func_options_prep [ARG]... -# -------------------------- -# All initialisations required before starting the option parse loop. -# Note that when calling hook functions, we pass through the list of -# positional parameters. If a hook function modifies that list, and -# needs to propogate that back to rest of this script, then the complete -# modified list must be put in 'func_run_hooks_result' before -# returning. -func_hookable func_options_prep -func_options_prep () +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () { - $debug_cmd - - # Option defaults: - opt_verbose=false - opt_warning_types= - - func_run_hooks func_options_prep ${1+"$@"} + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac - # save modified positional parameters for caller - func_options_prep_result=$func_run_hooks_result + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac } -# func_parse_options [ARG]... -# --------------------------- -# The main option parsing loop. -func_hookable func_parse_options -func_parse_options () +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () { - $debug_cmd - - func_parse_options_result= + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "$1" | $SED \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac - # this just eases exit handling - while test $# -gt 0; do - # Defer to hook functions for initial option parsing, so they - # get priority in the event of reusing an option name. - func_run_hooks func_parse_options ${1+"$@"} + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac - # Adjust func_parse_options positional parameters to match - eval set dummy "$func_run_hooks_result"; shift + func_quote_for_expand_result="$my_arg" +} - # Break out of the loop if we already parsed every option. - test $# -gt 0 || break - _G_opt=$1 - shift - case $_G_opt in - --debug|-x) debug_cmd='set -x' - func_echo "enabling shell trace mode" - $debug_cmd - ;; - - --no-warnings|--no-warning|--no-warn) - set dummy --warnings none ${1+"$@"} - shift - ;; +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" - --warnings|--warning|-W) - test $# = 0 && func_missing_arg $_G_opt && break - case " $warning_categories $1" in - *" $1 "*) - # trailing space prevents matching last $1 above - func_append_uniq opt_warning_types " $1" - ;; - *all) - opt_warning_types=$warning_categories - ;; - *none) - opt_warning_types=none - warning_func=: - ;; - *error) - opt_warning_types=$warning_categories - warning_func=func_fatal_error - ;; - *) - func_fatal_error \ - "unsupported warning category: '$1'" - ;; - esac - shift - ;; - - --verbose|-v) opt_verbose=: ;; - --version) func_version ;; - -\?|-h) func_usage ;; - --help) func_help ;; - - # Separate optargs to long options (plugins may need this): - --*=*) func_split_equals "$_G_opt" - set dummy "$func_split_equals_lhs" \ - "$func_split_equals_rhs" ${1+"$@"} - shift - ;; - - # Separate optargs to short options: - -W*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-v*|-x*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) break ;; - -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; - *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; - esac - done + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - func_parse_options_result=$func_quote_for_eval_result + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi } -# func_validate_options [ARG]... -# ------------------------------ -# Perform any sanity checks on option settings and/or unconsumed -# arguments. -func_hookable func_validate_options -func_validate_options () +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () { - $debug_cmd - - # Display all warnings if -W was not given. - test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + my_cmd="$1" + my_fail_exp="${2-:}" - func_run_hooks func_validate_options ${1+"$@"} - - # Bail if the options were screwed! - $exit_cmd $EXIT_FAILURE + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } - # save modified positional parameters for caller - func_validate_options_result=$func_run_hooks_result + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi } +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} -## ----------------- ## -## Helper functions. ## -## ----------------- ## - -# This section contains the helper functions used by the rest of the -# hookable option parser framework in ascii-betical order. +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $opt_debug + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} -# func_fatal_help ARG... -# ---------------------- -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () +# func_usage +# Echo short help message to standard output and exit. +func_usage () { - $debug_cmd + $opt_debug - eval \$ECHO \""Usage: $usage"\" - eval \$ECHO \""$fatal_help"\" - func_error ${1+"$@"} - exit $EXIT_FAILURE + $SED -n '/^# Usage:/,/^# *.*--help/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + echo + $ECHO "run \`$progname --help | more' for full usage" + exit $? } - -# func_help -# --------- -# Echo long help message to standard output and exit. +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. func_help () { - $debug_cmd + $opt_debug - func_usage_message - $ECHO "$long_help_message" - exit 0 + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ + p + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi } - -# func_missing_arg ARGNAME -# ------------------------ +# func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { - $debug_cmd + $opt_debug - func_error "Missing argument for '$1'." + func_error "missing argument for $1." exit_cmd=exit } -# func_split_equals STRING -# ------------------------ -# Set func_split_equals_lhs and func_split_equals_rhs shell variables after -# splitting STRING at the '=' sign. -test -z "$_G_HAVE_XSI_OPS" \ - && (eval 'x=a/b/c; - test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ - && _G_HAVE_XSI_OPS=yes - -if test yes = "$_G_HAVE_XSI_OPS" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_split_equals () - { - $debug_cmd - - func_split_equals_lhs=${1%%=*} - func_split_equals_rhs=${1#*=} - test "x$func_split_equals_lhs" = "x$1" \ - && func_split_equals_rhs= - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_split_equals () - { - $debug_cmd - - func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` - func_split_equals_rhs= - test "x$func_split_equals_lhs" = "x$1" \ - || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` - } -fi #func_split_equals - - -# func_split_short_opt SHORTOPT -# ----------------------------- +# func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. -if test yes = "$_G_HAVE_XSI_OPS" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_split_short_opt () - { - $debug_cmd - - func_split_short_opt_arg=${1#??} - func_split_short_opt_name=${1%"$func_split_short_opt_arg"} - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_split_short_opt () - { - $debug_cmd - - func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` - func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` - } -fi #func_split_short_opt - - -# func_usage -# ---------- -# Echo short help message to standard output and exit. -func_usage () +func_split_short_opt () { - $debug_cmd + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' - func_usage_message - $ECHO "Run '$progname --help |${PAGER-more}' for full usage" - exit 0 -} + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation -# func_usage_message -# ------------------ -# Echo short help message to standard output. -func_usage_message () +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () { - $debug_cmd + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' - eval \$ECHO \""Usage: $usage"\" - echo - $SED -n 's|^# || - /^Written by/{ - x;p;x - } - h - /^Written by/q' < "$progpath" - echo - eval \$ECHO \""$usage_message"\" -} + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation +exit_cmd=: -# func_version -# ------------ -# Echo version message to standard output and exit. -func_version () -{ - $debug_cmd - printf '%s\n' "$progname $scriptversion" - $SED -n ' - /(C)/!b go - :more - /\./!{ - N - s|\n# | | - b more - } - :go - /^# Written by /,/# warranty; / { - s|^# || - s|^# *$|| - s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| - p - } - /^# Written by / { - s|^# || - p - } - /^warranty; /q' < "$progpath" - exit $? -} -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" -# Set a version string. -scriptversion='(GNU libtool) 2.4.6' +# Global variables. +nonopt= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= -# func_echo ARG... -# ---------------- -# Libtool also displays the current mode in messages, so override -# funclib.sh func_echo with this custom definition. -func_echo () +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () { - $debug_cmd - - _G_message=$* - - func_echo_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_IFS - $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" - done - IFS=$func_echo_IFS -} - + eval "${1}=\$${1}\${2}" +} # func_append may be replaced by extended shell implementation -# func_warning ARG... -# ------------------- -# Libtool warnings are not categorized, so override funclib.sh -# func_warning with this simpler definition. -func_warning () +# func_append_quoted var value +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +func_append_quoted () { - $debug_cmd - - $warning_func ${1+"$@"} -} - + func_quote_for_eval "${2}" + eval "${1}=\$${1}\\ \$func_quote_for_eval_result" +} # func_append_quoted may be replaced by extended shell implementation -## ---------------- ## -## Options parsing. ## -## ---------------- ## - -# Hook in the functions to make sure our own options are parsed during -# the option parsing loop. - -usage='$progpath [OPTION]... [MODE-ARG]...' - -# Short help message in response to '-h'. -usage_message="Options: - --config show all configuration variables - --debug enable verbose shell tracing - -n, --dry-run display commands without modifying any files - --features display basic configuration information and exit - --mode=MODE use operation mode MODE - --no-warnings equivalent to '-Wnone' - --preserve-dup-deps don't remove duplicate dependency libraries - --quiet, --silent don't print informational messages - --tag=TAG use configuration variables from tag TAG - -v, --verbose print more informational messages than default - --version print version information - -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] - -h, --help, --help-all print short, long, or detailed help message -" -# Additional text appended to 'usage_message' in response to '--help'. -func_help () +# func_arith arithmetic-term... +func_arith () { - $debug_cmd + func_arith_result=`expr "${@}"` +} # func_arith may be replaced by extended shell implementation - func_usage_message - $ECHO "$long_help_message -MODE must be one of the following: - - clean remove files from the build directory - compile compile a source file into a libtool object - execute automatically set library path, then run a program - finish complete the installation of libtool libraries - install install libraries or executables - link create a library or an executable - uninstall remove libraries from an installed directory - -MODE-ARGS vary depending on the MODE. When passed as first option, -'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. -Try '$progname --help --mode=MODE' for a more detailed description of MODE. - -When reporting a bug, please describe a test case to reproduce it and -include the following information: - - host-triplet: $host - shell: $SHELL - compiler: $LTCC - compiler flags: $LTCFLAGS - linker: $LD (gnu? $with_gnu_ld) - version: $progname (GNU libtool) 2.4.6 - automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` - autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` - -Report bugs to . -GNU libtool home page: . -General help using GNU software: ." - exit 0 -} - - -# func_lo2o OBJECT-NAME -# --------------------- -# Transform OBJECT-NAME from a '.lo' suffix to the platform specific -# object suffix. +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation -lo2o=s/\\.lo\$/.$objext/ -o2lo=s/\\.$objext\$/.lo/ -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_lo2o () - { - case $1 in - *.lo) func_lo2o_result=${1%.lo}.$objext ;; - * ) func_lo2o_result=$1 ;; - esac - }' +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation - # func_xform LIBOBJ-OR-SOURCE - # --------------------------- - # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) - # suffix to a '.lo' libtool-object suffix. - eval 'func_xform () - { - func_xform_result=${1%.*}.lo - }' -else - # ...otherwise fall back to using sed. - func_lo2o () - { - func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` - } - func_xform () - { - func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` - } -fi +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation -# func_fatal_configuration ARG... -# ------------------------------- +# func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { - func__fatal_error ${1+"$@"} \ - "See the $PACKAGE documentation for more information." \ - "Fatal configuration error." + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." } # func_config -# ----------- # Display the configuration for all the tags in this script. func_config () { @@ -2149,19 +915,17 @@ exit $? } - # func_features -# ------------- # Display the features supported by this script. func_features () { echo "host: $host" - if test yes = "$build_libtool_libs"; then + if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi - if test yes = "$build_old_libs"; then + if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" @@ -2170,297 +934,289 @@ exit $? } - -# func_enable_tag TAGNAME -# ----------------------- +# func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { - # Global variable: - tagname=$1 + # Global variable: + tagname="$1" - re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" - re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" - sed_extractcf=/$re_begincf/,/$re_endcf/p - - # Validate tagname. - case $tagname in - *[!-_A-Za-z0-9,/]*) - func_fatal_error "invalid tag name: $tagname" - ;; - esac + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac - # Don't test for the "default" C tag, as we know it's - # there but not specially marked. - case $tagname in - CC) ;; + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; *) - if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then - taglist="$taglist $tagname" + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" - # Evaluate the configuration. Be careful to quote the path - # and the sed script, to avoid splitting on whitespace, but - # also don't use non-portable quotes within backquotes within - # quotes we have to do it in 2 steps: - extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` - eval "$extractedcf" - else - func_error "ignoring unknown tag $tagname" - fi - ;; - esac + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac } - # func_check_version_match -# ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { - if test "$package_revision" != "$macro_revision"; then - if test "$VERSION" != "$macro_version"; then - if test -z "$macro_version"; then - cat >&2 <<_LT_EOF + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF - else - cat >&2 <<_LT_EOF + else + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF - fi - else - cat >&2 <<_LT_EOF + fi + else + cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF - fi - - exit $EXIT_MISMATCH fi -} + exit $EXIT_MISMATCH + fi +} -# libtool_options_prep [ARG]... -# ----------------------------- -# Preparation for options parsed by libtool. -libtool_options_prep () -{ - $debug_mode - # Option defaults: - opt_config=false - opt_dlopen= - opt_dry_run=false - opt_help=false - opt_mode= - opt_preserve_dup_deps=false - opt_quiet=false +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac - nonopt= - preserve_args= - # Shorthand for --mode=foo, only valid as the first argument - case $1 in - clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; - compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; - execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; - finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; - install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; - link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; - uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; - esac - # Pass back the list of options. - func_quote_for_eval ${1+"$@"} - libtool_options_prep_result=$func_quote_for_eval_result -} -func_add_hook func_options_prep libtool_options_prep +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_warning=: +opt_verbose=: +opt_silent=false +opt_verbose=false -# libtool_parse_options [ARG]... -# --------------------------------- -# Provide handling for libtool specific options. -libtool_parse_options () +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. { - $debug_cmd - - # Perform our own loop to consume as many options as possible in - # each iteration. - while test $# -gt 0; do - _G_opt=$1 - shift - case $_G_opt in - --dry-run|--dryrun|-n) - opt_dry_run=: - ;; - - --config) func_config ;; - - --dlopen|-dlopen) - opt_dlopen="${opt_dlopen+$opt_dlopen -}$1" - shift - ;; - - --preserve-dup-deps) - opt_preserve_dup_deps=: ;; - - --features) func_features ;; - - --finish) set dummy --mode finish ${1+"$@"}; shift ;; - - --help) opt_help=: ;; - - --help-all) opt_help=': help-all' ;; - - --mode) test $# = 0 && func_missing_arg $_G_opt && break - opt_mode=$1 - case $1 in - # Valid mode arguments: - clean|compile|execute|finish|install|link|relink|uninstall) ;; - - # Catch anything else as an error - *) func_error "invalid argument for $_G_opt" - exit_cmd=exit - break - ;; - esac - shift - ;; - - --no-silent|--no-quiet) - opt_quiet=false - func_append preserve_args " $_G_opt" - ;; - - --no-warnings|--no-warning|--no-warn) - opt_warning=false - func_append preserve_args " $_G_opt" - ;; - - --no-verbose) - opt_verbose=false - func_append preserve_args " $_G_opt" - ;; - - --silent|--quiet) - opt_quiet=: - opt_verbose=false - func_append preserve_args " $_G_opt" - ;; - - --tag) test $# = 0 && func_missing_arg $_G_opt && break - opt_tag=$1 - func_append preserve_args " $_G_opt $1" - func_enable_tag "$1" - shift - ;; - - --verbose|-v) opt_quiet=false - opt_verbose=: - func_append preserve_args " $_G_opt" - ;; + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-warning|--no-warn) + opt_warning=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done - # An option not handled by this hook function: - *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; - esac - done + # Validate options: + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift + fi - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - libtool_parse_options_result=$func_quote_for_eval_result -} -func_add_hook func_parse_options libtool_parse_options + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + $opt_help || { + # Sanity checks first: + func_check_version_match -# libtool_validate_options [ARG]... -# --------------------------------- -# Perform any sanity checks on option settings and/or unconsumed -# arguments. -libtool_validate_options () -{ - # save first non-option argument - if test 0 -lt $#; then - nonopt=$1 - shift + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" fi - # preserve --debug - test : = "$debug_cmd" || func_append preserve_args " --debug" + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" - case $host in - # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 - # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 - *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps - ;; - esac + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi - $opt_help || { - # Sanity checks first: - func_check_version_match - - test yes != "$build_libtool_libs" \ - && test yes != "$build_old_libs" \ - && func_fatal_configuration "not configured to build any kind of library" - - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$opt_dlopen" && test execute != "$opt_mode"; then - func_error "unrecognized option '-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Change the help message to a mode-specific one. - generic_help=$help - help="Try '$progname --help --mode=$opt_mode' for more information." - } + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } - # Pass back the unparsed argument list - func_quote_for_eval ${1+"$@"} - libtool_validate_options_result=$func_quote_for_eval_result -} -func_add_hook func_validate_options libtool_validate_options + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE +} -# Process options as early as possible so that --help and --version -# can return quickly. -func_options ${1+"$@"} -eval set dummy "$func_options_result"; shift @@ -2468,52 +1224,24 @@ ## Main. ## ## ----------- ## -magic='%%%MAGIC variable%%%' -magic_exe='%%%MAGIC EXE variable%%%' - -# Global variables. -extracted_archives= -extracted_serial=0 - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - -# func_generated_by_libtool -# True iff stdin has been generated by Libtool. This function is only -# a basic sanity check; it will hardly flush out determined imposters. -func_generated_by_libtool_p () -{ - $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 -} - # func_lalib_p file -# True iff FILE is a libtool '.la' library or '.lo' object file. +# True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && - $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file -# True iff FILE is a libtool '.la' library or '.lo' object file. +# True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be -# fatal anyway. Works if 'file' does not exist. +# fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no @@ -2521,13 +1249,13 @@ for lalib_p_l in 1 2 3 4 do read lalib_p_line - case $lalib_p_line in + case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi - test yes = "$lalib_p" + test "$lalib_p" = yes } # func_ltwrapper_script_p file @@ -2536,8 +1264,7 @@ # determined imposters. func_ltwrapper_script_p () { - test -f "$1" && - $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p + func_lalib_p "$1" } # func_ltwrapper_executable_p file @@ -2562,7 +1289,7 @@ { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file @@ -2581,13 +1308,11 @@ # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { - $debug_cmd - + $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do - IFS=$sp$nl - eval cmd=\"$cmd\" IFS=$save_ifs + eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs @@ -2599,11 +1324,10 @@ # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing -# 'FILE.' does not work on cygwin managed mounts. +# `FILE.' does not work on cygwin managed mounts. func_source () { - $debug_cmd - + $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; @@ -2630,10 +1354,10 @@ # store the result into func_replace_sysroot_result. func_replace_sysroot () { - case $lt_sysroot:$1 in + case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" - func_replace_sysroot_result='='$func_stripname_result + func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. @@ -2650,8 +1374,7 @@ # arg is usually of the form 'gcc ...' func_infer_tag () { - $debug_cmd - + $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do @@ -2670,7 +1393,7 @@ for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. - eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. @@ -2695,7 +1418,7 @@ # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" - func_fatal_error "specify a tag with '--tag'" + func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi @@ -2711,15 +1434,15 @@ # but don't create it if we're doing a dry run. func_write_libtool_object () { - write_libobj=$1 - if test yes = "$build_libtool_libs"; then - write_lobj=\'$2\' + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' else write_lobj=none fi - if test yes = "$build_old_libs"; then - write_oldobj=\'$3\' + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' else write_oldobj=none fi @@ -2727,7 +1450,7 @@ $opt_dry_run || { cat >${write_libobj}T </dev/null` - if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | - $SED -e "$sed_naive_backslashify"` + $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi @@ -2792,19 +1514,18 @@ # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { - $debug_cmd - + $opt_debug # unfortunately, winepath doesn't convert paths, only file names - func_convert_core_path_wine_to_w32_result= + func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" - if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then - func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi @@ -2833,8 +1554,7 @@ # environment variable; do not put it in $PATH. func_cygpath () { - $debug_cmd - + $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then @@ -2843,7 +1563,7 @@ fi else func_cygpath_result= - func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath @@ -2854,11 +1574,10 @@ # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { - $debug_cmd - + $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | - $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 @@ -2869,14 +1588,13 @@ # func_to_host_file_result to ARG1). func_convert_file_check () { - $debug_cmd - - if test -z "$2" && test -n "$1"; then + $opt_debug + if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" - func_error " '$1'" + func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: - func_to_host_file_result=$1 + func_to_host_file_result="$1" fi } # end func_convert_file_check @@ -2888,11 +1606,10 @@ # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { - $debug_cmd - + $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" - func_error " '$3'" + func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. @@ -2901,7 +1618,7 @@ func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else - func_to_host_path_result=$3 + func_to_host_path_result="$3" fi fi } @@ -2913,10 +1630,9 @@ # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { - $debug_cmd - + $opt_debug case $4 in - $1 ) func_to_host_path_result=$3$func_to_host_path_result + $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in @@ -2930,7 +1646,7 @@ ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## -# invoked via '$to_host_file_cmd ARG' +# invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. @@ -2941,8 +1657,7 @@ # in func_to_host_file_result. func_to_host_file () { - $debug_cmd - + $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file @@ -2954,8 +1669,7 @@ # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { - $debug_cmd - + $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 @@ -2973,7 +1687,7 @@ # Copy ARG to func_to_host_file_result. func_convert_file_noop () { - func_to_host_file_result=$1 + func_to_host_file_result="$1" } # end func_convert_file_noop @@ -2984,12 +1698,11 @@ # func_to_host_file_result. func_convert_file_msys_to_w32 () { - $debug_cmd - - func_to_host_file_result=$1 + $opt_debug + func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" - func_to_host_file_result=$func_convert_core_msys_to_w32_result + func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -3001,9 +1714,8 @@ # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { - $debug_cmd - - func_to_host_file_result=$1 + $opt_debug + func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. @@ -3019,12 +1731,11 @@ # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { - $debug_cmd - - func_to_host_file_result=$1 + $opt_debug + func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" - func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -3036,13 +1747,12 @@ # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { - $debug_cmd - - func_to_host_file_result=$1 + $opt_debug + func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" - func_to_host_file_result=$func_cygpath_result + func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -3055,14 +1765,13 @@ # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { - $debug_cmd - - func_to_host_file_result=$1 + $opt_debug + func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" - func_to_host_file_result=$func_cygpath_result + func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } @@ -3072,7 +1781,7 @@ ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# -# invoked via '$to_host_path_cmd ARG' +# invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. @@ -3096,11 +1805,10 @@ to_host_path_cmd= func_init_to_host_path_cmd () { - $debug_cmd - + $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" - to_host_path_cmd=func_convert_path_$func_stripname_result + to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } @@ -3110,8 +1818,7 @@ # in func_to_host_path_result. func_to_host_path () { - $debug_cmd - + $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } @@ -3122,7 +1829,7 @@ # Copy ARG to func_to_host_path_result. func_convert_path_noop () { - func_to_host_path_result=$1 + func_to_host_path_result="$1" } # end func_convert_path_noop @@ -3133,9 +1840,8 @@ # func_to_host_path_result. func_convert_path_msys_to_w32 () { - $debug_cmd - - func_to_host_path_result=$1 + $opt_debug + func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; @@ -3143,7 +1849,7 @@ func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" @@ -3157,9 +1863,8 @@ # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { - $debug_cmd - - func_to_host_path_result=$1 + $opt_debug + func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" @@ -3178,15 +1883,14 @@ # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { - $debug_cmd - - func_to_host_path_result=$1 + $opt_debug + func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" @@ -3200,16 +1904,15 @@ # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { - $debug_cmd - - func_to_host_path_result=$1 + $opt_debug + func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" - func_to_host_path_result=$func_cygpath_result + func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" @@ -3224,9 +1927,8 @@ # func_to_host_file_result. func_convert_path_nix_to_cygwin () { - $debug_cmd - - func_to_host_path_result=$1 + $opt_debug + func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them @@ -3235,7 +1937,7 @@ func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" - func_to_host_path_result=$func_cygpath_result + func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" @@ -3244,31 +1946,13 @@ # end func_convert_path_nix_to_cygwin -# func_dll_def_p FILE -# True iff FILE is a Windows DLL '.def' file. -# Keep in sync with _LT_DLL_DEF_P in libtool.m4 -func_dll_def_p () -{ - $debug_cmd - - func_dll_def_p_tmp=`$SED -n \ - -e 's/^[ ]*//' \ - -e '/^\(;.*\)*$/d' \ - -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ - -e q \ - "$1"` - test DEF = "$func_dll_def_p_tmp" -} - - # func_mode_compile arg... func_mode_compile () { - $debug_cmd - + $opt_debug # Get the compilation command and the source file. base_compile= - srcfile=$nonopt # always keep a non-empty value in "srcfile" + srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal @@ -3281,12 +1965,12 @@ case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile - lastarg=$arg + lastarg="$arg" arg_mode=normal ;; target ) - libobj=$arg + libobj="$arg" arg_mode=normal continue ;; @@ -3296,7 +1980,7 @@ case $arg in -o) test -n "$libobj" && \ - func_fatal_error "you cannot specify '-o' more than once" + func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; @@ -3325,12 +2009,12 @@ func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= - save_ifs=$IFS; IFS=, + save_ifs="$IFS"; IFS=',' for arg in $args; do - IFS=$save_ifs + IFS="$save_ifs" func_append_quoted lastarg "$arg" done - IFS=$save_ifs + IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result @@ -3343,8 +2027,8 @@ # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # - lastarg=$srcfile - srcfile=$arg + lastarg="$srcfile" + srcfile="$arg" ;; esac # case $arg ;; @@ -3359,13 +2043,13 @@ func_fatal_error "you must specify an argument for -Xcompile" ;; target) - func_fatal_error "you must specify a target with '-o'" + func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" - libobj=$func_basename_result + libobj="$func_basename_result" } ;; esac @@ -3385,7 +2069,7 @@ case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) - func_fatal_error "cannot determine name of library object from '$libobj'" + func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac @@ -3394,8 +2078,8 @@ for arg in $later; do case $arg in -shared) - test yes = "$build_libtool_libs" \ - || func_fatal_configuration "cannot build a shared library" + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; @@ -3421,17 +2105,17 @@ func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && func_warning "libobj name '$libobj' may not contain shell special characters." + && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" - objname=$func_basename_result - xdir=$func_dirname_result - lobj=$xdir$objdir/$objname + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. - if test yes = "$build_old_libs"; then + if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" @@ -3443,16 +2127,16 @@ pic_mode=default ;; esac - if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c - if test no = "$compiler_c_o"; then - output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext - lockfile=$output_obj.lock + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" else output_obj= need_locks=no @@ -3461,12 +2145,12 @@ # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file - if test yes = "$need_locks"; then + if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done - elif test warn = "$need_locks"; then + elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: @@ -3474,7 +2158,7 @@ This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support '-c' and '-o' together. If you +your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -3496,11 +2180,11 @@ qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. - if test yes = "$build_libtool_libs"; then + if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile - if test no != "$pic_mode"; then + if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code @@ -3517,7 +2201,7 @@ func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' - if test warn = "$need_locks" && + if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: @@ -3528,7 +2212,7 @@ This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support '-c' and '-o' together. If you +your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -3544,20 +2228,20 @@ fi # Allow error messages only from the first compilation. - if test yes = "$suppress_opt"; then + if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. - if test yes = "$build_old_libs"; then - if test yes != "$pic_mode"; then + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi - if test yes = "$compiler_c_o"; then + if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi @@ -3566,7 +2250,7 @@ func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' - if test warn = "$need_locks" && + if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: @@ -3577,7 +2261,7 @@ This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because -your compiler does not support '-c' and '-o' together. If you +your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." @@ -3597,7 +2281,7 @@ func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked - if test no != "$need_locks"; then + if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi @@ -3607,7 +2291,7 @@ } $opt_help || { - test compile = "$opt_mode" && func_mode_compile ${1+"$@"} + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () @@ -3627,7 +2311,7 @@ Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE -(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated @@ -3646,16 +2330,16 @@ -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only - -shared do not build a '.o' file suitable for static linking - -static only build a '.o' file suitable for static linking + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler -COMPILE-COMMAND is a command to be used in creating a 'standard' object file +COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix '.c' with the -library object suffix, '.lo'." +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." ;; execute) @@ -3668,7 +2352,7 @@ -dlopen FILE add the directory containing FILE to the library path -This mode sets the library path environment variable according to '-dlopen' +This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated @@ -3687,7 +2371,7 @@ Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use -the '--dry-run' option if you just want to see what would be executed." +the \`--dry-run' option if you just want to see what would be executed." ;; install) @@ -3697,7 +2381,7 @@ Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be -either the 'install' or 'cp' program. +either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: @@ -3723,7 +2407,7 @@ -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) - -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE @@ -3737,8 +2421,7 @@ -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE use a list of object files found in FILE to specify objects - -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information @@ -3758,20 +2441,20 @@ -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) -All other options (arguments beginning with '-') are ignored. +All other options (arguments beginning with \`-') are ignored. -Every other argument is treated as a filename. Files ending in '.la' are +Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. -If the OUTPUT-FILE ends in '.la', then a libtool library is created, -only library objects ('.lo' files) may be specified, and '-rpath' is +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. -If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created -using 'ar' and 'ranlib', or on Windows using 'lib'. +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. -If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; @@ -3782,7 +2465,7 @@ Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE -(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. @@ -3790,17 +2473,17 @@ ;; *) - func_fatal_help "invalid operation mode '$opt_mode'" + func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo - $ECHO "Try '$progname --help' for more information about other modes." + $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then - if test : = "$opt_help"; then + if test "$opt_help" = :; then func_mode_help else { @@ -3808,7 +2491,7 @@ for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done - } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do @@ -3816,7 +2499,7 @@ func_mode_help done } | - $SED '1d + sed '1d /^When reporting/,/^Report/{ H d @@ -3833,17 +2516,16 @@ # func_mode_execute arg... func_mode_execute () { - $debug_cmd - + $opt_debug # The first argument is the command name. - cmd=$nonopt + cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ - || func_fatal_help "'$file' is not a file" + || func_fatal_help "\`$file' is not a file" dir= case $file in @@ -3853,7 +2535,7 @@ # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ - || func_fatal_help "'$lib' is not a valid libtool archive" + || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= @@ -3864,18 +2546,18 @@ if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ - func_warning "'$file' was not linked with '-export-dynamic'" + func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." - dir=$func_dirname_result + dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then - func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; @@ -3883,18 +2565,18 @@ *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." - dir=$func_dirname_result + dir="$func_dirname_result" ;; *) - func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir=$absdir + test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then @@ -3906,7 +2588,7 @@ # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. - libtool_execute_magic=$magic + libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= @@ -3919,12 +2601,12 @@ if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. - file=$progdir/$program + file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. - file=$progdir/$program + file="$progdir/$program" fi ;; esac @@ -3932,15 +2614,7 @@ func_append_quoted args "$file" done - if $opt_dry_run; then - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - echo "export $shlibpath_var" - fi - $ECHO "$cmd$args" - exit $EXIT_SUCCESS - else + if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" @@ -3957,18 +2631,25 @@ done # Now prepare to actually exec the command. - exec_cmd=\$cmd$args + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS fi } -test execute = "$opt_mode" && func_mode_execute ${1+"$@"} +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { - $debug_cmd - + $opt_debug libs= libdirs= admincmds= @@ -3982,11 +2663,11 @@ if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else - func_warning "'$opt' is not a valid libtool archive" + func_warning "\`$opt' is not a valid libtool archive" fi else - func_fatal_error "invalid argument '$opt'" + func_fatal_error "invalid argument \`$opt'" fi done @@ -4001,12 +2682,12 @@ # Remove sysroot references if $opt_dry_run; then for lib in $libs; do - echo "removing references to $lt_sysroot and '=' prefixes from $lib" + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do - $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done @@ -4031,7 +2712,7 @@ fi # Exit here if they wanted silent mode. - $opt_quiet && exit $EXIT_SUCCESS + $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" @@ -4042,27 +2723,27 @@ echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then - echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" - $ECHO " - use the '$flag' linker flag" + $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo @@ -4081,20 +2762,18 @@ exit $EXIT_SUCCESS } -test finish = "$opt_mode" && func_mode_finish ${1+"$@"} +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { - $debug_cmd - + $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). - if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. - case $nonopt in *shtool*) :;; *) false;; esac - then + case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " @@ -4121,7 +2800,7 @@ opts= prev= install_type= - isdir=false + isdir=no stripme= no_mode=: for arg @@ -4134,7 +2813,7 @@ fi case $arg in - -d) isdir=: ;; + -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg @@ -4152,7 +2831,7 @@ *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then - if test X-m = "X$prev" && test -n "$install_override_mode"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi @@ -4177,7 +2856,7 @@ func_fatal_help "you must specify an install program" test -n "$prev" && \ - func_fatal_help "the '$prev' option requires an argument" + func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else @@ -4199,19 +2878,19 @@ dest=$func_stripname_result # Check to see that the destination is a directory. - test -d "$dest" && isdir=: - if $isdir; then - destdir=$dest + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." - destdir=$func_dirname_result - destname=$func_basename_result + destdir="$func_dirname_result" + destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ - func_fatal_help "'$dest' is not a directory" + func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; @@ -4220,7 +2899,7 @@ case $file in *.lo) ;; *) - func_fatal_help "'$destdir' must be an absolute directory name" + func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done @@ -4229,7 +2908,7 @@ # This variable tells wrapper scripts just to set variables rather # than running their programs. - libtool_install_magic=$magic + libtool_install_magic="$magic" staticlibs= future_libdirs= @@ -4249,7 +2928,7 @@ # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ - || func_fatal_help "'$file' is not a valid libtool archive" + || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= @@ -4271,7 +2950,7 @@ fi func_dirname "$file" "/" "" - dir=$func_dirname_result + dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then @@ -4285,7 +2964,7 @@ # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ - func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. @@ -4294,36 +2973,29 @@ relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi - func_warning "relinking '$file'" + func_warning "relinking \`$file'" func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then - realname=$1 + realname="$1" shift - srcname=$realname - test -n "$relink_command" && srcname=${realname}T + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' - tstripme=$stripme + tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) - tstripme= - ;; - esac - ;; - os2*) - case $realname in - *_dll.a) - tstripme= + tstripme="" ;; esac ;; @@ -4334,7 +3006,7 @@ if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. - # Try 'ln -sf' first, because the 'ln' binary might depend on + # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname @@ -4345,14 +3017,14 @@ fi # Do each command in the postinstall commands. - lib=$destdir/$realname + lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" - name=$func_basename_result - instname=$dir/${name}i + name="$func_basename_result" + instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. @@ -4364,11 +3036,11 @@ # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then - destfile=$destdir/$destname + destfile="$destdir/$destname" else func_basename "$file" - destfile=$func_basename_result - destfile=$destdir/$destfile + destfile="$func_basename_result" + destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. @@ -4378,11 +3050,11 @@ staticdest=$func_lo2o_result ;; *.$objext) - staticdest=$destfile + staticdest="$destfile" destfile= ;; *) - func_fatal_help "cannot copy a libtool object to '$destfile'" + func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac @@ -4391,7 +3063,7 @@ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. - if test yes = "$build_old_libs"; then + if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result @@ -4403,23 +3075,23 @@ *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then - destfile=$destdir/$destname + destfile="$destdir/$destname" else func_basename "$file" - destfile=$func_basename_result - destfile=$destdir/$destfile + destfile="$func_basename_result" + destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install - stripped_ext= + stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result - stripped_ext=.exe + stripped_ext=".exe" fi ;; esac @@ -4447,19 +3119,19 @@ # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ - func_fatal_error "invalid libtool wrapper script '$wrapper'" + func_fatal_error "invalid libtool wrapper script \`$wrapper'" - finalize=: + finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi - libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then - func_warning "'$lib' has not been installed in '$libdir'" - finalize=false + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no fi done @@ -4467,29 +3139,29 @@ func_source "$wrapper" outputname= - if test no = "$fast_install" && test -n "$relink_command"; then + if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { - if $finalize; then + if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" - file=$func_basename_result - outputname=$tmpdir/$file + file="$func_basename_result" + outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` - $opt_quiet || { + $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else - func_error "error: relink '$file' with the above command before installing it" + func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi - file=$outputname + file="$outputname" else - func_warning "cannot relink '$file'" + func_warning "cannot relink \`$file'" fi } else @@ -4526,10 +3198,10 @@ for file in $staticlibs; do func_basename "$file" - name=$func_basename_result + name="$func_basename_result" # Set up the ranlib parameters. - oldlib=$destdir/$name + oldlib="$destdir/$name" func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result @@ -4544,18 +3216,18 @@ done test -n "$future_libdirs" && \ - func_warning "remember to run '$progname --finish$future_libdirs'" + func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } -test install = "$opt_mode" && func_mode_install ${1+"$@"} +test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p @@ -4563,17 +3235,16 @@ # a dlpreopen symbol table. func_generate_dlsyms () { - $debug_cmd - - my_outputname=$1 - my_originator=$2 - my_pic_p=${3-false} - my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= - if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then - my_dlsyms=${my_outputname}S.c + my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi @@ -4584,7 +3255,7 @@ "") ;; *.c) # Discover the nlist of each of the dlfiles. - nlist=$output_objdir/$my_outputname.nm + nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" @@ -4592,36 +3263,34 @@ func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ -/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif -#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE -/* DATA imports from DLLs on WIN32 can't be const, because runtime +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST -#elif defined __osf__ +#elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif -#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) - /* External symbol declarations for the compiler. */\ " - if test yes = "$dlself"; then - func_verbose "generating symbol list for '$output'" + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" @@ -4629,7 +3298,7 @@ progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 - func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done @@ -4649,10 +3318,10 @@ # Prepare the list of exported symbols if test -z "$export_symbols"; then - export_symbols=$output_objdir/$outputname.exp + export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols - eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' @@ -4662,7 +3331,7 @@ } else $opt_dry_run || { - eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in @@ -4676,22 +3345,22 @@ fi for dlprefile in $dlprefiles; do - func_verbose "extracting global C symbols from '$dlprefile'" + func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" - name=$func_basename_result + name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" - dlprefile_dlbasename= + dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` - if test -n "$dlprefile_dlname"; then + if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" - dlprefile_dlbasename=$func_basename_result + dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" @@ -4699,7 +3368,7 @@ fi fi $opt_dry_run || { - if test -n "$dlprefile_dlbasename"; then + if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" @@ -4755,11 +3424,6 @@ echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi - func_show_eval '$RM "${nlist}I"' - if test -n "$global_symbol_to_import"; then - eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' - fi - echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ @@ -4768,30 +3432,11 @@ void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[];\ -" - - if test -s "$nlist"I; then - echo >> "$output_objdir/$my_dlsyms" "\ -static void lt_syminit(void) -{ - LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; - for (; symbol->name; ++symbol) - {" - $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" - echo >> "$output_objdir/$my_dlsyms" "\ - } -}" - fi - echo >> "$output_objdir/$my_dlsyms" "\ +lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = -{ {\"$my_originator\", (void *) 0}," - - if test -s "$nlist"I; then - echo >> "$output_objdir/$my_dlsyms" "\ - {\"@INIT@\", (void *) <_syminit}," - fi +{\ + { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) @@ -4833,7 +3478,9 @@ *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) - $my_pic_p && pic_flag_for_symtable=" $pic_flag" + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi ;; esac ;; @@ -4850,10 +3497,10 @@ func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. - func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. - symfileobj=$output_objdir/${my_outputname}S.$objext + symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then @@ -4871,7 +3518,7 @@ esac ;; *) - func_fatal_error "unknown suffix for '$my_dlsyms'" + func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else @@ -4885,32 +3532,6 @@ fi } -# func_cygming_gnu_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is a GNU/binutils-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_gnu_implib_p () -{ - $debug_cmd - - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` - test -n "$func_cygming_gnu_implib_tmp" -} - -# func_cygming_ms_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is an MS-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_ms_implib_p () -{ - $debug_cmd - - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` - test -n "$func_cygming_ms_implib_tmp" -} - # func_win32_libid arg # return the library type of file 'arg' # @@ -4920,9 +3541,8 @@ # Despite the name, also deal with 64 bit binaries. func_win32_libid () { - $debug_cmd - - win32_libid_type=unknown + $opt_debug + win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import @@ -4932,29 +3552,16 @@ # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then - case $nm_interface in - "MS dumpbin") - if func_cygming_ms_implib_p "$1" || - func_cygming_gnu_implib_p "$1" - then - win32_nmres=import - else - win32_nmres= - fi - ;; - *) - func_to_tool_file "$1" func_convert_file_msys_to_w32 - win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | - $SED -n -e ' + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' 1,100{ / I /{ - s|.*|import| + s,.*,import, p q } }'` - ;; - esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; @@ -4986,8 +3593,7 @@ # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { - $debug_cmd - + $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } @@ -5004,8 +3610,7 @@ # specified import library. func_cygming_dll_for_implib_fallback_core () { - $debug_cmd - + $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ @@ -5041,8 +3646,8 @@ /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the - # archive that possess that section. Heuristic: eliminate - # all those that have a first or second character that is + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually @@ -5053,6 +3658,30 @@ $SED -e '/^\./d;/^.\./d;q' } +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified @@ -5066,17 +3695,16 @@ # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { - $debug_cmd - - if func_cygming_gnu_implib_p "$1"; then + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` - elif func_cygming_ms_implib_p "$1"; then + elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown - sharedlib_from_linklib_result= + sharedlib_from_linklib_result="" fi } @@ -5084,11 +3712,10 @@ # func_extract_an_archive dir oldlib func_extract_an_archive () { - $debug_cmd - - f_ex_an_ar_dir=$1; shift - f_ex_an_ar_oldlib=$1 - if test yes = "$lock_old_archive_extraction"; then + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" @@ -5097,7 +3724,7 @@ fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' - if test yes = "$lock_old_archive_extraction"; then + if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then @@ -5111,23 +3738,22 @@ # func_extract_archives gentop oldlib ... func_extract_archives () { - $debug_cmd - - my_gentop=$1; shift + $opt_debug + my_gentop="$1"; shift my_oldlibs=${1+"$@"} - my_oldobjs= - my_xlib= - my_xabs= - my_xdir= + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" - my_xlib=$func_basename_result + my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in @@ -5139,7 +3765,7 @@ esac done extracted_archives="$extracted_archives $my_xlib_u" - my_xdir=$my_gentop/$my_xlib_u + my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" @@ -5152,23 +3778,22 @@ cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` - func_basename "$darwin_archive" - darwin_base_archive=$func_basename_result + darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches; do - func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" - $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" - cd "unfat-$$/$darwin_base_archive-$darwin_arch" - func_extract_an_archive "`pwd`" "$darwin_base_archive" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" - $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do @@ -5190,7 +3815,7 @@ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done - func_extract_archives_result=$my_oldobjs + func_extract_archives_result="$my_oldobjs" } @@ -5205,7 +3830,7 @@ # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script -# will assume that the directory where it is stored is +# will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () @@ -5216,7 +3841,7 @@ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. @@ -5273,9 +3898,9 @@ # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ that is used only on +# /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" -# (application programs are unlikely to have options that match +# (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and @@ -5308,7 +3933,7 @@ # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then - echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } @@ -5319,7 +3944,7 @@ lt_dump_args_N=1; for lt_arg do - \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } @@ -5333,7 +3958,7 @@ *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then - \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} @@ -5343,7 +3968,7 @@ *) $ECHO "\ if test -n \"\$lt_option_debug\"; then - \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} @@ -5418,13 +4043,13 @@ test -n \"\$absdir\" && thisdir=\"\$absdir\" " - if test yes = "$fast_install"; then + if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" @@ -5441,7 +4066,7 @@ if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else - \$ECHO \"\$relink_command_output\" >&2 + $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi @@ -5476,7 +4101,7 @@ fi # Export our shlibpath_var if we have one. - if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" @@ -5496,7 +4121,7 @@ fi else # The program doesn't exist. - \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 @@ -5515,7 +4140,7 @@ cat < #include -#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) - /* declarations of non-ANSI functions */ -#if defined __MINGW32__ +#if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif -#elif defined __CYGWIN__ +#elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif -/* #elif defined other_platform || defined ... */ +/* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ -#if defined _MSC_VER +#if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC -#elif defined __MINGW32__ +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv -#elif defined __CYGWIN__ +#elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" -/* #elif defined other platforms ... */ +/* #elif defined (other platforms) ... */ #endif -#if defined PATH_MAX +#if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX -#elif defined MAXPATHLEN +#elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 @@ -5607,8 +4234,8 @@ # define PATH_SEPARATOR ':' #endif -#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ - defined __OS2__ +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 @@ -5641,10 +4268,10 @@ #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ - if (stale) { free (stale); stale = 0; } \ + if (stale) { free ((void *) stale); stale = 0; } \ } while (0) -#if defined LT_DEBUGWRAPPER +#if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; @@ -5673,16 +4300,11 @@ EOF cat < 0) && IS_PATH_SEPARATOR (new_value[len-1])) + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { - new_value[--len] = '\0'; + new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); @@ -6460,47 +5082,27 @@ # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { - $debug_cmd - + $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } -# func_suncc_cstd_abi -# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! -# Several compiler flags select an ABI that is incompatible with the -# Cstd library. Avoid specifying it if any are in CXXFLAGS. -func_suncc_cstd_abi () -{ - $debug_cmd - - case " $compile_command " in - *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) - suncc_use_cstd_abi=no - ;; - *) - suncc_use_cstd_abi=yes - ;; - esac -} - # func_mode_link arg... func_mode_link () { - $debug_cmd - + $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out - # what system we are compiling for in order to pass an extra + # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll that has undefined symbols, in which case not + # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. @@ -6544,11 +5146,10 @@ module=no no_install=no objs= - os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no - preload=false + preload=no prev= prevarg= release= @@ -6560,7 +5161,7 @@ vinfo= vinfo_number=no weak_libs= - single_module=$wl-single_module + single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. @@ -6568,15 +5169,15 @@ do case $arg in -shared) - test yes != "$build_libtool_libs" \ - && func_fatal_configuration "cannot build a shared library" + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) - if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then @@ -6609,7 +5210,7 @@ # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do - arg=$1 + arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result @@ -6626,21 +5227,21 @@ case $prev in bindir) - bindir=$arg + bindir="$arg" prev= continue ;; dlfiles|dlprefiles) - $preload || { + if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" - preload=: - } + preload=yes + fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) - if test no = "$dlself"; then + if test "$dlself" = no; then dlself=needless export_dynamic=yes fi @@ -6648,9 +5249,9 @@ continue ;; self) - if test dlprefiles = "$prev"; then + if test "$prev" = dlprefiles; then dlself=yes - elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless @@ -6660,7 +5261,7 @@ continue ;; *) - if test dlfiles = "$prev"; then + if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" @@ -6671,14 +5272,14 @@ esac ;; expsyms) - export_symbols=$arg + export_symbols="$arg" test -f "$arg" \ - || func_fatal_error "symbol file '$arg' does not exist" + || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) - export_symbols_regex=$arg + export_symbols_regex="$arg" prev= continue ;; @@ -6696,13 +5297,7 @@ continue ;; inst_prefix) - inst_prefix_dir=$arg - prev= - continue - ;; - mllvm) - # Clang does not use LLVM to link, so we can simply discard any - # '-mllvm $arg' options when doing the link step. + inst_prefix_dir="$arg" prev= continue ;; @@ -6726,21 +5321,21 @@ if test -z "$pic_object" || test -z "$non_pic_object" || - test none = "$pic_object" && - test none = "$non_pic_object"; then - func_fatal_error "cannot find name of object for '$arg'" + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir=$func_dirname_result + xdir="$func_dirname_result" - if test none != "$pic_object"; then + if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. - pic_object=$xdir$pic_object + pic_object="$xdir$pic_object" - if test dlfiles = "$prev"; then - if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue @@ -6751,7 +5346,7 @@ fi # CHECK ME: I think I busted this. -Ossama - if test dlprefiles = "$prev"; then + if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= @@ -6759,23 +5354,23 @@ # A PIC object. func_append libobjs " $pic_object" - arg=$pic_object + arg="$pic_object" fi # Non-PIC object. - if test none != "$non_pic_object"; then + if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. - non_pic_object=$xdir$non_pic_object + non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test none = "$pic_object"; then - arg=$non_pic_object + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. - non_pic_object=$pic_object + non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else @@ -6783,7 +5378,7 @@ if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir=$func_dirname_result + xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result @@ -6791,29 +5386,24 @@ func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else - func_fatal_error "'$arg' is not a valid libtool object" + func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else - func_fatal_error "link input file '$arg' does not exist" + func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; - os2dllname) - os2dllname=$arg - prev= - continue - ;; precious_regex) - precious_files_regex=$arg + precious_files_regex="$arg" prev= continue ;; release) - release=-$arg + release="-$arg" prev= continue ;; @@ -6825,7 +5415,7 @@ func_fatal_error "only absolute run-paths are allowed" ;; esac - if test rpath = "$prev"; then + if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; @@ -6840,7 +5430,7 @@ continue ;; shrext) - shrext_cmds=$arg + shrext_cmds="$arg" prev= continue ;; @@ -6880,7 +5470,7 @@ esac fi # test -n "$prev" - prevarg=$arg + prevarg="$arg" case $arg in -all-static) @@ -6894,7 +5484,7 @@ -allow-undefined) # FIXME: remove this flag sometime in the future. - func_fatal_error "'-allow-undefined' must not be used because it is the default" + func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) @@ -6926,7 +5516,7 @@ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi - if test X-export-symbols = "X$arg"; then + if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex @@ -6960,9 +5550,9 @@ func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then - func_fatal_error "require no space between '-L' and '$1'" + func_fatal_error "require no space between \`-L' and \`$1'" else - func_fatal_error "need path for '-L' option" + func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" @@ -6973,8 +5563,8 @@ *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ - func_fatal_error "cannot determine absolute directory name of '$dir'" - dir=$absdir + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" ;; esac case "$deplibs " in @@ -7009,7 +5599,7 @@ ;; -l*) - if test X-lc = "X$arg" || test X-lm = "X$arg"; then + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) @@ -7017,11 +5607,11 @@ ;; *-*-os2*) # These systems don't actually have a C library (as such) - test X-lc = "X$arg" && continue + test "X$arg" = "X-lc" && continue ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. - test X-lc = "X$arg" && continue + test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework @@ -7030,16 +5620,16 @@ ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype - test X-lc = "X$arg" && continue + test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work - test X-lc = "X$arg" && continue + test "X$arg" = "X-lc" && continue ;; esac - elif test X-lc_r = "X$arg"; then + elif test "X$arg" = "X-lc_r"; then case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; @@ -7049,11 +5639,6 @@ continue ;; - -mllvm) - prev=mllvm - continue - ;; - -module) module=yes continue @@ -7083,7 +5668,7 @@ ;; -multi_module) - single_module=$wl-multi_module + single_module="${wl}-multi_module" continue ;; @@ -7097,8 +5682,8 @@ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. - func_warning "'-no-install' is ignored for $host" - func_warning "assuming '-no-fast-install' instead" + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; @@ -7116,11 +5701,6 @@ continue ;; - -os2dllname) - prev=os2dllname - continue - ;; - -o) prev=output ;; -precious-files-regex) @@ -7208,14 +5788,14 @@ func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= - save_ifs=$IFS; IFS=, + save_ifs="$IFS"; IFS=',' for flag in $args; do - IFS=$save_ifs + IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done - IFS=$save_ifs + IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; @@ -7224,15 +5804,15 @@ func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= - save_ifs=$IFS; IFS=, + save_ifs="$IFS"; IFS=',' for flag in $args; do - IFS=$save_ifs + IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done - IFS=$save_ifs + IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; @@ -7255,7 +5835,7 @@ # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result + arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: @@ -7267,49 +5847,25 @@ # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC - # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support - # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization - # -specs=* GCC specs files - # -stdlib=* select c++ std lib with clang - # -fsanitize=* Clang/GCC memory and address sanitizer + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ - -specs=*|-fsanitize=*) + -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result + arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; - -Z*) - if test os2 = "`expr $host : '.*\(os2\)'`"; then - # OS/2 uses -Zxxx to specify OS/2-specific options - compiler_flags="$compiler_flags $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - case $arg in - -Zlinker | -Zstack) - prev=xcompiler - ;; - esac - continue - else - # Otherwise treat like 'Some other compiler flag' below - func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result - fi - ;; - # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result + arg="$func_quote_for_eval_result" ;; *.$objext) @@ -7330,21 +5886,21 @@ if test -z "$pic_object" || test -z "$non_pic_object" || - test none = "$pic_object" && - test none = "$non_pic_object"; then - func_fatal_error "cannot find name of object for '$arg'" + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir=$func_dirname_result + xdir="$func_dirname_result" - test none = "$pic_object" || { + if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. - pic_object=$xdir$pic_object + pic_object="$xdir$pic_object" - if test dlfiles = "$prev"; then - if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue @@ -7355,7 +5911,7 @@ fi # CHECK ME: I think I busted this. -Ossama - if test dlprefiles = "$prev"; then + if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= @@ -7363,23 +5919,23 @@ # A PIC object. func_append libobjs " $pic_object" - arg=$pic_object - } + arg="$pic_object" + fi # Non-PIC object. - if test none != "$non_pic_object"; then + if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. - non_pic_object=$xdir$non_pic_object + non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test none = "$pic_object"; then - arg=$non_pic_object + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. - non_pic_object=$pic_object + non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else @@ -7387,7 +5943,7 @@ if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" - xdir=$func_dirname_result + xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result @@ -7395,7 +5951,7 @@ func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else - func_fatal_error "'$arg' is not a valid libtool object" + func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; @@ -7411,11 +5967,11 @@ # A libtool-controlled library. func_resolve_sysroot "$arg" - if test dlfiles = "$prev"; then + if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= - elif test dlprefiles = "$prev"; then + elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= @@ -7430,7 +5986,7 @@ # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" - arg=$func_quote_for_eval_result + arg="$func_quote_for_eval_result" ;; esac # arg @@ -7442,9 +5998,9 @@ done # argument parsing loop test -n "$prev" && \ - func_fatal_help "the '$prevarg' option requires an argument" + func_fatal_help "the \`$prevarg' option requires an argument" - if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" @@ -7453,23 +6009,20 @@ oldlibs= # calculate the name of the file, without its directory func_basename "$output" - outputname=$func_basename_result - libobjs_save=$libobjs + outputname="$func_basename_result" + libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" - # Definition is injected by LT_CONFIG during libtool generation. - func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" - func_dirname "$output" "/" "" - output_objdir=$func_dirname_result$objdir + output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. @@ -7492,7 +6045,7 @@ # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do - if $opt_preserve_dup_deps; then + if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac @@ -7500,7 +6053,7 @@ func_append libs " $deplib" done - if test lib = "$linkmode"; then + if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps @@ -7532,7 +6085,7 @@ case $file in *.la) ;; *) - func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done @@ -7540,7 +6093,7 @@ prog) compile_deplibs= finalize_deplibs= - alldeplibs=false + alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" @@ -7552,32 +6105,32 @@ for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... - if test lib,link = "$linkmode,$pass"; then + if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done - deplibs=$tmp_deplibs + deplibs="$tmp_deplibs" fi - if test lib,link = "$linkmode,$pass" || - test prog,scan = "$linkmode,$pass"; then - libs=$deplibs + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" deplibs= fi - if test prog = "$linkmode"; then + if test "$linkmode" = prog; then case $pass in - dlopen) libs=$dlfiles ;; - dlpreopen) libs=$dlprefiles ;; + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi - if test lib,dlpreopen = "$linkmode,$pass"; then + if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs @@ -7598,26 +6151,26 @@ esac done done - libs=$dlprefiles + libs="$dlprefiles" fi - if test dlopen = "$pass"; then + if test "$pass" = dlopen; then # Collect dlpreopened libraries - save_deplibs=$deplibs + save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= - found=false + found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - if test prog,link = "$linkmode,$pass"; then + if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" - if test lib = "$linkmode"; then + if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; @@ -7627,13 +6180,13 @@ continue ;; -l*) - if test lib != "$linkmode" && test prog != "$linkmode"; then - func_warning "'-l' is ignored for archives/objects" + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result - if test lib = "$linkmode"; then + if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" @@ -7641,22 +6194,31 @@ for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library - lib=$searchdir/lib$name$search_ext + lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then - if test .la = "$search_ext"; then - found=: + if test "$search_ext" = ".la"; then + found=yes else - found=false + found=no fi break 2 fi done done - if $found; then - # deplib is a libtool library + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. - if test yes = "$allow_libtool_libs_with_static_runtimes"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then @@ -7664,19 +6226,19 @@ old_library= func_source "$lib" for l in $old_library $library_names; do - ll=$l + ll="$l" done - if test "X$ll" = "X$old_library"; then # only static version available - found=false + if test "X$ll" = "X$old_library" ; then # only static version available + found=no func_dirname "$lib" "" "." - ladir=$func_dirname_result + ladir="$func_dirname_result" lib=$ladir/$old_library - if test prog,link = "$linkmode,$pass"; then + if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" - test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi @@ -7685,25 +6247,15 @@ *) ;; esac fi - else - # deplib doesn't seem to be a libtool library - if test prog,link = "$linkmode,$pass"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" - fi - continue fi ;; # -l *.ltframework) - if test prog,link = "$linkmode,$pass"; then + if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" - if test lib = "$linkmode"; then + if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; @@ -7716,18 +6268,18 @@ case $linkmode in lib) deplibs="$deplib $deplibs" - test conv = "$pass" && continue + test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) - if test conv = "$pass"; then + if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi - if test scan = "$pass"; then + if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" @@ -7738,13 +6290,13 @@ func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) - func_warning "'-L' is ignored for archives/objects" + func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) - if test link = "$pass"; then + if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result @@ -7762,7 +6314,7 @@ lib=$func_resolve_sysroot_result ;; *.$libext) - if test conv = "$pass"; then + if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi @@ -7773,26 +6325,21 @@ case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) - valid_a_lib=false + valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=: + valid_a_lib=yes fi ;; pass_all) - valid_a_lib=: + valid_a_lib=yes ;; esac - if $valid_a_lib; then - echo - $ECHO "*** Warning: Linking the shared library $output against the" - $ECHO "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - else + if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" @@ -7800,13 +6347,18 @@ echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." + else + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) - if test link != "$pass"; then + if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" @@ -7817,10 +6369,10 @@ esac # linkmode ;; # *.$libext *.lo | *.$objext) - if test conv = "$pass"; then + if test "$pass" = conv; then deplibs="$deplib $deplibs" - elif test prog = "$linkmode"; then - if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" @@ -7833,20 +6385,22 @@ continue ;; %DEPLIBS%) - alldeplibs=: + alldeplibs=yes continue ;; esac # case $deplib - $found || test -f "$lib" \ - || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ - || func_fatal_error "'$lib' is not a valid libtool archive" + || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." - ladir=$func_dirname_result + ladir="$func_dirname_result" dlname= dlopen= @@ -7876,19 +6430,19 @@ done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - if test lib,link = "$linkmode,$pass" || - test prog,scan = "$linkmode,$pass" || - { test prog != "$linkmode" && test lib != "$linkmode"; }; then + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi - if test conv = "$pass"; then + if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then - func_fatal_error "cannot find name of link library for '$lib'" + func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" @@ -7896,15 +6450,15 @@ tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps; then + if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done - elif test prog != "$linkmode" && test lib != "$linkmode"; then - func_fatal_error "'$lib' is not a convenience library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" fi continue fi # $pass = conv @@ -7913,26 +6467,26 @@ # Get the name of the library we link against. linklib= if test -n "$old_library" && - { test yes = "$prefer_static_libs" || - test built,no = "$prefer_static_libs,$installed"; }; then + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do - linklib=$l + linklib="$l" done fi if test -z "$linklib"; then - func_fatal_error "cannot find name of link library for '$lib'" + func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. - if test dlopen = "$pass"; then - test -z "$libdir" \ - && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi if test -z "$dlname" || - test yes != "$dlopen_support" || - test no = "$build_libtool_libs" - then + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't @@ -7946,40 +6500,40 @@ # We need an absolute path. case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then - func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" - abs_ladir=$ladir + abs_ladir="$ladir" fi ;; esac func_basename "$lib" - laname=$func_basename_result + laname="$func_basename_result" # Find the relevant object directory and library name. - if test yes = "$installed"; then + if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - func_warning "library '$lib' was moved." - dir=$ladir - absdir=$abs_ladir - libdir=$abs_ladir + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" else - dir=$lt_sysroot$libdir - absdir=$lt_sysroot$libdir + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$libdir" fi - test yes = "$hardcode_automatic" && avoidtemprpath=yes + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir=$ladir - absdir=$abs_ladir + dir="$ladir" + absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else - dir=$ladir/$objdir - absdir=$abs_ladir/$objdir + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi @@ -7988,11 +6542,11 @@ name=$func_stripname_result # This library was specified with -dlpreopen. - if test dlpreopen = "$pass"; then - if test -z "$libdir" && test prog = "$linkmode"; then - func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi - case $host in + case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both @@ -8036,9 +6590,9 @@ if test -z "$libdir"; then # Link the convenience library - if test lib = "$linkmode"; then + if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" - elif test prog,link = "$linkmode,$pass"; then + elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else @@ -8048,14 +6602,14 @@ fi - if test prog = "$linkmode" && test link != "$pass"; then + if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" - linkalldeplibs=false - if test no != "$link_all_deplibs" || test -z "$library_names" || - test no = "$build_libtool_libs"; then - linkalldeplibs=: + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes fi tmp_libs= @@ -8067,14 +6621,14 @@ ;; esac # Need to link against all dependency_libs? - if $linkalldeplibs; then + if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi - if $opt_preserve_dup_deps; then + if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac @@ -8084,15 +6638,15 @@ continue fi # $linkmode = prog... - if test prog,link = "$linkmode,$pass"; then + if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && - { { test no = "$prefer_static_libs" || - test built,yes = "$prefer_static_libs,$installed"; } || + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. - case $temp_rpath: in + case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac @@ -8121,9 +6675,9 @@ esac fi # $linkmode,$pass = prog,link... - if $alldeplibs && - { test pass_all = "$deplibs_check_method" || - { test yes = "$build_libtool_libs" && + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue @@ -8132,19 +6686,19 @@ link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs - if test built = "$use_static_libs" && test yes = "$installed"; then + if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && - { test no = "$use_static_libs" || test -z "$old_library"; }; then + { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in - *cygwin* | *mingw* | *cegcc* | *os2*) + *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) - if test no = "$installed"; then + if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi @@ -8154,24 +6708,24 @@ # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! - dlopenmodule= + dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then - dlopenmodule=$dlpremoduletest + dlopenmodule="$dlpremoduletest" break fi done - if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo - if test prog = "$linkmode"; then + if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi - if test lib = "$linkmode" && - test yes = "$hardcode_into_libs"; then + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. @@ -8199,43 +6753,43 @@ # figure out the soname set dummy $library_names shift - realname=$1 + realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then - soname=$dlname + soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in - *cygwin* | mingw* | *cegcc* | *os2*) + *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result - versuffix=-$major + versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else - soname=$realname + soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use - soroot=$soname + soroot="$soname" func_basename "$soroot" - soname=$func_basename_result + soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else - func_verbose "extracting exported symbol list from '$soname'" + func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else - func_verbose "generating import library for '$soname'" + func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library @@ -8243,58 +6797,58 @@ linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" - if test prog = "$linkmode" || test relink != "$opt_mode"; then + if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) - if test no = "$hardcode_direct"; then - add=$dir/$linklib + if test "$hardcode_direct" = no; then + add="$dir/$linklib" case $host in - *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; - *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir=-L$dir ;; + *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) - # if the lib is a (non-dlopened) module then we cannot + # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | - $GREP ": [^:]* bundle" >/dev/null; then + $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" - if test -z "$old_library"; then + if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else - add=$dir/$old_library + add="$dir/$old_library" fi elif test -n "$old_library"; then - add=$dir/$old_library + add="$dir/$old_library" fi fi esac - elif test no = "$hardcode_minus_L"; then + elif test "$hardcode_minus_L" = no; then case $host in - *-*-sunos*) add_shlibpath=$dir ;; + *-*-sunos*) add_shlibpath="$dir" ;; esac - add_dir=-L$dir - add=-l$name - elif test no = "$hardcode_shlibpath_var"; then - add_shlibpath=$dir - add=-l$name + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" else lib_linked=no fi ;; relink) - if test yes = "$hardcode_direct" && - test no = "$hardcode_direct_absolute"; then - add=$dir/$linklib - elif test yes = "$hardcode_minus_L"; then - add_dir=-L$absdir + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in @@ -8303,10 +6857,10 @@ ;; esac fi - add=-l$name - elif test yes = "$hardcode_shlibpath_var"; then - add_shlibpath=$dir - add=-l$name + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" else lib_linked=no fi @@ -8314,7 +6868,7 @@ *) lib_linked=no ;; esac - if test yes != "$lib_linked"; then + if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi @@ -8324,15 +6878,15 @@ *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi - if test prog = "$linkmode"; then + if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" - if test yes != "$hardcode_direct" && - test yes != "$hardcode_minus_L" && - test yes = "$hardcode_shlibpath_var"; then + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; @@ -8341,33 +6895,33 @@ fi fi - if test prog = "$linkmode" || test relink = "$opt_mode"; then + if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. - if test yes = "$hardcode_direct" && - test no = "$hardcode_direct_absolute"; then - add=$libdir/$linklib - elif test yes = "$hardcode_minus_L"; then - add_dir=-L$libdir - add=-l$name - elif test yes = "$hardcode_shlibpath_var"; then + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac - add=-l$name - elif test yes = "$hardcode_automatic"; then + add="-l$name" + elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib"; then - add=$inst_prefix_dir$libdir/$linklib + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" else - add=$libdir/$linklib + add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. - add_dir=-L$libdir + add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in @@ -8376,10 +6930,10 @@ ;; esac fi - add=-l$name + add="-l$name" fi - if test prog = "$linkmode"; then + if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else @@ -8387,43 +6941,43 @@ test -n "$add" && deplibs="$add $deplibs" fi fi - elif test prog = "$linkmode"; then + elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. - if test unsupported != "$hardcode_direct"; then - test -n "$old_library" && linklib=$old_library + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi - elif test yes = "$build_libtool_libs"; then + elif test "$build_libtool_libs" = yes; then # Not a shared library - if test pass_all != "$deplibs_check_method"; then + if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo - $ECHO "*** Warning: This system cannot link to static lib archive $lib." + $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." - if test yes = "$module"; then + if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." - echo "*** 'nm' from GNU binutils and a full rebuild may help." + echo "*** \`nm' from GNU binutils and a full rebuild may help." fi - if test no = "$build_old_libs"; then + if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else @@ -8436,11 +6990,11 @@ fi fi # link shared/static library? - if test lib = "$linkmode"; then + if test "$linkmode" = lib; then if test -n "$dependency_libs" && - { test yes != "$hardcode_into_libs" || - test yes = "$build_old_libs" || - test yes = "$link_static"; }; then + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do @@ -8454,12 +7008,12 @@ *) func_append temp_deplibs " $libdir";; esac done - dependency_libs=$temp_deplibs + dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library - test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do @@ -8469,7 +7023,7 @@ func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac - if $opt_preserve_dup_deps; then + if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; @@ -8478,12 +7032,12 @@ func_append tmp_libs " $func_resolve_sysroot_result" done - if test no != "$link_all_deplibs"; then + if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in - -L*) path=$deplib ;; + -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result @@ -8491,12 +7045,12 @@ dir=$func_dirname_result # We need an absolute path. case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then - func_warning "cannot determine absolute directory name of '$dir'" - absdir=$dir + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" fi ;; esac @@ -8504,35 +7058,35 @@ case $host in *-*-darwin*) depdepl= - eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names"; then - for tmp in $deplibrary_names; do + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do depdepl=$tmp done - if test -f "$absdir/$objdir/$depdepl"; then - depdepl=$absdir/$objdir/$depdepl - darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then - darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi - func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" - func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) - path=-L$absdir/$objdir + path="-L$absdir/$objdir" ;; esac else - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ - func_fatal_error "'$deplib' is not a valid libtool archive" + func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ - func_warning "'$deplib' seems to be moved" + func_warning "\`$deplib' seems to be moved" - path=-L$absdir + path="-L$absdir" fi ;; esac @@ -8544,23 +7098,23 @@ fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs - if test link = "$pass"; then - if test prog = "$linkmode"; then + if test "$pass" = link; then + if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi - dependency_libs=$newdependency_libs - if test dlpreopen = "$pass"; then + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi - if test dlopen != "$pass"; then - test conv = "$pass" || { + if test "$pass" != dlopen; then + if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do @@ -8570,12 +7124,12 @@ esac done newlib_search_path= - } + fi - if test prog,link = "$linkmode,$pass"; then - vars="compile_deplibs finalize_deplibs" + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" else - vars=deplibs + vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order @@ -8633,93 +7187,62 @@ eval $var=\"$tmp_libs\" done # for var fi - - # Add Sun CC postdeps if required: - test CXX = "$tagname" && { - case $host_os in - linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C++ 5.9 - func_suncc_cstd_abi - - if test no != "$suncc_use_cstd_abi"; then - func_append postdeps ' -library=Cstd -library=Crun' - fi - ;; - esac - ;; - - solaris*) - func_cc_basename "$CC" - case $func_cc_basename_result in - CC* | sunCC*) - func_suncc_cstd_abi - - if test no != "$suncc_use_cstd_abi"; then - func_append postdeps ' -library=Cstd -library=Crun' - fi - ;; - esac - ;; - esac - } - # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= - for i in $dependency_libs; do + for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) - i= + i="" ;; esac - if test -n "$i"; then + if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass - if test prog = "$linkmode"; then - dlfiles=$newdlfiles + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" fi - if test prog = "$linkmode" || test lib = "$linkmode"; then - dlprefiles=$newdlprefiles + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) - if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then - func_warning "'-dlopen' is ignored for archives" + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) - func_warning "'-l' and '-L' are ignored for archives" ;; + func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ - func_warning "'-rpath' is ignored for archives" + func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ - func_warning "'-R' is ignored for archives" + func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ - func_warning "'-version-info/-version-number' is ignored for archives" + func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ - func_warning "'-release' is ignored for archives" + func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ - func_warning "'-export-symbols' is ignored for archives" + func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no - oldlibs=$output + oldlibs="$output" func_append objs "$old_deplibs" ;; lib) - # Make sure we only generate libraries of the form 'libNAME.la'. + # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" @@ -8728,10 +7251,10 @@ eval libname=\"$libname_spec\" ;; *) - test no = "$module" \ - && func_fatal_help "libtool library '$output' must begin with 'lib'" + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" - if test no != "$need_lib_prefix"; then + if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result @@ -8745,8 +7268,8 @@ esac if test -n "$objs"; then - if test pass_all != "$deplibs_check_method"; then - func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" @@ -8755,21 +7278,21 @@ fi fi - test no = "$dlself" \ - || func_warning "'-dlopen self' is ignored for libtool libraries" + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift - test 1 -lt "$#" \ - && func_warning "ignoring multiple '-rpath's for a libtool library" + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" - install_libdir=$1 + install_libdir="$1" oldlibs= if test -z "$rpath"; then - if test yes = "$build_libtool_libs"; then + if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. - # Some compilers have problems with a '.al' extension so + # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" @@ -8778,20 +7301,20 @@ fi test -n "$vinfo" && \ - func_warning "'-version-info/-version-number' is ignored for convenience libraries" + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ - func_warning "'-release' is ignored for convenience libraries" + func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. - save_ifs=$IFS; IFS=: + save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift - IFS=$save_ifs + IFS="$save_ifs" test -n "$7" && \ - func_fatal_help "too many parameters to '-version-info'" + func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts @@ -8799,45 +7322,45 @@ case $vinfo_number in yes) - number_major=$1 - number_minor=$2 - number_revision=$3 + number_major="$1" + number_minor="$2" + number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix - # that has an extra 1 added just for fun + # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor - darwin|freebsd-elf|linux|osf|windows|none) + darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result - age=$number_minor - revision=$number_revision + age="$number_minor" + revision="$number_revision" ;; - freebsd-aout|qnx|sunos) - current=$number_major - revision=$number_minor - age=0 + freebsd-aout|freebsd-elf|qnx|sunos) + current="$number_major" + revision="$number_minor" + age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result - age=$number_minor - revision=$number_minor + age="$number_minor" + revision="$number_minor" lt_irix_increment=no ;; *) - func_fatal_configuration "$modename: unknown library version type '$version_type'" + func_fatal_configuration "$modename: unknown library version type \`$version_type'" ;; esac ;; no) - current=$1 - revision=$2 - age=$3 + current="$1" + revision="$2" + age="$3" ;; esac @@ -8845,30 +7368,30 @@ case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "CURRENT '$current' must be a nonnegative integer" - func_fatal_error "'$vinfo' is not valid version information" + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "REVISION '$revision' must be a nonnegative integer" - func_fatal_error "'$vinfo' is not valid version information" + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - func_error "AGE '$age' must be a nonnegative integer" - func_fatal_error "'$vinfo' is not valid version information" + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then - func_error "AGE '$age' is greater than the current interface number '$current'" - func_fatal_error "'$vinfo' is not valid version information" + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. @@ -8883,36 +7406,26 @@ # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result - versuffix=$major.$age.$revision + versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result - xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - # On Darwin other compilers - case $CC in - nagfor*) - verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" - ;; - *) - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - ;; - esac ;; freebsd-aout) - major=.$current - versuffix=.$current.$revision + major=".$current" + versuffix=".$current.$revision"; ;; freebsd-elf) - func_arith $current - $age - major=.$func_arith_result - versuffix=$major.$age.$revision + major=".$current" + versuffix=".$current" ;; irix | nonstopux) - if test no = "$lt_irix_increment"; then + if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 @@ -8923,74 +7436,69 @@ nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac - verstring=$verstring_prefix$major.$revision + verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision - while test 0 -ne "$loop"; do + while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result - verstring=$verstring_prefix$major.$iface:$verstring + verstring="$verstring_prefix$major.$iface:$verstring" done - # Before this point, $major must not contain '.'. + # Before this point, $major must not contain `.'. major=.$major - versuffix=$major.$revision + versuffix="$major.$revision" ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result - versuffix=$major.$age.$revision + versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result - versuffix=.$current.$age.$revision - verstring=$current.$age.$revision + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age - while test 0 -ne "$loop"; do + while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result - verstring=$verstring:$iface.0 + verstring="$verstring:${iface}.0" done # Make executables depend on our current version. - func_append verstring ":$current.0" + func_append verstring ":${current}.0" ;; qnx) - major=.$current - versuffix=.$current - ;; - - sco) - major=.$current - versuffix=.$current + major=".$current" + versuffix=".$current" ;; sunos) - major=.$current - versuffix=.$current.$revision + major=".$current" + versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 file systems. + # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result - versuffix=-$major + versuffix="-$major" ;; *) - func_fatal_configuration "unknown library version type '$version_type'" + func_fatal_configuration "unknown library version type \`$version_type'" ;; esac @@ -9004,45 +7512,42 @@ verstring= ;; *) - verstring=0.0 + verstring="0.0" ;; esac - if test no = "$need_version"; then + if test "$need_version" = no; then versuffix= else - versuffix=.0.0 + versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided - if test yes,no = "$avoid_version,$need_version"; then + if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= - verstring= + verstring="" fi # Check to see if the archive will have undefined symbols. - if test yes = "$allow_undefined"; then - if test unsupported = "$allow_undefined_flag"; then - if test yes = "$build_old_libs"; then - func_warning "undefined symbols not allowed in $host shared libraries; building static only" - build_libtool_libs=no - else - func_fatal_error "can't build $host shared library unless -no-undefined is specified" - fi + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes fi else # Don't allow undefined symbols. - allow_undefined_flag=$no_undefined_flag + allow_undefined_flag="$no_undefined_flag" fi fi - func_generate_dlsyms "$libname" "$libname" : + func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" - test " " = "$libobjs" && libobjs= + test "X$libobjs" = "X " && libobjs= - if test relink != "$opt_mode"; then + if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= @@ -9051,8 +7556,8 @@ case $p in *.$objext | *.gcno) ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) - if test -n "$precious_files_regex"; then + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue @@ -9068,11 +7573,11 @@ fi # Now set the variables for building old libraries. - if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. @@ -9093,13 +7598,13 @@ *) func_append finalize_rpath " $libdir" ;; esac done - if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles=$dlfiles + old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in @@ -9109,7 +7614,7 @@ done # Make sure dlprefiles contains only unique files - old_dlprefiles=$dlprefiles + old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in @@ -9118,7 +7623,7 @@ esac done - if test yes = "$build_libtool_libs"; then + if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) @@ -9142,7 +7647,7 @@ ;; *) # Add libc to deplibs on all other systems if necessary. - if test yes = "$build_libtool_need_lc"; then + if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; @@ -9158,9 +7663,9 @@ # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? - release= - versuffix= - major= + release="" + versuffix="" + major="" newdeplibs= droppeddeps=no case $deplibs_check_method in @@ -9189,20 +7694,20 @@ -l*) func_stripname -l '' "$i" name=$func_stripname_result - if test yes = "$allow_libtool_libs_with_static_runtimes"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $i "*) func_append newdeplibs " $i" - i= + i="" ;; esac fi - if test -n "$i"; then + if test -n "$i" ; then libname=`eval "\\$ECHO \"$libname_spec\""` deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` set dummy $deplib_matches; shift deplib_match=$1 - if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then func_append newdeplibs " $i" else droppeddeps=yes @@ -9232,20 +7737,20 @@ $opt_dry_run || $RM conftest if $LTCC $LTCFLAGS -o conftest conftest.c $i; then ldd_output=`ldd conftest` - if test yes = "$allow_libtool_libs_with_static_runtimes"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $i "*) func_append newdeplibs " $i" - i= + i="" ;; esac fi - if test -n "$i"; then + if test -n "$i" ; then libname=`eval "\\$ECHO \"$libname_spec\""` deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` set dummy $deplib_matches; shift deplib_match=$1 - if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then func_append newdeplibs " $i" else droppeddeps=yes @@ -9282,24 +7787,24 @@ -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result - if test yes = "$allow_libtool_libs_with_static_runtimes"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" - a_deplib= + a_deplib="" ;; esac fi - if test -n "$a_deplib"; then + if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` if test -n "$file_magic_glob"; then libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob` else libnameglob=$libname fi - test yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob` + test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - if test yes = "$want_nocaseglob"; then + if test "$want_nocaseglob" = yes; then shopt -s nocaseglob potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` $nocaseglob @@ -9317,25 +7822,25 @@ # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? - potlib=$potent_lib + potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; - *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" - a_deplib= + a_deplib="" break 2 fi done done fi - if test -n "$a_deplib"; then + if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." @@ -9343,7 +7848,7 @@ echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib"; then + if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" @@ -9366,30 +7871,30 @@ -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result - if test yes = "$allow_libtool_libs_with_static_runtimes"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" - a_deplib= + a_deplib="" ;; esac fi - if test -n "$a_deplib"; then + if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do - potlib=$potent_lib # see symlink-check above in file_magic test + potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" - a_deplib= + a_deplib="" break 2 fi done done fi - if test -n "$a_deplib"; then + if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." @@ -9397,7 +7902,7 @@ echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib"; then + if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" @@ -9413,18 +7918,18 @@ done # Gone through all deplibs. ;; none | unknown | *) - newdeplibs= + newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` - if test yes = "$allow_libtool_libs_with_static_runtimes"; then - for i in $predeps $postdeps; do + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo - if test none = "$deplibs_check_method"; then + if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." @@ -9448,8 +7953,8 @@ ;; esac - if test yes = "$droppeddeps"; then - if test yes = "$module"; then + if test "$droppeddeps" = yes; then + if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" @@ -9458,12 +7963,12 @@ if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." - echo "*** 'nm' from GNU binutils and a full rebuild may help." + echo "*** \`nm' from GNU binutils and a full rebuild may help." fi - if test no = "$build_old_libs"; then - oldlibs=$output_objdir/$libname.$libext + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else @@ -9474,14 +7979,14 @@ echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." - if test no = "$allow_undefined"; then + if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." - if test no = "$build_old_libs"; then - oldlibs=$output_objdir/$libname.$libext + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else @@ -9527,7 +8032,7 @@ *) func_append new_libs " $deplib" ;; esac done - deplibs=$new_libs + deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= @@ -9535,25 +8040,25 @@ dlname= # Test again, we may have decided not to build it any more - if test yes = "$build_libtool_libs"; then - # Remove $wl instances when linking with ld. + if test "$build_libtool_libs" = yes; then + # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac - if test yes = "$hardcode_into_libs"; then + if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= - rpath=$finalize_rpath - test relink = "$opt_mode" || rpath=$compile_rpath$rpath + rpath="$finalize_rpath" + test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then - hardcode_libdirs=$libdir + hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -9578,7 +8083,7 @@ # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir=$hardcode_libdirs + libdir="$hardcode_libdirs" eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then @@ -9592,8 +8097,8 @@ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi - shlibpath=$finalize_shlibpath - test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + shlibpath="$finalize_shlibpath" + test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi @@ -9603,19 +8108,19 @@ eval library_names=\"$library_names_spec\" set dummy $library_names shift - realname=$1 + realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else - soname=$realname + soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi - lib=$output_objdir/$realname + lib="$output_objdir/$realname" linknames= for link do @@ -9629,7 +8134,7 @@ delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" - export_symbols=$output_objdir/$libname.uexp + export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi @@ -9638,31 +8143,31 @@ cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile - func_dll_def_p "$export_symbols" || { + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. - orig_export_symbols=$export_symbols + orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes - } + fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then - if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then - func_verbose "generating symbol list for '$libname.la'" - export_symbols=$output_objdir/$libname.exp + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds - save_ifs=$IFS; IFS='~' + save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do - IFS=$save_ifs + IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in @@ -9676,7 +8181,7 @@ try_normal_branch=no ;; esac - if test yes = "$try_normal_branch" \ + if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then @@ -9687,7 +8192,7 @@ output_la=$func_basename_result save_libobjs=$libobjs save_output=$output - output=$output_objdir/$output_la.nm + output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" @@ -9710,8 +8215,8 @@ break fi done - IFS=$save_ifs - if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi @@ -9719,16 +8224,16 @@ fi if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols=$export_symbols - test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi - if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands, which not all seds can handle. GNU sed should be fine + # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. @@ -9747,11 +8252,11 @@ ;; esac done - deplibs=$tmp_deplibs + deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && - test yes = "$compiler_needs_object" && + test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. @@ -9762,7 +8267,7 @@ eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else - gentop=$output_objdir/${outputname}x + gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience @@ -9771,18 +8276,18 @@ fi fi - if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking - if test relink = "$opt_mode"; then + if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. - if test yes = "$module" && test -n "$module_cmds"; then + if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds @@ -9800,7 +8305,7 @@ fi fi - if test : != "$skipped_export" && + if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then @@ -9833,8 +8338,8 @@ last_robj= k=1 - if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then - output=$output_objdir/$output_la.lnkscript + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs @@ -9846,14 +8351,14 @@ func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result - elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then - output=$output_objdir/$output_la.lnk + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= - if test yes = "$compiler_needs_object"; then + if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi @@ -9868,7 +8373,7 @@ else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." - output=$output_objdir/$output_la-$k.$objext + output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result @@ -9880,13 +8385,13 @@ func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result - if test -z "$objlist" || + if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. - if test 1 -eq "$k"; then + if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" @@ -9896,10 +8401,10 @@ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi - last_robj=$output_objdir/$output_la-$k.$objext + last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result - output=$output_objdir/$output_la-$k.$objext + output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result @@ -9911,9 +8416,9 @@ # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" - eval concat_cmds=\"\$concat_cmds$reload_cmds\" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then - eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" @@ -9921,9 +8426,9 @@ output= fi - ${skipped_export-false} && { - func_verbose "generating symbol list for '$libname.la'" - export_symbols=$output_objdir/$libname.exp + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. @@ -9932,16 +8437,16 @@ if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi - } + fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. - save_ifs=$IFS; IFS='~' + save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do - IFS=$save_ifs - $opt_quiet || { + IFS="$save_ifs" + $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } @@ -9949,7 +8454,7 @@ lt_exit=$? # Restore the uninstalled library and exit - if test relink = "$opt_mode"; then + if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) @@ -9958,7 +8463,7 @@ exit $lt_exit } done - IFS=$save_ifs + IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' @@ -9966,18 +8471,18 @@ fi fi - ${skipped_export-false} && { + if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols=$export_symbols - test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands, which not all seds can handle. GNU sed should be fine + # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. @@ -9986,7 +8491,7 @@ export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi - } + fi libobjs=$output # Restore the value of output. @@ -10000,7 +8505,7 @@ # value of $libobjs for piecewise linking. # Do each of the archive commands. - if test yes = "$module" && test -n "$module_cmds"; then + if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else @@ -10022,7 +8527,7 @@ # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then - gentop=$output_objdir/${outputname}x + gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles @@ -10030,12 +8535,11 @@ test "X$libobjs" = "X " && libobjs= fi - save_ifs=$IFS; IFS='~' + save_ifs="$IFS"; IFS='~' for cmd in $cmds; do - IFS=$sp$nl + IFS="$save_ifs" eval cmd=\"$cmd\" - IFS=$save_ifs - $opt_quiet || { + $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } @@ -10043,7 +8547,7 @@ lt_exit=$? # Restore the uninstalled library and exit - if test relink = "$opt_mode"; then + if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) @@ -10052,10 +8556,10 @@ exit $lt_exit } done - IFS=$save_ifs + IFS="$save_ifs" # Restore the uninstalled library and exit - if test relink = "$opt_mode"; then + if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then @@ -10075,39 +8579,39 @@ done # If -module or -export-dynamic was specified, set the dlname. - if test yes = "$module" || test yes = "$export_dynamic"; then + if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. - dlname=$soname + dlname="$soname" fi fi ;; obj) - if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then - func_warning "'-dlopen' is ignored for objects" + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) - func_warning "'-l' and '-L' are ignored for objects" ;; + func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ - func_warning "'-rpath' is ignored for objects" + func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ - func_warning "'-R' is ignored for objects" + func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ - func_warning "'-version-info' is ignored for objects" + func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ - func_warning "'-release' is ignored for objects" + func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ - func_fatal_error "cannot build library object '$output' from non-libtool objects" + func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" @@ -10115,7 +8619,7 @@ ;; *) libobj= - obj=$output + obj="$output" ;; esac @@ -10128,19 +8632,17 @@ # the extraction. reload_conv_objs= gentop= - # if reload_cmds runs $LD directly, get rid of -Wl from - # whole_archive_flag_spec and hope we can get by with turning comma - # into space. - case $reload_cmds in - *\$LD[\ \$]*) wl= ;; - esac + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` - reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else - gentop=$output_objdir/${obj}x + gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience @@ -10149,12 +8651,12 @@ fi # If we're not building shared, we need to use non_pic_objs - test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. - reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test - output=$obj + output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. @@ -10166,7 +8668,7 @@ exit $EXIT_SUCCESS fi - test yes = "$build_libtool_libs" || { + if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi @@ -10176,12 +8678,12 @@ # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS - } + fi - if test -n "$pic_flag" || test default != "$pic_mode"; then + if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" - output=$libobj + output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi @@ -10198,14 +8700,16 @@ output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ - func_warning "'-version-info' is ignored for programs" + func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ - func_warning "'-release' is ignored for programs" + func_warning "\`-release' is ignored for programs" - $preload \ - && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ - && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) @@ -10219,11 +8723,11 @@ *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). - if test CXX = "$tagname"; then + if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) - func_append compile_command " $wl-bind_at_load" - func_append finalize_command " $wl-bind_at_load" + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" ;; esac fi @@ -10259,7 +8763,7 @@ *) func_append new_libs " $deplib" ;; esac done - compile_deplibs=$new_libs + compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" @@ -10283,7 +8787,7 @@ if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then - hardcode_libdirs=$libdir + hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -10306,7 +8810,7 @@ fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; @@ -10323,10 +8827,10 @@ # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir=$hardcode_libdirs + libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi - compile_rpath=$rpath + compile_rpath="$rpath" rpath= hardcode_libdirs= @@ -10334,7 +8838,7 @@ if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then - hardcode_libdirs=$libdir + hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in @@ -10359,43 +8863,45 @@ # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then - libdir=$hardcode_libdirs + libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi - finalize_rpath=$rpath + finalize_rpath="$rpath" - if test -n "$libobjs" && test yes = "$build_old_libs"; then + if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi - func_generate_dlsyms "$outputname" "@PROGRAM@" false + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi - wrappers_required=: + wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. - wrappers_required=false + wrappers_required=no ;; *cygwin* | *mingw* ) - test yes = "$build_libtool_libs" || wrappers_required=false + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi ;; *) - if test no = "$need_relink" || test yes != "$build_libtool_libs"; then - wrappers_required=false + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no fi ;; esac - $wrappers_required || { + if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - link_command=$compile_command$compile_rpath + link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 @@ -10408,12 +8914,12 @@ fi # Delete the generated files. - if test -f "$output_objdir/${outputname}S.$objext"; then - func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status - } + fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" @@ -10443,9 +8949,9 @@ fi fi - if test yes = "$no_install"; then + if test "$no_install" = yes; then # We don't need to create a wrapper script. - link_command=$compile_var$compile_command$compile_rpath + link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. @@ -10462,28 +8968,27 @@ exit $EXIT_SUCCESS fi - case $hardcode_action,$fast_install in - relink,*) - # Fast installation is not supported - link_command=$compile_var$compile_command$compile_rpath - relink_command=$finalize_var$finalize_command$finalize_rpath - - func_warning "this platform does not like uninstalled shared libraries" - func_warning "'$output' will be relinked during installation" - ;; - *,yes) - link_command=$finalize_var$compile_command$finalize_rpath - relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` - ;; - *,no) - link_command=$compile_var$compile_command$compile_rpath - relink_command=$finalize_var$finalize_command$finalize_rpath - ;; - *,needless) - link_command=$finalize_var$compile_command$finalize_rpath - relink_command= - ;; - esac + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` @@ -10540,8 +9045,8 @@ func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result - cwrappersource=$output_path/$objdir/lt-$output_name.c - cwrapper=$output_path/$output_name.exe + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 @@ -10562,7 +9067,7 @@ trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. - if test "x$build" = "x$host"; then + if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result @@ -10585,27 +9090,25 @@ # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do - case $build_libtool_libs in - convenience) - oldobjs="$libobjs_save $symfileobj" - addlibs=$convenience - build_libtool_libs=no - ;; - module) - oldobjs=$libobjs_save - addlibs=$old_convenience + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" build_libtool_libs=no - ;; - *) + else oldobjs="$old_deplibs $non_pic_objects" - $preload && test -f "$symfileobj" \ - && func_append oldobjs " $symfileobj" - addlibs=$old_convenience - ;; - esac + if test "$preload" = yes && test -f "$symfileobj"; then + func_append oldobjs " $symfileobj" + fi + fi + addlibs="$old_convenience" + fi if test -n "$addlibs"; then - gentop=$output_objdir/${outputname}x + gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs @@ -10613,13 +9116,13 @@ fi # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then - gentop=$output_objdir/${outputname}x + gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles @@ -10640,7 +9143,7 @@ : else echo "copying selected object files to avoid basename conflicts..." - gentop=$output_objdir/${outputname}x + gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs @@ -10649,7 +9152,7 @@ for obj in $save_oldobjs do func_basename "$obj" - objbase=$func_basename_result + objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) @@ -10718,18 +9221,18 @@ else # the above command should be used before it gets too long oldobjs=$objlist - if test "$obj" = "$last_oldobj"; then + if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist - if test -z "$oldobjs"; then + if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" @@ -10746,7 +9249,7 @@ case $output in *.la) old_library= - test yes = "$build_old_libs" && old_library=$libname.$libext + test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior @@ -10761,31 +9264,31 @@ fi done # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - if test yes = "$hardcode_automatic"; then + if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do - if test yes = "$installed"; then + if test "$installed" = yes; then if test -z "$install_libdir"; then break fi - output=$output_objdir/${outputname}i + output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" - name=$func_basename_result + name="$func_basename_result" func_resolve_sysroot "$deplib" - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ - func_fatal_error "'$deplib' is not a valid libtool archive" + func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) @@ -10801,23 +9304,23 @@ *) func_append newdependency_libs " $deplib" ;; esac done - dependency_libs=$newdependency_libs + dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" - name=$func_basename_result - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ - func_fatal_error "'$lib' is not a valid libtool archive" + func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done - dlfiles=$newdlfiles + dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in @@ -10827,34 +9330,34 @@ # didn't already link the preopened objects directly into # the library: func_basename "$lib" - name=$func_basename_result - eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ - func_fatal_error "'$lib' is not a valid libtool archive" + func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done - dlprefiles=$newdlprefiles + dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done - dlfiles=$newdlfiles + dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done - dlprefiles=$newdlprefiles + dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin @@ -10870,9 +9373,10 @@ case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. - if test -n "$bindir"; then + if test "x$bindir" != x ; + then func_relative_path "$install_libdir" "$bindir" - tdlname=$func_relative_path_result/$dlname + tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname @@ -10881,7 +9385,7 @@ esac $ECHO > $output "\ # $outputname - a libtool library file -# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. @@ -10895,7 +9399,7 @@ # The name of the static archive. old_library='$old_library' -# Linker flags that cannot go in dependency_libs. +# Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. @@ -10921,7 +9425,7 @@ # Directory that this library needs to be installed in: libdir='$install_libdir'" - if test no,yes = "$installed,$need_relink"; then + if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi @@ -10936,29 +9440,27 @@ exit $EXIT_SUCCESS } -if test link = "$opt_mode" || test relink = "$opt_mode"; then - func_mode_link ${1+"$@"} -fi +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && + func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { - $debug_cmd - - RM=$nonopt + $opt_debug + RM="$nonopt" files= - rmforce=false + rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. - libtool_install_magic=$magic + libtool_install_magic="$magic" for arg do case $arg in - -f) func_append RM " $arg"; rmforce=: ;; + -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac @@ -10971,18 +9473,18 @@ for file in $files; do func_dirname "$file" "" "." - dir=$func_dirname_result - if test . = "$dir"; then - odir=$objdir + dir="$func_dirname_result" + if test "X$dir" = X.; then + odir="$objdir" else - odir=$dir/$objdir + odir="$dir/$objdir" fi func_basename "$file" - name=$func_basename_result - test uninstall = "$opt_mode" && odir=$dir + name="$func_basename_result" + test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates - if test clean = "$opt_mode"; then + if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; @@ -10997,11 +9499,11 @@ elif test -d "$file"; then exit_status=1 continue - elif $rmforce; then + elif test "$rmforce" = yes; then continue fi - rmfiles=$file + rmfiles="$file" case $name in *.la) @@ -11015,7 +9517,7 @@ done test -n "$old_library" && func_append rmfiles " $odir/$old_library" - case $opt_mode in + case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; @@ -11026,12 +9528,12 @@ uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. - func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. - func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; @@ -11047,19 +9549,21 @@ func_source $dir/$name # Add PIC object to the list of files to remove. - if test -n "$pic_object" && test none != "$pic_object"; then + if test -n "$pic_object" && + test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" && test none != "$non_pic_object"; then + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) - if test clean = "$opt_mode"; then + if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) @@ -11086,12 +9590,12 @@ # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles - func_append rmfiles " $odir/$name $odir/${name}S.$objext" - if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi - if test "X$noexename" != "X$name"; then - func_append rmfiles " $odir/lt-$noexename.c" + if test "X$noexename" != "X$name" ; then + func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi @@ -11100,7 +9604,7 @@ func_show_eval "$RM $rmfiles" 'exit_status=1' done - # Try to remove the $objdir's in the directories where we deleted files + # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" @@ -11110,17 +9614,16 @@ exit $exit_status } -if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then - func_mode_uninstall ${1+"$@"} -fi +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && + func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { - help=$generic_help + help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode '$opt_mode'" + func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" @@ -11131,7 +9634,7 @@ # The TAGs below are defined such that we never get into a situation -# where we disable both kinds of libraries. Given conflicting +# in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support @@ -11154,3 +9657,5 @@ # mode:shell-script # sh-indentation:2 # End: +# vi:sw=2 + diff -Nru nghttp2-1.13.0/m4/ax_check_compile_flag.m4 nghttp2-0.6.7/m4/ax_check_compile_flag.m4 --- nghttp2-1.13.0/m4/ax_check_compile_flag.m4 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/m4/ax_check_compile_flag.m4 2014-11-30 14:15:07.000000000 +0000 @@ -55,10 +55,10 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 4 +#serial 3 AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS @@ -67,7 +67,7 @@ [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_VAR_IF(CACHEVAR,yes, +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff -Nru nghttp2-1.13.0/m4/libtool.m4 nghttp2-0.6.7/m4/libtool.m4 --- nghttp2-1.13.0/m4/libtool.m4 2016-07-21 13:47:58.000000000 +0000 +++ nghttp2-0.6.7/m4/libtool.m4 2014-11-30 14:15:30.000000000 +0000 @@ -1,6 +1,8 @@ # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # -# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives @@ -8,30 +10,36 @@ # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl -# Copyright (C) 2014 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of of the License, or -# (at your option) any later version. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. # -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program or library that is built -# using GNU Libtool, you may include this file under the same -# distribution terms that you use for the rest of that program. +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. # -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) -# serial 58 LT_INIT +# serial 57 LT_INIT # LT_PREREQ(VERSION) @@ -59,7 +67,7 @@ # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], -[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl @@ -83,7 +91,7 @@ _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed -LIBTOOL_DEPS=$ltmain +LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' @@ -103,43 +111,26 @@ dnl AC_DEFUN([AM_PROG_LIBTOOL], []) -# _LT_PREPARE_CC_BASENAME -# ----------------------- -m4_defun([_LT_PREPARE_CC_BASENAME], [ -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in @S|@*""; do - case $cc_temp in - compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; - distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} -])# _LT_PREPARE_CC_BASENAME - - # _LT_CC_BASENAME(CC) # ------------------- -# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, -# but that macro is also expanded into generated libtool script, which -# arranges for $SED and $ECHO to be set by different means. +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], -[m4_require([_LT_PREPARE_CC_BASENAME])dnl -AC_REQUIRE([_LT_DECL_SED])dnl -AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl -func_cc_basename $1 -cc_basename=$func_cc_basename_result +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set -# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} @@ -186,16 +177,15 @@ m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl -m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ -# See if we are running on zsh, and set the options that allow our +# See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}"; then +if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) -if test -n "${ZSH_VERSION+set}"; then +if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi @@ -208,7 +198,7 @@ # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. - if test set != "${COLLECT_NAMES+set}"; then + if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -219,14 +209,14 @@ ofile=libtool can_build_shared=yes -# All known linkers require a '.a' archive for static linking (except MSVC, +# All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a -with_gnu_ld=$lt_cv_prog_gnu_ld +with_gnu_ld="$lt_cv_prog_gnu_ld" -old_CC=$CC -old_CFLAGS=$CFLAGS +old_CC="$CC" +old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc @@ -279,14 +269,14 @@ # _LT_PROG_LTMAIN # --------------- -# Note that this code is called both from 'configure', and 'config.status' +# Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, -# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) -ltmain=$ac_aux_dir/ltmain.sh +ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN @@ -296,7 +286,7 @@ # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS -# in macros and then make a single call at the end using the 'libtool' +# in macros and then make a single call at the end using the `libtool' # label. @@ -431,8 +421,8 @@ # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ -# Quote a variable value, and forward it to 'config.status' so that its -# declaration there will have the same value as in 'configure'. VARNAME +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) @@ -456,7 +446,7 @@ # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl -available_tags='_LT_TAGS'dnl +available_tags="_LT_TAGS"dnl ]) @@ -484,7 +474,7 @@ # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables -# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], @@ -510,8 +500,8 @@ # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations -# into 'config.status', and then the shell code to quote escape them in -# for loops in 'config.status'. Finally, any additional code accumulated +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], @@ -557,7 +547,7 @@ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -570,7 +560,7 @@ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -586,7 +576,7 @@ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the -# '#!' sequence but before initialization text begins. After this +# `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). @@ -608,7 +598,7 @@ _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF -test 0 = "$lt_write_fail" && chmod +x $1[]dnl +test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT @@ -631,7 +621,7 @@ } >&AS_MESSAGE_LOG_FD lt_cl_help="\ -'$as_me' creates a local libtool stub from the current configuration, +\`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. @@ -653,7 +643,7 @@ This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." -while test 0 != $[#] +while test $[#] != 0 do case $[1] in --version | --v* | -V ) @@ -666,10 +656,10 @@ lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] -Try '$[0] --help' for more information.]) ;; +Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] -Try '$[0] --help' for more information.]) ;; +Try \`$[0] --help' for more information.]) ;; esac shift done @@ -695,7 +685,7 @@ # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: -test yes = "$silent" && +test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false @@ -715,31 +705,27 @@ _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ - # See if we are running on zsh, and set the options that allow our + # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}"; then + if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi - cfgfile=${ofile}T + cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL -# Generated automatically by $as_me ($PACKAGE) $VERSION + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. - -# Provide generalized library-building support services. -# Written by Gordon Matzigkeit, 1996 - +# _LT_COPYING _LT_LIBTOOL_TAGS -# Configured defaults for sys_lib_dlsearch_path munging. -: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} - # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS @@ -747,24 +733,13 @@ _LT_EOF - cat <<'_LT_EOF' >> "$cfgfile" - -# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE - -_LT_PREPARE_MUNGE_PATH_LIST -_LT_PREPARE_CC_BASENAME - -# ### END FUNCTIONS SHARED WITH CONFIGURE - -_LT_EOF - case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. -if test set != "${COLLECT_NAMES+set}"; then +if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -781,6 +756,8 @@ sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) + _LT_PROG_REPLACE_SHELLFNS + mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" @@ -798,6 +775,7 @@ [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS @@ -996,7 +974,7 @@ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no - if test -z "$LT_MULTI_MODULE"; then + if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the @@ -1014,7 +992,7 @@ cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. - elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD @@ -1032,7 +1010,7 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) - LDFLAGS=$save_LDFLAGS + LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], @@ -1054,7 +1032,7 @@ _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD - elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD @@ -1064,32 +1042,32 @@ ]) case $host_os in rhapsody* | darwin1.[[012]]) - _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; - 10.[[012]][[,.]]*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac - if test yes = "$lt_cv_apple_cc_single_mod"; then + if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi - if test yes = "$lt_cv_ld_exported_symbols_list"; then - _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi - if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -1109,29 +1087,29 @@ _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - if test yes = "$lt_cv_ld_force_load"; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in - ifort*|nagfor*) _lt_dar_can_shared=yes ;; + ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test yes = "$_lt_dar_can_shared"; then + if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all - _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" - _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], -[ if test yes != "$lt_cv_apple_cc_single_mod"; then - _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else @@ -1151,7 +1129,7 @@ # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl -if test set = "${lt_cv_aix_libpath+set}"; then +if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], @@ -1169,7 +1147,7 @@ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then - _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) @@ -1189,8 +1167,8 @@ # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start -# of the generated configure script that will find a shell with a builtin -# printf (that we can use as an echo command). +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO @@ -1218,10 +1196,10 @@ # Invoke $ECHO with all args, space-separated. func_echo_all () { - $ECHO "$*" + $ECHO "$*" } -case $ECHO in +case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; @@ -1247,17 +1225,16 @@ AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], -[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], - [Search for dependent libraries within DIR (or the compiler's sysroot - if not specified).])], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= -case $with_sysroot in #( +case ${with_sysroot} in #( yes) - if test yes = "$GCC"; then + if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( @@ -1267,14 +1244,14 @@ no|'') ;; #( *) - AC_MSG_RESULT([$with_sysroot]) + AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl -[dependent libraries, and where our libraries should be installed.])]) +[dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- @@ -1282,33 +1259,31 @@ [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) -test no = "$enable_libtool_lock" || enable_libtool_lock=yes +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) - # Find out what ABI is being produced by ac_compile, and set mode - # options accordingly. + # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) - HPUX_IA64_MODE=32 + HPUX_IA64_MODE="32" ;; *ELF-64*) - HPUX_IA64_MODE=64 + HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. + # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then - if test yes = "$lt_cv_prog_gnu_ld"; then + if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" @@ -1337,46 +1312,9 @@ rm -rf conftest* ;; -mips64*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - emul=elf - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - emul="${emul}32" - ;; - *64-bit*) - emul="${emul}64" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *MSB*) - emul="${emul}btsmip" - ;; - *LSB*) - emul="${emul}ltsmip" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *N32*) - emul="${emul}n32" - ;; - esac - LD="${LD-ld} -m $emul" - fi - rm -rf conftest* - ;; - x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. Note that the listed cases only cover the - # situations where additional linker options are needed (such as when - # doing 32-bit compilation for a host where ld defaults to 64-bit, or - # vice versa); the common cases where no linker options are needed do - # not appear in the list. + # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in @@ -1395,10 +1333,10 @@ ;; esac ;; - powerpc64le-*linux*) + powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; - powerpc64-*linux*) + powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -1417,10 +1355,10 @@ x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - powerpcle-*linux*) + powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; - powerpc-*linux*) + powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -1438,20 +1376,19 @@ *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS=$CFLAGS + SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) - if test yes != "$lt_cv_cc_needs_belf"; then + if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS=$SAVE_CFLAGS + CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. + # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in @@ -1459,7 +1396,7 @@ case $lt_cv_prog_gnu_ld in yes*) case $host in - i?86-*-solaris*|x86_64-*-solaris*) + i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) @@ -1468,7 +1405,7 @@ esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD=${LD-ld}_sol2 + LD="${LD-ld}_sol2" fi ;; *) @@ -1484,7 +1421,7 @@ ;; esac -need_locks=$enable_libtool_lock +need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK @@ -1503,11 +1440,11 @@ [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) - if test 0 -eq "$ac_status"; then + if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) - if test 0 -ne "$ac_status"; then + if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi @@ -1515,7 +1452,7 @@ ]) ]) -if test no = "$lt_cv_ar_at_file"; then +if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file @@ -1546,7 +1483,7 @@ if test -n "$RANLIB"; then case $host_os in - bitrig* | openbsd*) + openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) @@ -1582,7 +1519,7 @@ [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -1609,7 +1546,7 @@ $RM conftest* ]) -if test yes = "[$]$2"; then +if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) @@ -1631,7 +1568,7 @@ m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no - save_LDFLAGS=$LDFLAGS + save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -1650,10 +1587,10 @@ fi fi $RM -r conftest* - LDFLAGS=$save_LDFLAGS + LDFLAGS="$save_LDFLAGS" ]) -if test yes = "[$]$2"; then +if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) @@ -1674,7 +1611,7 @@ AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 - teststring=ABCD + teststring="ABCD" case $build_os in msdosdjgpp*) @@ -1714,7 +1651,7 @@ lt_cv_sys_max_cmd_len=8192; ;; - bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -1765,22 +1702,22 @@ *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ - test undefined != "$lt_cv_sys_max_cmd_len"; then + test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8; do + for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && - test 17 != "$i" # 1/2 MB should be enough + test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring @@ -1796,7 +1733,7 @@ ;; esac ]) -if test -n "$lt_cv_sys_max_cmd_len"; then +if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) @@ -1824,7 +1761,7 @@ # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl -if test yes = "$cross_compiling"; then : +if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 @@ -1871,9 +1808,9 @@ # endif #endif -/* When -fvisibility=hidden is used, assume the code has been annotated +/* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ -#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif @@ -1899,7 +1836,7 @@ return status; }] _LT_EOF - if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in @@ -1920,7 +1857,7 @@ # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl -if test yes != "$enable_dlopen"; then +if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown @@ -1930,52 +1867,44 @@ case $host_os in beos*) - lt_cv_dlopen=load_add_on + lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) - lt_cv_dlopen=LoadLibrary + lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) - lt_cv_dlopen=dlopen + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) - # if libdl is installed we need to link against it + # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ - lt_cv_dlopen=dyld + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; - tpf*) - # Don't try to run any link tests for TPF. We know it's impossible - # because TPF is a cross-compiler, and we know how we open DSOs. - lt_cv_dlopen=dlopen - lt_cv_dlopen_libs= - lt_cv_dlopen_self=no - ;; - *) AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen=shl_load], + [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen=dlopen], + [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) @@ -1984,21 +1913,21 @@ ;; esac - if test no = "$lt_cv_dlopen"; then - enable_dlopen=no - else + if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes + else + enable_dlopen=no fi case $lt_cv_dlopen in dlopen) - save_CPPFLAGS=$CPPFLAGS - test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - save_LDFLAGS=$LDFLAGS + save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - save_LIBS=$LIBS + save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], @@ -2008,7 +1937,7 @@ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) - if test yes = "$lt_cv_dlopen_self"; then + if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl @@ -2018,9 +1947,9 @@ ]) fi - CPPFLAGS=$save_CPPFLAGS - LDFLAGS=$save_LDFLAGS - LIBS=$save_LIBS + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" ;; esac @@ -2112,8 +2041,8 @@ m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) -hard_links=nottested -if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes @@ -2123,8 +2052,8 @@ ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) - if test no = "$hard_links"; then - AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else @@ -2151,8 +2080,8 @@ _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl -AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", - [Define to the sub-directory where libtool stores uninstalled libraries.]) +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR @@ -2164,15 +2093,15 @@ _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || - test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. - if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && - test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else @@ -2186,12 +2115,12 @@ fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) -if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || - test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no -elif test yes = "$shlibpath_overrides_runpath" || - test no = "$enable_shared"; then +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi @@ -2215,7 +2144,7 @@ # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) - if test -n "$STRIP"; then + if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) @@ -2233,47 +2162,6 @@ ])# _LT_CMD_STRIPLIB -# _LT_PREPARE_MUNGE_PATH_LIST -# --------------------------- -# Make sure func_munge_path_list() is defined correctly. -m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], -[[# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x@S|@2 in - x) - ;; - *:) - eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" - ;; - x:*) - eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" - ;; - *) - eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" - ;; - esac -} -]])# _LT_PREPARE_PATH_LIST - - # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics @@ -2284,18 +2172,17 @@ m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl -m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ -if test yes = "$GCC"; then +if test "$GCC" = yes; then case $host_os in - darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; - *) lt_awk_arg='/^libraries:/' ;; + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in - mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; - *) lt_sed_strip_eq='s|=/|/|g' ;; + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in @@ -2311,35 +2198,28 @@ ;; esac # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary... + # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= - lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - # ...but if some path component already ends with the multilib dir we assume - # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). - case "$lt_multi_os_dir; $lt_search_path_spec " in - "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) - lt_multi_os_dir= - ;; - esac + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" - elif test -n "$lt_multi_os_dir"; then + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS = " "; FS = "/|\n";} { - lt_foo = ""; - lt_count = 0; +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { - lt_foo = "/" $lt_i lt_foo; + lt_foo="/" $lt_i lt_foo; } else { lt_count--; } @@ -2353,7 +2233,7 @@ # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else @@ -2362,7 +2242,7 @@ library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=.so +shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -2379,17 +2259,14 @@ # flags to be left without arguments need_version=unknown -AC_ARG_VAR([LT_SYS_LIBRARY_PATH], -[User-defined run-time library search path.]) - case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='$libname$release$shared_ext$major' + soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) @@ -2397,91 +2274,41 @@ need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 supports IA64 - library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line '#! .'. This would cause the generated library to - # depend on '.', always an invalid library. This was fixed in + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # Using Import Files as archive members, it is possible to support - # filename-based versioning of shared library archives on AIX. While - # this would work for both with and without runtime linking, it will - # prevent static linking of such archives. So we do filename-based - # shared library versioning with .so extension only, which is used - # when both runtime linking and shared linking is enabled. - # Unfortunately, runtime linking may impact performance, so we do - # not want this to be the default eventually. Also, we use the - # versioned .so libs for executables only if there is the -brtl - # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. - # To allow for filename-based versioning support, we need to create - # libNAME.so.V as an archive file, containing: - # *) an Import File, referring to the versioned filename of the - # archive as well as the shared archive member, telling the - # bitwidth (32 or 64) of that shared object, and providing the - # list of exported symbols of that shared object, eventually - # decorated with the 'weak' keyword - # *) the shared object with the F_LOADONLY flag set, to really avoid - # it being seen by the linker. - # At run time we better use the real file rather than another symlink, - # but for link time we create the symlink libNAME.so -> libNAME.so.V - - case $with_aix_soname,$aix_use_runtimelinking in - # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - aix,yes) # traditional libtool - dynamic_linker='AIX unversionable lib.so' + if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - aix,no) # traditional AIX only - dynamic_linker='AIX lib.a[(]lib.so.V[)]' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - ;; - svr4,*) # full svr4 only - dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,yes) # both, prefer svr4 - dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # unpreferred sharedlib libNAME.a needs extra handling - postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' - postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,no) # both, prefer aix - dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling - postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' - postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' - ;; - esac + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi shlibpath_var=LIBPATH fi ;; @@ -2491,18 +2318,18 @@ powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='$libname$shared_ext' + library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; @@ -2510,8 +2337,8 @@ bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -2523,7 +2350,7 @@ cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=.dll + shrext_cmds=".dll" need_version=no need_lib_prefix=no @@ -2532,8 +2359,8 @@ # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -2549,17 +2376,17 @@ case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' @@ -2568,8 +2395,8 @@ *,cl*) # Native MSVC libname_spec='$name' - soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' - library_names_spec='$libname.dll.lib' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' case $build_os in mingw*) @@ -2596,7 +2423,7 @@ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) - sys_lib_search_path_spec=$LIB + sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` @@ -2609,8 +2436,8 @@ esac # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' @@ -2623,7 +2450,7 @@ *) # Assume MSVC wrapper - library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac @@ -2636,8 +2463,8 @@ version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' - soname_spec='$libname$release$major$shared_ext' + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -2650,8 +2477,8 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -2669,13 +2496,12 @@ version_type=freebsd-$objformat case $version_type in freebsd-elf*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac @@ -2705,10 +2531,10 @@ need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=no + shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -2726,15 +2552,14 @@ dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - if test 32 = "$HPUX_IA64_MODE"; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -2742,8 +2567,8 @@ dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -2752,8 +2577,8 @@ dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... @@ -2766,8 +2591,8 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -2778,7 +2603,7 @@ case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test yes = "$lt_cv_prog_gnu_ld"; then + if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix @@ -2786,8 +2611,8 @@ esac need_lib_prefix=no need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -2806,8 +2631,8 @@ esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" - sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; @@ -2816,33 +2641,13 @@ dynamic_linker=no ;; -linux*android*) - version_type=none # Android doesn't support versioned libraries. - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext' - soname_spec='$libname$release$shared_ext' - finish_cmds= - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - dynamic_linker='Android linker' - # Don't embed -rpath directories since the linker doesn't support them. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - ;; - # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -2867,12 +2672,7 @@ # before this can be enabled. hardcode_into_libs=yes - # Ideally, we could use ldconfig to report *all* directores which are - # searched for libraries, however this is still not possible. Aside from not - # being certain /sbin/ldconfig is available, command - # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, - # even though it is searched at run-time. Try to do the best guess by - # appending ld.so.conf contents (and includes) to the search path. + # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" @@ -2904,12 +2704,12 @@ need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -2919,7 +2719,7 @@ newsos6) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -2928,68 +2728,58 @@ version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd* | bitrig*) +openbsd*) version_type=sunos - sys_lib_dlsearch_path_spec=/usr/lib + sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - need_version=no - else - need_version=yes - fi - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi ;; os2*) libname_spec='$name' - version_type=windows - shrext_cmds=.dll - need_version=no + shrext_cmds=".dll" need_lib_prefix=no - # OS/2 can only load a DLL with a base name of 8 characters or less. - soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; - v=$($ECHO $release$versuffix | tr -d .-); - n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); - $ECHO $n$v`$shared_ext' - library_names_spec='${libname}_dll.$libext' + library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' - shlibpath_var=BEGINLIBPATH - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' + shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) @@ -3000,8 +2790,8 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -3011,11 +2801,11 @@ sunos4*) version_type=sunos - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test yes = "$with_gnu_ld"; then + if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes @@ -3023,8 +2813,8 @@ sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -3045,24 +2835,24 @@ ;; sysv4*MP*) - if test -d /usr/nec; then + if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' - soname_spec='$libname$shared_ext.$major' + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=sco + version_type=freebsd-elf need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test yes = "$with_gnu_ld"; then + if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -3080,7 +2870,7 @@ version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes @@ -3088,8 +2878,8 @@ uts4*) version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -3098,30 +2888,20 @@ ;; esac AC_MSG_RESULT([$dynamic_linker]) -test no = "$dynamic_linker" && can_build_shared=no +test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test yes = "$GCC"; then +if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then - sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi - -if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then - sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi -# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... -configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec - -# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code -func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" - -# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool -configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH - _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) @@ -3154,41 +2934,39 @@ [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) -_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], - [Detected run-time system search path for libraries]) -_LT_DECL([], [configure_time_lt_sys_library_path], [2], - [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- -# find a file program that can recognize shared library +# find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD=$MAGIC_CMD - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$1"; then - lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD=$lt_cv_path_MAGIC_CMD + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -3211,11 +2989,11 @@ break fi done - IFS=$lt_save_ifs - MAGIC_CMD=$lt_save_MAGIC_CMD + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) -MAGIC_CMD=$lt_cv_path_MAGIC_CMD +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else @@ -3233,7 +3011,7 @@ # _LT_PATH_MAGIC # -------------- -# find a file program that can recognize a shared library +# find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then @@ -3260,16 +3038,16 @@ AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test no = "$withval" || with_gnu_ld=yes], + [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld -if test yes = "$GCC"; then +if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) - # gcc leaves a trailing carriage return, which upsets mingw + # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; @@ -3283,7 +3061,7 @@ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done - test -z "$LD" && LD=$ac_prog + test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. @@ -3294,37 +3072,37 @@ with_gnu_ld=unknown ;; esac -elif test yes = "$with_gnu_ld"; then +elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD=$ac_dir/$ac_prog + lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 conftest.i -cat conftest.i conftest.i >conftest2.i -: ${lt_DD:=$DD} -AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], -[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: -fi]) -rm -f conftest.i conftest2.i conftest.out]) -])# _LT_PATH_DD - - -# _LT_CMD_TRUNCATE -# ---------------- -# find command to truncate a binary pipe -m4_defun([_LT_CMD_TRUNCATE], -[m4_require([_LT_PATH_DD]) -AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], -[printf 0123456789abcdef0123456789abcdef >conftest.i -cat conftest.i conftest.i >conftest2.i -lt_cv_truncate_bin= -if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" -fi -rm -f conftest.i conftest2.i conftest.out -test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) -_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], - [Command to truncate a binary pipe]) -])# _LT_CMD_TRUNCATE - - # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies @@ -3447,13 +3188,13 @@ # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. -# 'unknown' -- same as none, but documents that we really don't know. +# `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path -# that responds to the $file_magic_cmd with a given extended regex. -# If you have 'file' or equivalent on your system and you're not sure -# whether 'pass_all' will *always* work, you probably want this one. +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) @@ -3480,7 +3221,8 @@ # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else @@ -3576,8 +3318,8 @@ lt_cv_deplibs_check_method=pass_all ;; -openbsd* | bitrig*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' @@ -3630,9 +3372,6 @@ tpf*) lt_cv_deplibs_check_method=pass_all ;; -os2*) - lt_cv_deplibs_check_method=pass_all - ;; esac ]) @@ -3673,38 +3412,33 @@ AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. - lt_cv_path_NM=$NM + lt_cv_path_NM="$NM" else - lt_nm_to_check=${ac_tool_prefix}nm + lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. - tmp_nm=$ac_dir/$lt_tmp_nm - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. - # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file - # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty - case $build_os in - mingw*) lt_bad_file=conftest.nm/nofile ;; - *) lt_bad_file=/dev/null ;; - esac - case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in - *$lt_bad_file* | *'Invalid file or object type'*) + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" - break 2 + break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" - break 2 + break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but @@ -3715,21 +3449,21 @@ esac fi done - IFS=$lt_save_ifs + IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) -if test no != "$lt_cv_path_NM"; then - NM=$lt_cv_path_NM +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) - case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) - DUMPBIN="$DUMPBIN -symbols -headers" + DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: @@ -3737,8 +3471,8 @@ esac fi AC_SUBST([DUMPBIN]) - if test : != "$DUMPBIN"; then - NM=$DUMPBIN + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm @@ -3784,8 +3518,8 @@ case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh; - # decide which one to use based on capabilities of $DLLTOOL + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib @@ -3797,7 +3531,7 @@ ;; *) # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd=$ECHO + lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) @@ -3824,28 +3558,13 @@ lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) -if test yes != "$lt_cv_path_mainfest_tool"; then +if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL -# _LT_DLL_DEF_P([FILE]) -# --------------------- -# True iff FILE is a Windows DLL '.def' file. -# Keep in sync with func_dll_def_p in the libtool script -AC_DEFUN([_LT_DLL_DEF_P], -[dnl - test DEF = "`$SED -n dnl - -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace - -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments - -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl - -e q dnl Only consider the first "real" line - $1`" dnl -])# _LT_DLL_DEF_P - - # LT_LIB_M # -------- # check for math library @@ -3857,11 +3576,11 @@ # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) - AC_CHECK_LIB(m, cos, LIBM=-lm) + AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) @@ -3880,7 +3599,7 @@ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= -if test yes = "$GCC"; then +if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; @@ -3932,7 +3651,7 @@ symcode='[[ABCDGISTW]]' ;; hpux*) - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; @@ -3965,44 +3684,14 @@ symcode='[[ABCDGIRSTW]]' ;; esac -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Gets list of data symbols to import. - lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" - # Adjust the below global symbol transforms to fixup imported variables. - lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" - lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" - lt_c_name_lib_hook="\ - -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ - -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" -else - # Disable hooks by default. - lt_cv_sys_global_symbol_to_import= - lt_cdecl_hook= - lt_c_name_hook= - lt_c_name_lib_hook= -fi - # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n"\ -$lt_cdecl_hook\ -" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ -$lt_c_name_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" - -# Transform an extracted symbol line into symbol name with lib prefix and -# symbol address. -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ -$lt_c_name_lib_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -4020,24 +3709,21 @@ # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function, - # D for any global variable and I for any imported variable. + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ -" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ -" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ -" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ -" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ -" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" @@ -4077,11 +3763,11 @@ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE -/* DATA imports from DLLs on WIN32 can't be const, because runtime +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST -#elif defined __osf__ +#elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else @@ -4107,7 +3793,7 @@ { { "@PROGRAM@", (void *) 0 }, _LT_EOF - $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; @@ -4127,9 +3813,9 @@ mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS - LIBS=conftstm.$ac_objext + LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS @@ -4150,7 +3836,7 @@ rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. - if test yes = "$pipe_works"; then + if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= @@ -4177,16 +3863,12 @@ [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) -_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], - [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) -_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], - [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS @@ -4202,18 +3884,17 @@ m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. - if test yes = "$GXX"; then + if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) @@ -4224,8 +3905,8 @@ ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -4241,11 +3922,6 @@ # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - case $host_os in - os2*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' - ;; - esac ;; darwin* | rhapsody*) # PIC is the default on this platform @@ -4295,7 +3971,7 @@ case $host_os in aix[[4-9]]*) # All AIX code is PIC. - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else @@ -4336,14 +4012,14 @@ case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' - if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default @@ -4380,7 +4056,7 @@ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) - # old Intel C++ for x86_64, which still supported -KPIC. + # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' @@ -4525,18 +4201,17 @@ fi ], [ - if test yes = "$GCC"; then + if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) @@ -4547,8 +4222,8 @@ ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -4565,11 +4240,6 @@ # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - case $host_os in - os2*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' - ;; - esac ;; darwin* | rhapsody*) @@ -4640,7 +4310,7 @@ case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else @@ -4648,30 +4318,11 @@ fi ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - case $cc_basename in - nagfor*) - # NAG Fortran compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - case $host_os in - os2*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' - ;; - esac ;; hpux9* | hpux10* | hpux11*) @@ -4687,7 +4338,7 @@ ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) @@ -4698,7 +4349,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in - # old Intel for x86_64, which still supported -KPIC. + # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' @@ -4723,12 +4374,6 @@ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) @@ -4826,7 +4471,7 @@ ;; sysv4*MP*) - if test -d /usr/nec; then + if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi @@ -4855,7 +4500,7 @@ fi ]) case $host_os in - # For platforms that do not support PIC, -DPIC is meaningless: + # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; @@ -4921,21 +4566,17 @@ case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else - _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) - _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in @@ -4984,9 +4625,9 @@ # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ' (' and ')$', so one must not match beginning or - # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', - # as well as any symbol that contains 'd'. + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if @@ -5002,7 +4643,7 @@ # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. - if test yes != "$GCC"; then + if test "$GCC" != yes; then with_gnu_ld=no fi ;; @@ -5010,7 +4651,7 @@ # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; - openbsd* | bitrig*) + openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) @@ -5023,7 +4664,7 @@ # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no - if test yes = "$with_gnu_ld"; then + if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility @@ -5045,24 +4686,24 @@ esac fi - if test yes = "$lt_use_gnu_ld_interface"; then + if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='$wl' + wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no - case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... @@ -5075,7 +4716,7 @@ case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken - if test ia64 != "$host_cpu"; then + if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 @@ -5094,7 +4735,7 @@ case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) @@ -5110,7 +4751,7 @@ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -5120,7 +4761,7 @@ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes @@ -5128,89 +4769,61 @@ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - shrext_cmds=.dll - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no - if test linux-dietlibc = "$host_os"; then + if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test no = "$tmp_diet" + && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -5221,47 +4834,42 @@ lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; - nagfor*) # NAGFOR 5.3 - tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac - _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test yes = "$supports_anon_versioning"; then + if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in - tcc*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' - ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test yes = "$supports_anon_versioning"; then + if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -5275,8 +4883,8 @@ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -5294,8 +4902,8 @@ _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -5307,7 +4915,7 @@ _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify @@ -5322,9 +4930,9 @@ # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -5341,15 +4949,15 @@ *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac - if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= @@ -5365,7 +4973,7 @@ # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes - if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported @@ -5373,57 +4981,34 @@ ;; aix[[4-9]]*) - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag= + no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else - _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive + # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do - if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi ;; esac @@ -5442,21 +5027,13 @@ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # traditional, no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - ;; - esac + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' - if test yes = "$GCC"; then + if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` + collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -5475,80 +5052,62 @@ ;; esac shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag="$shared_flag "'$wl-G' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' + _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' else - shared_flag='$wl-bM:SRE' + shared_flag='${wl}-bM:SRE' fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' fi fi - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else - if test ia64 = "$host_cpu"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' - if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; @@ -5557,7 +5116,7 @@ case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) @@ -5587,17 +5146,16 @@ # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll + shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes @@ -5606,18 +5164,18 @@ # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # Assume MSVC wrapper @@ -5626,7 +5184,7 @@ # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll + shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. @@ -5676,33 +5234,33 @@ ;; hpux9*) - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) - if test yes,no = "$GCC,$with_gnu_ld"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes @@ -5710,25 +5268,25 @@ ;; hpux11*) - if test yes,no = "$GCC,$with_gnu_ld"; then + if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ @@ -5736,14 +5294,14 @@ # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], - [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in @@ -5754,7 +5312,7 @@ *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. @@ -5765,16 +5323,16 @@ ;; irix5* | irix6* | nonstopux*) - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], - [save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], @@ -5787,32 +5345,21 @@ end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) - LDFLAGS=$save_LDFLAGS]) - if test yes = "$lt_cv_irix_exported_symbol"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi - _LT_TAGVAR(link_all_deplibs, $1)=no else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; - linux*) - case $cc_basename in - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - _LT_TAGVAR(ld_shlibs, $1)=yes - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out @@ -5827,7 +5374,7 @@ newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; @@ -5835,19 +5382,27 @@ *nto* | *qnx*) ;; - openbsd* | bitrig*) + openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac fi else _LT_TAGVAR(ld_shlibs, $1)=no @@ -5858,53 +5413,33 @@ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - shrext_cmds=.dll - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) - if test yes = "$GCC"; then - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag - if test yes = "$GCC"; then - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -5915,24 +5450,24 @@ solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' - if test yes = "$GCC"; then - wlarc='$wl' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' - _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) - wlarc='$wl' - _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi @@ -5942,11 +5477,11 @@ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. GCC discards it without '$wl', + # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - if test yes = "$GCC"; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi @@ -5956,10 +5491,10 @@ ;; sunos4*) - if test sequent = "$host_vendor"; then + if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -6008,43 +5543,43 @@ ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not + # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' - if test yes = "$GCC"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; @@ -6059,17 +5594,17 @@ ;; esac - if test sni = "$host_vendor"; then + if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) -test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld @@ -6086,7 +5621,7 @@ # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - if test yes,yes = "$GCC,$enable_shared"; then + if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -6166,12 +5701,12 @@ _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], - [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], - [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is - "absolute", i.e impossible to change by setting $shlibpath_var if the + "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR @@ -6212,10 +5747,10 @@ # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to 'libtool'. +# the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl -lt_save_CC=$CC +lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. @@ -6255,18 +5790,18 @@ LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB - # Report what library types will actually be built + # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test no = "$can_build_shared" && enable_shared=no + test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test yes = "$enable_shared" && enable_static=no + test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' @@ -6274,12 +5809,8 @@ ;; aix[[4-9]]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no fi ;; esac @@ -6287,13 +5818,13 @@ AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes + test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP -CC=$lt_save_CC +CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG @@ -6301,14 +5832,14 @@ # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to 'libtool'. +# the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl -if test -n "$CXX" && ( test no != "$CXX" && - ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || - (test g++ != "$CXX"))); then +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes @@ -6350,7 +5881,7 @@ # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_caught_CXX_error"; then +if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" @@ -6392,35 +5923,35 @@ if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately - if test yes = "$GXX"; then + if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi - if test yes = "$GXX"; then + if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. - if test yes = "$with_gnu_ld"; then - _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) - wlarc='$wl' + wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi @@ -6456,30 +5987,18 @@ _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag= + no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive + # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in @@ -6489,13 +6008,6 @@ ;; esac done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi ;; esac @@ -6514,21 +6026,13 @@ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - ;; - esac + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' - if test yes = "$GXX"; then + if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` + collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -6546,84 +6050,64 @@ fi esac shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag=$shared_flag' $wl-G' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' else # not using gcc - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' else - shared_flag='$wl-bM:SRE' + shared_flag='${wl}-bM:SRE' fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' fi fi - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. - # The "-G" linker flag allows undefined symbols. - _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else - if test ia64 = "$host_cpu"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' - if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared - # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; @@ -6633,7 +6117,7 @@ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -6661,58 +6145,57 @@ # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll + shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - func_to_tool_file "$lt_outputfile"~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -6723,34 +6206,6 @@ _LT_DARWIN_LINKER_FEATURES($1) ;; - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - shrext_cmds=.dll - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - dgux*) case $cc_basename in ec++*) @@ -6786,14 +6241,14 @@ ;; haiku*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default @@ -6805,7 +6260,7 @@ _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. @@ -6814,11 +6269,11 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test yes = "$GXX"; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no @@ -6828,15 +6283,15 @@ ;; hpux10*|hpux11*) - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi @@ -6862,13 +6317,13 @@ aCC*) case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists @@ -6879,20 +6334,20 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test yes = "$GXX"; then - if test no = "$with_gnu_ld"; then + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi @@ -6907,22 +6362,22 @@ interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is @@ -6931,17 +6386,17 @@ _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) - if test yes = "$GXX"; then - if test no = "$with_gnu_ld"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; @@ -6954,8 +6409,8 @@ # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. @@ -6964,10 +6419,10 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. @@ -6981,59 +6436,59 @@ # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac - _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ - $RANLIB $oldlib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -7047,18 +6502,18 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' - _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) @@ -7066,10 +6521,10 @@ *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on @@ -7127,17 +6582,22 @@ _LT_TAGVAR(ld_shlibs, $1)=yes ;; - openbsd* | bitrig*) + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' - _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else @@ -7153,9 +6613,9 @@ # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using @@ -7173,17 +6633,17 @@ cxx*) case $host in osf3*) - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ - $RM $lib.exp' + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac @@ -7198,21 +6658,21 @@ # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) - if test yes,no = "$GXX,$with_gnu_ld"; then - _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists @@ -7258,9 +6718,9 @@ # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no @@ -7268,7 +6728,7 @@ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. + # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; @@ -7285,30 +6745,30 @@ ;; gcx*) # Green Hills C++ Compiler - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker - if test yes,no = "$GXX,$with_gnu_ld"; then - _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else - # g++ 2.7 appears to require '-G' NOT '-shared' on this + # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. - _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when @@ -7316,11 +6776,11 @@ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) - _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi @@ -7329,52 +6789,52 @@ ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not + # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ - '"$_LT_TAGVAR(old_archive_cmds, $1)" + '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ - '"$_LT_TAGVAR(reload_cmds, $1)" + '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; @@ -7405,10 +6865,10 @@ esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) - test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - _LT_TAGVAR(GCC, $1)=$GXX - _LT_TAGVAR(LD, $1)=$LD + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -7435,7 +6895,7 @@ lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test yes != "$_lt_caught_CXX_error" +fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG @@ -7457,14 +6917,13 @@ AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { - case @S|@2 in - .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; - *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF - # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose @@ -7548,13 +7007,13 @@ pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do - case $prev$p in + case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. - if test x-L = "$p" || - test x-R = "$p"; then + if test $p = "-L" || + test $p = "-R"; then prev=$p continue fi @@ -7570,16 +7029,16 @@ case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac - if test no = "$pre_test_object_deps_done"; then - case $prev in + if test "$pre_test_object_deps_done" = no; then + case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then - _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else - _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being @@ -7587,9 +7046,9 @@ esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then - _LT_TAGVAR(postdeps, $1)=$prev$p + _LT_TAGVAR(postdeps, $1)="${prev}${p}" else - _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= @@ -7604,15 +7063,15 @@ continue fi - if test no = "$pre_test_object_deps_done"; then + if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then - _LT_TAGVAR(predep_objects, $1)=$p + _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then - _LT_TAGVAR(postdep_objects, $1)=$p + _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi @@ -7643,6 +7102,51 @@ _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; esac ]) @@ -7651,7 +7155,7 @@ esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then - _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) @@ -7671,10 +7175,10 @@ # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. +# to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) -if test -z "$F77" || test no = "$F77"; then +if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi @@ -7711,7 +7215,7 @@ # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_disable_F77"; then +if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t @@ -7733,7 +7237,7 @@ _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. - lt_save_CC=$CC + lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} @@ -7747,25 +7251,21 @@ AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test no = "$can_build_shared" && enable_shared=no + test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test yes = "$enable_shared" && enable_static=no + test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no fi ;; esac @@ -7773,11 +7273,11 @@ AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes + test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) - _LT_TAGVAR(GCC, $1)=$G77 - _LT_TAGVAR(LD, $1)=$LD + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -7794,9 +7294,9 @@ fi # test -n "$compiler" GCC=$lt_save_GCC - CC=$lt_save_CC - CFLAGS=$lt_save_CFLAGS -fi # test yes != "$_lt_disable_F77" + CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" +fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG @@ -7806,11 +7306,11 @@ # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. +# to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) -if test -z "$FC" || test no = "$FC"; then +if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi @@ -7847,7 +7347,7 @@ # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. -if test yes != "$_lt_disable_FC"; then +if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t @@ -7869,7 +7369,7 @@ _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. - lt_save_CC=$CC + lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} @@ -7885,25 +7385,21 @@ AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) - test no = "$can_build_shared" && enable_shared=no + test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test yes = "$enable_shared" && enable_static=no + test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no fi ;; esac @@ -7911,11 +7407,11 @@ AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes + test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) - _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu - _LT_TAGVAR(LD, $1)=$LD + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -7935,7 +7431,7 @@ GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS -fi # test yes != "$_lt_disable_FC" +fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG @@ -7945,7 +7441,7 @@ # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. +# to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE @@ -7979,7 +7475,7 @@ CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)=$LD +_LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. @@ -8016,7 +7512,7 @@ # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. +# to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE @@ -8050,7 +7546,7 @@ CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)=$LD +_LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. @@ -8087,7 +7583,7 @@ # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to 'libtool'. +# to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE @@ -8103,7 +7599,7 @@ lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests -lt_simple_link_test_code=$lt_simple_compile_test_code +lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER @@ -8113,7 +7609,7 @@ _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. -lt_save_CC=$CC +lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= @@ -8142,7 +7638,7 @@ [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) - test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) @@ -8253,7 +7749,7 @@ # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f "$lt_ac_sed" && continue + test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in @@ -8270,9 +7766,9 @@ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough - test 10 -lt "$lt_ac_count" && break + test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` - if test "$lt_ac_count" -gt "$lt_ac_max"; then + if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi @@ -8296,7 +7792,27 @@ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], -[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false @@ -8320,9 +7836,102 @@ ])# _LT_CHECK_SHELL_FEATURES +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) + + +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) + + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) + + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) + + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi + +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) + + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) + # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- -# Determine what file name conversion functions should be used by +# Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], diff -Nru nghttp2-1.13.0/m4/libxml2.m4 nghttp2-0.6.7/m4/libxml2.m4 --- nghttp2-1.13.0/m4/libxml2.m4 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/m4/libxml2.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,188 +0,0 @@ -# Configure paths for LIBXML2 -# Mike Hommey 2004-06-19 -# use CPPFLAGS instead of CFLAGS -# Toshio Kuratomi 2001-04-21 -# Adapted from: -# Configure paths for GLIB -# Owen Taylor 97-11-3 - -dnl AM_PATH_XML2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) -dnl Test for XML, and define XML_CPPFLAGS and XML_LIBS -dnl -AC_DEFUN([AM_PATH_XML2],[ -AC_ARG_WITH(xml-prefix, - [ --with-xml-prefix=PFX Prefix where libxml is installed (optional)], - xml_config_prefix="$withval", xml_config_prefix="") -AC_ARG_WITH(xml-exec-prefix, - [ --with-xml-exec-prefix=PFX Exec prefix where libxml is installed (optional)], - xml_config_exec_prefix="$withval", xml_config_exec_prefix="") -AC_ARG_ENABLE(xmltest, - [ --disable-xmltest Do not try to compile and run a test LIBXML program],, - enable_xmltest=yes) - - if test x$xml_config_exec_prefix != x ; then - xml_config_args="$xml_config_args" - if test x${XML2_CONFIG+set} != xset ; then - XML2_CONFIG=$xml_config_exec_prefix/bin/xml2-config - fi - fi - if test x$xml_config_prefix != x ; then - xml_config_args="$xml_config_args --prefix=$xml_config_prefix" - if test x${XML2_CONFIG+set} != xset ; then - XML2_CONFIG=$xml_config_prefix/bin/xml2-config - fi - fi - - AC_PATH_PROG(XML2_CONFIG, xml2-config, no) - min_xml_version=ifelse([$1], ,2.0.0,[$1]) - AC_MSG_CHECKING(for libxml - version >= $min_xml_version) - no_xml="" - if test "$XML2_CONFIG" = "no" ; then - no_xml=yes - else - XML_CPPFLAGS=`$XML2_CONFIG $xml_config_args --cflags` - XML_LIBS=`$XML2_CONFIG $xml_config_args --libs` - xml_config_major_version=`$XML2_CONFIG $xml_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - xml_config_minor_version=`$XML2_CONFIG $xml_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - xml_config_micro_version=`$XML2_CONFIG $xml_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - if test "x$enable_xmltest" = "xyes" ; then - ac_save_CPPFLAGS="$CPPFLAGS" - ac_save_LIBS="$LIBS" - CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" - LIBS="$XML_LIBS $LIBS" -dnl -dnl Now check if the installed libxml is sufficiently new. -dnl (Also sanity checks the results of xml2-config to some extent) -dnl - rm -f conf.xmltest - AC_TRY_RUN([ -#include -#include -#include -#include - -int -main() -{ - int xml_major_version, xml_minor_version, xml_micro_version; - int major, minor, micro; - char *tmp_version; - - system("touch conf.xmltest"); - - /* Capture xml2-config output via autoconf/configure variables */ - /* HP/UX 9 (%@#!) writes to sscanf strings */ - tmp_version = (char *)strdup("$min_xml_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string from xml2-config\n", "$min_xml_version"); - exit(1); - } - free(tmp_version); - - /* Capture the version information from the header files */ - tmp_version = (char *)strdup(LIBXML_DOTTED_VERSION); - if (sscanf(tmp_version, "%d.%d.%d", &xml_major_version, &xml_minor_version, &xml_micro_version) != 3) { - printf("%s, bad version string from libxml includes\n", "LIBXML_DOTTED_VERSION"); - exit(1); - } - free(tmp_version); - - /* Compare xml2-config output to the libxml headers */ - if ((xml_major_version != $xml_config_major_version) || - (xml_minor_version != $xml_config_minor_version) || - (xml_micro_version != $xml_config_micro_version)) - { - printf("*** libxml header files (version %d.%d.%d) do not match\n", - xml_major_version, xml_minor_version, xml_micro_version); - printf("*** xml2-config (version %d.%d.%d)\n", - $xml_config_major_version, $xml_config_minor_version, $xml_config_micro_version); - return 1; - } -/* Compare the headers to the library to make sure we match */ - /* Less than ideal -- doesn't provide us with return value feedback, - * only exits if there's a serious mismatch between header and library. - */ - LIBXML_TEST_VERSION; - - /* Test that the library is greater than our minimum version */ - if ((xml_major_version > major) || - ((xml_major_version == major) && (xml_minor_version > minor)) || - ((xml_major_version == major) && (xml_minor_version == minor) && - (xml_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** An old version of libxml (%d.%d.%d) was found.\n", - xml_major_version, xml_minor_version, xml_micro_version); - printf("*** You need a version of libxml newer than %d.%d.%d. The latest version of\n", - major, minor, micro); - printf("*** libxml is always available from ftp://ftp.xmlsoft.org.\n"); - printf("***\n"); - printf("*** If you have already installed a sufficiently new version, this error\n"); - printf("*** probably means that the wrong copy of the xml2-config shell script is\n"); - printf("*** being found. The easiest way to fix this is to remove the old version\n"); - printf("*** of LIBXML, but you can also set the XML2_CONFIG environment to point to the\n"); - printf("*** correct copy of xml2-config. (In this case, you will have to\n"); - printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); - printf("*** so that the correct libraries are found at run-time))\n"); - } - return 1; -} -],, no_xml=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CPPFLAGS="$ac_save_CPPFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - - if test "x$no_xml" = x ; then - AC_MSG_RESULT(yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "$XML2_CONFIG" = "no" ; then - echo "*** The xml2-config script installed by LIBXML could not be found" - echo "*** If libxml was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the XML2_CONFIG environment variable to the" - echo "*** full path to xml2-config." - else - if test -f conf.xmltest ; then - : - else - echo "*** Could not run libxml test program, checking why..." - CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" - LIBS="$LIBS $XML_LIBS" - AC_TRY_LINK([ -#include -#include -], [ LIBXML_TEST_VERSION; return 0;], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding LIBXML or finding the wrong" - echo "*** version of LIBXML. If it is not finding LIBXML, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means LIBXML was incorrectly installed" - echo "*** or that you have moved LIBXML since it was installed. In the latter case, you" - echo "*** may want to edit the xml2-config script: $XML2_CONFIG" ]) - CPPFLAGS="$ac_save_CPPFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - - XML_CPPFLAGS="" - XML_LIBS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(XML_CPPFLAGS) - AC_SUBST(XML_LIBS) - rm -f conf.xmltest -]) diff -Nru nghttp2-1.13.0/m4/lt~obsolete.m4 nghttp2-0.6.7/m4/lt~obsolete.m4 --- nghttp2-1.13.0/m4/lt~obsolete.m4 2016-07-21 13:47:58.000000000 +0000 +++ nghttp2-0.6.7/m4/lt~obsolete.m4 2014-11-30 14:15:30.000000000 +0000 @@ -1,7 +1,6 @@ # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # -# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software -# Foundation, Inc. +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives @@ -12,7 +11,7 @@ # These exist entirely to fool aclocal when bootstrapping libtool. # -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # @@ -26,7 +25,7 @@ # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until diff -Nru nghttp2-1.13.0/m4/ltoptions.m4 nghttp2-0.6.7/m4/ltoptions.m4 --- nghttp2-1.13.0/m4/ltoptions.m4 2016-07-21 13:47:58.000000000 +0000 +++ nghttp2-0.6.7/m4/ltoptions.m4 2014-11-30 14:15:30.000000000 +0000 @@ -1,14 +1,14 @@ # Helper functions for option handling. -*- Autoconf -*- # -# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software -# Foundation, Inc. +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# serial 8 ltoptions.m4 +# serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) @@ -29,7 +29,7 @@ [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), - [m4_warning([Unknown $1 option '$2'])])[]dnl + [m4_warning([Unknown $1 option `$2'])])[]dnl ]) @@ -75,15 +75,13 @@ dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither - dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], - [_LT_ENABLE_FAST_INSTALL]) - _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], - [_LT_WITH_AIX_SONAME([aix])]) + [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS @@ -114,7 +112,7 @@ [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the 'dlopen' option into LT_INIT's first parameter.]) +put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -150,7 +148,7 @@ _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the 'win32-dll' option into LT_INIT's first parameter.]) +put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -159,9 +157,9 @@ # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- -# implement the --enable-shared flag, and supports the 'shared' and -# 'disable-shared' LT_INIT options. -# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], @@ -174,14 +172,14 @@ *) enable_shared=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done - IFS=$lt_save_ifs + IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) @@ -213,9 +211,9 @@ # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- -# implement the --enable-static flag, and support the 'static' and -# 'disable-static' LT_INIT options. -# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], @@ -228,14 +226,14 @@ *) enable_static=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done - IFS=$lt_save_ifs + IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) @@ -267,9 +265,9 @@ # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- -# implement the --enable-fast-install flag, and support the 'fast-install' -# and 'disable-fast-install' LT_INIT options. -# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], @@ -282,14 +280,14 @@ *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done - IFS=$lt_save_ifs + IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) @@ -306,14 +304,14 @@ [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put -the 'fast-install' option into LT_INIT's first parameter.]) +the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put -the 'disable-fast-install' option into LT_INIT's first parameter.]) +the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: @@ -321,64 +319,11 @@ dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) -# _LT_WITH_AIX_SONAME([DEFAULT]) -# ---------------------------------- -# implement the --with-aix-soname flag, and support the `aix-soname=aix' -# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT -# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. -m4_define([_LT_WITH_AIX_SONAME], -[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl -shared_archive_member_spec= -case $host,$enable_shared in -power*-*-aix[[5-9]]*,yes) - AC_MSG_CHECKING([which variant of shared library versioning to provide]) - AC_ARG_WITH([aix-soname], - [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], - [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], - [case $withval in - aix|svr4|both) - ;; - *) - AC_MSG_ERROR([Unknown argument to --with-aix-soname]) - ;; - esac - lt_cv_with_aix_soname=$with_aix_soname], - [AC_CACHE_VAL([lt_cv_with_aix_soname], - [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) - with_aix_soname=$lt_cv_with_aix_soname]) - AC_MSG_RESULT([$with_aix_soname]) - if test aix != "$with_aix_soname"; then - # For the AIX way of multilib, we name the shared archive member - # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', - # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. - # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, - # the AIX toolchain works better with OBJECT_MODE set (default 32). - if test 64 = "${OBJECT_MODE-32}"; then - shared_archive_member_spec=shr_64 - else - shared_archive_member_spec=shr - fi - fi - ;; -*) - with_aix_soname=aix - ;; -esac - -_LT_DECL([], [shared_archive_member_spec], [0], - [Shared archive member basename, for filename based shared library versioning on AIX])dnl -])# _LT_WITH_AIX_SONAME - -LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) -LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) -LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) - - # _LT_WITH_PIC([MODE]) # -------------------- -# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. -# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], @@ -389,17 +334,19 @@ *) pic_mode=default # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done - IFS=$lt_save_ifs + IFS="$lt_save_ifs" ;; esac], - [pic_mode=m4_default([$1], [default])]) + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC @@ -412,7 +359,7 @@ [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you -put the 'pic-only' option into LT_INIT's first parameter.]) +put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: diff -Nru nghttp2-1.13.0/m4/ltsugar.m4 nghttp2-0.6.7/m4/ltsugar.m4 --- nghttp2-1.13.0/m4/ltsugar.m4 2016-07-21 13:47:58.000000000 +0000 +++ nghttp2-0.6.7/m4/ltsugar.m4 2014-11-30 14:15:30.000000000 +0000 @@ -1,7 +1,6 @@ # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # -# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software -# Foundation, Inc. +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives @@ -34,7 +33,7 @@ # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support -# Autoconf-2.59, which quotes differently. +# Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], @@ -45,7 +44,7 @@ # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ -# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different diff -Nru nghttp2-1.13.0/m4/ltversion.m4 nghttp2-0.6.7/m4/ltversion.m4 --- nghttp2-1.13.0/m4/ltversion.m4 2016-07-21 13:47:58.000000000 +0000 +++ nghttp2-0.6.7/m4/ltversion.m4 2014-11-30 14:15:30.000000000 +0000 @@ -1,6 +1,6 @@ # ltversion.m4 -- version numbers -*- Autoconf -*- # -# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives @@ -9,15 +9,15 @@ # @configure_input@ -# serial 4179 ltversion.m4 +# serial 3337 ltversion.m4 # This file is part of GNU Libtool -m4_define([LT_PACKAGE_VERSION], [2.4.6]) -m4_define([LT_PACKAGE_REVISION], [2.4.6]) +m4_define([LT_PACKAGE_VERSION], [2.4.2]) +m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.4.6' -macro_revision='2.4.6' +[macro_version='2.4.2' +macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) diff -Nru nghttp2-1.13.0/Makefile.am nghttp2-0.6.7/Makefile.am --- nghttp2-1.13.0/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -20,34 +20,16 @@ # 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. -SUBDIRS = lib third-party src examples python tests integration-tests \ - doc contrib script - -# Now with python setuptools, make uninstall will leave many files we -# cannot easily remove (e.g., easy-install.pth). Disable it for -# distcheck rule. -AM_DISTCHECK_CONFIGURE_FLAGS = --disable-python-bindings +SUBDIRS = lib third-party src examples python tests doc contrib ACLOCAL_AMFLAGS = -I m4 dist_doc_DATA = README.rst EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-make \ - Dockerfile.android \ - cmakeconfig.h.in \ - CMakeLists.txt \ - CMakeOptions.txt \ - cmake/FindSpdylay.cmake \ - cmake/ExtractValidFlags.cmake \ - cmake/FindJemalloc.cmake \ - cmake/FindLibev.cmake \ - cmake/FindCUnit.cmake \ - cmake/Version.cmake \ - cmake/FindCython.cmake \ - cmake/FindLibevent.cmake \ - cmake/FindJansson.cmake + Dockerfile.android -.PHONY: clang-format +.PONY: clang-format # Format source files using clang-format. Don't format source files # under third-party directory since we are not responsible for thier diff -Nru nghttp2-1.13.0/Makefile.in nghttp2-0.6.7/Makefile.in --- nghttp2-1.13.0/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/Makefile.in 2014-11-30 14:15:34.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -30,17 +30,7 @@ # included in all copies or substantial portions of the Software. VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -105,6 +95,13 @@ host_triplet = @host@ target_triplet = @target@ subdir = . +DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ + $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/configure $(am__configure_deps) \ + $(srcdir)/config.h.in \ + $(top_srcdir)/lib/includes/nghttp2/nghttp2ver.h.in \ + $(dist_doc_DATA) COPYING compile config.guess config.sub \ + install-sh missing ltmain.sh ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -114,14 +111,11 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ - $(am__configure_deps) $(dist_doc_DATA) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d @@ -214,10 +208,6 @@ CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) -am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ - $(top_srcdir)/lib/includes/nghttp2/nghttp2ver.h.in AUTHORS \ - COPYING ChangeLog INSTALL NEWS README compile config.guess \ - config.sub install-sh ltmain.sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -263,7 +253,6 @@ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -282,7 +271,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -298,7 +286,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -314,10 +301,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -329,7 +312,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -367,11 +349,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -426,7 +407,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -447,30 +427,11 @@ # 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. -SUBDIRS = lib third-party src examples python tests integration-tests \ - doc contrib script - - -# Now with python setuptools, make uninstall will leave many files we -# cannot easily remove (e.g., easy-install.pth). Disable it for -# distcheck rule. -AM_DISTCHECK_CONFIGURE_FLAGS = --disable-python-bindings +SUBDIRS = lib third-party src examples python tests doc contrib ACLOCAL_AMFLAGS = -I m4 dist_doc_DATA = README.rst EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-make \ - Dockerfile.android \ - cmakeconfig.h.in \ - CMakeLists.txt \ - CMakeOptions.txt \ - cmake/FindSpdylay.cmake \ - cmake/ExtractValidFlags.cmake \ - cmake/FindJemalloc.cmake \ - cmake/FindLibev.cmake \ - cmake/FindCUnit.cmake \ - cmake/Version.cmake \ - cmake/FindCython.cmake \ - cmake/FindLibevent.cmake \ - cmake/FindJansson.cmake + Dockerfile.android all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -491,6 +452,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -744,15 +706,15 @@ $(am__post_remove_distdir) dist-tarZ: distdir - @echo WARNING: "Support for distribution archives compressed with" \ - "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir - @echo WARNING: "Support for shar distribution archives is" \ - "deprecated." >&2 + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) @@ -788,17 +750,17 @@ esac chmod -R a-w $(distdir) chmod u+w $(distdir) - mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build/sub \ - && ../../configure \ + && $(am__cd) $(distdir)/_build \ + && ../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ - --srcdir=../.. --prefix="$$dc_install_base" \ + --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -978,10 +940,8 @@ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-dist_docDATA -.PRECIOUS: Makefile - -.PHONY: clang-format +.PONY: clang-format # Format source files using clang-format. Don't format source files # under third-party directory since we are not responsible for thier diff -Nru nghttp2-1.13.0/missing nghttp2-0.6.7/missing --- nghttp2-1.13.0/missing 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/missing 2014-11-30 14:15:34.000000000 +0000 @@ -3,7 +3,7 @@ scriptversion=2013-10-28.13; # UTC -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify diff -Nru nghttp2-1.13.0/nghttpx.conf.sample nghttp2-0.6.7/nghttpx.conf.sample --- nghttp2-1.13.0/nghttpx.conf.sample 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/nghttpx.conf.sample 2014-11-30 14:15:07.000000000 +0000 @@ -10,7 +10,7 @@ # # * The options which do not take argument in the command-line *take* # argument in the configuration file. Specify 'yes' as argument -# (e.g., http2-proxy=yes). If other string is given, it disables the +# (e.g., spdy-proxy=yes). If other string is given, it disables the # option. # # * To specify private key and certificate file, use private-key-file @@ -25,5 +25,5 @@ # backend=127.0.0.1,80 # private-key-file=/path/to/server.key # certificate-file=/path/to/server.crt -# http2-proxy=no +# spdy-proxy=no # workers=1 diff -Nru nghttp2-1.13.0/python/CMakeLists.txt nghttp2-0.6.7/python/CMakeLists.txt --- nghttp2-1.13.0/python/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/python/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -# EXTRA_DIST = cnghttp2.pxd nghttp2.pyx - -if(ENABLE_PYTHON_BINDINGS) - add_custom_target(python ALL - COMMAND "${PYTHON_EXECUTABLE}" setup.py build - VERBATIM - DEPENDS nghttp2.c nghttp2 - ) - - configure_file(install-python.cmake.in install-python.cmake ESCAPE_QUOTES @ONLY) - install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/install-python.cmake") - - add_custom_command(OUTPUT nghttp2.c - COMMAND "${CYTHON_EXECUTABLE}" -o nghttp2.c - "${CMAKE_CURRENT_SOURCE_DIR}/nghttp2.pyx" - VERBATIM - DEPENDS nghttp2.pyx - ) - - # Instead of calling "setup.py clean --all", this should do... - set_directory_properties(PROPERTIES - ADDITIONAL_MAKE_CLEAN_FILES "build;python_nghttp2.egg-info" - ) - -## This works also, except that the installation target is missing... -# include(UseCython) -# cython_add_module(python_nghttp2 nghttp2.pyx) -# set_target_properties(python_nghttp2 PROPERTIES -# OUTPUT_NAME nghttp2 -# ) -# target_include_directories(python_nghttp2 PRIVATE -# "${CMAKE_SOURCE_DIR}/lib" -# "${CMAKE_SOURCE_DIR}/lib/includes" -# "${CMAKE_BINARY_DIR}/lib/includes" -# ) -# target_link_libraries(python_nghttp2 -# nghttp2 -# ) -endif() diff -Nru nghttp2-1.13.0/python/cnghttp2.pxd nghttp2-0.6.7/python/cnghttp2.pxd --- nghttp2-1.13.0/python/cnghttp2.pxd 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/python/cnghttp2.pxd 2014-11-30 14:15:07.000000000 +0000 @@ -34,7 +34,6 @@ ctypedef enum nghttp2_error: NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE - NGHTTP2_ERR_DEFERRED ctypedef enum nghttp2_flag: NGHTTP2_FLAG_NONE @@ -250,7 +249,7 @@ int32_t stream_id int32_t weight uint8_t exclusive - + int nghttp2_submit_request(nghttp2_session *session, const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd, @@ -283,15 +282,8 @@ int nghttp2_session_terminate_session(nghttp2_session *session, uint32_t error_code) - int nghttp2_session_resume_data(nghttp2_session *session, - int32_t stream_id) - const char* nghttp2_strerror(int lib_error_code) - int nghttp2_session_check_server_session(nghttp2_session *session) - - int nghttp2_session_get_stream_remote_close(nghttp2_session *session, int32_t stream_id) - int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, size_t deflate_hd_table_bufsize_max) @@ -314,27 +306,56 @@ int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater, size_t hd_table_bufsize_max) - ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, - nghttp2_nv *nv_out, int *inflate_flags, - const uint8_t *input, size_t inlen, - int in_final) + ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, + nghttp2_nv *nv_out, int *inflate_flags, + uint8_t *input, size_t inlen, int in_final) int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) +cdef extern from 'nghttp2_helper.h': + + void nghttp2_free(void *ptr) + +cdef extern from 'nghttp2_frame.h': + + void nghttp2_nv_array_del(nghttp2_nv *nva) + +cdef extern from 'nghttp2_hd.h': + + # This is macro + int NGHTTP2_HD_ENTRY_OVERHEAD + ctypedef enum nghttp2_hd_inflate_flag: NGHTTP2_HD_INFLATE_EMIT NGHTTP2_HD_INFLATE_FINAL + ctypedef struct nghttp2_hd_entry: + nghttp2_nv nv + uint8_t flags + + ctypedef struct nghttp2_hd_ringbuf: + size_t len + + ctypedef struct nghttp2_hd_context: + nghttp2_hd_ringbuf hd_table + ctypedef struct nghttp2_hd_deflater: - pass + nghttp2_hd_context ctx ctypedef struct nghttp2_hd_inflater: - pass + nghttp2_hd_context ctx + + nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context, + size_t index) - size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater) +cdef extern from 'nghttp2_buf.h': + + ctypedef struct nghttp2_bufs: + pass - const nghttp2_nv * nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx) + void nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_size, + size_t max_chunk) - size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater) + void nghttp2_bufs_free(nghttp2_bufs *bufs) - const nghttp2_nv *nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx) + ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) diff -Nru nghttp2-1.13.0/python/install-python.cmake.in nghttp2-0.6.7/python/install-python.cmake.in --- nghttp2-1.13.0/python/install-python.cmake.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/python/install-python.cmake.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -get_filename_component(rootdir "$ENV{DESTDIR}" ABSOLUTE) -if(rootdir STREQUAL "") - set(rootdir /) -endif() -execute_process( - COMMAND "@PYTHON_EXECUTABLE@" setup.py install - --skip-build - --root=${rootdir} --prefix=${CMAKE_INSTALL_PREFIX} - WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@" -) diff -Nru nghttp2-1.13.0/python/Makefile.am nghttp2-0.6.7/python/Makefile.am --- nghttp2-1.13.0/python/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/python/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -25,7 +25,7 @@ # clean-local in parallel build. .NOTPARALLEL: -EXTRA_DIST = cnghttp2.pxd nghttp2.pyx CMakeLists.txt install-python.cmake.in +EXTRA_DIST = cnghttp2.pxd nghttp2.pyx if ENABLE_PYTHON_BINDINGS @@ -36,8 +36,7 @@ $(PYTHON) setup.py install --prefix=$(DESTDIR)$(prefix) uninstall-local: - rm -f $(DESTDIR)$(libdir)/python*/site-packages/nghttp2.so - rm -f $(DESTDIR)$(libdir)/python*/site-packages/python_nghttp2-*.egg + rm -rf $(DESTDIR)$(libdir)/python*/site-packages/*nghttp2* clean-local: $(PYTHON) setup.py clean --all diff -Nru nghttp2-1.13.0/python/Makefile.in nghttp2-0.6.7/python/Makefile.in --- nghttp2-1.13.0/python/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/python/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -37,17 +37,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -112,6 +102,8 @@ host_triplet = @host@ target_triplet = @target@ subdir = python +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(srcdir)/setup.py.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -121,13 +113,11 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = setup.py @@ -152,12 +142,10 @@ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/setup.py.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -176,7 +164,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -192,7 +179,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -208,10 +194,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -223,7 +205,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -261,11 +242,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -320,7 +300,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -333,7 +312,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -EXTRA_DIST = cnghttp2.pxd nghttp2.pyx CMakeLists.txt install-python.cmake.in +EXTRA_DIST = cnghttp2.pxd nghttp2.pyx all: all-am .SUFFIXES: @@ -350,6 +329,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu python/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu python/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -447,9 +427,9 @@ maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -@ENABLE_PYTHON_BINDINGS_FALSE@uninstall-local: @ENABLE_PYTHON_BINDINGS_FALSE@install-exec-local: @ENABLE_PYTHON_BINDINGS_FALSE@clean-local: +@ENABLE_PYTHON_BINDINGS_FALSE@uninstall-local: clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am @@ -531,8 +511,6 @@ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am uninstall-local -.PRECIOUS: Makefile - # This will avoid that setup.py gets deleted before it is executed in # clean-local in parallel build. @@ -545,8 +523,7 @@ @ENABLE_PYTHON_BINDINGS_TRUE@ $(PYTHON) setup.py install --prefix=$(DESTDIR)$(prefix) @ENABLE_PYTHON_BINDINGS_TRUE@uninstall-local: -@ENABLE_PYTHON_BINDINGS_TRUE@ rm -f $(DESTDIR)$(libdir)/python*/site-packages/nghttp2.so -@ENABLE_PYTHON_BINDINGS_TRUE@ rm -f $(DESTDIR)$(libdir)/python*/site-packages/python_nghttp2-*.egg +@ENABLE_PYTHON_BINDINGS_TRUE@ rm -rf $(DESTDIR)$(libdir)/python*/site-packages/*nghttp2* @ENABLE_PYTHON_BINDINGS_TRUE@clean-local: @ENABLE_PYTHON_BINDINGS_TRUE@ $(PYTHON) setup.py clean --all diff -Nru nghttp2-1.13.0/python/nghttp2.pyx nghttp2-0.6.7/python/nghttp2.pyx --- nghttp2-1.13.0/python/nghttp2.pyx 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/python/nghttp2.pyx 2014-11-30 14:15:07.000000000 +0000 @@ -31,7 +31,7 @@ DEFAULT_HEADER_TABLE_SIZE = cnghttp2.NGHTTP2_DEFAULT_HEADER_TABLE_SIZE DEFLATE_MAX_HEADER_TABLE_SIZE = 4096 -HD_ENTRY_OVERHEAD = 32 +HD_ENTRY_OVERHEAD = cnghttp2.NGHTTP2_HD_ENTRY_OVERHEAD class HDTableEntry: @@ -44,6 +44,18 @@ def space(self): return self.namelen + self.valuelen + HD_ENTRY_OVERHEAD +cdef _get_hd_table(cnghttp2.nghttp2_hd_context *ctx): + cdef int length = ctx.hd_table.len + cdef cnghttp2.nghttp2_hd_entry *entry + res = [] + for i in range(length): + entry = cnghttp2.nghttp2_hd_table_get(ctx, i) + k = _get_pybytes(entry.nv.name, entry.nv.namelen) + v = _get_pybytes(entry.nv.value, entry.nv.valuelen) + res.append(HDTableEntry(k, entry.nv.namelen, + v, entry.nv.valuelen)) + return res + cdef _get_pybytes(uint8_t *b, uint16_t blen): return b[:blen] @@ -145,16 +157,7 @@ def get_hd_table(self): '''Returns copy of current dynamic header table.''' - cdef size_t length = cnghttp2.nghttp2_hd_deflate_get_num_table_entries( - self._deflater) - cdef const cnghttp2.nghttp2_nv *nv - res = [] - for i in range(62, length + 1): - nv = cnghttp2.nghttp2_hd_deflate_get_table_entry(self._deflater, i) - k = _get_pybytes(nv.name, nv.namelen) - v = _get_pybytes(nv.value, nv.valuelen) - res.append(HDTableEntry(k, nv.namelen, v, nv.valuelen)) - return res + return _get_hd_table(&self._deflater.ctx) cdef class HDInflater: '''Performs header decompression. @@ -191,9 +194,9 @@ res = [] while True: inflate_flags = 0 - rv = cnghttp2.nghttp2_hd_inflate_hd2(self._inflater, &nv, - &inflate_flags, - buf, buflen, 1) + rv = cnghttp2.nghttp2_hd_inflate_hd(self._inflater, &nv, + &inflate_flags, + buf, buflen, 1) if rv < 0: raise Exception(_strerror(rv)) buf += rv @@ -221,16 +224,7 @@ def get_hd_table(self): '''Returns copy of current dynamic header table.''' - cdef size_t length = cnghttp2.nghttp2_hd_inflate_get_num_table_entries( - self._inflater) - cdef const cnghttp2.nghttp2_nv *nv - res = [] - for i in range(62, length + 1): - nv = cnghttp2.nghttp2_hd_inflate_get_table_entry(self._inflater, i) - k = _get_pybytes(nv.name, nv.namelen) - v = _get_pybytes(nv.value, nv.valuelen) - res.append(HDTableEntry(k, nv.namelen, v, nv.valuelen)) - return res + return _get_hd_table(&self._inflater.ctx) cdef _strerror(int liberror_code): return cnghttp2.nghttp2_strerror(liberror_code).decode('utf-8') @@ -264,35 +258,19 @@ except ImportError: asyncio = None -# body generator flags -DATA_OK = 0 -DATA_EOF = 1 -DATA_DEFERRED = 2 - -class _ByteIOWrapper: - - def __init__(self, b): - self.b = b - - def generate(self, n): - data = self.b.read1(n) - if not data: - return None, DATA_EOF - return data, DATA_OK - def wrap_body(body): if body is None: return body elif isinstance(body, str): - return _ByteIOWrapper(io.BytesIO(body.encode('utf-8'))).generate + return io.BytesIO(body.encode('utf-8')) elif isinstance(body, bytes): - return _ByteIOWrapper(io.BytesIO(body)).generate + return io.BytesIO(body) elif isinstance(body, io.IOBase): - return _ByteIOWrapper(body).generate - else: - # assume that callable in the form f(n) returning tuple byte - # string and flag. return body + else: + raise Exception(('body must be None or instance of str or ' + 'bytes or io.IOBase')) + cdef _get_stream_user_data(cnghttp2.nghttp2_session *session, int32_t stream_id): @@ -344,6 +322,8 @@ logging.debug('client_on_header, type:%s, stream_id:%s', frame.hd.type, frame.hd.stream_id) if frame.hd.type == cnghttp2.NGHTTP2_HEADERS: + if frame.headers.cat == cnghttp2.NGHTTP2_HCAT_REQUEST: + return 0 handler = _get_stream_user_data(session, frame.hd.stream_id) elif frame.hd.type == cnghttp2.NGHTTP2_PUSH_PROMISE: handler = _get_stream_user_data(session, frame.push_promise.promised_stream_id) @@ -420,6 +400,12 @@ handler = _get_stream_user_data(session, frame.hd.stream_id) if not handler: return 0 + # Check required header fields. We expect that :authority + # or host header field. + if handler.scheme is None or handler.method is None or\ + handler.host is None or handler.path is None: + return http2._rst_stream(frame.hd.stream_id, + cnghttp2.NGHTTP2_PROTOCOL_ERROR) if handler.cookies: handler.headers.append((b'cookie', b'; '.join(handler.cookies))) @@ -473,13 +459,6 @@ if (frame.hd.flags & cnghttp2.NGHTTP2_FLAG_ACK) != 0: return 0 http2._start_settings_timer() - elif frame.hd.type == cnghttp2.NGHTTP2_HEADERS: - if (frame.hd.flags & cnghttp2.NGHTTP2_FLAG_END_STREAM) and \ - cnghttp2.nghttp2_session_check_server_session(session): - # Send RST_STREAM if remote is not closed yet - if cnghttp2.nghttp2_session_get_stream_remote_close( - session, frame.hd.stream_id) == 0: - http2._rst_stream(frame.hd.stream_id, cnghttp2.NGHTTP2_NO_ERROR) cdef int server_on_frame_not_send(cnghttp2.nghttp2_session *session, const cnghttp2.nghttp2_frame *frame, @@ -517,44 +496,29 @@ return 0 -cdef ssize_t data_source_read(cnghttp2.nghttp2_session *session, - int32_t stream_id, - uint8_t *buf, size_t length, - uint32_t *data_flags, - cnghttp2.nghttp2_data_source *source, - void *user_data): - cdef http2 = <_HTTP2SessionCoreBase>user_data - generator = source.ptr +cdef ssize_t server_data_source_read(cnghttp2.nghttp2_session *session, + int32_t stream_id, + uint8_t *buf, size_t length, + uint32_t *data_flags, + cnghttp2.nghttp2_data_source *source, + void *user_data): + cdef http2 = <_HTTP2SessionCore>user_data + handler = source.ptr - http2.enter_callback() try: - data, flag = generator(length) + data = handler.response_body.read(length) except: sys.stderr.write(traceback.format_exc()) return cnghttp2.NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - finally: - http2.leave_callback() - - if flag == DATA_DEFERRED: - return cnghttp2.NGHTTP2_ERR_DEFERRED if data: nread = len(data) memcpy(buf, data, nread) - else: - nread = 0 + return nread - if flag == DATA_EOF: - data_flags[0] = cnghttp2.NGHTTP2_DATA_FLAG_EOF - if cnghttp2.nghttp2_session_check_server_session(session): - # Send RST_STREAM if remote is not closed yet - if cnghttp2.nghttp2_session_get_stream_remote_close( - session, stream_id) == 0: - http2._rst_stream(stream_id, cnghttp2.NGHTTP2_NO_ERROR) - elif flag != DATA_OK: - return cnghttp2.NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE + data_flags[0] = cnghttp2.NGHTTP2_DATA_FLAG_EOF - return nread + return 0 cdef int client_on_begin_headers(cnghttp2.nghttp2_session *session, const cnghttp2.nghttp2_frame *frame, @@ -587,12 +551,15 @@ sys.stderr.write(traceback.format_exc()) return http2._rst_stream(frame.hd.stream_id) elif frame.hd.type == cnghttp2.NGHTTP2_HEADERS: - if frame.headers.cat == cnghttp2.NGHTTP2_HCAT_RESPONSE or frame.headers.cat == cnghttp2.NGHTTP2_HCAT_PUSH_RESPONSE: + if frame.headers.cat == cnghttp2.NGHTTP2_HCAT_RESPONSE: handler = _get_stream_user_data(session, frame.hd.stream_id) if not handler: return 0 - # TODO handle 1xx non-final response + # Check required header fields. We expect a status. + if handler.status is None: + return http2._rst_stream(frame.hd.stream_id, + cnghttp2.NGHTTP2_PROTOCOL_ERROR) if handler.cookies: handler.headers.append((b'cookie', b'; '.join(handler.cookies))) @@ -620,6 +587,10 @@ cnghttp2.nghttp2_session_set_stream_user_data(session, frame.push_promise.promised_stream_id, NULL) + if push_handler.scheme is None or push_handler.method is None or\ + push_handler.host is None or push_handler.path is None: + return http2._rst_stream(frame.push_promise.promised_stream_id, + cnghttp2.NGHTTP2_PROTOCOL_ERROR) try: handler.on_push_promise(push_handler) except: @@ -639,13 +610,36 @@ return 0 http2._start_settings_timer() +cdef ssize_t client_data_source_read(cnghttp2.nghttp2_session *session, + int32_t stream_id, + uint8_t *buf, size_t length, + uint32_t *data_flags, + cnghttp2.nghttp2_data_source *source, + void *user_data): + cdef http2 = <_HTTP2ClientSessionCore>user_data + body = source.ptr + + try: + data = body.read(length) + except: + sys.stderr.write(traceback.format_exc()) + return cnghttp2.NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + + if data: + nread = len(data) + memcpy(buf, data, nread) + return nread + + data_flags[0] = cnghttp2.NGHTTP2_DATA_FLAG_EOF + + return 0 + cdef class _HTTP2SessionCoreBase: cdef cnghttp2.nghttp2_session *session cdef transport cdef handler_class cdef handlers cdef settings_timer - cdef inside_callback def __cinit__(self, transport, handler_class=None): self.session = NULL @@ -653,7 +647,6 @@ self.handler_class = handler_class self.handlers = set() self.settings_timer = None - self.inside_callback = False def __dealloc__(self): cnghttp2.nghttp2_session_del(self.session) @@ -690,17 +683,6 @@ cnghttp2.nghttp2_session_want_write(self.session) == 0: self.transport.close() - def resume(self, stream_id): - cnghttp2.nghttp2_session_resume_data(self.session, stream_id) - if not self.inside_callback: - self.send_data() - - def enter_callback(self): - self.inside_callback = True - - def leave_callback(self): - self.inside_callback = False - def _make_handler(self, stream_id): logging.debug('_make_handler, stream_id:%s', stream_id) handler = self.handler_class(self, stream_id) @@ -716,7 +698,6 @@ handler.stream_id = stream_id handler.http2 = self handler.remote_address = self._get_remote_address() - handler.client_certificate = self._get_client_certificate() self.handlers.add(handler) def _rst_stream(self, stream_id, @@ -732,13 +713,6 @@ def _get_remote_address(self): return self.transport.get_extra_info('peername') - def _get_client_certificate(self): - sock = self.transport.get_extra_info('socket') - try: - return sock.getpeercert() - except AttributeError: - return None - def _start_settings_timer(self): loop = asyncio.get_event_loop() self.settings_timer = loop.call_later(self.SETTINGS_TIMEOUT, @@ -856,8 +830,8 @@ nvlen = _make_nva(&nva, handler.response_headers) if handler.response_body: - prd.source.ptr = handler.response_body - prd.read_callback = data_source_read + prd.source.ptr = handler + prd.read_callback = server_data_source_read prd_ptr = &prd else: prd_ptr = NULL @@ -901,11 +875,6 @@ return promised_handler - def connection_lost(self): - for handler in self.handlers: - handler.on_close(cnghttp2.NGHTTP2_INTERNAL_ERROR) - self.handlers = set() - cdef class _HTTP2ClientSessionCore(_HTTP2SessionCoreBase): def __cinit__(self, *args, **kwargs): cdef cnghttp2.nghttp2_session_callbacks *callbacks @@ -965,21 +934,21 @@ body = wrap_body(body) - custom_headers = _encode_headers(headers) - headers = [ - (b':method', method.encode('utf-8')), - (b':scheme', scheme.encode('utf-8')), - (b':authority', host.encode('utf-8')), - (b':path', path.encode('utf-8')) - ] - headers.extend(custom_headers) + if headers is None: + headers = [] + + headers = _encode_headers(headers) + headers.append((b':scheme', scheme.encode('utf-8'))) + headers.append((b':method', method.encode('utf-8'))) + headers.append((b':authority', host.encode('utf-8'))) + headers.append((b':path', path.encode('utf-8'))) nva = NULL nvlen = _make_nva(&nva, headers) if body: prd.source.ptr = body - prd.read_callback = data_source_read + prd.read_callback = client_data_source_read prd_ptr = &prd else: prd_ptr = NULL @@ -1014,6 +983,7 @@ handler.method = push_promise.method handler.host = push_promise.host handler.path = push_promise.path + handler.headers = push_promise.headers handler.cookies = push_promise.cookies handler.stream_id = push_promise.stream_id handler.http2 = self @@ -1061,9 +1031,6 @@ Contains a tuple of the form (host, port) referring to the client's address. - client_certificate - May contain the client certifcate in its non-binary form - stream_id Stream ID of this stream @@ -1079,9 +1046,6 @@ path This is a value of :path header field. - headers - Request header fields - """ def __init__(self, http2, stream_id): @@ -1092,8 +1056,6 @@ self.http2 = http2 # address of the client self.remote_address = self.http2._get_remote_address() - # certificate of the client - self._client_certificate = self.http2._get_client_certificate() # :scheme header field in request self.scheme = None # :method header field in request @@ -1111,10 +1073,6 @@ def client_address(self): return self.remote_address - @property - def client_certificate(self): - return self._client_certificate - def on_headers(self): '''Called when request HEADERS is arrived. @@ -1150,26 +1108,8 @@ 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, 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 and flag. The flag is either DATA_OK, - DATA_EOF and DATA_DEFERRED. For non-empty byte string and - it is not the last chunk of response, DATA_OK is returned - as flag. If this is the last chunk of the response (byte - string is possibly None), DATA_EOF must be returned as - flag. If there is no data available right now, but - additional data are anticipated, return tuple (None, - DATA_DEFERRD). When data arrived, call resume() and - restart response body transmission. - - Only the body generator can pause response body - generation; instance of io.IOBase must not block. - - If instance of str is specified as body, it is encoded - using UTF-8. + instance of either str, bytes or io.IOBase. If instance of str + is specified, it is encoded using UTF-8. The headers is a list of tuple of the form (name, value). The name and value can be either unicode string or @@ -1202,9 +1142,11 @@ request_headers parameter). 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 has the - same semantics of body parameter of send_response(). + 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 headers and request_headers are a list of tuple of the form (name, value). The name and value can be either @@ -1232,15 +1174,16 @@ promised_handler.path = path.encode('utf-8') promised_handler._set_response_prop(status, headers, body) - headers = [ - (b':method', promised_handler.method), - (b':scheme', promised_handler.scheme), - (b':authority', promised_handler.host), - (b':path', promised_handler.path) - ] - headers.extend(_encode_headers(request_headers)) + if request_headers is None: + request_headers = [] + + request_headers = _encode_headers(request_headers) + request_headers.append((b':scheme', promised_handler.scheme)) + request_headers.append((b':method', promised_handler.method)) + request_headers.append((b':authority', promised_handler.host)) + request_headers.append((b':path', promised_handler.path)) - promised_handler.headers = headers + promised_handler.headers = request_headers return self.http2.push(self, promised_handler) @@ -1250,17 +1193,13 @@ if headers is None: headers = [] - self.response_headers = [(b':status', str(status).encode('utf-8'))] - self.response_headers.extend(_encode_headers(headers)) + self.response_headers = _encode_headers(headers) + self.response_headers.append((b':status', str(status)\ + .encode('utf-8'))) self.response_body = body - def resume(self): - self.http2.resume(self.stream_id) - def _encode_headers(headers): - if not headers: - return [] return [(k if isinstance(k, bytes) else k.encode('utf-8'), v if isinstance(v, bytes) else v.encode('utf-8')) \ for k, v in headers] @@ -1277,36 +1216,45 @@ logging.info('connection_made, address:%s, port:%s', address[0], address[1]) self.transport = transport + self.connection_header = cnghttp2.NGHTTP2_CLIENT_CONNECTION_PREFACE sock = self.transport.get_extra_info('socket') - try: - sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - except OSError as e: - logging.info('failed to set tcp-nodelay: %s', str(e)) + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) ssl_ctx = self.transport.get_extra_info('sslcontext') if ssl_ctx: protocol = sock.selected_npn_protocol() logging.info('npn, protocol:%s', protocol) - if protocol is None or protocol.encode('utf-8') != \ + if protocol.encode('utf-8') != \ cnghttp2.NGHTTP2_PROTO_VERSION_ID: self.transport.abort() - return - try: - self.http2 = _HTTP2SessionCore\ - (self.transport, - self.RequestHandlerClass) - except Exception as err: - sys.stderr.write(traceback.format_exc()) - self.transport.abort() - return - def connection_lost(self, exc): logging.info('connection_lost') if self.http2: - self.http2.connection_lost() self.http2 = None def data_received(self, data): + nread = min(len(data), len(self.connection_header)) + + if self.connection_header.startswith(data[:nread]): + data = data[nread:] + self.connection_header = self.connection_header[nread:] + if len(self.connection_header) == 0: + try: + self.http2 = _HTTP2SessionCore\ + (self.transport, + self.RequestHandlerClass) + except Exception as err: + sys.stderr.write(traceback.format_exc()) + self.transport.abort() + return + + self.data_received = self.data_received2 + self.resume_writing = self.resume_writing2 + self.data_received(data) + else: + self.transport.abort() + + def data_received2(self, data): try: self.http2.data_received(data) except Exception as err: @@ -1314,7 +1262,7 @@ self.transport.close() return - def resume_writing(self): + def resume_writing2(self): try: self.http2.send_data() except Exception as err: @@ -1381,8 +1329,7 @@ When whole response is received, on_response_done() is invoked. - When stream is closed or underlying connection is lost, - on_close(error_code) is called. + When stream is closed, on_close(error_code) is called. The application can send follow up requests using HTTP2Client.send_request() method. @@ -1409,11 +1356,6 @@ path This is a value of :path header field. - headers - Response header fields. There is a special exception. If this - object is passed to push_promise(), this instance variable contains - pushed request header fields. - """ def __init__(self, http2=None, stream_id=-1): @@ -1496,9 +1438,6 @@ ''' self.http2.push(push_promise, handler) - def resume(self): - self.http2.resume(self.stream_id) - class _HTTP2ClientSession(asyncio.Protocol): def __init__(self, client): @@ -1522,6 +1461,8 @@ cnghttp2.NGHTTP2_PROTO_VERSION_ID: self.transport.abort() + # Send preamble + self.transport.write(cnghttp2.NGHTTP2_CLIENT_CONNECTION_PREFACE) self.http2 = _HTTP2ClientSessionCore(self.transport) # Clear pending requests diff -Nru nghttp2-1.13.0/python/setup.py.in nghttp2-0.6.7/python/setup.py.in --- nghttp2-1.13.0/python/setup.py.in 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/python/setup.py.in 2014-11-30 14:15:07.000000000 +0000 @@ -21,9 +21,14 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -from setuptools import setup, Extension +import sys +from distutils.core import setup +from distutils.extension import Extension -LIBS = ['nghttp2'] +if sys.platform == "win32": + LIBS = ['nghttp2_imp', 'ws2_32'] +else: + LIBS = ['nghttp2'] setup( name = 'python-nghttp2', @@ -31,16 +36,14 @@ author = 'Tatsuhiro Tsujikawa', version = '@PACKAGE_VERSION@', author_email = 'tatsuhiro.t@gmail.com', - url = 'https://nghttp2.org/', + url = 'http://tatsuhiro-t.github.io/nghttp2/', keywords = [], ext_modules = [Extension("nghttp2", ["nghttp2.c"], include_dirs=['@top_srcdir@/lib', '@top_srcdir@/lib/includes', '@top_builddir@/lib/includes'], - library_dirs=['@top_builddir@/lib/.libs', - '@top_builddir@/lib', - '@top_builddir@'], + library_dirs=['@top_builddir@/lib/.libs'], libraries=LIBS)], long_description='TBD' ) diff -Nru nghttp2-1.13.0/README.rst nghttp2-0.6.7/README.rst --- nghttp2-1.13.0/README.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/README.rst 2014-11-30 14:15:07.000000000 +0000 @@ -1,46 +1,60 @@ nghttp2 - HTTP/2 C Library ========================== -This is an implementation of the Hypertext Transfer Protocol version 2 +This is an implementation of Hypertext Transfer Protocol version 2 in C. -The framing layer of HTTP/2 is implemented as a reusable C -library. On top of that, we have implemented an HTTP/2 client, server -and proxy. We have also developed load test and benchmarking tools for +The framing layer of HTTP/2 is implemented as a form of reusable C +library. On top of that, we have implemented HTTP/2 client, server +and proxy. We have also developed load test and benchmarking tool for HTTP/2 and SPDY. -An HPACK encoder and decoder are available as a public API. +HPACK encoder and decoder are available as public API. -An experimental high level C++ library is also available. +The experimental high level C++ library is also available. -We have Python bindings of this library, but we do not have full -code coverage yet. +We have Python binding of this libary, but we have not covered +everything yet. Development Status ------------------ -We have implemented `RFC 7540 `_ -HTTP/2 and `RFC 7541 `_ HPACK - -Header Compression for HTTP/2 - -The nghttp2 code base was forked from the spdylay -(https://github.com/tatsuhiro-t/spdylay) project. +We started to implement h2-14 +(http://tools.ietf.org/html/draft-ietf-httpbis-http2-14), the header +compression +(http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09) +and HTTP Alternative Services +(http://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-04). + +The nghttp2 code base was forked from spdylay project. + +=========================== ======= +HTTP/2 Features Support +=========================== ======= +Core frames handling Yes +Dependency Tree Yes +Large header (CONTINUATION) Yes +ALTSVC extension Yes +=========================== ======= Public Test Server ------------------ -The following endpoints are available to try out our nghttp2 +The following endpoints are available to try out nghttp2 implementation. * https://nghttp2.org/ (TLS + ALPN/NPN) - This endpoint supports ``h2``, ``h2-16``, ``h2-14``, ``spdy/3.1`` - and ``http/1.1`` via ALPN/NPN and requires TLSv1.2 for HTTP/2 - connection. + NPN offer ``h2-14``, ``spdy/3.1`` and ``http/1.1``. + + This endpoint requires TLSv1.2 for HTTP/2 connection. -* http://nghttp2.org/ (HTTP Upgrade and HTTP/2 Direct) +* http://nghttp2.org/ (Upgrade / Direct) + + ``h2c-14`` and ``http/1.1``. We configured this server to send + ALTSVC frame or Alt-Svc header field to announce that alternative + service is available at port 443. - ``h2c`` and ``http/1.1``. Requirements ------------ @@ -58,22 +72,20 @@ * sphinx (http://sphinx-doc.org/) -To build and run the application programs (``nghttp``, ``nghttpd``, -``nghttpx`` and ``h2load``) in the ``src`` directory, the following packages -are required: +To build and run the application programs (``nghttp``, ``nghttpd`` and +``nghttpx``) in ``src`` directory, the following packages are +required: * OpenSSL >= 1.0.1 -* libev >= 4.11 +* libevent-openssl >= 2.0.8 * zlib >= 1.2.3 -ALPN support requires OpenSSL >= 1.0.2 (released 22 January 2015). -LibreSSL >= 2.2.0 can be used instead of OpenSSL, but OpenSSL has more -features than LibreSSL at the time of this writing. +ALPN support requires unreleased version OpenSSL >= 1.0.2. -To enable the SPDY protocol in the application program ``nghttpx`` and +To enable SPDY protocol in the application program ``nghttpx`` and ``h2load``, the following package is required: -* spdylay >= 1.3.2 +* spdylay >= 1.3.0 To enable ``-a`` option (getting linked assets from the downloaded resource) in ``nghttp``, the following package is required: @@ -84,10 +96,6 @@ * jansson >= 2.5 -To build sources under the examples directory, libevent is required: - -* libevent-openssl >= 2.0.8 - To mitigate heap fragmentation in long running server programs (``nghttpd`` and ``nghttpx``), jemalloc is recommended: @@ -102,47 +110,35 @@ * cython >= 0.19 * python >= 2.7 -* python-setuptools -If you are using Ubuntu 14.04 LTS (trusty) or Debian 7.0 (wheezy) and above run the following to install the needed packages: +If you are using Ubuntu 14.04 LTS, you need the following packages +installed: -.. code-block:: text +* make +* binutils +* autoconf +* automake +* autotools-dev +* libtool +* pkg-config +* zlib1g-dev +* libcunit1-dev +* libssl-dev +* libxml2-dev +* libevent-dev +* libjansson-dev +* libjemalloc-dev +* cython +* python3.4-dev - sudo apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config \ - zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \ - libjemalloc-dev cython python3-dev python-setuptools - -From Ubuntu 15.10, spdylay has been available as a package named -`libspdylay-dev`. For the earlier Ubuntu release, you need to build -it yourself: http://tatsuhiro-t.github.io/spdylay/ - -To enable mruby support for nghttpx, `mruby -`_ is required. We need to build -mruby with C++ ABI explicitly turned on, and probably need other -mrgems, mruby is manged by git submodule under third-party/mruby -directory. Currently, mruby support for nghttpx is disabled by -default. To enable mruby support, use ``--with-mruby`` configure -option. Note that at the time of this writing, libmruby-dev and mruby -packages in Debian/Ubuntu are not usable for nghttp2, since they do -not enable C++ ABI. To build mruby, the following packages are -required: - -* ruby -* bison +spdylay is not packaged in Ubuntu, so you need to build it yourself: +http://tatsuhiro-t.github.io/spdylay/ -nghttpx supports `neverbleed `_, -privilege separation engine for OpenSSL / LibreSSL. In short, it -minimizes the risk of private key leakage when serious bug like -Heartbleed is exploited. The neverbleed is disabled by default. To -enable it, use ``--with-neverbleed`` configure option. - -Building from git ------------------ +Build from git +-------------- Building from git is easy, but please be sure that at least autoconf 2.68 is -used: - -.. code-block:: text +used:: $ autoreconf -i $ automake @@ -150,88 +146,23 @@ $ ./configure $ make -To compile the source code, gcc >= 4.8.3 or clang >= 3.4 is required. - -.. note:: - - To enable mruby support in nghttpx, run ``git submodule update - --init`` before running configure script, and use ``--with-mruby`` - configure option. +To compile source code, gcc >= 4.8.3 or clang >= 3.4 is required. .. note:: - Mac OS X users may need the ``--disable-threads`` configure option to - disable multi-threading in nghttpd, nghttpx and h2load to prevent - them from crashing. A patch is welcome to make multi threading work + Mac OS X users may need ``--disable-threads`` configure option to + disable multi threading in nghttpd, nghttpx and h2load to prevent + them from crashing. Patch is welcome to make multi threading work on Mac OS X platform. -.. note:: - - To compile the associated applications (nghttp, nghttpd, nghttpx - and h2load), you must use the ``--enable-app`` configure option and - ensure that the specified requirements above are met. Normally, - configure script checks required dependencies to build these - applications, and enable ``--enable-app`` automatically, so you - don't have to use it explicitly. But if you found that - applications were not built, then using ``--enable-app`` may find - that cause, such as the missing dependency. - -Notes for building on Windows (MSVC) ------------------------------------- - -The easiest way to build native Windows nghttp2 dll is use `cmake -`_. The free version of `Visual C++ Build Tools -`_ works -fine. - -1. Install cmake for windows -2. Open "Visual C++ ... Native Build Tool Command Prompt", and inside - nghttp2 directly, run ``cmake``. -3. Then run ``cmake --build`` to build library. -4. nghttp2.dll, nghttp2.lib, nghttp2.exp are placed under lib directory. - -Note that the above steps most likely produce nghttp2 library only. -No bundled applications are compiled. - -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: - -.. code-block:: text - - $ 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 --------------------------- +Building documentation +---------------------- .. note:: Documentation is still incomplete. -To build the documentation, run: - -.. code-block:: text +To build documentation, run:: $ make html @@ -242,146 +173,10 @@ The online documentation is available at https://nghttp2.org/documentation/ -Unit tests ----------- - -Unit tests are done by simply running ``make check``. - -Integration tests ------------------ - -We have the integration tests for the nghttpx proxy server. The tests are -written in the `Go programming language `_ and uses -its testing framework. We depend on the following libraries: - -* golang.org/x/net/http2 -* golang.org/x/net/websocket -* https://github.com/tatsuhiro-t/go-nghttp2 -* https://github.com/tatsuhiro-t/spdy - -To download the above packages, after settings ``GOPATH``, run the -following command under ``integration-tests`` directory: - -.. code-block:: text - - $ make itprep - -To run the tests, run the following command under -``integration-tests`` directory: - -.. code-block:: text - - $ make it - -Inside the tests, we use port 3009 to run the test subject server. - -.. note:: - - github.com/tatsuhiro-t/spdy is a copy used to be available at - golang.org/x/net/spdy, but it is now gone. - -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 already 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 --------------------------------- -The ``src`` directory contains the HTTP/2 client, server and proxy programs. +The src directory contains HTTP/2 client, server and proxy programs. nghttp - client +++++++++++++++ @@ -390,220 +185,145 @@ with prior knowledge, HTTP Upgrade and NPN/ALPN TLS extension. It has verbose output mode for framing information. Here is sample -output from ``nghttp`` client: +output from ``nghttp`` client:: -.. code-block:: text + $ src/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 + (niv=3) + [SETTINGS_MAX_CONCURRENT_STREAMS(3):100] + [SETTINGS_INITIAL_WINDOW_SIZE(4):65535] + [SETTINGS_COMPRESS_DATA(5):1] + [ 0.068] send HEADERS frame + ; END_STREAM | END_HEADERS + (padlen=0) + ; Open new stream + :authority: nghttp2.org + :method: GET + :path: / + :scheme: https + accept: */* + accept-encoding: gzip, deflate + user-agent: nghttp2/0.4.0-DEV + [ 0.068] recv SETTINGS frame + (niv=2) + [SETTINGS_MAX_CONCURRENT_STREAMS(3):100] + [SETTINGS_INITIAL_WINDOW_SIZE(4):65535] + [ 0.068] send SETTINGS frame + ; ACK + (niv=0) + [ 0.079] recv SETTINGS frame + ; 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 + ; END_HEADERS + (padlen=0) + ; First response header + [ 0.080] recv DATA frame + [ 0.080] recv DATA frame + [ 0.081] recv DATA frame + [ 0.093] recv DATA frame + [ 0.093] recv DATA frame + [ 0.094] recv DATA frame + [ 0.094] recv DATA frame + [ 0.094] recv DATA frame + [ 0.096] recv DATA frame + [ 0.096] send WINDOW_UPDATE frame + (window_size_increment=36554) + [ 0.096] send WINDOW_UPDATE frame + (window_size_increment=36554) + [ 0.108] recv DATA frame + [ 0.108] recv DATA frame + ; END_STREAM + [ 0.108] send GOAWAY frame + (last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[]) + +The HTTP Upgrade is performed like this:: - $ nghttp -nv https://nghttp2.org - [ 0.190] Connected - The negotiated protocol: h2 - [ 0.212] recv SETTINGS frame - (niv=2) - [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] - [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] - [ 0.212] send SETTINGS frame - (niv=2) - [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] - [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] - [ 0.212] send SETTINGS frame - ; ACK - (niv=0) - [ 0.212] send PRIORITY frame - (dep_stream_id=0, weight=201, exclusive=0) - [ 0.212] send PRIORITY frame - (dep_stream_id=0, weight=101, exclusive=0) - [ 0.212] send PRIORITY frame - (dep_stream_id=0, weight=1, exclusive=0) - [ 0.212] send PRIORITY frame - (dep_stream_id=7, weight=1, exclusive=0) - [ 0.212] send PRIORITY frame - (dep_stream_id=3, weight=1, exclusive=0) - [ 0.212] send HEADERS frame - ; END_STREAM | END_HEADERS | PRIORITY - (padlen=0, dep_stream_id=11, weight=16, exclusive=0) - ; Open new stream - :method: GET - :path: / - :scheme: https - :authority: nghttp2.org - accept: */* - accept-encoding: gzip, deflate - user-agent: nghttp2/1.0.1-DEV - [ 0.221] recv SETTINGS frame - ; ACK - (niv=0) - [ 0.221] recv (stream_id=13) :method: GET - [ 0.221] recv (stream_id=13) :scheme: https - [ 0.221] recv (stream_id=13) :path: /stylesheets/screen.css - [ 0.221] recv (stream_id=13) :authority: nghttp2.org - [ 0.221] recv (stream_id=13) accept-encoding: gzip, deflate - [ 0.222] recv (stream_id=13) user-agent: nghttp2/1.0.1-DEV - [ 0.222] recv PUSH_PROMISE frame - ; END_HEADERS - (padlen=0, promised_stream_id=2) - [ 0.222] recv (stream_id=13) :status: 200 - [ 0.222] recv (stream_id=13) date: Thu, 21 May 2015 16:38:14 GMT - [ 0.222] recv (stream_id=13) content-type: text/html - [ 0.222] recv (stream_id=13) last-modified: Fri, 15 May 2015 15:38:06 GMT - [ 0.222] recv (stream_id=13) etag: W/"555612de-19f6" - [ 0.222] recv (stream_id=13) link: ; rel=preload; as=stylesheet - [ 0.222] recv (stream_id=13) content-encoding: gzip - [ 0.222] recv (stream_id=13) server: nghttpx nghttp2/1.0.1-DEV - [ 0.222] recv (stream_id=13) via: 1.1 nghttpx - [ 0.222] recv (stream_id=13) strict-transport-security: max-age=31536000 - [ 0.222] recv HEADERS frame - ; END_HEADERS - (padlen=0) - ; First response header - [ 0.222] recv DATA frame - ; END_STREAM - [ 0.222] recv (stream_id=2) :status: 200 - [ 0.222] recv (stream_id=2) date: Thu, 21 May 2015 16:38:14 GMT - [ 0.222] recv (stream_id=2) content-type: text/css - [ 0.222] recv (stream_id=2) last-modified: Fri, 15 May 2015 15:38:06 GMT - [ 0.222] recv (stream_id=2) etag: W/"555612de-9845" - [ 0.222] recv (stream_id=2) content-encoding: gzip - [ 0.222] recv (stream_id=2) server: nghttpx nghttp2/1.0.1-DEV - [ 0.222] recv (stream_id=2) via: 1.1 nghttpx - [ 0.222] recv (stream_id=2) strict-transport-security: max-age=31536000 - [ 0.222] recv HEADERS frame - ; END_HEADERS - (padlen=0) - ; First push response header - [ 0.228] recv DATA frame - ; END_STREAM - [ 0.228] send GOAWAY frame - (last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[]) - -The HTTP Upgrade is performed like so: - -.. code-block:: text - - $ nghttp -nvu http://nghttp2.org - [ 0.011] Connected - [ 0.011] HTTP Upgrade request + $ src/nghttp -nvu http://nghttp2.org + [ 0.013] HTTP Upgrade request GET / HTTP/1.1 Host: nghttp2.org Connection: Upgrade, HTTP2-Settings - Upgrade: h2c - HTTP2-Settings: AAMAAABkAAQAAP__ + Upgrade: h2c-14 + HTTP2-Settings: AwAAAGQEAAD__wUAAAAB Accept: */* - User-Agent: nghttp2/1.0.1-DEV + User-Agent: nghttp2/0.4.0-DEV - [ 0.018] HTTP Upgrade response + [ 0.024] HTTP Upgrade response HTTP/1.1 101 Switching Protocols Connection: Upgrade - Upgrade: h2c + Upgrade: h2c-14 - [ 0.018] HTTP Upgrade success - [ 0.018] recv SETTINGS frame - (niv=2) - [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] - [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] - [ 0.018] send SETTINGS frame - (niv=2) - [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] - [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] - [ 0.018] send SETTINGS frame - ; ACK - (niv=0) - [ 0.018] send PRIORITY frame - (dep_stream_id=0, weight=201, exclusive=0) - [ 0.018] send PRIORITY frame - (dep_stream_id=0, weight=101, exclusive=0) - [ 0.018] send PRIORITY frame - (dep_stream_id=0, weight=1, exclusive=0) - [ 0.018] send PRIORITY frame - (dep_stream_id=7, weight=1, exclusive=0) - [ 0.018] send PRIORITY frame - (dep_stream_id=3, weight=1, exclusive=0) - [ 0.018] send PRIORITY frame - (dep_stream_id=11, weight=16, exclusive=0) - [ 0.019] recv (stream_id=1) :method: GET - [ 0.019] recv (stream_id=1) :scheme: http - [ 0.019] recv (stream_id=1) :path: /stylesheets/screen.css - [ 0.019] recv (stream_id=1) host: nghttp2.org - [ 0.019] recv (stream_id=1) user-agent: nghttp2/1.0.1-DEV - [ 0.019] recv PUSH_PROMISE frame - ; END_HEADERS - (padlen=0, promised_stream_id=2) - [ 0.019] recv (stream_id=1) :status: 200 - [ 0.019] recv (stream_id=1) date: Thu, 21 May 2015 16:39:16 GMT - [ 0.019] recv (stream_id=1) content-type: text/html - [ 0.019] recv (stream_id=1) content-length: 6646 - [ 0.019] recv (stream_id=1) last-modified: Fri, 15 May 2015 15:38:06 GMT - [ 0.019] recv (stream_id=1) etag: "555612de-19f6" - [ 0.019] recv (stream_id=1) link: ; rel=preload; as=stylesheet - [ 0.019] recv (stream_id=1) accept-ranges: bytes - [ 0.019] recv (stream_id=1) server: nghttpx nghttp2/1.0.1-DEV - [ 0.019] recv (stream_id=1) via: 1.1 nghttpx - [ 0.019] recv HEADERS frame - ; END_HEADERS - (padlen=0) - ; First response header - [ 0.019] recv DATA frame - ; END_STREAM - [ 0.019] recv (stream_id=2) :status: 200 - [ 0.019] recv (stream_id=2) date: Thu, 21 May 2015 16:39:16 GMT - [ 0.019] recv (stream_id=2) content-type: text/css - [ 0.019] recv (stream_id=2) content-length: 38981 - [ 0.019] recv (stream_id=2) last-modified: Fri, 15 May 2015 15:38:06 GMT - [ 0.019] recv (stream_id=2) etag: "555612de-9845" - [ 0.019] recv (stream_id=2) accept-ranges: bytes - [ 0.019] recv (stream_id=2) server: nghttpx nghttp2/1.0.1-DEV - [ 0.019] recv (stream_id=2) via: 1.1 nghttpx - [ 0.019] recv HEADERS frame - ; END_HEADERS - (padlen=0) - ; First push response header - [ 0.026] recv DATA frame - [ 0.027] recv DATA frame - [ 0.027] send WINDOW_UPDATE frame - (window_size_increment=33343) - [ 0.032] send WINDOW_UPDATE frame - (window_size_increment=33707) - [ 0.032] recv DATA frame - ; END_STREAM - [ 0.032] recv SETTINGS frame - ; ACK - (niv=0) - [ 0.032] send GOAWAY frame - (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: - -.. code-block:: text - - $ nghttp -nas https://nghttp2.org/ - ***** Statistics ***** - - Request timing: - 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' - - 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. + [ 0.024] HTTP Upgrade success + [ 0.024] send SETTINGS frame + (niv=3) + [SETTINGS_MAX_CONCURRENT_STREAMS(3):100] + [SETTINGS_INITIAL_WINDOW_SIZE(4):65535] + [SETTINGS_COMPRESS_DATA(5):1] + [ 0.024] recv SETTINGS frame + (niv=2) + [SETTINGS_MAX_CONCURRENT_STREAMS(3):100] + [SETTINGS_INITIAL_WINDOW_SIZE(4):65535] + [ 0.024] recv ALTSVC frame + (max-age=86400, port=443, protocol_id=h2-14, host=nghttp2.org, origin=http://nghttp2.org) + [ 0.024] send SETTINGS frame + ; 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 + ; END_HEADERS + (padlen=0) + ; First response header + [ 0.024] recv DATA frame + [ 0.025] recv DATA frame + [ 0.031] recv DATA frame + [ 0.031] recv DATA frame + [ 0.032] recv DATA frame + [ 0.032] recv DATA frame + [ 0.033] recv DATA frame + [ 0.033] recv DATA frame + [ 0.033] send WINDOW_UPDATE frame + (window_size_increment=33164) + [ 0.033] send WINDOW_UPDATE frame + (window_size_increment=33164) + [ 0.038] recv DATA frame + [ 0.038] recv DATA frame + [ 0.038] recv DATA frame + ; END_STREAM + [ 0.038] recv SETTINGS frame + ; ACK + (niv=0) + [ 0.038] send GOAWAY frame + (last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[]) nghttpd - server ++++++++++++++++ @@ -613,139 +333,116 @@ By default, it uses SSL/TLS connection. Use ``--no-tls`` option to disable it. -``nghttpd`` only accepts HTTP/2 connections via NPN/ALPN or direct -HTTP/2 connections. No HTTP Upgrade is supported. +``nghttpd`` only accepts the HTTP/2 connection via NPN/ALPN or direct +HTTP/2 connection. No HTTP Upgrade is supported. -The ``-p`` option allows users to configure server push. +``-p`` option allows users to configure server push. -Just like ``nghttp``, it has a verbose output mode for framing -information. Here is sample output from ``nghttpd``: +Just like ``nghttp``, it has verbose output mode for framing +information. Here is sample output from ``nghttpd`` server:: -.. code-block:: text - - $ nghttpd --no-tls -v 8080 - IPv4: listen 0.0.0.0:8080 - IPv6: listen :::8080 - [id=1] [ 1.521] send SETTINGS frame - (niv=1) - [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] - [id=1] [ 1.521] recv SETTINGS frame + $ src/nghttpd --no-tls -v 8080 + IPv4: listen on port 8080 + IPv6: listen on port 8080 + [id=1] [ 15.921] send SETTINGS frame (niv=2) - [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] - [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] - [id=1] [ 1.521] recv SETTINGS frame + [SETTINGS_MAX_CONCURRENT_STREAMS(3):100] + [SETTINGS_COMPRESS_DATA(5):1] + [id=1] [ 15.921] recv SETTINGS frame + (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 + ; END_STREAM | END_HEADERS + (padlen=0) + ; Open new stream + [id=1] [ 15.921] recv SETTINGS frame ; ACK (niv=0) - [id=1] [ 1.521] recv PRIORITY frame - (dep_stream_id=0, weight=201, exclusive=0) - [id=1] [ 1.521] recv PRIORITY frame - (dep_stream_id=0, weight=101, exclusive=0) - [id=1] [ 1.521] recv PRIORITY frame - (dep_stream_id=0, weight=1, exclusive=0) - [id=1] [ 1.521] recv PRIORITY frame - (dep_stream_id=7, weight=1, exclusive=0) - [id=1] [ 1.521] recv PRIORITY frame - (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 - ; END_STREAM | END_HEADERS | PRIORITY - (padlen=0, dep_stream_id=11, weight=16, exclusive=0) - ; Open new stream - [id=1] [ 1.521] send SETTINGS frame + [id=1] [ 15.921] send SETTINGS frame ; ACK (niv=0) - [id=1] [ 1.521] send HEADERS frame + [id=1] [ 15.921] send HEADERS frame ; END_HEADERS (padlen=0) ; First response header :status: 200 - server: nghttpd nghttp2/1.0.0-DEV - content-length: 10 cache-control: max-age=3600 - 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 + 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 + ; COMPRESSED + [id=1] [ 15.922] send DATA frame ; END_STREAM - [id=1] [ 1.522] stream_id=13 closed - [id=1] [ 1.522] recv GOAWAY frame - (last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[]) - [id=1] [ 1.522] closed + [id=1] [ 15.922] stream_id=1 closed + [id=1] [ 15.922] recv GOAWAY frame + (last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[]) + [id=1] [ 15.922] closed nghttpx - proxy +++++++++++++++ -``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. - -We reworked ``nghttpx`` command-line interface, and as a result, there -are several incompatibles from 1.8.0 or earlier. This is necessary to -extend its capability, and secure the further feature enhancements in -the future release. Please read `Migration from nghttpx v1.8.0 or -earlier -`_ -to know how to migrate from earlier releases. - -``nghttpx`` implements `important performance-oriented features -`_ 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`` also offers the functionality to share session -cache and ticket keys among multiple ``nghttpx`` instances via -memcached. - -``nghttpx`` has 2 operation modes: - -================== ====================== ================ ============= -Mode option Frontend Backend Note -================== ====================== ================ ============= -default mode HTTP/2, SPDY, HTTP/1.1 HTTP/1.1, HTTP/2 Reverse proxy -``--http2-proxy`` HTTP/2, SPDY, HTTP/1.1 HTTP/1.1, HTTP/2 Forward proxy -================== ====================== ================ ============= +``nghttpx`` is a multi-threaded reverse proxy for ``h2-14``, SPDY and +HTTP/1.1 and powers nghttp2.org site. It has several operation modes: + +================== ============================ ============== ============= +Mode option Frontend Backend Note +================== ============================ ============== ============= +default mode HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/1.1 Reverse proxy +``--http2-proxy`` HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/1.1 SPDY proxy +``--http2-bridge`` HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/2 (TLS) +``--client`` HTTP/2, HTTP/1.1 HTTP/2 (TLS) +``--client-proxy`` HTTP/2, HTTP/1.1 HTTP/2 (TLS) Forward proxy +================== ============================ ============== ============= The interesting mode at the moment is the default mode. It works like -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. +a reverse proxy and listens for ``h2-14``, SPDY and HTTP/1.1 and can +be deployed SSL/TLS terminator for existing web server. -In all modes, the frontend connections are encrypted by SSL/TLS by -default. To disable encryption, use the ``no-tls`` keyword in -``--frontend`` option. If encryption is disabled, SPDY is disabled in -the frontend and incoming HTTP/1.1 connections can be upgraded to -HTTP/2 through HTTP Upgrade. On the other hard, backend connections -are not encrypted by default. To encrypt backend connections, use -``tls`` keyword in ``--backend`` option. +The default mode, ``--http2-proxy`` and ``--http2-bridge`` modes use +SSL/TLS in the frontend connection by default. To disable SSL/TLS, +use ``--frontend-no-tls`` option. If that option is used, SPDY is +disabled in the frontend and incoming HTTP/1.1 connection 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 +``--backend-no-tls`` option. -``nghttpx`` supports a configuration file. See the ``--conf`` option and +``nghttpx`` supports configuration file. See ``--conf`` option and sample configuration file ``nghttpx.conf.sample``. -In the default mode, ``nghttpx`` works as reverse proxy to the backend -server: +``nghttpx`` does not support server push. -.. code-block:: text +In the default mode, (without any of ``--http2-proxy``, +``--http2-bridge``, ``--client-proxy`` and ``--client`` options), +``nghttpx`` works as reverse proxy to the backend server:: - Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> Web Server + Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Web Server [reverse proxy] -With the ``--http2-proxy`` option, it works as forward proxy, and it -is so called secure HTTP/2 proxy (aka SPDY proxy): - -.. code-block:: text +With ``--http2-proxy`` option, it works as so called secure proxy (aka +SPDY proxy):: Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy [secure proxy] (e.g., Squid, ATS) -The ``Client`` in the above example needs to be configured to use +The ``Client`` in the above is needs to be configured to use ``nghttpx`` as secure proxy. -At the time of this writing, both Chrome and Firefox support secure -HTTP/2 proxy. One way to configure Chrome to use a secure proxy is to -create a proxy.pac script like this: +At the time of this writing, Chrome is the only browser which supports +secure proxy. The one way to configure Chrome to use secure proxy is +create proxy.pac script like this: .. code-block:: javascript @@ -754,21 +451,45 @@ } ``SERVERADDR`` and ``PORT`` is the hostname/address and port of the -machine nghttpx is running on. Please note that Chrome requires a valid +machine nghttpx is running. Please note that Chrome requires valid certificate for secure proxy. -Then run Chrome with the following arguments: - -.. code-block:: text +Then run Chrome with the following arguments:: $ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn -The backend HTTP/2 connections can be tunneled through an HTTP proxy. -The proxy is specified using ``--backend-http-proxy-uri``. The -following figure illustrates how nghttpx talks to the outside HTTP/2 -proxy through an HTTP proxy: +With ``--http2-bridge``, it accepts HTTP/2, SPDY and HTTP/1.1 +connections and communicates with backend in HTTP/2:: -.. code-block:: text + Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/2) --> Web or HTTP/2 Proxy etc + (e.g., nghttpx -s) + +With ``--client-proxy`` option, it works as forward proxy and expects +that the backend is HTTP/2 proxy:: + + Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --> HTTP/2 Proxy + [forward proxy] (e.g., nghttpx -s) + +The ``Client`` needs to be configured to use nghttpx as forward +proxy. The frontend HTTP/1.1 connection can be upgraded to HTTP/2 +through HTTP Upgrade. With the above configuration, one can use +HTTP/1.1 client to access and test their HTTP/2 servers. + +With ``--client`` option, it works as reverse proxy and expects that +the backend is HTTP/2 Web server:: + + Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --> Web Server + [reverse proxy] + +The frontend HTTP/1.1 connection can be upgraded to HTTP/2 +through HTTP Upgrade. + +For the operation modes which talk to the backend in HTTP/2 over +SSL/TLS, the backend connections can be tunneled through HTTP proxy. +The proxy is specified using ``--backend-http-proxy-uri`` option. The +following figure illustrates the example of ``--http2-bridge`` and +``--backend-http-proxy-uri`` options to talk to the outside HTTP/2 +proxy through HTTP proxy:: Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/2) -- @@ -779,19 +500,13 @@ ----------------- The ``h2load`` program is a benchmarking tool for HTTP/2 and SPDY. -The SPDY support is enabled if the program was built with the spdylay +The SPDY support is enabled if the program was built with spdylay library. The UI of ``h2load`` is heavily inspired by ``weighttp`` (https://github.com/lighttpd/weighttp). The typical usage is as -follows: - -.. code-block:: text +follows:: - $ h2load -n100000 -c100 -m100 https://localhost:8443/ + $ src/h2load -n1000 -c10 -m10 https://127.0.0.1:8443/ starting benchmark... - 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 @@ -803,47 +518,43 @@ progress: 90% done progress: 100% done - 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: 3812300 bytes total, 1009900 bytes headers, 1000000 bytes data - min max mean sd +/- sd - 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 -per client. With the ``-t`` option, ``h2load`` will use multiple native -threads to avoid saturating a single core on client side. + finished in 0 sec, 152 millisec and 152 microsec, 6572 req/s, 749 kbytes/s + requests: 1000 total, 1000 started, 1000 done, 0 succeeded, 1000 failed, 0 errored + status codes: 0 2xx, 0 3xx, 1000 4xx, 0 5xx + traffic: 141100 bytes total, 840 bytes headers, 116000 bytes data + +The above example issued total 1000 requests, using 10 concurrent +clients (thus 10 HTTP/2 sessions), and maximum 10 streams per client. +With ``-t`` option, ``h2load`` will use multiple native threads to +avoid saturating single core on client side. .. warning:: **Don't use this tool against publicly available servers.** That is - considered a DOS attack. Please only use it against your private + considered a DOS attack. Please only use against your private servers. HPACK tools ----------- -The ``src`` directory contains the HPACK tools. The ``deflatehd`` program is a -command-line header compression tool. The ``inflatehd`` program is a +The ``src`` directory contains HPACK tools. The ``deflatehd`` is a +command-line header compression tool. The ``inflatehd`` is command-line header decompression tool. Both tools read input from -stdin and write output to stdout. Errors are written to stderr. -They take JSON as input and output. We (mostly) use the same JSON data -format described at https://github.com/http2jp/hpack-test-case. +stdin and write output to stdout. The errors are written to stderr. +They take JSON as input and output. We use (mostly) same JSON data +format described at https://github.com/http2jp/hpack-test-case deflatehd - header compressor +++++++++++++++++++++++++++++ -The ``deflatehd`` program reads JSON data or HTTP/1-style header fields from +The ``deflatehd`` reads JSON data or HTTP/1-style header fields from stdin and outputs compressed header block in JSON. -For the JSON input, the root JSON object must include a ``cases`` key. +For the JSON input, the root JSON object must include ``cases`` key. Its value has to include the sequence of input header set. They share the same compression context and are processed in the order they appear. Each item in the sequence is a JSON object and it must -include a ``headers`` key. Its value is an array of JSON objects, +include ``headers`` key. Its value is an array of a JSON object, which includes exactly one name/value pair. Example: @@ -869,12 +580,10 @@ } -With the ``-t`` option, the program can accept more familiar HTTP/1 style -header field blocks. Each header set is delimited by an empty line: +With ``-t`` option, the program can accept more familiar HTTP/1 style +header field block. Each header set is delimited by empty line: -Example: - -.. code-block:: text +Example:: :method: GET :scheme: https @@ -883,29 +592,29 @@ :method: POST user-agent: nghttp2 -The output is in JSON object. It should include a ``cases`` key and its -value is an array of JSON objects, which has at least the following keys: +The output is JSON object. It should include ``cases`` key and its +value is an array of JSON object, which has at least following keys: seq The index of header set in the input. input_length - The sum of the length of the name/value pairs in the input. + The sum of length of name/value pair in the input. output_length - The length of the compressed header block. + The length of compressed header block. percentage_of_original_size ``input_length`` / ``output_length`` * 100 wire - The compressed header block as a hex string. + The compressed header block in hex string. headers The input header set. header_table_size - The header table size adjusted before deflating the header set. + The header table size adjusted before deflating header set. Examples: @@ -972,7 +681,7 @@ The output can be used as the input for ``inflatehd`` and ``deflatehd``. -With the ``-d`` option, the extra ``header_table`` key is added and its +With ``-d`` option, the extra ``header_table`` key is added and its associated value includes the state of dynamic header table after the corresponding header set was processed. The value includes at least the following keys: @@ -996,10 +705,10 @@ ``max_deflate_size``. 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 + The maximum header table size encoder uses. This can be smaller + than ``max_size``. In this case, 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 outside the + ``max_size``, the encoder has to keep track of entries ouside the ``max_deflate_size`` but inside the ``max_size`` and make sure that they are no longer referenced. @@ -1160,14 +869,14 @@ inflatehd - header decompressor +++++++++++++++++++++++++++++++ -The ``inflatehd`` program reads JSON data from stdin and outputs decompressed +The ``inflatehd`` reads JSON data from stdin and outputs decompressed name/value pairs in JSON. -The root JSON object must include the ``cases`` key. Its value has to -include the sequence of compressed header blocks. They share the same +The root JSON object must include ``cases`` key. Its value has to +include the sequence of compressed header block. They share the same compression context and are processed in the order they appear. Each -item in the sequence is a JSON object and it must have at least a -``wire`` key. Its value is a compressed header block as a hex string. +item in the sequence is a JSON object and it must have at least +``wire`` key. Its value is a compressed header block in hex string. Example: @@ -1181,17 +890,17 @@ ] } -The output is a JSON object. It should include a ``cases`` key and its -value is an array of JSON objects, which has at least following keys: +The output is JSON object. It should include ``cases`` key and its +value is an array of JSON object, which has at least following keys: seq - The index of the header set in the input. + The index of header set in the input. headers - A JSON array that includes decompressed name/value pairs. + The JSON array includes decompressed name/value pairs. wire - The compressed header block as a hex string. + The compressed header block in hex string. header_table_size The header table size adjusted before inflating compressed header @@ -1255,8 +964,8 @@ The output can be used as the input for ``deflatehd`` and ``inflatehd``. -With the ``-d`` option, the extra ``header_table`` key is added and its -associated value includes the state of the dynamic header table after the +With ``-d`` option, the extra ``header_table`` key is added and its +associated value includes the state of dynamic header table after the corresponding header set was processed. The format is the same as ``deflatehd``. @@ -1265,10 +974,10 @@ libnghttp2_asio is C++ library built on top of libnghttp2 and provides high level abstraction API to build HTTP/2 applications. It depends -on the Boost::ASIO library and OpenSSL. Currently libnghttp2_asio -provides both client and server APIs. +on Boost::ASIO library and OpenSSL. Currently libnghttp2_asio +provides server side API. -libnghttp2_asio is not built by default. Use the ``--enable-asio-lib`` +libnghttp2_asio is not built by default. Use ``--enable-asio-lib`` configure flag to build libnghttp2_asio. The required Boost libraries are: @@ -1276,83 +985,25 @@ * Boost::System * Boost::Thread -The server API is designed to build an HTTP/2 server very easily to utilize -C++11 anonymous functions and closures. The bare minimum example of -an HTTP/2 server looks like this: +Server API is designed to build HTTP/2 server very easily to utilize +C++11 anonymous function and closure. The bare minimum example of +HTTP/2 server looks like this: .. code-block:: cpp - #include - - #include + #include using namespace nghttp2::asio_http2; using namespace nghttp2::asio_http2::server; int main(int argc, char *argv[]) { - boost::system::error_code ec; http2 server; - server.handle("/", [](const request &req, const response &res) { - res.write_head(200); - res.end("hello, world\n"); - }); - - if (server.listen_and_serve(ec, "localhost", "3000")) { - std::cerr << "error: " << ec.message() << std::endl; - } - } - -Here is sample code to use the client API: - -.. code-block:: cpp - - #include - - #include - - using boost::asio::ip::tcp; - - using namespace nghttp2::asio_http2; - using namespace nghttp2::asio_http2::client; - - int main(int argc, char *argv[]) { - boost::system::error_code ec; - boost::asio::io_service io_service; - - // connect to localhost:3000 - session sess(io_service, "localhost", "3000"); - - sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) { - boost::system::error_code ec; - - 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; - - res.on_data([](const uint8_t *data, std::size_t len) { - std::cerr.write(reinterpret_cast(data), len); - std::cerr << std::endl; - }); - }); - - req->on_close([&sess](uint32_t error_code) { - // shutdown session after first request was done. - sess.shutdown(); - }); + server.listen("*", 3000, [](const std::shared_ptr &req, + const std::shared_ptr &res) { + res->write_head(200); + res->end("hello, world"); }); - - sess.on_error([](const boost::system::error_code &ec) { - std::cerr << "error: " << ec.message() << std::endl; - }); - - io_service.run(); } For more details, see the documentation of libnghttp2_asio. @@ -1360,19 +1011,19 @@ Python bindings --------------- -The ``python`` directory contains nghttp2 Python bindings. The +This ``python`` directory contains nghttp2 Python bindings. The bindings currently provide HPACK compressor and decompressor classes -and an HTTP/2 server. +and HTTP/2 server. The extension module is called ``nghttp2``. ``make`` will build the bindings and target Python version is -determined by the ``configure`` script. If the detected Python version is not -what you expect, specify a path to Python executable in a ``PYTHON`` +determined by configure script. If the detected Python version is not +what you expect, specify a path to Python executable in ``PYTHON`` variable as an argument to configure script (e.g., ``./configure PYTHON=/usr/bin/python3.4``). -The following example code illustrates basic usage of the HPACK compressor +The following example code illustrates basic usage of HPACK compressor and decompressor in Python: .. code-block:: python @@ -1399,21 +1050,21 @@ event callback method. The first callback method invoked is ``on_headers()``. It is called -when HEADERS frame, which includes the request header fields, has arrived. +when HEADERS frame, which includes request header fields, has arrived. -If the request has a request body, ``on_data(data)`` is invoked for each +If request has request body, ``on_data(data)`` is invoked for each chunk of received data. -Once the entire request is received, ``on_request_done()`` is invoked. +When whole request is received, ``on_request_done()`` is invoked. -When the stream is closed, ``on_close(error_code)`` is called. +When stream is closed, ``on_close(error_code)`` is called. -The application can send a response using ``send_response()`` method. +The application can send response using ``send_response()`` method. It can be used in ``on_headers()``, ``on_data()`` or ``on_request_done()``. -The application can push resources using the ``push()`` method. It must be -used before the ``send_response()`` call. +The application can push resource using ``push()`` method. It must be +used before ``send_response()`` call. The following instance variables are available: @@ -1483,15 +1134,14 @@ code under the same license nghttp2 is already using unless stated and agreed otherwise. -When changing existing source code, do not alter the copyright of +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 (or your employer, as -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 +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! @@ -1499,16 +1149,3 @@ See `Contribution Guidelines `_ for more details. - -Release schedule ----------------- - -In general, we follow `Semantic Versioning `_. We -release MINOR version update every month, and usually we ship it -around 25th day of every month. - -We may release PATCH releases between the regular releases, mainly for -severe security bug fixes. - -We have no plan to break API compatibility changes involving soname -bump, so MAJOR version will stay 1 for the foreseeable future. diff -Nru nghttp2-1.13.0/script/CMakeLists.txt nghttp2-0.6.7/script/CMakeLists.txt --- nghttp2-1.13.0/script/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/script/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -# EXTRA_DIST = README.rst -install( - PROGRAMS fetch-ocsp-response - DESTINATION "${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}" -) diff -Nru nghttp2-1.13.0/script/fetch-ocsp-response nghttp2-0.6.7/script/fetch-ocsp-response --- nghttp2-1.13.0/script/fetch-ocsp-response 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/script/fetch-ocsp-response 1970-01-01 00:00:00.000000000 +0000 @@ -1,253 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# nghttp2 - HTTP/2 C Library - -# Copyright (c) 2015 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. - -# This program was translated from the program originally developed by -# h2o project (https://github.com/h2o/h2o), written in Perl. It had -# the following copyright notice: - -# Copyright (c) 2015 DeNA Co., Ltd. -# -# 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. - -from __future__ import unicode_literals -import argparse -import io -import os -import os.path -import re -import shutil -import subprocess -import sys -import tempfile - -# make this program work for both Python 3 and Python 2. -try: - from urllib.parse import urlparse - stdout_bwrite = sys.stdout.buffer.write -except ImportError: - from urlparse import urlparse - stdout_bwrite = sys.stdout.write - - -def die(msg): - sys.stderr.write(msg) - sys.stderr.write('\n') - sys.exit(255) - - -def tempfail(msg): - sys.stderr.write(msg) - sys.stderr.write('\n') - sys.exit(os.EX_TEMPFAIL) - - -def run_openssl(args, allow_tempfail=False): - buf = io.BytesIO() - try: - p = subprocess.Popen(args, stdout=subprocess.PIPE) - except Exception as e: - die('failed to invoke {}:{}'.format(args, e)) - try: - while True: - data = p.stdout.read() - if len(data) == 0: - break - buf.write(data) - if p.wait() != 0: - raise Exception('nonzero return code {}'.format(p.returncode)) - return buf.getvalue() - except Exception as e: - msg = 'OpenSSL exitted abnormally: {}:{}'.format(args, e) - tempfail(msg) if allow_tempfail else die(msg) - - -def read_file(path): - with open(path, 'rb') as f: - return f.read() - - -def write_file(path, data): - with open(path, 'wb') as f: - f.write(data) - - -def detect_openssl_version(cmd): - return run_openssl([cmd, 'version']).decode('utf-8').strip() - - -def extract_ocsp_uri(cmd, cert_fn): - # obtain ocsp uri - ocsp_uri = run_openssl( - [cmd, 'x509', '-in', cert_fn, '-noout', - '-ocsp_uri']).decode('utf-8').strip() - - if not re.match(r'^https?://', ocsp_uri): - die('failed to extract ocsp URI from {}'.format(cert_fn)) - - return ocsp_uri - - -def save_issuer_certificate(issuer_fn, cert_fn): - # save issuer certificate - chain = read_file(cert_fn).decode('utf-8') - m = re.match( - r'.*?-----END CERTIFICATE-----.*?(-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----)', - chain, re.DOTALL) - if not m: - die('--issuer option was not used, and failed to extract issuer certificate from the certificate') - write_file(issuer_fn, (m.group(1) + '\n').encode('utf-8')) - - -def send_and_receive_ocsp(respder_fn, cmd, cert_fn, issuer_fn, ocsp_uri, - ocsp_host, openssl_version): - # obtain response (without verification) - sys.stderr.write('sending OCSP request to {}\n'.format(ocsp_uri)) - args = [ - cmd, 'ocsp', '-issuer', issuer_fn, '-cert', cert_fn, '-url', ocsp_uri, - '-noverify', '-respout', respder_fn - ] - ver = openssl_version.lower() - if ver.startswith('openssl 1.') or ver.startswith('libressl '): - args.extend(['-header', 'Host', ocsp_host]) - resp = run_openssl(args, allow_tempfail=True) - return resp.decode('utf-8') - - -def verify_response(cmd, tempdir, issuer_fn, respder_fn): - # verify the response - sys.stderr.write('verifying the response signature\n') - - verify_fn = os.path.join(tempdir, 'verify.out') - - # try from exotic options - allextra = [ - # for comodo - ['-VAfile', issuer_fn], - # these options are only available in OpenSSL >= 1.0.2 - ['-partial_chain', '-trusted_first', '-CAfile', issuer_fn], - # for OpenSSL <= 1.0.1 - ['-CAfile', issuer_fn], - ] - - for extra in allextra: - with open(verify_fn, 'w+b') as f: - args = [cmd, 'ocsp', '-respin', respder_fn] - args.extend(extra) - p = subprocess.Popen(args, stdout=f, stderr=f) - if p.wait() == 0: - # OpenSSL <= 1.0.1, openssl ocsp still returns exit - # code 0 even if verification was failed. So check - # the error message in stderr output. - f.seek(0) - if f.read().decode('utf-8').find( - 'Response Verify Failure') != -1: - continue - sys.stderr.write('verify OK (used: {})\n'.format(extra)) - return True - - sys.stderr.write(read_file(verify_fn).decode('utf-8')) - return False - - -def fetch_ocsp_response(cmd, cert_fn, tempdir, issuer_fn=None): - openssl_version = detect_openssl_version(cmd) - - sys.stderr.write( - 'fetch-ocsp-response (using {})\n'.format(openssl_version)) - - ocsp_uri = extract_ocsp_uri(cmd, cert_fn) - ocsp_host = urlparse(ocsp_uri).netloc - - if not issuer_fn: - issuer_fn = os.path.join(tempdir, 'issuer.crt') - save_issuer_certificate(issuer_fn, cert_fn) - - respder_fn = os.path.join(tempdir, 'resp.der') - resp = send_and_receive_ocsp( - respder_fn, cmd, cert_fn, issuer_fn, ocsp_uri, ocsp_host, - openssl_version) - - sys.stderr.write('{}\n'.format(resp)) - - # OpenSSL 1.0.2 still returns exit code 0 even if ocsp responder - # returned error status (e.g., trylater(3)) - if resp.find('Responder Error:') != -1: - raise Exception('responder returned error') - - if not verify_response(cmd, tempdir, issuer_fn, respder_fn): - tempfail('failed to verify the response') - - # success - res = read_file(respder_fn) - stdout_bwrite(res) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - description= - '''The command issues an OCSP request for given server certificate, verifies the response and prints the resulting DER.''', - epilog= - '''The command exits 0 if successful, or 75 (EX_TEMPFAIL) on temporary error. Other exit codes may be returned in case of hard errors.''') - parser.add_argument( - '--issuer', - metavar='FILE', - help= - 'issuer certificate (if omitted, is extracted from the certificate chain)') - parser.add_argument('--openssl', - metavar='CMD', - help='openssl command to use (default: "openssl")', - default='openssl') - parser.add_argument('certificate', - help='path to certificate file to validate') - args = parser.parse_args() - - tempdir = None - try: - # Python3.2 has tempfile.TemporaryDirectory, which has nice - # feature to delete its tree by cleanup() function. We have - # to support Python2.7, so we have to do this manually. - tempdir = tempfile.mkdtemp() - fetch_ocsp_response(args.openssl, args.certificate, tempdir, - args.issuer) - finally: - if tempdir: - shutil.rmtree(tempdir) diff -Nru nghttp2-1.13.0/script/Makefile.am nghttp2-0.6.7/script/Makefile.am --- nghttp2-1.13.0/script/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/script/Makefile.am 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -# nghttp2 - HTTP/2 C Library - -# Copyright (c) 2015 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. - -EXTRA_DIST = README.rst CMakeLists.txt -dist_pkgdata_SCRIPTS = fetch-ocsp-response diff -Nru nghttp2-1.13.0/script/Makefile.in nghttp2-0.6.7/script/Makefile.in --- nghttp2-1.13.0/script/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/script/Makefile.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,602 +0,0 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2014 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# nghttp2 - HTTP/2 C Library - -# Copyright (c) 2015 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. - -VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -target_triplet = @target@ -subdir = script -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ - $(top_srcdir)/m4/ax_boost_base.m4 \ - $(top_srcdir)/m4/ax_boost_system.m4 \ - $(top_srcdir)/m4/ax_boost_thread.m4 \ - $(top_srcdir)/m4/ax_check_compile_flag.m4 \ - $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ - $(top_srcdir)/m4/ax_have_epoll.m4 \ - $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(dist_pkgdata_SCRIPTS) \ - $(am__DIST_COMMON) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(pkgdatadir)" -SCRIPTS = $(dist_pkgdata_SCRIPTS) -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -am__DIST_COMMON = $(srcdir)/Makefile.in -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -BOOST_ASIO_LIB = @BOOST_ASIO_LIB@ -BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ -BOOST_LDFLAGS = @BOOST_LDFLAGS@ -BOOST_SYSTEM_LIB = @BOOST_SYSTEM_LIB@ -BOOST_THREAD_LIB = @BOOST_THREAD_LIB@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CUNIT_CFLAGS = @CUNIT_CFLAGS@ -CUNIT_LIBS = @CUNIT_LIBS@ -CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -CYTHON = @CYTHON@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ -FGREP = @FGREP@ -GREP = @GREP@ -HAVE_CXX11 = @HAVE_CXX11@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JANSSON_CFLAGS = @JANSSON_CFLAGS@ -JANSSON_LIBS = @JANSSON_LIBS@ -JEMALLOC_LIBS = @JEMALLOC_LIBS@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ -LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ -LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ -LIBSPDYLAY_LIBS = @LIBSPDYLAY_LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -LT_AGE = @LT_AGE@ -LT_CURRENT = @LT_CURRENT@ -LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ -OPENSSL_LIBS = @OPENSSL_LIBS@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -PYTHON = @PYTHON@ -PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ -PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ -PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ -PYTHON_VERSION = @PYTHON_VERSION@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ -VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ -XML2_CONFIG = @XML2_CONFIG@ -XML_CPPFLAGS = @XML_CPPFLAGS@ -XML_LIBS = @XML_LIBS@ -ZLIB_CFLAGS = @ZLIB_CFLAGS@ -ZLIB_LIBS = @ZLIB_LIBS@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -runstatedir = @runstatedir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target = @target@ -target_alias = @target_alias@ -target_cpu = @target_cpu@ -target_os = @target_os@ -target_vendor = @target_vendor@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -EXTRA_DIST = README.rst CMakeLists.txt -dist_pkgdata_SCRIPTS = fetch-ocsp-response -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu script/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu script/Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -install-dist_pkgdataSCRIPTS: $(dist_pkgdata_SCRIPTS) - @$(NORMAL_INSTALL) - @list='$(dist_pkgdata_SCRIPTS)'; test -n "$(pkgdatadir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ - done | \ - sed -e 'p;s,.*/,,;n' \ - -e 'h;s|.*|.|' \ - -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ - $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ - { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ - if ($$2 == $$4) { files[d] = files[d] " " $$1; \ - if (++n[d] == $(am__install_max)) { \ - print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ - else { print "f", d "/" $$4, $$1 } } \ - END { for (d in files) print "f", d, files[d] }' | \ - while read type dir files; do \ - if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ - test -z "$$files" || { \ - echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(pkgdatadir)$$dir'"; \ - $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(pkgdatadir)$$dir" || exit $$?; \ - } \ - ; done - -uninstall-dist_pkgdataSCRIPTS: - @$(NORMAL_UNINSTALL) - @list='$(dist_pkgdata_SCRIPTS)'; test -n "$(pkgdatadir)" || exit 0; \ - files=`for p in $$list; do echo "$$p"; done | \ - sed -e 's,.*/,,;$(transform)'`; \ - dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -tags TAGS: - -ctags CTAGS: - -cscope cscopelist: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(SCRIPTS) -installdirs: - for dir in "$(DESTDIR)$(pkgdatadir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-dist_pkgdataSCRIPTS - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-dist_pkgdataSCRIPTS - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic clean-libtool \ - cscopelist-am ctags-am distclean distclean-generic \ - distclean-libtool distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am \ - install-dist_pkgdataSCRIPTS install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ - uninstall-am uninstall-dist_pkgdataSCRIPTS - -.PRECIOUS: Makefile - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff -Nru nghttp2-1.13.0/script/README.rst nghttp2-0.6.7/script/README.rst --- nghttp2-1.13.0/script/README.rst 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/script/README.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -fetch-ocsp-response is a Python script which performs OCSP query and -get response. It uses openssl command under the hood. nghttpx uses -it to enable OCSP stapling feature. - -fetch-ocsp-response is a translation from original fetch-ocsp-response -written in Perl and which has been developed as part of h2o project -(https://github.com/h2o/h2o). - -fetch-ocsp-response is usually installed under $(pkgdatadir), which is -$(prefix)/share/nghttp2. diff -Nru nghttp2-1.13.0/src/allocator.h nghttp2-0.6.7/src/allocator.h --- nghttp2-1.13.0/src/allocator.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/allocator.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,206 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 ALLOCATOR_H -#define ALLOCATOR_H - -#include "nghttp2_config.h" - -#include - -#include "template.h" - -namespace nghttp2 { - -struct MemBlock { - // The next MemBlock to chain them. This is for book keeping - // purpose to free them later. - MemBlock *next; - // begin is the pointer to the beginning of buffer. last is the - // location of next write. end is the one beyond of the end of the - // buffer. - uint8_t *begin, *last, *end; -}; - -// BlockAllocator allocates memory block with given size at once, and -// cuts the region from it when allocation is requested. If the -// requested size is larger than given threshold, it will be allocated -// in a distinct buffer on demand. -struct BlockAllocator { - BlockAllocator(size_t block_size, size_t isolation_threshold) - : retain(nullptr), - head(nullptr), - block_size(block_size), - isolation_threshold(std::min(block_size, isolation_threshold)) {} - - ~BlockAllocator() { reset(); } - - BlockAllocator(BlockAllocator &&other) noexcept - : retain(other.retain), - head(other.head), - block_size(other.block_size), - isolation_threshold(other.isolation_threshold) { - other.retain = nullptr; - other.head = nullptr; - } - - BlockAllocator &operator=(BlockAllocator &&other) noexcept { - reset(); - - retain = other.retain; - head = other.head; - block_size = other.block_size; - isolation_threshold = other.isolation_threshold; - - other.retain = nullptr; - other.head = nullptr; - - return *this; - } - - BlockAllocator(const BlockAllocator &) = delete; - BlockAllocator &operator=(const BlockAllocator &) = delete; - - void reset() { - for (auto mb = retain; mb;) { - auto next = mb->next; - delete[] reinterpret_cast(mb); - mb = next; - } - - retain = nullptr; - head = nullptr; - } - - MemBlock *alloc_mem_block(size_t size) { - auto block = new uint8_t[sizeof(MemBlock) + size]; - auto mb = reinterpret_cast(block); - - mb->next = retain; - mb->begin = mb->last = block + sizeof(MemBlock); - mb->end = mb->begin + size; - retain = mb; - return mb; - } - - void *alloc(size_t size) { - if (size >= isolation_threshold) { - auto mb = alloc_mem_block(size); - mb->last = mb->end; - return mb->begin; - } - - if (!head || head->end - head->last < static_cast(size)) { - head = alloc_mem_block(block_size); - } - - auto res = head->last; - - head->last = reinterpret_cast( - (reinterpret_cast(head->last + size) + 0xf) & ~0xf); - - return res; - } - - // This holds live memory block to free them in dtor. - MemBlock *retain; - // Current memory block to use. - MemBlock *head; - // size of single memory block - size_t block_size; - // if allocation greater or equal to isolation_threshold bytes is - // requested, allocate dedicated block. - size_t isolation_threshold; -}; - -// Makes a copy of |src|. The resulting string will be -// NULL-terminated. -template -StringRef make_string_ref(BlockAllocator &alloc, const StringRef &src) { - auto dst = static_cast(alloc.alloc(src.size() + 1)); - auto p = dst; - p = std::copy(std::begin(src), std::end(src), p); - *p = '\0'; - return StringRef{dst, src.size()}; -} - -// private function used in concat_string_ref. this is the base -// function of concat_string_ref_count(). -inline size_t concat_string_ref_count(size_t acc) { return acc; } - -// private function used in concat_string_ref. This function counts -// the sum of length of given arguments. The calculated length is -// accumulated, and passed to the next function. -template -size_t concat_string_ref_count(size_t acc, const StringRef &value, - Args &&... args) { - return concat_string_ref_count(acc + value.size(), - std::forward(args)...); -} - -// private function used in concat_string_ref. this is the base -// function of concat_string_ref_copy(). -inline uint8_t *concat_string_ref_copy(uint8_t *p) { return p; } - -// private function used in concat_string_ref. This function copies -// given strings into |p|. |p| is incremented by the copied length, -// and returned. In the end, return value points to the location one -// beyond the last byte written. -template -uint8_t *concat_string_ref_copy(uint8_t *p, const StringRef &value, - Args &&... args) { - p = std::copy(std::begin(value), std::end(value), p); - return concat_string_ref_copy(p, std::forward(args)...); -} - -// Returns the string which is the concatenation of |args| in the -// given order. The resulting string will be NULL-terminated. -template -StringRef concat_string_ref(BlockAllocator &alloc, Args &&... args) { - size_t len = concat_string_ref_count(0, std::forward(args)...); - auto dst = static_cast(alloc.alloc(len + 1)); - auto p = dst; - p = concat_string_ref_copy(p, std::forward(args)...); - *p = '\0'; - return StringRef{dst, len}; -} - -struct ByteRef { - // The pointer to the beginning of the buffer. - uint8_t *base; - // The length of the buffer. - size_t len; -}; - -// Makes a buffer with given size. The resulting byte string might -// not be NULL-terminated. -template -ByteRef make_byte_ref(BlockAllocator &alloc, size_t size) { - auto dst = static_cast(alloc.alloc(size)); - return {dst, size}; -} - -} // namespace aria2 - -#endif // ALLOCATOR_H diff -Nru nghttp2-1.13.0/src/app_helper.cc nghttp2-0.6.7/src/app_helper.cc --- nghttp2-1.13.0/src/app_helper.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/app_helper.cc 2014-11-30 14:15:07.000000000 +0000 @@ -23,21 +23,11 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include -#ifdef HAVE_SYS_SOCKET_H #include -#endif // HAVE_SYS_SOCKET_H -#ifdef HAVE_NETDB_H #include -#endif // HAVE_NETDB_H -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H -#ifdef HAVE_FCNTL_H #include -#endif // HAVE_FCNTL_H -#ifdef HAVE_NETINET_IN_H #include -#endif // HAVE_NETINET_IN_H #include #include @@ -58,11 +48,47 @@ #include "app_helper.h" #include "util.h" #include "http2.h" -#include "template.h" namespace nghttp2 { namespace { +const char *strstatus(uint32_t error_code) { + switch (error_code) { + case NGHTTP2_NO_ERROR: + return "NO_ERROR"; + case NGHTTP2_PROTOCOL_ERROR: + return "PROTOCOL_ERROR"; + case NGHTTP2_INTERNAL_ERROR: + return "INTERNAL_ERROR"; + case NGHTTP2_FLOW_CONTROL_ERROR: + return "FLOW_CONTROL_ERROR"; + case NGHTTP2_SETTINGS_TIMEOUT: + return "SETTINGS_TIMEOUT"; + case NGHTTP2_STREAM_CLOSED: + return "STREAM_CLOSED"; + case NGHTTP2_FRAME_SIZE_ERROR: + return "FRAME_SIZE_ERROR"; + case NGHTTP2_REFUSED_STREAM: + return "REFUSED_STREAM"; + case NGHTTP2_CANCEL: + return "CANCEL"; + case NGHTTP2_COMPRESSION_ERROR: + return "COMPRESSION_ERROR"; + case NGHTTP2_CONNECT_ERROR: + return "CONNECT_ERROR"; + case NGHTTP2_ENHANCE_YOUR_CALM: + return "ENHANCE_YOUR_CALM"; + case NGHTTP2_INADEQUATE_SECURITY: + return "INADEQUATE_SECURITY"; + case NGHTTP2_HTTP_1_1_REQUIRED: + return "HTTP_1_1_REQUIRED"; + default: + return "UNKNOWN"; + } +} +} // namespace + +namespace { const char *strsettingsid(int32_t id) { switch (id) { case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: @@ -84,7 +110,7 @@ } // namespace namespace { -std::string strframetype(uint8_t type) { +const char *strframetype(uint8_t type) { switch (type) { case NGHTTP2_DATA: return "DATA"; @@ -104,15 +130,11 @@ return "GOAWAY"; case NGHTTP2_WINDOW_UPDATE: return "WINDOW_UPDATE"; - case NGHTTP2_ALTSVC: + case NGHTTP2_EXT_ALTSVC: return "ALTSVC"; + default: + return "UNKNOWN"; } - - std::string s = "extension(0x"; - s += util::format_hex(&type, 1); - s += ')'; - - return s; }; } // namespace @@ -142,8 +164,11 @@ namespace { void print_nv(nghttp2_nv *nv) { - fprintf(outfile, "%s%s%s: %s\n", ansi_esc("\033[1;34m"), nv->name, - ansi_escend(), nv->value); + fprintf(outfile, "%s", ansi_esc("\033[1;34m")); + fwrite(nv->name, nv->namelen, 1, outfile); + fprintf(outfile, "%s: ", ansi_escend()); + fwrite(nv->value, nv->valuelen, 1, outfile); + fprintf(outfile, "\n"); } } // namespace namespace { @@ -249,7 +274,7 @@ namespace { void print_frame(print_type ptype, const nghttp2_frame *frame) { fprintf(outfile, "%s%s%s frame ", frame_name_ansi_esc(ptype), - strframetype(frame->hd.type).c_str(), ansi_escend()); + strframetype(frame->hd.type), ansi_escend()); print_frame_hd(frame->hd); if (frame->hd.flags) { print_frame_attr_indent(); @@ -266,7 +291,7 @@ print_frame_attr_indent(); fprintf(outfile, "(padlen=%zu", frame->headers.padlen); if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) { - fprintf(outfile, ", dep_stream_id=%d, weight=%u, exclusive=%d", + fprintf(outfile, ", stream_id=%d, weight=%u, exclusive=%d", frame->headers.pri_spec.stream_id, frame->headers.pri_spec.weight, frame->headers.pri_spec.exclusive); } @@ -292,7 +317,7 @@ case NGHTTP2_PRIORITY: print_frame_attr_indent(); - fprintf(outfile, "(dep_stream_id=%d, weight=%u, exclusive=%d)\n", + fprintf(outfile, "(stream_id=%d, weight=%u, exclusive=%d)\n", frame->priority.pri_spec.stream_id, frame->priority.pri_spec.weight, frame->priority.pri_spec.exclusive); @@ -300,7 +325,7 @@ case NGHTTP2_RST_STREAM: print_frame_attr_indent(); fprintf(outfile, "(error_code=%s(0x%02x))\n", - nghttp2_http2_strerror(frame->rst_stream.error_code), + strstatus(frame->rst_stream.error_code), frame->rst_stream.error_code); break; case NGHTTP2_SETTINGS: @@ -329,8 +354,7 @@ print_frame_attr_indent(); fprintf(outfile, "(last_stream_id=%d, error_code=%s(0x%02x), " "opaque_data(%u)=[%s])\n", - frame->goaway.last_stream_id, - nghttp2_http2_strerror(frame->goaway.error_code), + frame->goaway.last_stream_id, strstatus(frame->goaway.error_code), frame->goaway.error_code, static_cast(frame->goaway.opaque_data_len), util::ascii_dump(frame->goaway.opaque_data, @@ -341,12 +365,32 @@ fprintf(outfile, "(window_size_increment=%d)\n", frame->window_update.window_size_increment); break; - case NGHTTP2_ALTSVC: { - auto altsvc = static_cast(frame->ext.payload); + case NGHTTP2_EXT_ALTSVC: { print_frame_attr_indent(); - fprintf(outfile, "(origin=[%.*s], altsvc_field_value=[%.*s])\n", - static_cast(altsvc->origin_len), altsvc->origin, - static_cast(altsvc->field_value_len), altsvc->field_value); + + auto altsvc = static_cast(frame->ext.payload); + + fprintf(outfile, "(max-age=%u, port=%u, protocol_id=", altsvc->max_age, + altsvc->port); + + if (altsvc->protocol_id_len) { + fwrite(altsvc->protocol_id, altsvc->protocol_id_len, 1, outfile); + } + + fprintf(outfile, ", host="); + + if (altsvc->host_len) { + fwrite(altsvc->host, altsvc->host_len, 1, outfile); + } + + fprintf(outfile, ", origin="); + + if (altsvc->origin_len) { + fwrite(altsvc->origin, altsvc->origin_len, 1, outfile); + } + + fprintf(outfile, ")\n"); + break; } default: @@ -364,11 +408,8 @@ namelen, valuelen}; print_timer(); - fprintf(outfile, " recv (stream_id=%d", frame->hd.stream_id); - if (flags & NGHTTP2_NV_FLAG_NO_INDEX) { - fprintf(outfile, ", sensitive"); - } - fprintf(outfile, ") "); + fprintf(outfile, " recv (stream_id=%d, noind=%d) ", frame->hd.stream_id, + (flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0); print_nv(&nv); fflush(outfile); @@ -388,11 +429,10 @@ int verbose_on_invalid_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, - int lib_error_code, + uint32_t error_code, void *user_data) { print_timer(); - fprintf(outfile, " [INVALID; error=%s] recv ", - nghttp2_strerror(lib_error_code)); + fprintf(outfile, " [INVALID; status=%s] recv ", strstatus(error_code)); print_frame(PRINT_RECV, frame); fflush(outfile); return 0; @@ -424,15 +464,6 @@ return 0; } -int verbose_error_callback(nghttp2_session *session, const char *msg, - size_t len, void *user_data) { - print_timer(); - fprintf(outfile, " [ERROR] %.*s\n", (int)len, msg); - fflush(outfile); - - return 0; -} - namespace { std::chrono::steady_clock::time_point base_tv; } // namespace @@ -451,7 +482,7 @@ size_t inlen) { int rv; z_stream zst; - uint8_t temp_out[8_k]; + uint8_t temp_out[8192]; auto temp_outlen = sizeof(temp_out); zst.next_in = Z_NULL; diff -Nru nghttp2-1.13.0/src/app_helper.h nghttp2-0.6.7/src/app_helper.h --- nghttp2-1.13.0/src/app_helper.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/app_helper.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,11 +27,9 @@ #include "nghttp2_config.h" -#include +#include #include -#ifdef HAVE_SYS_TIME_H #include -#endif // HAVE_SYS_TIME_H #include #include @@ -51,7 +49,8 @@ int verbose_on_invalid_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, - int lib_error_code, void *user_data); + uint32_t error_code, + void *user_data); int verbose_on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame, void *user_data); @@ -60,9 +59,6 @@ int32_t stream_id, const uint8_t *data, size_t len, void *user_data); -int verbose_error_callback(nghttp2_session *session, const char *msg, - size_t len, void *user_data); - // Returns difference between |a| and |b| in milliseconds, assuming // |a| is more recent than |b|. template diff -Nru nghttp2-1.13.0/src/asio_client_request.cc nghttp2-0.6.7/src/asio_client_request.cc --- nghttp2-1.13.0/src/asio_client_request.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_request.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "nghttp2_config.h" - -#include - -#include "asio_client_request_impl.h" - -#include "template.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -request::request() : impl_(make_unique()) {} - -request::~request() {} - -void request::write_trailer(header_map h) const { - impl_->write_trailer(std::move(h)); -} - -void request::cancel(uint32_t error_code) const { impl_->cancel(error_code); } - -void request::on_response(response_cb cb) const { - impl_->on_response(std::move(cb)); -} - -void request::on_push(request_cb cb) const { impl_->on_push(std::move(cb)); } - -void request::on_close(close_cb cb) const { impl_->on_close(std::move(cb)); } - -const uri_ref &request::uri() const { return impl_->uri(); } - -const std::string &request::method() const { return impl_->method(); } - -const header_map &request::header() const { return impl_->header(); } - -void request::resume() const { impl_->resume(); } - -request_impl &request::impl() const { return *impl_; } - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_client_request_impl.cc nghttp2-0.6.7/src/asio_client_request_impl.cc --- nghttp2-1.13.0/src/asio_client_request_impl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_request_impl.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_client_request_impl.h" - -#include "asio_client_stream.h" -#include "asio_client_session_impl.h" -#include "template.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -request_impl::request_impl() : strm_(nullptr), header_buffer_size_(0) {} - -void request_impl::write_trailer(header_map h) { - auto sess = strm_->session(); - sess->write_trailer(*strm_, std::move(h)); -} - -void request_impl::cancel(uint32_t error_code) { - auto sess = strm_->session(); - sess->cancel(*strm_, error_code); -} - -void request_impl::on_response(response_cb cb) { response_cb_ = std::move(cb); } - -void request_impl::call_on_response(response &res) { - if (response_cb_) { - response_cb_(res); - } -} - -void request_impl::on_push(request_cb cb) { push_request_cb_ = std::move(cb); } - -void request_impl::call_on_push(request &push_req) { - if (push_request_cb_) { - push_request_cb_(push_req); - } -}; - -void request_impl::on_close(close_cb cb) { close_cb_ = std::move(cb); } - -void request_impl::call_on_close(uint32_t error_code) { - if (close_cb_) { - close_cb_(error_code); - } -} - -void request_impl::on_read(generator_cb cb) { generator_cb_ = std::move(cb); } - -generator_cb::result_type request_impl::call_on_read(uint8_t *buf, - std::size_t len, - uint32_t *data_flags) { - if (generator_cb_) { - return generator_cb_(buf, len, data_flags); - } - - *data_flags |= NGHTTP2_DATA_FLAG_EOF; - - return 0; -} - -void request_impl::resume() { - auto sess = strm_->session(); - sess->resume(*strm_); -} - -void request_impl::header(header_map h) { header_ = std::move(h); } - -header_map &request_impl::header() { return header_; } - -const header_map &request_impl::header() const { return header_; } - -void request_impl::stream(class stream *strm) { strm_ = strm; } - -void request_impl::uri(uri_ref uri) { uri_ = std::move(uri); } - -const uri_ref &request_impl::uri() const { return uri_; } - -uri_ref &request_impl::uri() { return uri_; } - -void request_impl::method(std::string s) { method_ = std::move(s); } - -const std::string &request_impl::method() const { return method_; } - -size_t request_impl::header_buffer_size() const { return header_buffer_size_; } - -void request_impl::update_header_buffer_size(size_t len) { - header_buffer_size_ += len; -} - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_client_request_impl.h nghttp2-0.6.7/src/asio_client_request_impl.h --- nghttp2-1.13.0/src/asio_client_request_impl.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_request_impl.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_CLIENT_REQUEST_IMPL_H -#define ASIO_CLIENT_REQUEST_IMPL_H - -#include "nghttp2_config.h" - -#include - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -class response; -class stream; - -class request_impl { -public: - request_impl(); - - request_impl(const request_impl &) = delete; - request_impl &operator=(const request_impl &) = delete; - - void write_trailer(header_map h); - - void cancel(uint32_t error_code); - - void on_response(response_cb cb); - void call_on_response(response &res); - - void on_push(request_cb cb); - void call_on_push(request &push_req); - - void on_close(close_cb cb); - void call_on_close(uint32_t error_code); - - void on_read(generator_cb cb); - generator_cb::result_type call_on_read(uint8_t *buf, std::size_t len, - uint32_t *data_flags); - - void resume(); - - void header(header_map h); - header_map &header(); - const header_map &header() const; - - void stream(class stream *strm); - - void uri(uri_ref uri); - const uri_ref &uri() const; - uri_ref &uri(); - - void method(std::string s); - const std::string &method() const; - - size_t header_buffer_size() const; - void update_header_buffer_size(size_t len); - -private: - header_map header_; - response_cb response_cb_; - request_cb push_request_cb_; - close_cb close_cb_; - generator_cb generator_cb_; - class stream *strm_; - uri_ref uri_; - std::string method_; - size_t header_buffer_size_; -}; - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 - -#endif // ASIO_CLIENT_REQUEST_IMPL_H diff -Nru nghttp2-1.13.0/src/asio_client_response.cc nghttp2-0.6.7/src/asio_client_response.cc --- nghttp2-1.13.0/src/asio_client_response.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_response.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "nghttp2_config.h" - -#include - -#include "asio_client_response_impl.h" - -#include "template.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -response::response() : impl_(make_unique()) {} - -response::~response() {} - -void response::on_data(data_cb cb) const { impl_->on_data(std::move(cb)); } - -int response::status_code() const { return impl_->status_code(); } - -int64_t response::content_length() const { return impl_->content_length(); } - -const header_map &response::header() const { return impl_->header(); } - -response_impl &response::impl() const { return *impl_; } - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_client_response_impl.cc nghttp2-0.6.7/src/asio_client_response_impl.cc --- nghttp2-1.13.0/src/asio_client_response_impl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_response_impl.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_client_response_impl.h" - -#include "template.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -response_impl::response_impl() - : content_length_(-1), header_buffer_size_(0), status_code_(0) {} - -void response_impl::on_data(data_cb cb) { data_cb_ = std::move(cb); } - -void response_impl::call_on_data(const uint8_t *data, std::size_t len) { - if (data_cb_) { - data_cb_(data, len); - } -} - -void response_impl::status_code(int sc) { status_code_ = sc; } - -int response_impl::status_code() const { return status_code_; } - -void response_impl::content_length(int64_t n) { content_length_ = n; } - -int64_t response_impl::content_length() const { return content_length_; } - -header_map &response_impl::header() { return header_; } - -const header_map &response_impl::header() const { return header_; } - -size_t response_impl::header_buffer_size() const { return header_buffer_size_; } - -void response_impl::update_header_buffer_size(size_t len) { - header_buffer_size_ += len; -} - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_client_response_impl.h nghttp2-0.6.7/src/asio_client_response_impl.h --- nghttp2-1.13.0/src/asio_client_response_impl.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_response_impl.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_CLIENT_RESPONSE_IMPL_H -#define ASIO_CLIENT_RESPONSE_IMPL_H - -#include "nghttp2_config.h" - -#include - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -class response_impl { -public: - response_impl(); - - response_impl(const response_impl &) = delete; - response_impl &operator=(const response_impl &) = delete; - - void on_data(data_cb cb); - - void call_on_data(const uint8_t *data, std::size_t len); - - void status_code(int sc); - int status_code() const; - - void content_length(int64_t n); - int64_t content_length() const; - - header_map &header(); - const header_map &header() const; - - size_t header_buffer_size() const; - void update_header_buffer_size(size_t len); - -private: - data_cb data_cb_; - - header_map header_; - - int64_t content_length_; - size_t header_buffer_size_; - int status_code_; -}; - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 - -#endif // ASIO_CLIENT_RESPONSE_IMPL_H diff -Nru nghttp2-1.13.0/src/asio_client_session.cc nghttp2-0.6.7/src/asio_client_session.cc --- nghttp2-1.13.0/src/asio_client_session.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_session.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,124 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "nghttp2_config.h" - -#include - -#include "asio_client_session_tcp_impl.h" -#include "asio_client_session_tls_impl.h" -#include "asio_common.h" -#include "template.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -using boost::asio::ip::tcp; - -session::session(boost::asio::io_service &io_service, const std::string &host, - const std::string &service) - : impl_(std::make_shared( - io_service, host, service, boost::posix_time::seconds(60))) { - impl_->start_resolve(host, service); -} - -session::session(boost::asio::io_service &io_service, const std::string &host, - const std::string &service, - const boost::posix_time::time_duration &connect_timeout) - : impl_(std::make_shared(io_service, host, service, - connect_timeout)) { - impl_->start_resolve(host, service); -} - -session::session(boost::asio::io_service &io_service, - boost::asio::ssl::context &tls_ctx, const std::string &host, - const std::string &service) - : impl_(std::make_shared( - io_service, tls_ctx, host, service, boost::posix_time::seconds(60))) { - impl_->start_resolve(host, service); -} - -session::session(boost::asio::io_service &io_service, - boost::asio::ssl::context &tls_ctx, const std::string &host, - const std::string &service, - const boost::posix_time::time_duration &connect_timeout) - : impl_(std::make_shared(io_service, tls_ctx, host, - service, connect_timeout)) { - impl_->start_resolve(host, service); -} - -session::~session() {} - -session::session(session &&other) noexcept : impl_(std::move(other.impl_)) {} - -session &session::operator=(session &&other) noexcept { - if (this == &other) { - return *this; - } - - impl_ = std::move(other.impl_); - return *this; -} - -void session::on_connect(connect_cb cb) const { - impl_->on_connect(std::move(cb)); -} - -void session::on_error(error_cb cb) const { impl_->on_error(std::move(cb)); } - -void session::shutdown() const { impl_->shutdown(); } - -boost::asio::io_service &session::io_service() const { - return impl_->io_service(); -} - -const request *session::submit(boost::system::error_code &ec, - const std::string &method, - const std::string &uri, header_map h) const { - return impl_->submit(ec, method, uri, generator_cb(), std::move(h)); -} - -const request *session::submit(boost::system::error_code &ec, - const std::string &method, - const std::string &uri, std::string data, - header_map h) const { - return impl_->submit(ec, method, uri, string_generator(std::move(data)), - std::move(h)); -} - -const request *session::submit(boost::system::error_code &ec, - const std::string &method, - const std::string &uri, generator_cb cb, - header_map h) const { - return impl_->submit(ec, method, uri, std::move(cb), std::move(h)); -} - -void session::read_timeout(const boost::posix_time::time_duration &t) { - impl_->read_timeout(t); -} - -} // namespace client -} // namespace asio_http2 -} // nghttp2 diff -Nru nghttp2-1.13.0/src/asio_client_session_impl.cc nghttp2-0.6.7/src/asio_client_session_impl.cc --- nghttp2-1.13.0/src/asio_client_session_impl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_session_impl.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,730 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_client_session_impl.h" - -#include - -#include "asio_client_stream.h" -#include "asio_client_request_impl.h" -#include "asio_client_response_impl.h" -#include "asio_common.h" -#include "template.h" -#include "util.h" -#include "http2.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -session_impl::session_impl( - boost::asio::io_service &io_service, - const boost::posix_time::time_duration &connect_timeout) - : wblen_(0), - io_service_(io_service), - resolver_(io_service), - deadline_(io_service), - connect_timeout_(connect_timeout), - read_timeout_(boost::posix_time::seconds(60)), - session_(nullptr), - data_pending_(nullptr), - data_pendinglen_(0), - writing_(false), - inside_callback_(false), - stopped_(false) {} - -session_impl::~session_impl() { - // finish up all active stream - for (auto &p : streams_) { - auto &strm = p.second; - auto &req = strm->request().impl(); - req.call_on_close(NGHTTP2_INTERNAL_ERROR); - } - - nghttp2_session_del(session_); -} - -void session_impl::start_resolve(const std::string &host, - const std::string &service) { - deadline_.expires_from_now(connect_timeout_); - - auto self = this->shared_from_this(); - - resolver_.async_resolve({host, service}, - [this, self](const boost::system::error_code &ec, - tcp::resolver::iterator endpoint_it) { - if (ec) { - not_connected(ec); - return; - } - - start_connect(endpoint_it); - }); - - deadline_.async_wait(std::bind(&session_impl::handle_deadline, self)); -} - -void session_impl::handle_deadline() { - if (stopped_) { - return; - } - - if (deadline_.expires_at() <= - boost::asio::deadline_timer::traits_type::now()) { - call_error_cb(boost::asio::error::timed_out); - stop(); - deadline_.expires_at(boost::posix_time::pos_infin); - return; - } - - deadline_.async_wait( - std::bind(&session_impl::handle_deadline, this->shared_from_this())); -} - -void session_impl::connected(tcp::resolver::iterator endpoint_it) { - if (!setup_session()) { - return; - } - - socket().set_option(boost::asio::ip::tcp::no_delay(true)); - - do_write(); - do_read(); - - auto &connect_cb = on_connect(); - if (connect_cb) { - connect_cb(endpoint_it); - } -} - -void session_impl::not_connected(const boost::system::error_code &ec) { - call_error_cb(ec); - stop(); -} - -void session_impl::on_connect(connect_cb cb) { connect_cb_ = std::move(cb); } - -void session_impl::on_error(error_cb cb) { error_cb_ = std::move(cb); } - -const connect_cb &session_impl::on_connect() const { return connect_cb_; } - -const error_cb &session_impl::on_error() const { return error_cb_; } - -void session_impl::call_error_cb(const boost::system::error_code &ec) { - if (stopped_) { - return; - } - auto &error_cb = on_error(); - if (!error_cb) { - return; - } - error_cb(ec); -} - -namespace { -int on_begin_headers_callback(nghttp2_session *session, - const nghttp2_frame *frame, void *user_data) { - if (frame->hd.type != NGHTTP2_PUSH_PROMISE) { - return 0; - } - - auto sess = static_cast(user_data); - sess->create_push_stream(frame->push_promise.promised_stream_id); - - return 0; -} -} // namespace - -namespace { -int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, - const uint8_t *name, size_t namelen, - const uint8_t *value, size_t valuelen, uint8_t flags, - void *user_data) { - auto sess = static_cast(user_data); - stream *strm; - - switch (frame->hd.type) { - case NGHTTP2_HEADERS: { - strm = sess->find_stream(frame->hd.stream_id); - if (!strm) { - return 0; - } - - // ignore trailers - if (frame->headers.cat == NGHTTP2_HCAT_HEADERS && - !strm->expect_final_response()) { - return 0; - } - - auto token = http2::lookup_token(name, namelen); - - auto &res = strm->response().impl(); - if (token == http2::HD__STATUS) { - res.status_code(util::parse_uint(value, valuelen)); - } else { - if (res.header_buffer_size() + namelen + valuelen > 64_k) { - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, - frame->hd.stream_id, NGHTTP2_INTERNAL_ERROR); - break; - } - res.update_header_buffer_size(namelen + valuelen); - - if (token == http2::HD_CONTENT_LENGTH) { - res.content_length(util::parse_uint(value, valuelen)); - } - - res.header().emplace( - std::string(name, name + namelen), - header_value{std::string(value, value + valuelen), - (flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0}); - } - break; - } - case NGHTTP2_PUSH_PROMISE: { - strm = sess->find_stream(frame->push_promise.promised_stream_id); - if (!strm) { - return 0; - } - - auto &req = strm->request().impl(); - auto &uri = req.uri(); - - switch (http2::lookup_token(name, namelen)) { - case http2::HD__METHOD: - req.method(std::string(value, value + valuelen)); - break; - case http2::HD__SCHEME: - uri.scheme.assign(value, value + valuelen); - break; - case http2::HD__PATH: - split_path(uri, value, value + valuelen); - break; - case http2::HD__AUTHORITY: - uri.host.assign(value, value + valuelen); - break; - case http2::HD_HOST: - if (uri.host.empty()) { - uri.host.assign(value, value + valuelen); - } - // fall through - default: - if (req.header_buffer_size() + namelen + valuelen > 64_k) { - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, - frame->hd.stream_id, NGHTTP2_INTERNAL_ERROR); - break; - } - req.update_header_buffer_size(namelen + valuelen); - - req.header().emplace( - std::string(name, name + namelen), - header_value{std::string(value, value + valuelen), - (flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0}); - } - - break; - } - default: - return 0; - } - - return 0; -} -} // namespace - -namespace { -int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, - void *user_data) { - auto sess = static_cast(user_data); - auto strm = sess->find_stream(frame->hd.stream_id); - - switch (frame->hd.type) { - case NGHTTP2_DATA: { - if (!strm) { - return 0; - } - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - strm->response().impl().call_on_data(nullptr, 0); - } - break; - } - case NGHTTP2_HEADERS: { - if (!strm) { - return 0; - } - - // ignore trailers - if (frame->headers.cat == NGHTTP2_HCAT_HEADERS && - !strm->expect_final_response()) { - return 0; - } - - if (strm->expect_final_response()) { - // wait for final response - return 0; - } - - auto &req = strm->request().impl(); - req.call_on_response(strm->response()); - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - strm->response().impl().call_on_data(nullptr, 0); - } - break; - } - case NGHTTP2_PUSH_PROMISE: { - if (!strm) { - return 0; - } - - auto push_strm = sess->find_stream(frame->push_promise.promised_stream_id); - if (!push_strm) { - return 0; - } - - strm->request().impl().call_on_push(push_strm->request()); - - break; - } - } - return 0; -} -} // namespace - -namespace { -int 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) { - auto sess = static_cast(user_data); - auto strm = sess->find_stream(stream_id); - if (!strm) { - return 0; - } - - auto &res = strm->response().impl(); - res.call_on_data(data, len); - - return 0; -} -} // namespace - -namespace { -int on_stream_close_callback(nghttp2_session *session, int32_t stream_id, - uint32_t error_code, void *user_data) { - auto sess = static_cast(user_data); - auto strm = sess->pop_stream(stream_id); - if (!strm) { - return 0; - } - - strm->request().impl().call_on_close(error_code); - - return 0; -} -} // namespace - -bool session_impl::setup_session() { - nghttp2_session_callbacks *callbacks; - nghttp2_session_callbacks_new(&callbacks); - auto cb_del = defer(nghttp2_session_callbacks_del, callbacks); - - nghttp2_session_callbacks_set_on_begin_headers_callback( - callbacks, on_begin_headers_callback); - nghttp2_session_callbacks_set_on_header_callback(callbacks, - on_header_callback); - nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, - on_frame_recv_callback); - nghttp2_session_callbacks_set_on_data_chunk_recv_callback( - callbacks, on_data_chunk_recv_callback); - nghttp2_session_callbacks_set_on_stream_close_callback( - callbacks, on_stream_close_callback); - - auto rv = nghttp2_session_client_new(&session_, callbacks, this); - if (rv != 0) { - call_error_cb(make_error_code(static_cast(rv))); - return false; - } - - const uint32_t window_size = 256_m; - - std::array iv{ - {{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}, - // typically client is just a *sink* and just process data as - // much as possible. Use large window size by default. - {NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, window_size}}}; - nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, iv.data(), iv.size()); - // increase connection window size up to window_size - nghttp2_session_set_local_window_size(session_, NGHTTP2_FLAG_NONE, 0, - window_size); - return true; -} - -int session_impl::write_trailer(stream &strm, header_map h) { - int rv; - auto nva = std::vector(); - nva.reserve(h.size()); - for (auto &hd : h) { - nva.push_back(nghttp2::http2::make_nv(hd.first, hd.second.value, - hd.second.sensitive)); - } - - rv = nghttp2_submit_trailer(session_, strm.stream_id(), nva.data(), - nva.size()); - - if (rv != 0) { - return -1; - } - - signal_write(); - - return 0; -} - -void session_impl::cancel(stream &strm, uint32_t error_code) { - if (stopped_) { - return; - } - - nghttp2_submit_rst_stream(session_, NGHTTP2_FLAG_NONE, strm.stream_id(), - error_code); - signal_write(); -} - -void session_impl::resume(stream &strm) { - if (stopped_) { - return; - } - - nghttp2_session_resume_data(session_, strm.stream_id()); - signal_write(); -} - -stream *session_impl::find_stream(int32_t stream_id) { - auto it = streams_.find(stream_id); - if (it == std::end(streams_)) { - return nullptr; - } - return (*it).second.get(); -} - -std::unique_ptr session_impl::pop_stream(int32_t stream_id) { - auto it = streams_.find(stream_id); - if (it == std::end(streams_)) { - return nullptr; - } - auto strm = std::move((*it).second); - streams_.erase(it); - return strm; -} - -stream *session_impl::create_push_stream(int32_t stream_id) { - auto strm = create_stream(); - strm->stream_id(stream_id); - auto p = streams_.emplace(stream_id, std::move(strm)); - assert(p.second); - return (*p.first).second.get(); -} - -std::unique_ptr session_impl::create_stream() { - return make_unique(this); -} - -const request *session_impl::submit(boost::system::error_code &ec, - const std::string &method, - const std::string &uri, generator_cb cb, - header_map h) { - ec.clear(); - - if (stopped_) { - ec = make_error_code(static_cast(NGHTTP2_INTERNAL_ERROR)); - return nullptr; - } - - http_parser_url u{}; - // TODO Handle CONNECT method - if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) { - ec = make_error_code(boost::system::errc::invalid_argument); - return nullptr; - } - - if ((u.field_set & (1 << UF_SCHEMA)) == 0 || - (u.field_set & (1 << UF_HOST)) == 0) { - ec = make_error_code(boost::system::errc::invalid_argument); - return nullptr; - } - - auto strm = create_stream(); - auto &req = strm->request().impl(); - auto &uref = req.uri(); - - http2::copy_url_component(uref.scheme, &u, UF_SCHEMA, uri.c_str()); - http2::copy_url_component(uref.host, &u, UF_HOST, uri.c_str()); - http2::copy_url_component(uref.raw_path, &u, UF_PATH, uri.c_str()); - http2::copy_url_component(uref.raw_query, &u, UF_QUERY, uri.c_str()); - - if (util::ipv6_numeric_addr(uref.host.c_str())) { - uref.host = "[" + uref.host; - uref.host += ']'; - } - if (u.field_set & (1 << UF_PORT)) { - uref.host += ':'; - uref.host += util::utos(u.port); - } - - if (uref.raw_path.empty()) { - uref.raw_path = "/"; - } - - uref.path = percent_decode(uref.raw_path); - - auto path = uref.raw_path; - if (u.field_set & (1 << UF_QUERY)) { - path += '?'; - path += uref.raw_query; - } - - auto nva = std::vector(); - nva.reserve(3 + h.size()); - nva.push_back(http2::make_nv_ls(":method", method)); - nva.push_back(http2::make_nv_ls(":scheme", uref.scheme)); - nva.push_back(http2::make_nv_ls(":path", path)); - nva.push_back(http2::make_nv_ls(":authority", uref.host)); - for (auto &kv : h) { - nva.push_back( - http2::make_nv(kv.first, kv.second.value, kv.second.sensitive)); - } - - req.header(std::move(h)); - - nghttp2_data_provider *prdptr = nullptr; - nghttp2_data_provider prd; - - if (cb) { - strm->request().impl().on_read(std::move(cb)); - prd.source.ptr = strm.get(); - prd.read_callback = - [](nghttp2_session *session, int32_t stream_id, uint8_t *buf, - size_t length, uint32_t *data_flags, nghttp2_data_source *source, - void *user_data) -> ssize_t { - auto strm = static_cast(source->ptr); - return strm->request().impl().call_on_read(buf, length, data_flags); - }; - prdptr = &prd; - } - - auto stream_id = nghttp2_submit_request(session_, nullptr, nva.data(), - nva.size(), prdptr, strm.get()); - if (stream_id < 0) { - ec = make_error_code(static_cast(stream_id)); - return nullptr; - } - - signal_write(); - - strm->stream_id(stream_id); - - auto p = streams_.emplace(stream_id, std::move(strm)); - assert(p.second); - return &(*p.first).second->request(); -} - -void session_impl::shutdown() { - if (stopped_) { - return; - } - - nghttp2_session_terminate_session(session_, NGHTTP2_NO_ERROR); - signal_write(); -} - -boost::asio::io_service &session_impl::io_service() { return io_service_; } - -void session_impl::signal_write() { - if (!inside_callback_) { - do_write(); - } -} - -bool session_impl::should_stop() const { - return !writing_ && !nghttp2_session_want_read(session_) && - !nghttp2_session_want_write(session_); -} - -namespace { -struct callback_guard { - callback_guard(session_impl &sess) : sess(sess) { sess.enter_callback(); } - ~callback_guard() { sess.leave_callback(); } - - session_impl &sess; -}; -} // namespace - -void session_impl::enter_callback() { - assert(!inside_callback_); - inside_callback_ = true; -} - -void session_impl::leave_callback() { - assert(inside_callback_); - inside_callback_ = false; -} - -void session_impl::do_read() { - if (stopped_) { - return; - } - - deadline_.expires_from_now(read_timeout_); - - auto self = this->shared_from_this(); - - read_socket([this, self](const boost::system::error_code &ec, - std::size_t bytes_transferred) { - if (ec) { - if (!should_stop()) { - call_error_cb(ec); - } - stop(); - return; - } - - { - callback_guard cg(*this); - - auto rv = - nghttp2_session_mem_recv(session_, rb_.data(), bytes_transferred); - - if (rv != static_cast(bytes_transferred)) { - call_error_cb(make_error_code( - static_cast(rv < 0 ? rv : NGHTTP2_ERR_PROTO))); - stop(); - return; - } - } - - do_write(); - - if (should_stop()) { - stop(); - return; - } - - do_read(); - }); -} - -void session_impl::do_write() { - if (stopped_) { - return; - } - - if (writing_) { - return; - } - - if (data_pending_) { - std::copy_n(data_pending_, data_pendinglen_, std::begin(wb_) + wblen_); - - wblen_ += data_pendinglen_; - - data_pending_ = nullptr; - data_pendinglen_ = 0; - } - - { - callback_guard cg(*this); - - for (;;) { - const uint8_t *data; - auto n = nghttp2_session_mem_send(session_, &data); - if (n < 0) { - call_error_cb(make_error_code(static_cast(n))); - stop(); - return; - } - - if (n == 0) { - break; - } - - if (wblen_ + n > wb_.size()) { - data_pending_ = data; - data_pendinglen_ = n; - - break; - } - - std::copy_n(data, n, std::begin(wb_) + wblen_); - - wblen_ += n; - } - } - - if (wblen_ == 0) { - if (should_stop()) { - stop(); - } - return; - } - - writing_ = true; - - // Reset read deadline here, because normally client is sending - // something, it does not expect timeout while doing it. - deadline_.expires_from_now(read_timeout_); - - auto self = this->shared_from_this(); - - write_socket( - [this, self](const boost::system::error_code &ec, std::size_t n) { - if (ec) { - call_error_cb(ec); - stop(); - return; - } - - wblen_ = 0; - writing_ = false; - - do_write(); - }); -} - -void session_impl::stop() { - if (stopped_) { - return; - } - - shutdown_socket(); - deadline_.cancel(); - stopped_ = true; -} - -bool session_impl::stopped() const { return stopped_; } - -void session_impl::read_timeout(const boost::posix_time::time_duration &t) { - read_timeout_ = t; -} - -} // namespace client -} // namespace asio_http2 -} // nghttp2 diff -Nru nghttp2-1.13.0/src/asio_client_session_impl.h nghttp2-0.6.7/src/asio_client_session_impl.h --- nghttp2-1.13.0/src/asio_client_session_impl.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_session_impl.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,137 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_CLIENT_SESSION_IMPL_H -#define ASIO_CLIENT_SESSION_IMPL_H - -#include "nghttp2_config.h" - -#include - -#include - -#include "template.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -class stream; - -using boost::asio::ip::tcp; - -class session_impl : public std::enable_shared_from_this { -public: - session_impl(boost::asio::io_service &io_service, - const boost::posix_time::time_duration &connect_timeout); - virtual ~session_impl(); - - void start_resolve(const std::string &host, const std::string &service); - - void connected(tcp::resolver::iterator endpoint_it); - void not_connected(const boost::system::error_code &ec); - - void on_connect(connect_cb cb); - void on_error(error_cb cb); - - const connect_cb &on_connect() const; - const error_cb &on_error() const; - - int write_trailer(stream &strm, header_map h); - - void cancel(stream &strm, uint32_t error_code); - void resume(stream &strm); - - std::unique_ptr create_stream(); - std::unique_ptr pop_stream(int32_t stream_id); - stream *create_push_stream(int32_t stream_id); - stream *find_stream(int32_t stream_id); - - const request *submit(boost::system::error_code &ec, - const std::string &method, const std::string &uri, - generator_cb cb, header_map h); - - virtual void start_connect(tcp::resolver::iterator endpoint_it) = 0; - virtual tcp::socket &socket() = 0; - virtual void read_socket(std::function< - void(const boost::system::error_code &ec, std::size_t n)> h) = 0; - virtual void write_socket(std::function< - void(const boost::system::error_code &ec, std::size_t n)> h) = 0; - virtual void shutdown_socket() = 0; - - void shutdown(); - - boost::asio::io_service &io_service(); - - void signal_write(); - - void enter_callback(); - void leave_callback(); - - void do_read(); - void do_write(); - - void read_timeout(const boost::posix_time::time_duration &t); - - void stop(); - bool stopped() const; - -protected: - boost::array rb_; - boost::array wb_; - std::size_t wblen_; - -private: - bool should_stop() const; - bool setup_session(); - void call_error_cb(const boost::system::error_code &ec); - void handle_deadline(); - - boost::asio::io_service &io_service_; - tcp::resolver resolver_; - - std::map> streams_; - - connect_cb connect_cb_; - error_cb error_cb_; - - boost::asio::deadline_timer deadline_; - boost::posix_time::time_duration connect_timeout_; - boost::posix_time::time_duration read_timeout_; - - nghttp2_session *session_; - - const uint8_t *data_pending_; - std::size_t data_pendinglen_; - - bool writing_; - bool inside_callback_; - bool stopped_; -}; - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 - -#endif // ASIO_CLIENT_SESSION_IMPL_H diff -Nru nghttp2-1.13.0/src/asio_client_session_tcp_impl.cc nghttp2-0.6.7/src/asio_client_session_tcp_impl.cc --- nghttp2-1.13.0/src/asio_client_session_tcp_impl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_session_tcp_impl.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_client_session_tcp_impl.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -session_tcp_impl::session_tcp_impl( - boost::asio::io_service &io_service, const std::string &host, - const std::string &service, - const boost::posix_time::time_duration &connect_timeout) - : session_impl(io_service, connect_timeout), socket_(io_service) {} - -session_tcp_impl::~session_tcp_impl() {} - -void session_tcp_impl::start_connect(tcp::resolver::iterator endpoint_it) { - boost::asio::async_connect(socket_, endpoint_it, - [this](const boost::system::error_code &ec, - tcp::resolver::iterator endpoint_it) { - if (stopped()) { - return; - } - - if (ec) { - not_connected(ec); - return; - } - - connected(endpoint_it); - }); -} - -tcp::socket &session_tcp_impl::socket() { return socket_; } - -void session_tcp_impl::read_socket( - std::function h) { - socket_.async_read_some(boost::asio::buffer(rb_), h); -} - -void session_tcp_impl::write_socket( - std::function h) { - boost::asio::async_write(socket_, boost::asio::buffer(wb_, wblen_), h); -} - -void session_tcp_impl::shutdown_socket() { - boost::system::error_code ignored_ec; - socket_.close(ignored_ec); -} - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_client_session_tcp_impl.h nghttp2-0.6.7/src/asio_client_session_tcp_impl.h --- nghttp2-1.13.0/src/asio_client_session_tcp_impl.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_session_tcp_impl.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_CLIENT_SESSION_TCP_IMPL_H -#define ASIO_CLIENT_SESSION_TCP_IMPL_H - -#include "asio_client_session_impl.h" - -#include - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -using boost::asio::ip::tcp; - -class session_tcp_impl : public session_impl { -public: - session_tcp_impl(boost::asio::io_service &io_service, const std::string &host, - const std::string &service, - const boost::posix_time::time_duration &connect_timeout); - virtual ~session_tcp_impl(); - - virtual void start_connect(tcp::resolver::iterator endpoint_it); - virtual tcp::socket &socket(); - virtual void read_socket(std::function< - void(const boost::system::error_code &ec, std::size_t n)> h); - virtual void write_socket(std::function< - void(const boost::system::error_code &ec, std::size_t n)> h); - virtual void shutdown_socket(); - -private: - tcp::socket socket_; -}; - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 - -#endif // ASIO_CLIENT_SESSION_TCP_IMPL_H diff -Nru nghttp2-1.13.0/src/asio_client_session_tls_impl.cc nghttp2-0.6.7/src/asio_client_session_tls_impl.cc --- nghttp2-1.13.0/src/asio_client_session_tls_impl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_session_tls_impl.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_client_session_tls_impl.h" -#include "asio_common.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -session_tls_impl::session_tls_impl( - boost::asio::io_service &io_service, boost::asio::ssl::context &tls_ctx, - const std::string &host, const std::string &service, - const boost::posix_time::time_duration &connect_timeout) - : session_impl(io_service, connect_timeout), socket_(io_service, tls_ctx) { - // this callback setting is no effect is - // ssl::context::set_verify_mode(boost::asio::ssl::verify_peer) is - // not used, which is what we want. - socket_.set_verify_callback(boost::asio::ssl::rfc2818_verification(host)); -} - -session_tls_impl::~session_tls_impl() {} - -void session_tls_impl::start_connect(tcp::resolver::iterator endpoint_it) { - boost::asio::async_connect( - socket(), endpoint_it, [this](const boost::system::error_code &ec, - tcp::resolver::iterator endpoint_it) { - if (stopped()) { - return; - } - - if (ec) { - not_connected(ec); - return; - } - - socket_.async_handshake( - boost::asio::ssl::stream_base::client, - [this, endpoint_it](const boost::system::error_code &ec) { - if (stopped()) { - return; - } - - if (ec) { - not_connected(ec); - return; - } - - if (!tls_h2_negotiated(socket_)) { - not_connected(make_error_code( - NGHTTP2_ASIO_ERR_TLS_NO_APP_PROTO_NEGOTIATED)); - return; - } - - connected(endpoint_it); - }); - }); -} - -tcp::socket &session_tls_impl::socket() { return socket_.next_layer(); } - -void session_tls_impl::read_socket( - std::function h) { - socket_.async_read_some(boost::asio::buffer(rb_), h); -} - -void session_tls_impl::write_socket( - std::function h) { - boost::asio::async_write(socket_, boost::asio::buffer(wb_, wblen_), h); -} - -void session_tls_impl::shutdown_socket() { - boost::system::error_code ignored_ec; - socket_.lowest_layer().close(ignored_ec); -} - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_client_session_tls_impl.h nghttp2-0.6.7/src/asio_client_session_tls_impl.h --- nghttp2-1.13.0/src/asio_client_session_tls_impl.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_session_tls_impl.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_CLIENT_SESSION_TLS_IMPL_H -#define ASIO_CLIENT_SESSION_TLS_IMPL_H - -#include "asio_client_session_impl.h" - -#include - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -using boost::asio::ip::tcp; - -using ssl_socket = boost::asio::ssl::stream; - -class session_tls_impl : public session_impl { -public: - session_tls_impl(boost::asio::io_service &io_service, - boost::asio::ssl::context &tls_ctx, const std::string &host, - const std::string &service, - const boost::posix_time::time_duration &connect_timeout); - virtual ~session_tls_impl(); - - virtual void start_connect(tcp::resolver::iterator endpoint_it); - virtual tcp::socket &socket(); - virtual void read_socket(std::function< - void(const boost::system::error_code &ec, std::size_t n)> h); - virtual void write_socket(std::function< - void(const boost::system::error_code &ec, std::size_t n)> h); - virtual void shutdown_socket(); - -private: - ssl_socket socket_; -}; - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 - -#endif // ASIO_CLIENT_SESSION_TLS_IMPL_H diff -Nru nghttp2-1.13.0/src/asio_client_stream.cc nghttp2-0.6.7/src/asio_client_stream.cc --- nghttp2-1.13.0/src/asio_client_stream.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_stream.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_client_stream.h" - -#include "asio_client_request_impl.h" -#include "asio_client_response_impl.h" -#include "asio_client_session_impl.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -stream::stream(session_impl *sess) : sess_(sess), stream_id_(0) { - request_.impl().stream(this); -} - -void stream::stream_id(int32_t stream_id) { stream_id_ = stream_id; } - -int32_t stream::stream_id() const { return stream_id_; } - -class request &stream::request() { - return request_; -} - -class response &stream::response() { - return response_; -} - -session_impl *stream::session() const { return sess_; } - -bool stream::expect_final_response() const { - return response_.status_code() / 100 == 1; -} - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_client_stream.h nghttp2-0.6.7/src/asio_client_stream.h --- nghttp2-1.13.0/src/asio_client_stream.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_stream.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_CLIENT_STREAM_H -#define ASIO_CLIENT_STREAM_H - -#include "nghttp2_config.h" - -#include - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -class request; -class response; -class session_impl; - -class stream { -public: - stream(session_impl *sess); - - stream(const stream &) = delete; - stream &operator=(const stream &) = delete; - - void stream_id(int32_t stream_id); - int32_t stream_id() const; - - class request &request(); - class response &response(); - - session_impl *session() const; - - bool expect_final_response() const; - -private: - nghttp2::asio_http2::client::request request_; - nghttp2::asio_http2::client::response response_; - session_impl *sess_; - uint32_t stream_id_; -}; - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 - -#endif // ASIO_CLIENT_STREAM_H diff -Nru nghttp2-1.13.0/src/asio_client_tls_context.cc nghttp2-0.6.7/src/asio_client_tls_context.cc --- nghttp2-1.13.0/src/asio_client_tls_context.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_tls_context.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_client_tls_context.h" - -#include - -#include - -#include "ssl.h" -#include "util.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace client { - -namespace { -int client_select_next_proto_cb(SSL *ssl, unsigned char **out, - unsigned char *outlen, const unsigned char *in, - unsigned int inlen, void *arg) { - if (!util::select_h2(const_cast(out), outlen, in, - inlen)) { - return SSL_TLSEXT_ERR_NOACK; - } - return SSL_TLSEXT_ERR_OK; -} -} // namespace - -boost::system::error_code -configure_tls_context(boost::system::error_code &ec, - boost::asio::ssl::context &tls_ctx) { - ec.clear(); - - auto ctx = tls_ctx.native_handle(); - - SSL_CTX_set_next_proto_select_cb(ctx, client_select_next_proto_cb, nullptr); - -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - auto proto_list = util::get_default_alpn(); - - SSL_CTX_set_alpn_protos(ctx, proto_list.data(), proto_list.size()); -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - return ec; -} - -} // namespace client -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_client_tls_context.h nghttp2-0.6.7/src/asio_client_tls_context.h --- nghttp2-1.13.0/src/asio_client_tls_context.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_client_tls_context.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_CLIENT_TLS_CONTEXT_H -#define ASIO_CLIENT_TLS_CONTEXT_H - -#include "nghttp2_config.h" - -#include - -#endif // ASIO_CLIENT_TLS_CONTEXT_H diff -Nru nghttp2-1.13.0/src/asio_common.cc nghttp2-0.6.7/src/asio_common.cc --- nghttp2-1.13.0/src/asio_common.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_common.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,194 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_common.h" - -#include - -#include "util.h" -#include "template.h" -#include "http2.h" - -namespace nghttp2 { -namespace asio_http2 { - -class nghttp2_category_impl : public boost::system::error_category { -public: - const char *name() const noexcept { return "nghttp2"; } - std::string message(int ev) const { return nghttp2_strerror(ev); } -}; - -const boost::system::error_category &nghttp2_category() noexcept { - static nghttp2_category_impl cat; - return cat; -} - -boost::system::error_code make_error_code(nghttp2_error ev) { - return boost::system::error_code(static_cast(ev), nghttp2_category()); -} - -class nghttp2_asio_category_impl : public boost::system::error_category { -public: - const char *name() const noexcept { return "nghttp2_asio"; } - std::string message(int ev) const { - switch (ev) { - case NGHTTP2_ASIO_ERR_NO_ERROR: - return "no error"; - case NGHTTP2_ASIO_ERR_TLS_NO_APP_PROTO_NEGOTIATED: - return "tls: no application protocol negotiated"; - default: - return "unknown"; - } - } -}; - -const boost::system::error_category &nghttp2_asio_category() noexcept { - static nghttp2_asio_category_impl cat; - return cat; -} - -boost::system::error_code make_error_code(nghttp2_asio_error ev) { - return boost::system::error_code(static_cast(ev), - nghttp2_asio_category()); -} - -generator_cb string_generator(std::string data) { - auto strio = std::make_shared>(std::move(data), - data.size()); - return [strio](uint8_t *buf, size_t len, uint32_t *data_flags) { - auto &data = strio->first; - auto &left = strio->second; - auto n = std::min(len, left); - std::copy_n(data.c_str() + data.size() - left, n, buf); - left -= n; - if (left == 0) { - *data_flags |= NGHTTP2_DATA_FLAG_EOF; - } - return n; - }; -} - -generator_cb deferred_generator() { - return [](uint8_t *buf, size_t len, uint32_t *data_flags) { - return NGHTTP2_ERR_DEFERRED; - }; -} - -template -std::shared_ptr> defer_shared(F &&f, T &&... t) { - return std::make_shared>(std::forward(f), - std::forward(t)...); -} - -generator_cb file_generator(const std::string &path) { - auto fd = open(path.c_str(), O_RDONLY); - if (fd == -1) { - return generator_cb(); - } - - return file_generator_from_fd(fd); -} - -generator_cb file_generator_from_fd(int fd) { - auto d = defer_shared(close, fd); - - return [fd, d](uint8_t *buf, size_t len, uint32_t *data_flags) - -> generator_cb::result_type { - ssize_t n; - while ((n = read(fd, buf, len)) == -1 && errno == EINTR) - ; - - if (n == -1) { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - - if (n == 0) { - *data_flags |= NGHTTP2_DATA_FLAG_EOF; - } - - return n; - }; -} - -bool check_path(const std::string &path) { return util::check_path(path); } - -std::string percent_decode(const std::string &s) { - return util::percent_decode(std::begin(s), std::end(s)); -} - -std::string http_date(int64_t t) { return util::http_date(t); } - -boost::system::error_code host_service_from_uri(boost::system::error_code &ec, - std::string &scheme, - std::string &host, - std::string &service, - const std::string &uri) { - ec.clear(); - - http_parser_url u{}; - if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) { - ec = make_error_code(boost::system::errc::invalid_argument); - return ec; - } - - if ((u.field_set & (1 << UF_SCHEMA)) == 0 || - (u.field_set & (1 << UF_HOST)) == 0) { - ec = make_error_code(boost::system::errc::invalid_argument); - return ec; - } - - http2::copy_url_component(scheme, &u, UF_SCHEMA, uri.c_str()); - http2::copy_url_component(host, &u, UF_HOST, uri.c_str()); - - if (u.field_set & (1 << UF_PORT)) { - http2::copy_url_component(service, &u, UF_PORT, uri.c_str()); - } else { - service = scheme; - } - - return ec; -} - -bool tls_h2_negotiated(ssl_socket &socket) { - auto ssl = socket.native_handle(); - - const unsigned char *next_proto = nullptr; - unsigned int next_proto_len = 0; - - SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (next_proto == nullptr) { - SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - if (next_proto == nullptr) { - return false; - } - - return util::check_h2_is_selected(StringRef{next_proto, next_proto_len}); -} - -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_common.h nghttp2-0.6.7/src/asio_common.h --- nghttp2-1.13.0/src/asio_common.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_common.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_COMMON_H -#define ASIO_COMMON_H - -#include "nghttp2_config.h" - -#include - -#include - -#include "util.h" - -namespace nghttp2 { - -namespace asio_http2 { - -boost::system::error_code make_error_code(nghttp2_error ev); - -boost::system::error_code make_error_code(nghttp2_asio_error ev); - -generator_cb string_generator(std::string data); - -// Returns generator_cb, which just returns NGHTTP2_ERR_DEFERRED -generator_cb deferred_generator(); - -template -void split_path(uri_ref &dst, InputIt first, InputIt last) { - auto path_last = std::find(first, last, '?'); - InputIt query_first; - if (path_last == last) { - query_first = path_last = last; - } else { - query_first = path_last + 1; - } - dst.path = util::percent_decode(first, path_last); - dst.raw_path.assign(first, path_last); - dst.raw_query.assign(query_first, last); -} - -using boost::asio::ip::tcp; - -using ssl_socket = boost::asio::ssl::stream; - -bool tls_h2_negotiated(ssl_socket &socket); - -} // namespace asio_http2 - -} // namespace nghttp2 - -#endif // ASIO_COMMON_H diff -Nru nghttp2-1.13.0/src/asio_connection.h nghttp2-0.6.7/src/asio_connection.h --- nghttp2-1.13.0/src/asio_connection.h 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/asio_connection.h 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,172 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 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. + */ +// We wrote this code based on the original code which has the +// following license: +// +// connection.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_SERVER2_CONNECTION_HPP +#define HTTP_SERVER2_CONNECTION_HPP + +#include "nghttp2_config.h" + +#include + +#include +#include +#include + +#include +#include "asio_http2_handler.h" +#include "util.h" + +namespace nghttp2 { + +namespace asio_http2 { + +namespace server { + +/// Represents a single connection from a client. +template +class connection : public std::enable_shared_from_this>, + private boost::noncopyable { +public: + /// Construct a connection with the given io_service. + template + explicit connection(request_cb cb, boost::asio::io_service &task_io_service, + SocketArgs &&... args) + : socket_(std::forward(args)...), request_cb_(std::move(cb)), + task_io_service_(task_io_service), writing_(false) {} + + /// Start the first asynchronous operation for the connection. + void start() { + handler_ = std::make_shared( + socket_.get_io_service(), task_io_service_, [this]() { do_write(); }, + request_cb_); + if (handler_->start() != 0) { + return; + } + do_read(); + } + + socket_type &socket() { return socket_; } + + void do_read() { + auto self = this->shared_from_this(); + + socket_.async_read_some(boost::asio::buffer(buffer_), + [this, self](const boost::system::error_code &e, + std::size_t bytes_transferred) { + if (!e) { + if (handler_->on_read(buffer_, bytes_transferred) != 0) { + return; + } + + do_write(); + + if (!writing_ && handler_->should_stop()) { + return; + } + + do_read(); + } + + // If an error occurs then no new asynchronous operations are + // started. This means that all shared_ptr references to the + // connection object will disappear and the object will be + // destroyed automatically after this handler returns. The + // connection class's destructor closes the socket. + }); + } + + void do_write() { + auto self = this->shared_from_this(); + + if (writing_) { + return; + } + + int rv; + std::size_t nwrite; + + rv = handler_->on_write(outbuf_, nwrite); + + if (rv != 0) { + return; + } + + if (nwrite == 0) { + return; + } + + writing_ = true; + + boost::asio::async_write( + socket_, boost::asio::buffer(outbuf_, nwrite), + [this, self](const boost::system::error_code &e, std::size_t) { + if (!e) { + writing_ = false; + + do_write(); + } + }); + + // No new asynchronous operations are started. This means that all + // shared_ptr references to the connection object will disappear and + // the object will be destroyed automatically after this handler + // returns. The connection class's destructor closes the socket. + } + +private: + socket_type socket_; + + request_cb request_cb_; + + boost::asio::io_service &task_io_service_; + + std::shared_ptr handler_; + + /// Buffer for incoming data. + boost::array buffer_; + + boost::array outbuf_; + + bool writing_; +}; + +} // namespace server + +} // namespace asio_http2 + +} // namespace nghttp2 + +#endif // HTTP_SERVER2_CONNECTION_HPP diff -Nru nghttp2-1.13.0/src/asio_http2_handler.cc nghttp2-0.6.7/src/asio_http2_handler.cc --- nghttp2-1.13.0/src/asio_http2_handler.cc 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/asio_http2_handler.cc 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,745 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 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. + */ +#include "asio_http2_handler.h" + +#include + +#include "http2.h" +#include "util.h" + +namespace nghttp2 { + +namespace asio_http2 { + +channel::channel() : impl_(util::make_unique()) {} + +void channel::post(void_cb cb) { impl_->post(std::move(cb)); } + +channel_impl &channel::impl() { return *impl_; } + +channel_impl::channel_impl() : strand_(nullptr) {} + +void channel_impl::post(void_cb cb) { strand_->post(std::move(cb)); } + +void channel_impl::strand(boost::asio::io_service::strand *strand) { + strand_ = strand; +} + +namespace server { + +extern std::shared_ptr cached_date; + +request::request() : impl_(util::make_unique()) {} + +const std::vector
&request::headers() const { return impl_->headers(); } + +const std::string &request::method() const { return impl_->method(); } + +const std::string &request::scheme() const { return impl_->scheme(); } + +const std::string &request::authority() const { return impl_->authority(); } + +const std::string &request::host() const { return impl_->host(); } + +const std::string &request::path() const { return impl_->path(); } + +bool request::push(std::string method, std::string path, + std::vector
headers) { + return impl_->push(std::move(method), std::move(path), std::move(headers)); +} + +bool request::pushed() const { return impl_->pushed(); } + +bool request::closed() const { return impl_->closed(); } + +void request::on_data(data_cb cb) { return impl_->on_data(std::move(cb)); } + +void request::on_end(void_cb cb) { return impl_->on_end(std::move(cb)); } + +bool request::run_task(thread_cb start) { + return impl_->run_task(std::move(start)); +} + +request_impl &request::impl() { return *impl_; } + +response::response() : impl_(util::make_unique()) {} + +void response::write_head(unsigned int status_code, + std::vector
headers) { + impl_->write_head(status_code, std::move(headers)); +} + +void response::end(std::string data) { impl_->end(std::move(data)); } + +void response::end(read_cb cb) { impl_->end(std::move(cb)); } + +void response::resume() { impl_->resume(); } + +unsigned int response::status_code() const { return impl_->status_code(); } + +bool response::started() const { return impl_->started(); } + +response_impl &response::impl() { return *impl_; } + +request_impl::request_impl() : pushed_(false) {} + +const std::vector
&request_impl::headers() const { return headers_; } + +const std::string &request_impl::method() const { return method_; } + +const std::string &request_impl::scheme() const { return scheme_; } + +const std::string &request_impl::authority() const { return authority_; } + +const std::string &request_impl::host() const { return host_; } + +const std::string &request_impl::path() const { return path_; } + +void request_impl::set_header(std::vector
headers) { + headers_ = std::move(headers); +} + +void request_impl::add_header(std::string name, std::string value) { + headers_.push_back(header{std::move(name), std::move(value)}); +} + +void request_impl::method(std::string arg) { method_ = std::move(arg); } + +void request_impl::scheme(std::string arg) { scheme_ = std::move(arg); } + +void request_impl::authority(std::string arg) { authority_ = std::move(arg); } + +void request_impl::host(std::string arg) { host_ = std::move(arg); } + +void request_impl::path(std::string arg) { path_ = std::move(arg); } + +bool request_impl::push(std::string method, std::string path, + std::vector
headers) { + if (closed()) { + return false; + } + + auto handler = handler_.lock(); + auto stream = stream_.lock(); + auto rv = handler->push_promise(*stream, std::move(method), std::move(path), + std::move(headers)); + return rv == 0; +} + +bool request_impl::pushed() const { return pushed_; } + +void request_impl::pushed(bool f) { pushed_ = f; } + +bool request_impl::closed() const { + return handler_.expired() || stream_.expired(); +} + +void request_impl::on_data(data_cb cb) { on_data_cb_ = std::move(cb); } + +void request_impl::on_end(void_cb cb) { on_end_cb_ = std::move(cb); } + +bool request_impl::run_task(thread_cb start) { + if (closed()) { + return false; + } + + auto handler = handler_.lock(); + + return handler->run_task(std::move(start)); +} + +void request_impl::handler(std::weak_ptr h) { + handler_ = std::move(h); +} + +void request_impl::stream(std::weak_ptr s) { + stream_ = std::move(s); +} + +void request_impl::call_on_data(const uint8_t *data, std::size_t len) { + if (on_data_cb_) { + on_data_cb_(data, len); + } +} + +void request_impl::call_on_end() { + if (on_end_cb_) { + on_end_cb_(); + } +} + +response_impl::response_impl() : status_code_(200), started_(false) {} + +unsigned int response_impl::status_code() const { return status_code_; } + +void response_impl::write_head(unsigned int status_code, + std::vector
headers) { + status_code_ = status_code; + headers_ = std::move(headers); +} + +void response_impl::end(std::string data) { + if (started_) { + return; + } + + auto strio = std::make_shared>(std::move(data), + data.size()); + auto read_cb = [strio](uint8_t *buf, size_t len) { + auto nread = std::min(len, strio->second); + memcpy(buf, strio->first.c_str(), nread); + strio->second -= nread; + if (strio->second == 0) { + return std::make_pair(nread, true); + } + + return std::make_pair(nread, false); + }; + + end(std::move(read_cb)); +} + +void response_impl::end(read_cb cb) { + if (started_ || closed()) { + return; + } + + read_cb_ = std::move(cb); + started_ = true; + + auto handler = handler_.lock(); + auto stream = stream_.lock(); + + if (handler->start_response(*stream) != 0) { + handler->stream_error(stream->get_stream_id(), NGHTTP2_INTERNAL_ERROR); + return; + } + + if (!handler->inside_callback()) { + handler->initiate_write(); + } +} + +bool response_impl::closed() const { + return handler_.expired() || stream_.expired(); +} + +void response_impl::resume() { + if (closed()) { + return; + } + + auto handler = handler_.lock(); + auto stream = stream_.lock(); + handler->resume(*stream); + + if (!handler->inside_callback()) { + handler->initiate_write(); + } +} + +bool response_impl::started() const { return started_; } + +const std::vector
&response_impl::headers() const { return headers_; } + +void response_impl::handler(std::weak_ptr h) { + handler_ = std::move(h); +} + +void response_impl::stream(std::weak_ptr s) { + stream_ = std::move(s); +} + +std::pair response_impl::call_read(uint8_t *data, + std::size_t len) { + if (read_cb_) { + return read_cb_(data, len); + } + + return std::make_pair(0, true); +} + +http2_stream::http2_stream(int32_t stream_id) + : request_(std::make_shared()), + response_(std::make_shared()), stream_id_(stream_id) {} + +int32_t http2_stream::get_stream_id() const { return stream_id_; } + +const std::shared_ptr &http2_stream::get_request() { return request_; } + +const std::shared_ptr &http2_stream::get_response() { + return response_; +} + +namespace { +int stream_error(nghttp2_session *session, int32_t stream_id, + uint32_t error_code) { + return nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id, + error_code); +} +} // namespace + +namespace { +int on_begin_headers_callback(nghttp2_session *session, + const nghttp2_frame *frame, void *user_data) { + auto handler = static_cast(user_data); + + if (frame->hd.type != NGHTTP2_HEADERS || + frame->headers.cat != NGHTTP2_HCAT_REQUEST) { + return 0; + } + + handler->create_stream(frame->hd.stream_id); + + return 0; +} +} // namespace + +namespace { +int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, + const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, uint8_t flags, + void *user_data) { + auto handler = static_cast(user_data); + auto stream_id = frame->hd.stream_id; + + if (frame->hd.type != NGHTTP2_HEADERS || + frame->headers.cat != NGHTTP2_HCAT_REQUEST) { + return 0; + } + + auto stream = handler->find_stream(stream_id); + if (!stream) { + return 0; + } + + if (!nghttp2_check_header_name(name, namelen) || + !nghttp2_check_header_value(value, valuelen)) { + stream_error(session, stream_id, NGHTTP2_PROTOCOL_ERROR); + + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + + auto &req = stream->get_request()->impl(); + + if (name[0] == ':' && !req.headers().empty()) { + stream_error(session, stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + + if (util::streq(":method", name, namelen)) { + if (!req.method().empty()) { + stream_error(session, stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + req.method(std::string(value, value + valuelen)); + } else if (util::streq(":scheme", name, namelen)) { + if (!req.scheme().empty()) { + stream_error(session, stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + req.scheme(std::string(value, value + valuelen)); + } else if (util::streq(":authority", name, namelen)) { + if (!req.authority().empty()) { + stream_error(session, stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + req.authority(std::string(value, value + valuelen)); + } else if (util::streq(":path", name, namelen)) { + if (!req.path().empty()) { + stream_error(session, stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + req.path(std::string(value, value + valuelen)); + } else { + if (name[0] == ':') { + stream_error(session, stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + + if (util::streq("host", name, namelen)) { + req.host(std::string(value, value + valuelen)); + } + + req.add_header(std::string(name, name + namelen), + std::string(value, value + valuelen)); + } + + return 0; +} +} // namespace + +namespace { +int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, + void *user_data) { + auto handler = static_cast(user_data); + auto stream = handler->find_stream(frame->hd.stream_id); + + switch (frame->hd.type) { + case NGHTTP2_DATA: + if (!stream) { + break; + } + + if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + stream->get_request()->impl().call_on_end(); + } + + break; + case NGHTTP2_HEADERS: { + if (!stream || frame->headers.cat != NGHTTP2_HCAT_REQUEST) { + break; + } + + auto &req = stream->get_request()->impl(); + + if (req.method().empty() || req.scheme().empty() || req.path().empty() || + (req.authority().empty() && req.host().empty())) { + stream_error(session, frame->hd.stream_id, NGHTTP2_PROTOCOL_ERROR); + return 0; + } + + if (req.host().empty()) { + req.host(req.authority()); + } + + handler->call_on_request(*stream); + + if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + stream->get_request()->impl().call_on_end(); + } + + break; + } + } + + return 0; +} +} // namespace + +namespace { +int 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) { + auto handler = static_cast(user_data); + auto stream = handler->find_stream(stream_id); + + if (!stream) { + return 0; + } + + stream->get_request()->impl().call_on_data(data, len); + + return 0; +} + +} // namespace + +namespace { +int on_stream_close_callback(nghttp2_session *session, int32_t stream_id, + uint32_t error_code, void *user_data) { + auto handler = static_cast(user_data); + + handler->close_stream(stream_id); + + return 0; +} +} // namespace + +namespace { +int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame, + void *user_data) { + auto handler = static_cast(user_data); + + if (frame->hd.type != NGHTTP2_PUSH_PROMISE) { + return 0; + } + + auto stream = handler->find_stream(frame->push_promise.promised_stream_id); + + if (!stream) { + return 0; + } + + handler->call_on_request(*stream); + + return 0; +} +} // namespace + +namespace { +int on_frame_not_send_callback(nghttp2_session *session, + const nghttp2_frame *frame, int lib_error_code, + void *user_data) { + if (frame->hd.type != NGHTTP2_HEADERS) { + return 0; + } + + // Issue RST_STREAM so that stream does not hang around. + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id, + NGHTTP2_INTERNAL_ERROR); + + return 0; +} +} // namespace + +http2_handler::http2_handler(boost::asio::io_service &io_service, + boost::asio::io_service &task_io_service_, + connection_write writefun, request_cb cb) + : writefun_(writefun), request_cb_(std::move(cb)), io_service_(io_service), + task_io_service_(task_io_service_), + strand_(std::make_shared(io_service_)), + session_(nullptr), buf_(nullptr), buflen_(0), inside_callback_(false) {} + +http2_handler::~http2_handler() { nghttp2_session_del(session_); } + +int http2_handler::start() { + int rv; + + nghttp2_session_callbacks *callbacks; + rv = nghttp2_session_callbacks_new(&callbacks); + if (rv != 0) { + return -1; + } + + auto cb_del = util::defer(callbacks, nghttp2_session_callbacks_del); + + nghttp2_session_callbacks_set_on_begin_headers_callback( + callbacks, on_begin_headers_callback); + nghttp2_session_callbacks_set_on_header_callback(callbacks, + on_header_callback); + nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, + on_frame_recv_callback); + nghttp2_session_callbacks_set_on_data_chunk_recv_callback( + callbacks, on_data_chunk_recv_callback); + nghttp2_session_callbacks_set_on_stream_close_callback( + callbacks, on_stream_close_callback); + nghttp2_session_callbacks_set_on_frame_send_callback(callbacks, + on_frame_send_callback); + nghttp2_session_callbacks_set_on_frame_not_send_callback( + callbacks, on_frame_not_send_callback); + + nghttp2_option *option; + rv = nghttp2_option_new(&option); + if (rv != 0) { + return -1; + } + + auto opt_del = util::defer(option, nghttp2_option_del); + + nghttp2_option_set_recv_client_preface(option, 1); + + rv = nghttp2_session_server_new2(&session_, callbacks, this, option); + if (rv != 0) { + return -1; + } + + nghttp2_settings_entry ent{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}; + nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, &ent, 1); + + return 0; +} + +std::shared_ptr http2_handler::create_stream(int32_t stream_id) { + auto stream = std::make_shared(stream_id); + streams_.emplace(stream_id, stream); + + auto self = shared_from_this(); + auto &req = stream->get_request()->impl(); + auto &res = stream->get_response()->impl(); + req.handler(self); + req.stream(stream); + res.handler(self); + res.stream(stream); + + return stream; +} + +void http2_handler::close_stream(int32_t stream_id) { + streams_.erase(stream_id); +} + +std::shared_ptr http2_handler::find_stream(int32_t stream_id) { + auto i = streams_.find(stream_id); + if (i == std::end(streams_)) { + return nullptr; + } + + return (*i).second; +} + +void http2_handler::call_on_request(http2_stream &stream) { + request_cb_(stream.get_request(), stream.get_response()); +} + +bool http2_handler::should_stop() const { + return !nghttp2_session_want_read(session_) && + !nghttp2_session_want_write(session_); +} + +int http2_handler::start_response(http2_stream &stream) { + int rv; + + auto &res = stream.get_response()->impl(); + auto &headers = res.headers(); + auto nva = std::vector(); + nva.reserve(2 + headers.size()); + auto status = util::utos(res.status_code()); + auto date = cached_date; + nva.push_back(nghttp2::http2::make_nv_ls(":status", status)); + nva.push_back(nghttp2::http2::make_nv_ls("date", *date)); + for (auto &hd : headers) { + nva.push_back(nghttp2::http2::make_nv(hd.name, hd.value)); + } + + nghttp2_data_provider prd; + prd.source.ptr = &stream; + prd.read_callback = + [](nghttp2_session *session, int32_t stream_id, uint8_t *buf, + size_t length, uint32_t *data_flags, nghttp2_data_source *source, + void *user_data) -> ssize_t { + auto &stream = *static_cast(source->ptr); + auto rv = stream.get_response()->impl().call_read(buf, length); + if (rv.first < 0) { + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + + if (rv.second) { + *data_flags |= NGHTTP2_DATA_FLAG_EOF; + } else if (rv.first == 0) { + return NGHTTP2_ERR_DEFERRED; + } + + return rv.first; + }; + + rv = nghttp2_submit_response(session_, stream.get_stream_id(), nva.data(), + nva.size(), &prd); + + if (rv != 0) { + return -1; + } + + return 0; +} + +void http2_handler::enter_callback() { + assert(!inside_callback_); + inside_callback_ = true; +} + +void http2_handler::leave_callback() { + assert(inside_callback_); + inside_callback_ = false; +} + +bool http2_handler::inside_callback() const { return inside_callback_; } + +void http2_handler::stream_error(int32_t stream_id, uint32_t error_code) { + ::nghttp2::asio_http2::server::stream_error(session_, stream_id, error_code); +} + +void http2_handler::initiate_write() { writefun_(); } + +void http2_handler::resume(http2_stream &stream) { + nghttp2_session_resume_data(session_, stream.get_stream_id()); +} + +int http2_handler::push_promise(http2_stream &stream, std::string method, + std::string path, std::vector
headers) { + int rv; + + auto &req = stream.get_request()->impl(); + + auto nva = std::vector(); + nva.reserve(5 + headers.size()); + nva.push_back(nghttp2::http2::make_nv_ls(":method", method)); + nva.push_back(nghttp2::http2::make_nv_ls(":scheme", req.scheme())); + if (!req.authority().empty()) { + nva.push_back(nghttp2::http2::make_nv_ls(":authority", req.authority())); + } + nva.push_back(nghttp2::http2::make_nv_ls(":path", path)); + if (!req.host().empty()) { + nva.push_back(nghttp2::http2::make_nv_ls("host", req.host())); + } + + for (auto &hd : headers) { + nva.push_back(nghttp2::http2::make_nv(hd.name, hd.value)); + } + + rv = nghttp2_submit_push_promise(session_, NGHTTP2_FLAG_NONE, + stream.get_stream_id(), nva.data(), + nva.size(), nullptr); + + if (rv < 0) { + return -1; + } + + auto promised_stream = create_stream(rv); + auto &promised_req = promised_stream->get_request()->impl(); + promised_req.pushed(true); + promised_req.method(std::move(method)); + promised_req.scheme(req.scheme()); + promised_req.authority(req.authority()); + promised_req.path(std::move(path)); + promised_req.host(req.host()); + promised_req.set_header(std::move(headers)); + if (!req.host().empty()) { + promised_req.add_header("host", req.host()); + } + + return 0; +} + +bool http2_handler::run_task(thread_cb start) { + auto strand = strand_; + + try { + task_io_service_.post([start, strand]() { + channel chan; + chan.impl().strand(strand.get()); + + start(chan); + }); + + return true; + } catch (std::exception &ex) { + return false; + } +} + +boost::asio::io_service &http2_handler::io_service() { return io_service_; } + +callback_guard::callback_guard(http2_handler &h) : handler(h) { + handler.enter_callback(); +} + +callback_guard::~callback_guard() { handler.leave_callback(); } + +} // namespace server + +} // namespace asio_http2 + +} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_http2_handler.h nghttp2-0.6.7/src/asio_http2_handler.h --- nghttp2-1.13.0/src/asio_http2_handler.h 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/asio_http2_handler.h 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,265 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 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 HTTP2_HANDLER_H +#define HTTP2_HANDLER_H + +#include "nghttp2_config.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace nghttp2 { +namespace asio_http2 { + +class channel_impl { +public: + channel_impl(); + void post(void_cb cb); + void strand(boost::asio::io_service::strand *strand); + +private: + boost::asio::io_service::strand *strand_; +}; + +namespace server { + +class http2_handler; +class http2_stream; + +class request_impl { +public: + request_impl(); + + const std::vector
&headers() const; + const std::string &method() const; + const std::string &scheme() const; + const std::string &authority() const; + const std::string &host() const; + const std::string &path() const; + + bool push(std::string method, std::string path, + std::vector
headers = {}); + + bool pushed() const; + bool closed() const; + + void on_data(data_cb cb); + void on_end(void_cb cb); + + bool run_task(thread_cb start); + + void set_header(std::vector
headers); + void add_header(std::string name, std::string value); + void method(std::string method); + void scheme(std::string scheme); + void authority(std::string authority); + void host(std::string host); + void path(std::string path); + void pushed(bool f); + void handler(std::weak_ptr h); + void stream(std::weak_ptr s); + void call_on_data(const uint8_t *data, std::size_t len); + void call_on_end(); + +private: + std::vector
headers_; + std::string method_; + std::string scheme_; + std::string authority_; + std::string host_; + std::string path_; + data_cb on_data_cb_; + void_cb on_end_cb_; + std::weak_ptr handler_; + std::weak_ptr stream_; + bool pushed_; +}; + +class response_impl { +public: + response_impl(); + void write_head(unsigned int status_code, std::vector
headers = {}); + void end(std::string data = ""); + void end(read_cb cb); + void resume(); + bool closed() const; + + unsigned int status_code() const; + const std::vector
&headers() const; + bool started() const; + void handler(std::weak_ptr h); + void stream(std::weak_ptr s); + read_cb::result_type call_read(uint8_t *data, std::size_t len); + +private: + std::vector
headers_; + read_cb read_cb_; + std::weak_ptr handler_; + std::weak_ptr stream_; + unsigned int status_code_; + bool started_; +}; + +class http2_stream { +public: + http2_stream(int32_t stream_id); + + int32_t get_stream_id() const; + const std::shared_ptr &get_request(); + const std::shared_ptr &get_response(); + +private: + std::shared_ptr request_; + std::shared_ptr response_; + int32_t stream_id_; +}; + +struct callback_guard { + callback_guard(http2_handler &h); + ~callback_guard(); + http2_handler &handler; +}; + +typedef std::function connection_write; + +class http2_handler : public std::enable_shared_from_this { +public: + http2_handler(boost::asio::io_service &io_service, + boost::asio::io_service &task_io_service, + connection_write writefun, request_cb cb); + + ~http2_handler(); + + int start(); + + std::shared_ptr create_stream(int32_t stream_id); + void close_stream(int32_t stream_id); + std::shared_ptr find_stream(int32_t stream_id); + + void call_on_request(http2_stream &stream); + + bool should_stop() const; + + int start_response(http2_stream &stream); + + void stream_error(int32_t stream_id, uint32_t error_code); + + void initiate_write(); + + void enter_callback(); + void leave_callback(); + bool inside_callback() const; + + void resume(http2_stream &stream); + + int push_promise(http2_stream &stream, std::string method, std::string path, + std::vector
headers); + + bool run_task(thread_cb start); + + boost::asio::io_service &io_service(); + + template + int on_read(const boost::array &buffer, std::size_t len) { + callback_guard cg(*this); + + int rv; + + rv = nghttp2_session_mem_recv(session_, buffer.data(), len); + + if (rv < 0) { + return -1; + } + + return 0; + } + + template + int on_write(boost::array &buffer, std::size_t &len) { + callback_guard cg(*this); + + len = 0; + + if (buf_) { + std::copy(buf_, buf_ + buflen_, std::begin(buffer)); + + len += buflen_; + + buf_ = nullptr; + buflen_ = 0; + } + + for (;;) { + const uint8_t *data; + auto nread = nghttp2_session_mem_send(session_, &data); + if (nread < 0) { + return -1; + } + + if (nread == 0) { + break; + } + + if (len + nread > buffer.size()) { + buf_ = data; + buflen_ = nread; + + break; + } + + std::copy(data, data + nread, std::begin(buffer) + len); + + len += nread; + } + + return 0; + } + +private: + std::map> streams_; + connection_write writefun_; + request_cb request_cb_; + boost::asio::io_service &io_service_; + boost::asio::io_service &task_io_service_; + std::shared_ptr strand_; + nghttp2_session *session_; + const uint8_t *buf_; + std::size_t buflen_; + bool inside_callback_; +}; + +} // namespace server +} // namespace asio_http2 +} // namespace nghttp + +#endif // HTTP2_HANDLER_H diff -Nru nghttp2-1.13.0/src/asio_http2_impl.cc nghttp2-0.6.7/src/asio_http2_impl.cc --- nghttp2-1.13.0/src/asio_http2_impl.cc 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/asio_http2_impl.cc 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,182 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 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. + */ +#include "asio_http2_impl.h" + +#include + +#include + +#include + +#include "asio_server.h" +#include "util.h" +#include "ssl.h" + +namespace nghttp2 { + +namespace asio_http2 { + +namespace server { + +http2::http2() : impl_(util::make_unique()) {} + +http2::~http2() {} + +void http2::listen(const std::string &address, uint16_t port, request_cb cb) { + impl_->listen(address, port, std::move(cb)); +} + +void http2::num_threads(size_t num_threads) { impl_->num_threads(num_threads); } + +void http2::tls(std::string private_key_file, std::string certificate_file) { + impl_->tls(std::move(private_key_file), std::move(certificate_file)); +} + +void http2::num_concurrent_tasks(size_t num_concurrent_tasks) { + impl_->num_concurrent_tasks(num_concurrent_tasks); +} + +void http2::backlog(int backlog) { impl_->backlog(backlog); } + +http2_impl::http2_impl() + : num_threads_(1), num_concurrent_tasks_(1), backlog_(-1) {} + +namespace { +std::vector &get_alpn_token() { + static auto alpn_token = util::get_default_alpn(); + return alpn_token; +} +} // namespace + +void http2_impl::listen(const std::string &address, uint16_t port, + request_cb cb) { + std::unique_ptr ssl_ctx; + + if (!private_key_file_.empty() && !certificate_file_.empty()) { + ssl_ctx = util::make_unique( + boost::asio::ssl::context::sslv23); + + ssl_ctx->use_private_key_file(private_key_file_, + boost::asio::ssl::context::pem); + ssl_ctx->use_certificate_chain_file(certificate_file_); + + auto ctx = ssl_ctx->native_handle(); + + SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | + SSL_OP_NO_COMPRESSION | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | + SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET | + SSL_OP_CIPHER_SERVER_PREFERENCE); + SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); + SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); + SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); + + SSL_CTX_set_cipher_list(ctx, ssl::DEFAULT_CIPHER_LIST); + + auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (ecdh) { + SSL_CTX_set_tmp_ecdh(ctx, ecdh); + EC_KEY_free(ecdh); + } + + SSL_CTX_set_next_protos_advertised_cb( + ctx, + [](SSL *s, const unsigned char **data, unsigned int *len, void *arg) { + auto &token = get_alpn_token(); + + *data = token.data(); + *len = token.size(); + + return SSL_TLSEXT_ERR_OK; + }, + nullptr); + } + + server(address, port, num_threads_, num_concurrent_tasks_, std::move(cb), + std::move(ssl_ctx), backlog_).run(); +} + +void http2_impl::num_threads(size_t num_threads) { num_threads_ = num_threads; } + +void http2_impl::tls(std::string private_key_file, + std::string certificate_file) { + private_key_file_ = std::move(private_key_file); + certificate_file_ = std::move(certificate_file); +} + +void http2_impl::num_concurrent_tasks(size_t num_concurrent_tasks) { + num_concurrent_tasks_ = num_concurrent_tasks; +} + +void http2_impl::backlog(int backlog) { backlog_ = backlog; } + +} // namespace server + +template +std::shared_ptr> defer_shared(T &&t, F f) { + return std::make_shared>(std::forward(t), + std::forward(f)); +} + +read_cb file_reader(const std::string &path) { + auto fd = open(path.c_str(), O_RDONLY); + if (fd == -1) { + return read_cb(); + } + + return file_reader_from_fd(fd); +} + +read_cb file_reader_from_fd(int fd) { + auto d = defer_shared(static_cast(fd), close); + + return [fd, d](uint8_t *buf, size_t len) -> read_cb::result_type { + int rv; + while ((rv = read(fd, buf, len)) == -1 && errno == EINTR) + ; + + if (rv == -1) { + return std::make_pair(-1, false); + } + + if (rv == 0) { + return std::make_pair(rv, true); + } + + return std::make_pair(rv, false); + }; +} + +bool check_path(const std::string &path) { return util::check_path(path); } + +std::string percent_decode(const std::string &s) { + return util::percentDecode(std::begin(s), std::end(s)); +} + +std::string http_date(int64_t t) { return util::http_date(t); } + +} // namespace asio_http2 + +} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_http2_impl.h nghttp2-0.6.7/src/asio_http2_impl.h --- nghttp2-1.13.0/src/asio_http2_impl.h 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/asio_http2_impl.h 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 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 ASIO_HTTP2_IMPL_H +#define ASIO_HTTP2_IMPL_H + +#include "nghttp2_config.h" + +#include + +namespace nghttp2 { + +namespace asio_http2 { + +namespace server { + +class server; + +class http2_impl { +public: + http2_impl(); + void listen(const std::string &address, uint16_t port, request_cb cb); + void num_threads(size_t num_threads); + void tls(std::string private_key_file, std::string certificate_file); + void num_concurrent_tasks(size_t num_concurrent_tasks); + void backlog(int backlog); + +private: + std::string private_key_file_; + std::string certificate_file_; + std::unique_ptr server_; + std::size_t num_threads_; + std::size_t num_concurrent_tasks_; + int backlog_; +}; + +} // namespace server + +} // namespace asio_http2 + +} // namespace nghttp2 + +#endif // ASIO_HTTP2_IMPL_H diff -Nru nghttp2-1.13.0/src/asio_io_service_pool.cc nghttp2-0.6.7/src/asio_io_service_pool.cc --- nghttp2-1.13.0/src/asio_io_service_pool.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_io_service_pool.cc 2014-11-30 14:15:07.000000000 +0000 @@ -33,13 +33,22 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#include "asio_io_service_pool.h" + +#include "asio_server.h" +#include +#include +#include +#include namespace nghttp2 { namespace asio_http2 { -io_service_pool::io_service_pool(std::size_t pool_size) : next_io_service_(0) { +namespace server { + +io_service_pool::io_service_pool(std::size_t pool_size, + std::size_t thread_pool_size) + : next_io_service_(0), thread_pool_size_(thread_pool_size) { if (pool_size == 0) { throw std::runtime_error("io_service_pool size is 0"); } @@ -52,27 +61,32 @@ io_services_.push_back(io_service); work_.push_back(work); } + + auto work = std::make_shared(task_io_service_); + work_.push_back(work); } -void io_service_pool::run(bool asynchronous) { - // Create a pool of threads to run all of the io_services. - for (std::size_t i = 0; i < io_services_.size(); ++i) { - futures_.push_back(std::async(std::launch::async, - (size_t (boost::asio::io_service::*)(void)) & - boost::asio::io_service::run, - io_services_[i])); +void io_service_pool::run() { + for (std::size_t i = 0; i < thread_pool_size_; ++i) { + thread_pool_.create_thread([this]() { task_io_service_.run(); }); } - if (!asynchronous) { - join(); + // Create a pool of threads to run all of the io_services. + auto futs = std::vector>(); + + for (std::size_t i = 0; i < io_services_.size(); ++i) { + futs.push_back(std::async(std::launch::async, + (size_t (boost::asio::io_service::*)(void)) & + boost::asio::io_service::run, + io_services_[i])); } -} -void io_service_pool::join() { // Wait for all threads in the pool to exit. - for (auto &fut : futures_) { + for (auto &fut : futs) { fut.get(); } + + thread_pool_.join_all(); } void io_service_pool::stop() { @@ -80,6 +94,8 @@ for (auto &iosv : io_services_) { iosv->stop(); } + + task_io_service_.stop(); } boost::asio::io_service &io_service_pool::get_io_service() { @@ -92,11 +108,12 @@ return io_service; } -const std::vector> & -io_service_pool::io_services() const { - return io_services_; +boost::asio::io_service &io_service_pool::get_task_io_service() { + return task_io_service_; } +} // namespace server + } // namespace asio_http2 } // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_io_service_pool.h nghttp2-0.6.7/src/asio_io_service_pool.h --- nghttp2-1.13.0/src/asio_io_service_pool.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_io_service_pool.h 2014-11-30 14:15:07.000000000 +0000 @@ -34,15 +34,14 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef ASIO_IO_SERVICE_POOL_H -#define ASIO_IO_SERVICE_POOL_H +#ifndef HTTP_SERVER2_IO_SERVICE_POOL_HPP +#define HTTP_SERVER2_IO_SERVICE_POOL_HPP #include "nghttp2_config.h" #include #include -#include - +#include #include #include @@ -52,44 +51,48 @@ namespace asio_http2 { +namespace server { + /// A pool of io_service objects. class io_service_pool : private boost::noncopyable { public: /// Construct the io_service pool. - explicit io_service_pool(std::size_t pool_size); + explicit io_service_pool(std::size_t pool_size, std::size_t thread_pool_size); /// Run all io_service objects in the pool. - void run(bool asynchronous = false); + void run(); /// Stop all io_service objects in the pool. void stop(); - /// Join on all io_service objects in the pool. - void join(); - /// Get an io_service to use. boost::asio::io_service &get_io_service(); - /// Get access to all io_service objects. - const std::vector> & - io_services() const; + boost::asio::io_service &get_task_io_service(); private: + typedef std::shared_ptr io_service_ptr; + typedef std::shared_ptr work_ptr; + /// The pool of io_services. - std::vector> io_services_; + std::vector io_services_; + + boost::asio::io_service task_io_service_; + boost::thread_group thread_pool_; /// The work that keeps the io_services running. - std::vector> work_; + std::vector work_; /// The next io_service to use for a connection. std::size_t next_io_service_; - /// Futures to all the io_service objects - std::vector> futures_; + std::size_t thread_pool_size_; }; +} // namespace server + } // namespace asio_http2 } // namespace nghttp2 -#endif // ASIO_IO_SERVICE_POOL_H +#endif // HTTP_SERVER2_IO_SERVICE_POOL_HPP diff -Nru nghttp2-1.13.0/src/asio_server.cc nghttp2-0.6.7/src/asio_server.cc --- nghttp2-1.13.0/src/asio_server.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server.cc 2014-11-30 14:15:07.000000000 +0000 @@ -36,157 +36,125 @@ #include "asio_server.h" -#include "asio_server_connection.h" -#include "asio_common.h" -#include "util.h" +#include namespace nghttp2 { namespace asio_http2 { namespace server { -server::server(std::size_t io_service_pool_size, - const boost::posix_time::time_duration &tls_handshake_timeout, - const boost::posix_time::time_duration &read_timeout) - : io_service_pool_(io_service_pool_size), - tls_handshake_timeout_(tls_handshake_timeout), - read_timeout_(read_timeout) {} - -boost::system::error_code -server::listen_and_serve(boost::system::error_code &ec, - boost::asio::ssl::context *tls_context, - const std::string &address, const std::string &port, - int backlog, serve_mux &mux, bool asynchronous) { - ec.clear(); - - if (bind_and_listen(ec, address, port, backlog)) { - return ec; - } - - for (auto &acceptor : acceptors_) { - if (tls_context) { - start_accept(*tls_context, acceptor, mux); +server::server(const std::string &address, uint16_t port, + std::size_t io_service_pool_size, std::size_t thread_pool_size, + request_cb cb, + std::unique_ptr ssl_ctx, int backlog) + : io_service_pool_(io_service_pool_size, thread_pool_size), + signals_(io_service_pool_.get_io_service()), + tick_timer_(io_service_pool_.get_io_service(), + boost::posix_time::seconds(1)), + ssl_ctx_(std::move(ssl_ctx)), request_cb_(std::move(cb)) { + // Register to handle the signals that indicate when the server should exit. + // It is safe to register for the same signal multiple times in a program, + // provided all registration for the specified signal is made through Asio. + signals_.add(SIGINT); + signals_.add(SIGTERM); +#if defined(SIGQUIT) + signals_.add(SIGQUIT); +#endif // defined(SIGQUIT) + signals_.async_wait([this](const boost::system::error_code &error, + int signal_number) { io_service_pool_.stop(); }); + + // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). + boost::asio::ip::tcp::resolver resolver(io_service_pool_.get_io_service()); + boost::asio::ip::tcp::resolver::query query(address, std::to_string(port)); + + for (auto itr = resolver.resolve(query); + itr != boost::asio::ip::tcp::resolver::iterator(); ++itr) { + boost::asio::ip::tcp::endpoint endpoint = *itr; + auto acceptor = + boost::asio::ip::tcp::acceptor(io_service_pool_.get_io_service()); + + acceptor.open(endpoint.protocol()); + acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + acceptor.bind(endpoint); + if (backlog == -1) { + acceptor.listen(); } else { - start_accept(acceptor, mux); + acceptor.listen(backlog); } + acceptors_.push_back(std::move(acceptor)); } - io_service_pool_.run(asynchronous); + start_accept(); - return ec; + start_timer(); } -boost::system::error_code server::bind_and_listen(boost::system::error_code &ec, - const std::string &address, - const std::string &port, - int backlog) { - // Open the acceptor with the option to reuse the address (i.e. - // SO_REUSEADDR). - tcp::resolver resolver(io_service_pool_.get_io_service()); - tcp::resolver::query query(address, port); - auto it = resolver.resolve(query, ec); - if (ec) { - return ec; - } - - for (; it != tcp::resolver::iterator(); ++it) { - tcp::endpoint endpoint = *it; - auto acceptor = tcp::acceptor(io_service_pool_.get_io_service()); - - if (acceptor.open(endpoint.protocol(), ec)) { - continue; - } - - acceptor.set_option(tcp::acceptor::reuse_address(true)); - - if (acceptor.bind(endpoint, ec)) { - continue; - } - - if (acceptor.listen( - backlog == -1 ? boost::asio::socket_base::max_connections : backlog, - ec)) { - continue; - } - - acceptors_.push_back(std::move(acceptor)); - } - - if (acceptors_.empty()) { - return ec; - } +void server::run() { io_service_pool_.run(); } - // ec could have some errors since we may have failed to bind some - // interfaces. - ec.clear(); +std::shared_ptr cached_date; - return ec; +namespace { +void update_date() { + cached_date = std::make_shared(util::http_date(time(nullptr))); } +} // namespace -void server::start_accept(boost::asio::ssl::context &tls_context, - tcp::acceptor &acceptor, serve_mux &mux) { - auto new_connection = std::make_shared>( - mux, tls_handshake_timeout_, read_timeout_, - io_service_pool_.get_io_service(), tls_context); - - acceptor.async_accept( - new_connection->socket().lowest_layer(), - [this, &tls_context, &acceptor, &mux, new_connection]( - const boost::system::error_code &e) { - if (!e) { - new_connection->socket().lowest_layer().set_option( - tcp::no_delay(true)); - new_connection->start_tls_handshake_deadline(); - new_connection->socket().async_handshake( - boost::asio::ssl::stream_base::server, - [new_connection](const boost::system::error_code &e) { - if (e) { - new_connection->stop(); - return; - } - - if (!tls_h2_negotiated(new_connection->socket())) { - new_connection->stop(); - return; - } - - new_connection->start(); - }); - } +void server::start_timer() { + update_date(); - start_accept(tls_context, acceptor, mux); - }); + tick_timer_.async_wait([this](const boost::system::error_code &e) { + tick_timer_.expires_at(tick_timer_.expires_at() + + boost::posix_time::seconds(1)); + start_timer(); + }); } -void server::start_accept(tcp::acceptor &acceptor, serve_mux &mux) { - auto new_connection = std::make_shared>( - mux, tls_handshake_timeout_, read_timeout_, - io_service_pool_.get_io_service()); - - acceptor.async_accept( - new_connection->socket(), [this, &acceptor, &mux, new_connection]( - const boost::system::error_code &e) { - if (!e) { - new_connection->socket().set_option(tcp::no_delay(true)); - new_connection->start_read_deadline(); - new_connection->start(); - } +typedef boost::asio::ssl::stream ssl_socket; - start_accept(acceptor, mux); - }); -} +void server::start_accept() { + if (ssl_ctx_) { + auto new_connection = std::make_shared>( + request_cb_, io_service_pool_.get_task_io_service(), + io_service_pool_.get_io_service(), *ssl_ctx_); -void server::stop() { - io_service_pool_.stop(); - for (auto &acceptor : acceptors_) { - acceptor.close(); - } -} + for (auto &acceptor : acceptors_) { + acceptor.async_accept( + new_connection->socket().lowest_layer(), + [this, new_connection](const boost::system::error_code &e) { + if (!e) { + new_connection->socket().lowest_layer().set_option( + boost::asio::ip::tcp::no_delay(true)); + new_connection->socket().async_handshake( + boost::asio::ssl::stream_base::server, + [new_connection](const boost::system::error_code &e) { + if (!e) { + new_connection->start(); + } + }); + } -void server::join() { io_service_pool_.join(); } + start_accept(); + }); + } + } else { + auto new_connection = + std::make_shared>( + request_cb_, io_service_pool_.get_task_io_service(), + io_service_pool_.get_io_service()); + + for (auto &acceptor : acceptors_) { + acceptor.async_accept( + new_connection->socket(), + [this, new_connection](const boost::system::error_code &e) { + if (!e) { + new_connection->socket().set_option( + boost::asio::ip::tcp::no_delay(true)); + new_connection->start(); + } -const std::vector> & -server::io_services() const { - return io_service_pool_.io_services(); + start_accept(); + }); + } + } } } // namespace server diff -Nru nghttp2-1.13.0/src/asio_server_connection.h nghttp2-0.6.7/src/asio_server_connection.h --- nghttp2-1.13.0/src/asio_server_connection.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_connection.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,246 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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. - */ -// We wrote this code based on the original code which has the -// following license: -// -// connection.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_SERVER_CONNECTION_H -#define ASIO_SERVER_CONNECTION_H - -#include "nghttp2_config.h" - -#include - -#include -#include - -#include - -#include "asio_server_http2_handler.h" -#include "asio_server_serve_mux.h" -#include "util.h" -#include "template.h" - -namespace nghttp2 { - -namespace asio_http2 { - -namespace server { - -/// Represents a single connection from a client. -template -class connection : public std::enable_shared_from_this>, - private boost::noncopyable { -public: - /// Construct a connection with the given io_service. - template - explicit connection( - serve_mux &mux, - const boost::posix_time::time_duration &tls_handshake_timeout, - const boost::posix_time::time_duration &read_timeout, - SocketArgs &&... args) - : socket_(std::forward(args)...), - mux_(mux), - deadline_(socket_.get_io_service()), - tls_handshake_timeout_(tls_handshake_timeout), - read_timeout_(read_timeout), - writing_(false), - stopped_(false) {} - - /// Start the first asynchronous operation for the connection. - void start() { - boost::system::error_code ec; - - handler_ = std::make_shared( - socket_.get_io_service(), socket_.lowest_layer().remote_endpoint(ec), - [this]() { do_write(); }, mux_); - if (handler_->start() != 0) { - stop(); - return; - } - do_read(); - } - - socket_type &socket() { return socket_; } - - void start_tls_handshake_deadline() { - deadline_.expires_from_now(tls_handshake_timeout_); - deadline_.async_wait( - std::bind(&connection::handle_deadline, this->shared_from_this())); - } - - void start_read_deadline() { - deadline_.expires_from_now(read_timeout_); - deadline_.async_wait( - std::bind(&connection::handle_deadline, this->shared_from_this())); - } - - void handle_deadline() { - if (stopped_) { - return; - } - - if (deadline_.expires_at() <= - boost::asio::deadline_timer::traits_type::now()) { - stop(); - deadline_.expires_at(boost::posix_time::pos_infin); - return; - } - - deadline_.async_wait( - std::bind(&connection::handle_deadline, this->shared_from_this())); - } - - void do_read() { - auto self = this->shared_from_this(); - - deadline_.expires_from_now(read_timeout_); - - socket_.async_read_some( - boost::asio::buffer(buffer_), - [this, self](const boost::system::error_code &e, - std::size_t bytes_transferred) { - if (e) { - stop(); - return; - } - - if (handler_->on_read(buffer_, bytes_transferred) != 0) { - stop(); - return; - } - - do_write(); - - if (!writing_ && handler_->should_stop()) { - stop(); - return; - } - - do_read(); - - // If an error occurs then no new asynchronous operations are - // started. This means that all shared_ptr references to the - // connection object will disappear and the object will be - // destroyed automatically after this handler returns. The - // connection class's destructor closes the socket. - }); - } - - void do_write() { - auto self = this->shared_from_this(); - - if (writing_) { - return; - } - - int rv; - std::size_t nwrite; - - rv = handler_->on_write(outbuf_, nwrite); - - if (rv != 0) { - stop(); - return; - } - - if (nwrite == 0) { - if (handler_->should_stop()) { - stop(); - } - return; - } - - writing_ = true; - - // Reset read deadline here, because normally client is sending - // something, it does not expect timeout while doing it. - deadline_.expires_from_now(read_timeout_); - - boost::asio::async_write( - socket_, boost::asio::buffer(outbuf_, nwrite), - [this, self](const boost::system::error_code &e, std::size_t) { - if (e) { - stop(); - return; - } - - writing_ = false; - - do_write(); - }); - - // No new asynchronous operations are started. This means that all - // shared_ptr references to the connection object will disappear and - // the object will be destroyed automatically after this handler - // returns. The connection class's destructor closes the socket. - } - - void stop() { - if (stopped_) { - return; - } - - stopped_ = true; - boost::system::error_code ignored_ec; - socket_.lowest_layer().close(ignored_ec); - deadline_.cancel(); - } - -private: - socket_type socket_; - - serve_mux &mux_; - - std::shared_ptr handler_; - - /// Buffer for incoming data. - boost::array buffer_; - - boost::array outbuf_; - - boost::asio::deadline_timer deadline_; - boost::posix_time::time_duration tls_handshake_timeout_; - boost::posix_time::time_duration read_timeout_; - - bool writing_; - bool stopped_; -}; - -} // namespace server - -} // namespace asio_http2 - -} // namespace nghttp2 - -#endif // ASIO_SERVER_CONNECTION_H diff -Nru nghttp2-1.13.0/src/asio_server.h nghttp2-0.6.7/src/asio_server.h --- nghttp2-1.13.0/src/asio_server.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server.h 2014-11-30 14:15:07.000000000 +0000 @@ -34,19 +34,21 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef ASIO_SERVER_H -#define ASIO_SERVER_H +#ifndef HTTP_SERVER2_SERVER_HPP +#define HTTP_SERVER2_SERVER_HPP #include "nghttp2_config.h" #include #include #include - #include +#include +#include -#include +#include +#include "asio_connection.h" #include "asio_io_service_pool.h" namespace nghttp2 { @@ -55,54 +57,40 @@ namespace server { -class serve_mux; - -using boost::asio::ip::tcp; - -using ssl_socket = boost::asio::ssl::stream; - +/// The top-level class of the HTTP server. class server : private boost::noncopyable { public: - explicit server(std::size_t io_service_pool_size, - const boost::posix_time::time_duration &tls_handshake_timeout, - const boost::posix_time::time_duration &read_timeout); - - boost::system::error_code - listen_and_serve(boost::system::error_code &ec, - boost::asio::ssl::context *tls_context, - const std::string &address, const std::string &port, - int backlog, serve_mux &mux, bool asynchronous = false); - void join(); - void stop(); - - /// Get access to all io_service objects. - const std::vector> & - io_services() const; + /// Construct the server to listen on the specified TCP address and port, and + /// serve up files from the given directory. + explicit server(const std::string &address, uint16_t port, + std::size_t io_service_pool_size, + std::size_t thread_pool_size, request_cb cb, + std::unique_ptr ssl_ctx, + int backlog = -1); + + /// Run the server's io_service loop. + void run(); private: /// Initiate an asynchronous accept operation. - void start_accept(tcp::acceptor &acceptor, serve_mux &mux); - /// Same as above but with tls_context - void start_accept(boost::asio::ssl::context &tls_context, - tcp::acceptor &acceptor, serve_mux &mux); - - /// Resolves address and bind socket to the resolved addresses. - boost::system::error_code bind_and_listen(boost::system::error_code &ec, - const std::string &address, - const std::string &port, - int backlog); + void start_accept(); + + void start_timer(); - /// The pool of io_service objects used to perform asynchronous - /// operations. + /// The pool of io_service objects used to perform asynchronous operations. io_service_pool io_service_pool_; + /// The signal_set is used to register for process termination notifications. + boost::asio::signal_set signals_; + + boost::asio::deadline_timer tick_timer_; + /// Acceptor used to listen for incoming connections. - std::vector acceptors_; + std::vector acceptors_; std::unique_ptr ssl_ctx_; - boost::posix_time::time_duration tls_handshake_timeout_; - boost::posix_time::time_duration read_timeout_; + request_cb request_cb_; }; } // namespace server @@ -111,4 +99,4 @@ } // namespace nghttp2 -#endif // ASIO_SERVER_H +#endif // HTTP_SERVER2_SERVER_HPP diff -Nru nghttp2-1.13.0/src/asio_server_http2.cc nghttp2-0.6.7/src/asio_server_http2.cc --- nghttp2-1.13.0/src/asio_server_http2.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_http2.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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. - */ -#include "nghttp2_config.h" - -#include - -#include "asio_server_http2_impl.h" -#include "asio_server.h" -#include "template.h" - -namespace nghttp2 { - -namespace asio_http2 { - -namespace server { - -http2::http2() : impl_(make_unique()) {} - -http2::~http2() {} - -http2::http2(http2 &&other) noexcept : impl_(std::move(other.impl_)) {} - -http2 &http2::operator=(http2 &&other) noexcept { - if (this == &other) { - return *this; - } - - impl_ = std::move(other.impl_); - - return *this; -} - -boost::system::error_code http2::listen_and_serve(boost::system::error_code &ec, - const std::string &address, - const std::string &port, - bool asynchronous) { - return impl_->listen_and_serve(ec, nullptr, address, port, asynchronous); -} - -boost::system::error_code http2::listen_and_serve( - boost::system::error_code &ec, boost::asio::ssl::context &tls_context, - const std::string &address, const std::string &port, bool asynchronous) { - return impl_->listen_and_serve(ec, &tls_context, address, port, asynchronous); -} - -void http2::num_threads(size_t num_threads) { impl_->num_threads(num_threads); } - -void http2::backlog(int backlog) { impl_->backlog(backlog); } - -void http2::tls_handshake_timeout(const boost::posix_time::time_duration &t) { - impl_->tls_handshake_timeout(t); -} - -void http2::read_timeout(const boost::posix_time::time_duration &t) { - impl_->read_timeout(t); -} - -bool http2::handle(std::string pattern, request_cb cb) { - return impl_->handle(std::move(pattern), std::move(cb)); -} - -void http2::stop() { impl_->stop(); } - -void http2::join() { return impl_->join(); } - -const std::vector> & -http2::io_services() const { - return impl_->io_services(); -} - -} // namespace server - -} // namespace asio_http2 - -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_http2_handler.cc nghttp2-0.6.7/src/asio_server_http2_handler.cc --- nghttp2-1.13.0/src/asio_server_http2_handler.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_http2_handler.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,483 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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. - */ -#include "asio_server_http2_handler.h" - -#include - -#include "asio_common.h" -#include "asio_server_serve_mux.h" -#include "asio_server_stream.h" -#include "asio_server_request_impl.h" -#include "asio_server_response_impl.h" -#include "http2.h" -#include "util.h" -#include "template.h" - -namespace nghttp2 { - -namespace asio_http2 { - -namespace server { - -namespace { -int stream_error(nghttp2_session *session, int32_t stream_id, - uint32_t error_code) { - return nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id, - error_code); -} -} // namespace - -namespace { -int on_begin_headers_callback(nghttp2_session *session, - const nghttp2_frame *frame, void *user_data) { - auto handler = static_cast(user_data); - - if (frame->hd.type != NGHTTP2_HEADERS || - frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - return 0; - } - - handler->create_stream(frame->hd.stream_id); - - return 0; -} -} // namespace - -namespace { -int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, - const uint8_t *name, size_t namelen, - const uint8_t *value, size_t valuelen, uint8_t flags, - void *user_data) { - auto handler = static_cast(user_data); - auto stream_id = frame->hd.stream_id; - - if (frame->hd.type != NGHTTP2_HEADERS || - frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - return 0; - } - - auto strm = handler->find_stream(stream_id); - if (!strm) { - return 0; - } - - auto &req = strm->request().impl(); - auto &uref = req.uri(); - - switch (nghttp2::http2::lookup_token(name, namelen)) { - case nghttp2::http2::HD__METHOD: - req.method(std::string(value, value + valuelen)); - break; - case nghttp2::http2::HD__SCHEME: - uref.scheme.assign(value, value + valuelen); - break; - case nghttp2::http2::HD__AUTHORITY: - uref.host.assign(value, value + valuelen); - break; - case nghttp2::http2::HD__PATH: - split_path(uref, value, value + valuelen); - break; - case nghttp2::http2::HD_HOST: - if (uref.host.empty()) { - uref.host.assign(value, value + valuelen); - } - // fall through - default: - if (req.header_buffer_size() + namelen + valuelen > 64_k) { - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id, - NGHTTP2_INTERNAL_ERROR); - break; - } - req.update_header_buffer_size(namelen + valuelen); - - req.header().emplace(std::string(name, name + namelen), - header_value{std::string(value, value + valuelen), - (flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0}); - } - - return 0; -} -} // namespace - -namespace { -int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, - void *user_data) { - auto handler = static_cast(user_data); - auto strm = handler->find_stream(frame->hd.stream_id); - - switch (frame->hd.type) { - case NGHTTP2_DATA: - if (!strm) { - break; - } - - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - strm->request().impl().call_on_data(nullptr, 0); - } - - break; - case NGHTTP2_HEADERS: { - if (!strm || frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - break; - } - - auto &req = strm->request().impl(); - req.remote_endpoint(handler->remote_endpoint()); - - handler->call_on_request(*strm); - - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - strm->request().impl().call_on_data(nullptr, 0); - } - - break; - } - } - - return 0; -} -} // namespace - -namespace { -int 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) { - auto handler = static_cast(user_data); - auto strm = handler->find_stream(stream_id); - - if (!strm) { - return 0; - } - - strm->request().impl().call_on_data(data, len); - - return 0; -} - -} // namespace - -namespace { -int on_stream_close_callback(nghttp2_session *session, int32_t stream_id, - uint32_t error_code, void *user_data) { - auto handler = static_cast(user_data); - - auto strm = handler->find_stream(stream_id); - if (!strm) { - return 0; - } - - strm->response().impl().call_on_close(error_code); - - handler->close_stream(stream_id); - - return 0; -} -} // namespace - -namespace { -int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame, - void *user_data) { - auto handler = static_cast(user_data); - - if (frame->hd.type != NGHTTP2_PUSH_PROMISE) { - return 0; - } - - auto strm = handler->find_stream(frame->push_promise.promised_stream_id); - - if (!strm) { - return 0; - } - - auto &res = strm->response().impl(); - res.push_promise_sent(); - - return 0; -} -} // namespace - -namespace { -int on_frame_not_send_callback(nghttp2_session *session, - const nghttp2_frame *frame, int lib_error_code, - void *user_data) { - if (frame->hd.type != NGHTTP2_HEADERS) { - return 0; - } - - // Issue RST_STREAM so that stream does not hang around. - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id, - NGHTTP2_INTERNAL_ERROR); - - return 0; -} -} // namespace - -http2_handler::http2_handler(boost::asio::io_service &io_service, - boost::asio::ip::tcp::endpoint ep, - connection_write writefun, serve_mux &mux) - : writefun_(writefun), - mux_(mux), - io_service_(io_service), - remote_ep_(ep), - session_(nullptr), - buf_(nullptr), - buflen_(0), - inside_callback_(false), - tstamp_cached_(time(nullptr)), - formatted_date_(util::http_date(tstamp_cached_)) {} - -http2_handler::~http2_handler() { nghttp2_session_del(session_); } - -const std::string &http2_handler::http_date() { - auto t = time(nullptr); - if (t != tstamp_cached_) { - tstamp_cached_ = t; - formatted_date_ = util::http_date(t); - } - return formatted_date_; -} - -int http2_handler::start() { - int rv; - - nghttp2_session_callbacks *callbacks; - rv = nghttp2_session_callbacks_new(&callbacks); - if (rv != 0) { - return -1; - } - - auto cb_del = defer(nghttp2_session_callbacks_del, callbacks); - - nghttp2_session_callbacks_set_on_begin_headers_callback( - callbacks, on_begin_headers_callback); - nghttp2_session_callbacks_set_on_header_callback(callbacks, - on_header_callback); - nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, - on_frame_recv_callback); - nghttp2_session_callbacks_set_on_data_chunk_recv_callback( - callbacks, on_data_chunk_recv_callback); - nghttp2_session_callbacks_set_on_stream_close_callback( - callbacks, on_stream_close_callback); - nghttp2_session_callbacks_set_on_frame_send_callback(callbacks, - on_frame_send_callback); - nghttp2_session_callbacks_set_on_frame_not_send_callback( - callbacks, on_frame_not_send_callback); - - rv = nghttp2_session_server_new(&session_, callbacks, this); - if (rv != 0) { - return -1; - } - - nghttp2_settings_entry ent{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}; - nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, &ent, 1); - - return 0; -} - -stream *http2_handler::create_stream(int32_t stream_id) { - auto p = streams_.emplace(stream_id, make_unique(this, stream_id)); - assert(p.second); - return (*p.first).second.get(); -} - -void http2_handler::close_stream(int32_t stream_id) { - streams_.erase(stream_id); -} - -stream *http2_handler::find_stream(int32_t stream_id) { - auto i = streams_.find(stream_id); - if (i == std::end(streams_)) { - return nullptr; - } - - return (*i).second.get(); -} - -void http2_handler::call_on_request(stream &strm) { - auto cb = mux_.handler(strm.request().impl()); - cb(strm.request(), strm.response()); -} - -bool http2_handler::should_stop() const { - return !nghttp2_session_want_read(session_) && - !nghttp2_session_want_write(session_); -} - -int http2_handler::start_response(stream &strm) { - int rv; - - auto &res = strm.response().impl(); - auto &header = res.header(); - auto nva = std::vector(); - nva.reserve(2 + header.size()); - auto status = util::utos(res.status_code()); - auto date = http_date(); - nva.push_back(nghttp2::http2::make_nv_ls(":status", status)); - nva.push_back(nghttp2::http2::make_nv_ls("date", date)); - for (auto &hd : header) { - nva.push_back(nghttp2::http2::make_nv(hd.first, hd.second.value, - hd.second.sensitive)); - } - - nghttp2_data_provider *prd_ptr = nullptr, prd; - auto &req = strm.request().impl(); - if (::nghttp2::http2::expect_response_body(req.method(), res.status_code())) { - prd.source.ptr = &strm; - prd.read_callback = - [](nghttp2_session *session, int32_t stream_id, uint8_t *buf, - size_t length, uint32_t *data_flags, nghttp2_data_source *source, - void *user_data) -> ssize_t { - auto &strm = *static_cast(source->ptr); - return strm.response().impl().call_read(buf, length, data_flags); - }; - prd_ptr = &prd; - } - rv = nghttp2_submit_response(session_, strm.get_stream_id(), nva.data(), - nva.size(), prd_ptr); - - if (rv != 0) { - return -1; - } - - signal_write(); - - return 0; -} - -int http2_handler::submit_trailer(stream &strm, header_map h) { - int rv; - auto nva = std::vector(); - nva.reserve(h.size()); - for (auto &hd : h) { - nva.push_back(nghttp2::http2::make_nv(hd.first, hd.second.value, - hd.second.sensitive)); - } - - rv = nghttp2_submit_trailer(session_, strm.get_stream_id(), nva.data(), - nva.size()); - - if (rv != 0) { - return -1; - } - - signal_write(); - - return 0; -} - -void http2_handler::enter_callback() { - assert(!inside_callback_); - inside_callback_ = true; -} - -void http2_handler::leave_callback() { - assert(inside_callback_); - inside_callback_ = false; -} - -void http2_handler::stream_error(int32_t stream_id, uint32_t error_code) { - ::nghttp2::asio_http2::server::stream_error(session_, stream_id, error_code); - signal_write(); -} - -void http2_handler::signal_write() { - if (!inside_callback_) { - initiate_write(); - } -} - -void http2_handler::initiate_write() { writefun_(); } - -void http2_handler::resume(stream &strm) { - nghttp2_session_resume_data(session_, strm.get_stream_id()); - signal_write(); -} - -response *http2_handler::push_promise(boost::system::error_code &ec, - stream &strm, std::string method, - std::string raw_path_query, - header_map h) { - int rv; - - ec.clear(); - - auto &req = strm.request().impl(); - - auto nva = std::vector(); - nva.reserve(4 + h.size()); - nva.push_back(nghttp2::http2::make_nv_ls(":method", method)); - nva.push_back(nghttp2::http2::make_nv_ls(":scheme", req.uri().scheme)); - nva.push_back(nghttp2::http2::make_nv_ls(":authority", req.uri().host)); - nva.push_back(nghttp2::http2::make_nv_ls(":path", raw_path_query)); - - for (auto &hd : h) { - nva.push_back(nghttp2::http2::make_nv(hd.first, hd.second.value, - hd.second.sensitive)); - } - - rv = nghttp2_submit_push_promise(session_, NGHTTP2_FLAG_NONE, - strm.get_stream_id(), nva.data(), nva.size(), - nullptr); - - if (rv < 0) { - ec = make_error_code(static_cast(rv)); - return nullptr; - } - - auto promised_strm = create_stream(rv); - auto &promised_req = promised_strm->request().impl(); - promised_req.header(std::move(h)); - promised_req.method(std::move(method)); - - auto &uref = promised_req.uri(); - uref.scheme = req.uri().scheme; - uref.host = req.uri().host; - split_path(uref, std::begin(raw_path_query), std::end(raw_path_query)); - - auto &promised_res = promised_strm->response().impl(); - promised_res.pushed(true); - - signal_write(); - - return &promised_strm->response(); -} - -boost::asio::io_service &http2_handler::io_service() { return io_service_; } - -const boost::asio::ip::tcp::endpoint &http2_handler::remote_endpoint() { - return remote_ep_; -} - -callback_guard::callback_guard(http2_handler &h) : handler(h) { - handler.enter_callback(); -} - -callback_guard::~callback_guard() { handler.leave_callback(); } - -} // namespace server - -} // namespace asio_http2 - -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_http2_handler.h nghttp2-0.6.7/src/asio_server_http2_handler.h --- nghttp2-1.13.0/src/asio_server_http2_handler.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_http2_handler.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,171 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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 ASIO_SERVER_HTTP2_HANDLER_H -#define ASIO_SERVER_HTTP2_HANDLER_H - -#include "nghttp2_config.h" - -#include -#include -#include - -#include - -#include - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -class http2_handler; -class stream; -class serve_mux; - -struct callback_guard { - callback_guard(http2_handler &h); - ~callback_guard(); - http2_handler &handler; -}; - -using connection_write = std::function; - -class http2_handler : public std::enable_shared_from_this { -public: - http2_handler(boost::asio::io_service &io_service, - boost::asio::ip::tcp::endpoint ep, connection_write writefun, - serve_mux &mux); - - ~http2_handler(); - - int start(); - - stream *create_stream(int32_t stream_id); - void close_stream(int32_t stream_id); - stream *find_stream(int32_t stream_id); - - void call_on_request(stream &s); - - bool should_stop() const; - - int start_response(stream &s); - - int submit_trailer(stream &s, header_map h); - - void stream_error(int32_t stream_id, uint32_t error_code); - - void initiate_write(); - - void enter_callback(); - void leave_callback(); - - void resume(stream &s); - - response *push_promise(boost::system::error_code &ec, stream &s, - std::string method, std::string raw_path_query, - header_map h); - - void signal_write(); - - boost::asio::io_service &io_service(); - - const boost::asio::ip::tcp::endpoint &remote_endpoint(); - - const std::string &http_date(); - - template - int on_read(const boost::array &buffer, std::size_t len) { - callback_guard cg(*this); - - int rv; - - rv = nghttp2_session_mem_recv(session_, buffer.data(), len); - - if (rv < 0) { - return -1; - } - - return 0; - } - - template - int on_write(boost::array &buffer, std::size_t &len) { - callback_guard cg(*this); - - len = 0; - - if (buf_) { - std::copy_n(buf_, buflen_, std::begin(buffer)); - - len += buflen_; - - buf_ = nullptr; - buflen_ = 0; - } - - for (;;) { - const uint8_t *data; - auto nread = nghttp2_session_mem_send(session_, &data); - if (nread < 0) { - return -1; - } - - if (nread == 0) { - break; - } - - if (len + nread > buffer.size()) { - buf_ = data; - buflen_ = nread; - - break; - } - - std::copy_n(data, nread, std::begin(buffer) + len); - - len += nread; - } - - return 0; - } - -private: - std::map> streams_; - connection_write writefun_; - serve_mux &mux_; - boost::asio::io_service &io_service_; - boost::asio::ip::tcp::endpoint remote_ep_; - nghttp2_session *session_; - const uint8_t *buf_; - std::size_t buflen_; - bool inside_callback_; - time_t tstamp_cached_; - std::string formatted_date_; -}; - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp - -#endif // ASIO_SERVER_HTTP2_HANDLER_H diff -Nru nghttp2-1.13.0/src/asio_server_http2_impl.cc nghttp2-0.6.7/src/asio_server_http2_impl.cc --- nghttp2-1.13.0/src/asio_server_http2_impl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_http2_impl.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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. - */ -#include "asio_server_http2_impl.h" - -#include - -#include "asio_server.h" -#include "util.h" -#include "ssl.h" -#include "template.h" - -namespace nghttp2 { - -namespace asio_http2 { - -namespace server { - -http2_impl::http2_impl() - : num_threads_(1), - backlog_(-1), - tls_handshake_timeout_(boost::posix_time::seconds(60)), - read_timeout_(boost::posix_time::seconds(60)) {} - -boost::system::error_code http2_impl::listen_and_serve( - boost::system::error_code &ec, boost::asio::ssl::context *tls_context, - const std::string &address, const std::string &port, bool asynchronous) { - server_.reset( - new server(num_threads_, tls_handshake_timeout_, read_timeout_)); - return server_->listen_and_serve(ec, tls_context, address, port, backlog_, - mux_, asynchronous); -} - -void http2_impl::num_threads(size_t num_threads) { num_threads_ = num_threads; } - -void http2_impl::backlog(int backlog) { backlog_ = backlog; } - -void http2_impl::tls_handshake_timeout( - const boost::posix_time::time_duration &t) { - tls_handshake_timeout_ = t; -} - -void http2_impl::read_timeout(const boost::posix_time::time_duration &t) { - read_timeout_ = t; -} - -bool http2_impl::handle(std::string pattern, request_cb cb) { - return mux_.handle(std::move(pattern), std::move(cb)); -} - -void http2_impl::stop() { return server_->stop(); } - -void http2_impl::join() { return server_->join(); } - -const std::vector> & -http2_impl::io_services() const { - return server_->io_services(); -} - -} // namespace server - -} // namespace asio_http2 - -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_http2_impl.h nghttp2-0.6.7/src/asio_server_http2_impl.h --- nghttp2-1.13.0/src/asio_server_http2_impl.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_http2_impl.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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 ASIO_SERVER_HTTP2_IMPL_H -#define ASIO_SERVER_HTTP2_IMPL_H - -#include "nghttp2_config.h" - -#include - -#include "asio_server_serve_mux.h" - -namespace nghttp2 { - -namespace asio_http2 { - -namespace server { - -class server; - -class http2_impl { -public: - http2_impl(); - boost::system::error_code listen_and_serve( - boost::system::error_code &ec, boost::asio::ssl::context *tls_context, - const std::string &address, const std::string &port, bool asynchronous); - void num_threads(size_t num_threads); - void backlog(int backlog); - void tls_handshake_timeout(const boost::posix_time::time_duration &t); - void read_timeout(const boost::posix_time::time_duration &t); - bool handle(std::string pattern, request_cb cb); - void stop(); - void join(); - const std::vector> & - io_services() const; - -private: - std::unique_ptr server_; - std::size_t num_threads_; - int backlog_; - serve_mux mux_; - boost::posix_time::time_duration tls_handshake_timeout_; - boost::posix_time::time_duration read_timeout_; -}; - -} // namespace server - -} // namespace asio_http2 - -} // namespace nghttp2 - -#endif // ASIO_SERVER_HTTP2_IMPL_H diff -Nru nghttp2-1.13.0/src/asio_server_request.cc nghttp2-0.6.7/src/asio_server_request.cc --- nghttp2-1.13.0/src/asio_server_request.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_request.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "nghttp2_config.h" - -#include - -#include "asio_server_request_impl.h" - -#include "template.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -request::request() : impl_(make_unique()) {} - -request::~request() {} - -const header_map &request::header() const { return impl_->header(); } - -const std::string &request::method() const { return impl_->method(); } - -const uri_ref &request::uri() const { return impl_->uri(); } - -void request::on_data(data_cb cb) const { - return impl_->on_data(std::move(cb)); -} - -request_impl &request::impl() const { return *impl_; } - -const boost::asio::ip::tcp::endpoint &request::remote_endpoint() const { - return impl_->remote_endpoint(); -} - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_request_handler.cc nghttp2-0.6.7/src/asio_server_request_handler.cc --- nghttp2-1.13.0/src/asio_server_request_handler.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_request_handler.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_server_request_handler.h" - -#include "util.h" -#include "http2.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -namespace { -std::string create_html(int status_code) { - BlockAllocator balloc(1024, 1024); - std::string res; - res.reserve(512); - auto status = ::nghttp2::http2::get_status_string(balloc, status_code); - res += R"()"; - res += status; - res += "

"; - res += status; - res += "

"; - return res; -} -} // namespace - -request_cb redirect_handler(int status_code, std::string uri) { - return [status_code, uri](const request &req, const response &res) { - header_map h; - h.emplace("location", header_value{std::move(uri)}); - std::string html; - if (req.method() == "GET") { - html = create_html(status_code); - } - h.emplace("content-length", header_value{util::utos(html.size())}); - - res.write_head(status_code, std::move(h)); - res.end(std::move(html)); - }; -} - -request_cb status_handler(int status_code) { - return [status_code](const request &req, const response &res) { - if (!::nghttp2::http2::expect_response_body(status_code)) { - res.write_head(status_code); - res.end(); - return; - } - // we supply content-length for HEAD request, but body will not be - // sent. - auto html = create_html(status_code); - header_map h; - h.emplace("content-length", header_value{util::utos(html.size())}); - h.emplace("content-type", header_value{"text/html; charset=utf-8"}); - - res.write_head(status_code, std::move(h)); - res.end(std::move(html)); - }; -} - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_request_handler.h nghttp2-0.6.7/src/asio_server_request_handler.h --- nghttp2-1.13.0/src/asio_server_request_handler.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_request_handler.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_SERVER_REQUEST_HANDLER_H -#define ASIO_SERVER_REQUEST_HANDLER_H - -#include "nghttp2_config.h" - -#include - -#endif // ASIO_SERVER_REQUEST_HANDLER_H diff -Nru nghttp2-1.13.0/src/asio_server_request_impl.cc nghttp2-0.6.7/src/asio_server_request_impl.cc --- nghttp2-1.13.0/src/asio_server_request_impl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_request_impl.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_server_request_impl.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -request_impl::request_impl() : strm_(nullptr), header_buffer_size_(0) {} - -const header_map &request_impl::header() const { return header_; } - -const std::string &request_impl::method() const { return method_; } - -const uri_ref &request_impl::uri() const { return uri_; } - -uri_ref &request_impl::uri() { return uri_; } - -void request_impl::header(header_map h) { header_ = std::move(h); } - -header_map &request_impl::header() { return header_; } - -void request_impl::method(std::string arg) { method_ = std::move(arg); } - -void request_impl::on_data(data_cb cb) { on_data_cb_ = std::move(cb); } - -void request_impl::stream(class stream *s) { strm_ = s; } - -void request_impl::call_on_data(const uint8_t *data, std::size_t len) { - if (on_data_cb_) { - on_data_cb_(data, len); - } -} - -const boost::asio::ip::tcp::endpoint &request_impl::remote_endpoint() const { - return remote_ep_; -} - -void request_impl::remote_endpoint(boost::asio::ip::tcp::endpoint ep) { - remote_ep_ = std::move(ep); -} - -size_t request_impl::header_buffer_size() const { return header_buffer_size_; } - -void request_impl::update_header_buffer_size(size_t len) { - header_buffer_size_ += len; -} - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_request_impl.h nghttp2-0.6.7/src/asio_server_request_impl.h --- nghttp2-1.13.0/src/asio_server_request_impl.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_request_impl.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_SERVER_REQUEST_IMPL_H -#define ASIO_SERVER_REQUEST_IMPL_H - -#include "nghttp2_config.h" - -#include -#include - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -class stream; - -class request_impl { -public: - request_impl(); - - void header(header_map h); - const header_map &header() const; - header_map &header(); - - void method(std::string method); - const std::string &method() const; - - const uri_ref &uri() const; - uri_ref &uri(); - - void on_data(data_cb cb); - - void stream(class stream *s); - void call_on_data(const uint8_t *data, std::size_t len); - - const boost::asio::ip::tcp::endpoint &remote_endpoint() const; - void remote_endpoint(boost::asio::ip::tcp::endpoint ep); - - size_t header_buffer_size() const; - void update_header_buffer_size(size_t len); - -private: - class stream *strm_; - header_map header_; - std::string method_; - uri_ref uri_; - data_cb on_data_cb_; - boost::asio::ip::tcp::endpoint remote_ep_; - size_t header_buffer_size_; -}; - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp2 - -#endif // ASIO_SERVER_REQUEST_IMPL_H diff -Nru nghttp2-1.13.0/src/asio_server_response.cc nghttp2-0.6.7/src/asio_server_response.cc --- nghttp2-1.13.0/src/asio_server_response.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_response.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "nghttp2_config.h" - -#include - -#include "asio_server_response_impl.h" - -#include "template.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -response::response() : impl_(make_unique()) {} - -response::~response() {} - -void response::write_head(unsigned int status_code, header_map h) const { - impl_->write_head(status_code, std::move(h)); -} - -void response::end(std::string data) const { impl_->end(std::move(data)); } - -void response::end(generator_cb cb) const { impl_->end(std::move(cb)); } - -void response::write_trailer(header_map h) const { - impl_->write_trailer(std::move(h)); -} - -void response::on_close(close_cb cb) const { impl_->on_close(std::move(cb)); } - -void response::cancel(uint32_t error_code) const { impl_->cancel(error_code); } - -const response *response::push(boost::system::error_code &ec, - std::string method, std::string path, - header_map h) const { - return impl_->push(ec, std::move(method), std::move(path), std::move(h)); -} - -void response::resume() const { impl_->resume(); } - -unsigned int response::status_code() const { return impl_->status_code(); } - -boost::asio::io_service &response::io_service() const { - return impl_->io_service(); -} - -response_impl &response::impl() const { return *impl_; } - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_response_impl.cc nghttp2-0.6.7/src/asio_server_response_impl.cc --- nghttp2-1.13.0/src/asio_server_response_impl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_response_impl.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,166 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_server_response_impl.h" - -#include "asio_server_stream.h" -#include "asio_server_request_impl.h" -#include "asio_server_http2_handler.h" -#include "asio_common.h" - -#include "http2.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -response_impl::response_impl() - : strm_(nullptr), - generator_cb_(deferred_generator()), - status_code_(200), - state_(response_state::INITIAL), - pushed_(false), - push_promise_sent_(false) {} - -unsigned int response_impl::status_code() const { return status_code_; } - -void response_impl::write_head(unsigned int status_code, header_map h) { - if (state_ != response_state::INITIAL) { - return; - } - - status_code_ = status_code; - header_ = std::move(h); - - state_ = response_state::HEADER_DONE; - - if (pushed_ && !push_promise_sent_) { - return; - } - - start_response(); -} - -void response_impl::end(std::string data) { - end(string_generator(std::move(data))); -} - -void response_impl::end(generator_cb cb) { - if (state_ == response_state::BODY_STARTED) { - return; - } - - generator_cb_ = std::move(cb); - - if (state_ == response_state::INITIAL) { - write_head(status_code_); - } else { - // generator_cb is changed, start writing in case it is deferred. - auto handler = strm_->handler(); - handler->resume(*strm_); - } - - state_ = response_state::BODY_STARTED; -} - -void response_impl::write_trailer(header_map h) { - auto handler = strm_->handler(); - handler->submit_trailer(*strm_, std::move(h)); -} - -void response_impl::start_response() { - auto handler = strm_->handler(); - - auto &req = strm_->request().impl(); - - if (!::nghttp2::http2::expect_response_body(req.method(), status_code_)) { - state_ = response_state::BODY_STARTED; - } - - if (handler->start_response(*strm_) != 0) { - handler->stream_error(strm_->get_stream_id(), NGHTTP2_INTERNAL_ERROR); - return; - } -} - -void response_impl::on_close(close_cb cb) { close_cb_ = std::move(cb); } - -void response_impl::call_on_close(uint32_t error_code) { - if (close_cb_) { - close_cb_(error_code); - } -} - -void response_impl::cancel(uint32_t error_code) { - auto handler = strm_->handler(); - handler->stream_error(strm_->get_stream_id(), error_code); -} - -response *response_impl::push(boost::system::error_code &ec, std::string method, - std::string raw_path_query, header_map h) const { - auto handler = strm_->handler(); - return handler->push_promise(ec, *strm_, std::move(method), - std::move(raw_path_query), std::move(h)); -} - -void response_impl::resume() { - auto handler = strm_->handler(); - handler->resume(*strm_); -} - -boost::asio::io_service &response_impl::io_service() { - return strm_->handler()->io_service(); -} - -void response_impl::pushed(bool f) { pushed_ = f; } - -void response_impl::push_promise_sent() { - if (push_promise_sent_) { - return; - } - push_promise_sent_ = true; - if (state_ == response_state::INITIAL) { - return; - } - start_response(); -} - -const header_map &response_impl::header() const { return header_; } - -void response_impl::stream(class stream *s) { strm_ = s; } - -generator_cb::result_type -response_impl::call_read(uint8_t *data, std::size_t len, uint32_t *data_flags) { - if (generator_cb_) { - return generator_cb_(data, len, data_flags); - } - - *data_flags |= NGHTTP2_DATA_FLAG_EOF; - - return 0; -} - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_response_impl.h nghttp2-0.6.7/src/asio_server_response_impl.h --- nghttp2-1.13.0/src/asio_server_response_impl.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_response_impl.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_SERVER_RESPONSE_IMPL_H -#define ASIO_SERVER_RESPONSE_IMPL_H - -#include "nghttp2_config.h" - -#include - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -class stream; - -enum class response_state { - INITIAL, - // response_impl::write_head() was called - HEADER_DONE, - // response_impl::end() was called - BODY_STARTED, -}; - -class response_impl { -public: - response_impl(); - void write_head(unsigned int status_code, header_map h = header_map{}); - void end(std::string data = ""); - void end(generator_cb cb); - void write_trailer(header_map h); - void on_close(close_cb cb); - void resume(); - - void cancel(uint32_t error_code); - - response *push(boost::system::error_code &ec, std::string method, - std::string raw_path_query, header_map) const; - - boost::asio::io_service &io_service(); - - void start_response(); - - unsigned int status_code() const; - const header_map &header() const; - void pushed(bool f); - void push_promise_sent(); - void stream(class stream *s); - generator_cb::result_type call_read(uint8_t *data, std::size_t len, - uint32_t *data_flags); - void call_on_close(uint32_t error_code); - -private: - class stream *strm_; - header_map header_; - generator_cb generator_cb_; - close_cb close_cb_; - unsigned int status_code_; - response_state state_; - // true if this is pushed stream's response - bool pushed_; - // true if PUSH_PROMISE is sent if this is response of a pushed - // stream - bool push_promise_sent_; -}; - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp2 - -#endif // ASIO_SERVER_RESPONSE_IMPL_H diff -Nru nghttp2-1.13.0/src/asio_server_serve_mux.cc nghttp2-0.6.7/src/asio_server_serve_mux.cc --- nghttp2-1.13.0/src/asio_server_serve_mux.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_serve_mux.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_server_serve_mux.h" - -#include "asio_server_request_impl.h" -#include "asio_server_request_handler.h" -#include "util.h" -#include "http2.h" - -namespace nghttp2 { - -namespace asio_http2 { - -namespace server { - -bool serve_mux::handle(std::string pattern, request_cb cb) { - if (pattern.empty() || !cb) { - return false; - } - - auto it = mux_.find(pattern); - if (it != std::end(mux_) && (*it).second.user_defined) { - return false; - } - - // if pattern ends with '/' (e.g., /foo/), add implicit permanent - // redirect for '/foo'. - if (pattern.size() >= 2 && pattern.back() == '/') { - auto redirect_pattern = pattern.substr(0, pattern.size() - 1); - auto it = mux_.find(redirect_pattern); - if (it == std::end(mux_) || !(*it).second.user_defined) { - std::string path; - if (pattern[0] == '/') { - path = pattern; - } else { - // skip host part - path = pattern.substr(pattern.find('/')); - } - if (it == std::end(mux_)) { - mux_.emplace(std::move(redirect_pattern), - handler_entry{false, - redirect_handler(301, std::move(path)), - pattern}); - } else { - (*it).second = handler_entry{ - false, redirect_handler(301, std::move(path)), pattern}; - } - } - } - mux_.emplace(pattern, handler_entry{true, std::move(cb), pattern}); - - return true; -} - -request_cb serve_mux::handler(request_impl &req) const { - auto &path = req.uri().path; - if (req.method() != "CONNECT") { - auto clean_path = ::nghttp2::http2::path_join(StringRef{}, StringRef{}, - StringRef{path}, StringRef{}); - if (clean_path != path) { - auto new_uri = util::percent_encode_path(clean_path); - auto &uref = req.uri(); - if (!uref.raw_query.empty()) { - new_uri += '?'; - new_uri += uref.raw_query; - } - - return redirect_handler(301, std::move(new_uri)); - } - } - auto &host = req.uri().host; - - auto cb = match(host + path); - if (cb) { - return cb; - } - cb = match(path); - if (cb) { - return cb; - } - return status_handler(404); -} - -namespace { -bool path_match(const std::string &pattern, const std::string &path) { - if (pattern.back() != '/') { - return pattern == path; - } - return util::starts_with(path, pattern); -} -} // namespace - -request_cb serve_mux::match(const std::string &path) const { - const handler_entry *ent = nullptr; - size_t best = 0; - for (auto &kv : mux_) { - auto &pattern = kv.first; - if (!path_match(pattern, path)) { - continue; - } - if (!ent || best < pattern.size()) { - best = pattern.size(); - ent = &kv.second; - } - } - if (ent) { - return ent->cb; - } - return request_cb(); -} - -} // namespace server - -} // namespace asio_http2 - -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_serve_mux.h nghttp2-0.6.7/src/asio_server_serve_mux.h --- nghttp2-1.13.0/src/asio_server_serve_mux.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_serve_mux.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_SERVER_SERVE_MUX_H -#define ASIO_SERVER_SERVE_MUX_H - -#include "nghttp2_config.h" - -#include - -namespace nghttp2 { - -namespace asio_http2 { - -namespace server { - -class request_impl; - -// port from go's ServeMux - -struct handler_entry { - bool user_defined; - request_cb cb; - std::string pattern; -}; - -class serve_mux { -public: - bool handle(std::string pattern, request_cb cb); - request_cb handler(request_impl &req) const; - request_cb match(const std::string &path) const; - -private: - std::map mux_; -}; - -} // namespace server - -} // namespace asio_http2 - -} // namespace nghttp2 - -#endif // ASIO_SERVER_SERVE_MUX_H diff -Nru nghttp2-1.13.0/src/asio_server_stream.cc nghttp2-0.6.7/src/asio_server_stream.cc --- nghttp2-1.13.0/src/asio_server_stream.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_stream.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_server_stream.h" - -#include "asio_server_http2_handler.h" -#include "asio_server_request_impl.h" -#include "asio_server_response_impl.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -stream::stream(http2_handler *h, int32_t stream_id) - : handler_(h), stream_id_(stream_id) { - request_.impl().stream(this); - response_.impl().stream(this); -} - -int32_t stream::get_stream_id() const { return stream_id_; } - -class request &stream::request() { - return request_; -} - -class response &stream::response() { - return response_; -} - -http2_handler *stream::handler() const { return handler_; } - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_stream.h nghttp2-0.6.7/src/asio_server_stream.h --- nghttp2-1.13.0/src/asio_server_stream.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_stream.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_SERVER_STREAM_H -#define ASIO_SERVER_STREAM_H - -#include "nghttp2_config.h" - -#include - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -class http2_handler; - -class stream { -public: - stream(http2_handler *h, int32_t stream_id); - - int32_t get_stream_id() const; - class request &request(); - class response &response(); - - http2_handler *handler() const; - -private: - http2_handler *handler_; - class request request_; - class response response_; - int32_t stream_id_; -}; - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp2 - -#endif // ASIO_SERVER_STREAM_H diff -Nru nghttp2-1.13.0/src/asio_server_tls_context.cc nghttp2-0.6.7/src/asio_server_tls_context.cc --- nghttp2-1.13.0/src/asio_server_tls_context.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_tls_context.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "asio_server_tls_context.h" - -#include - -#include - -#include "ssl.h" -#include "util.h" - -namespace nghttp2 { -namespace asio_http2 { -namespace server { - -namespace { -std::vector &get_alpn_token() { - static auto alpn_token = util::get_default_alpn(); - return alpn_token; -} -} // namespace - -#if OPENSSL_VERSION_NUMBER >= 0x10002000L -namespace { -int alpn_select_proto_cb(SSL *ssl, const unsigned char **out, - unsigned char *outlen, const unsigned char *in, - unsigned int inlen, void *arg) { - if (!util::select_h2(out, outlen, in, inlen)) { - return SSL_TLSEXT_ERR_NOACK; - } - return SSL_TLSEXT_ERR_OK; -} -} // namespace -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - -boost::system::error_code -configure_tls_context_easy(boost::system::error_code &ec, - boost::asio::ssl::context &tls_context) { - ec.clear(); - - auto ctx = tls_context.native_handle(); - - auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | - SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | - SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET | - SSL_OP_CIPHER_SERVER_PREFERENCE; - - SSL_CTX_set_options(ctx, ssl_opts); - SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); - SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); - - SSL_CTX_set_cipher_list(ctx, ssl::DEFAULT_CIPHER_LIST); - -#ifndef OPENSSL_NO_EC - auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - if (ecdh) { - SSL_CTX_set_tmp_ecdh(ctx, ecdh); - EC_KEY_free(ecdh); - } -#endif /* OPENSSL_NO_EC */ - - SSL_CTX_set_next_protos_advertised_cb( - ctx, - [](SSL *s, const unsigned char **data, unsigned int *len, void *arg) { - auto &token = get_alpn_token(); - - *data = token.data(); - *len = token.size(); - - return SSL_TLSEXT_ERR_OK; - }, - nullptr); - -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - // ALPN selection callback - SSL_CTX_set_alpn_select_cb(ctx, alpn_select_proto_cb, nullptr); -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - return ec; -} - -} // namespace server -} // namespace asio_http2 -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/asio_server_tls_context.h nghttp2-0.6.7/src/asio_server_tls_context.h --- nghttp2-1.13.0/src/asio_server_tls_context.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/asio_server_tls_context.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_SERVER_TLS_CONTEXT_H -#define ASIO_SERVER_TLS_CONTEXT_H - -#include "nghttp2_config.h" - -#include - -#endif // ASIO_SERVER_TLS_CONTEXT_H diff -Nru nghttp2-1.13.0/src/base64.h nghttp2-0.6.7/src/base64.h --- nghttp2-1.13.0/src/base64.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/base64.h 2014-11-30 14:15:07.000000000 +0000 @@ -33,8 +33,9 @@ namespace base64 { -template std::string encode(InputIt first, InputIt last) { - static constexpr char CHAR_TABLE[] = { +template +std::string encode(InputIterator first, InputIterator last) { + static const char CHAR_TABLE[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', @@ -47,38 +48,39 @@ return res; } size_t r = len % 3; - res.resize((len + 2) / 3 * 4); - auto j = last - r; - auto p = std::begin(res); + InputIterator j = last - r; + char temp[4]; while (first != j) { - uint32_t n = static_cast(*first++) << 16; - n += static_cast(*first++) << 8; - n += static_cast(*first++); - *p++ = CHAR_TABLE[n >> 18]; - *p++ = CHAR_TABLE[(n >> 12) & 0x3fu]; - *p++ = CHAR_TABLE[(n >> 6) & 0x3fu]; - *p++ = CHAR_TABLE[n & 0x3fu]; + int n = static_cast(*first++) << 16; + n += static_cast(*first++) << 8; + n += static_cast(*first++); + temp[0] = CHAR_TABLE[n >> 18]; + temp[1] = CHAR_TABLE[(n >> 12) & 0x3fu]; + temp[2] = CHAR_TABLE[(n >> 6) & 0x3fu]; + temp[3] = CHAR_TABLE[n & 0x3fu]; + res.append(temp, sizeof(temp)); } - if (r == 2) { - uint32_t n = static_cast(*first++) << 16; - n += static_cast(*first++) << 8; - *p++ = CHAR_TABLE[n >> 18]; - *p++ = CHAR_TABLE[(n >> 12) & 0x3fu]; - *p++ = CHAR_TABLE[(n >> 6) & 0x3fu]; - *p++ = '='; + int n = static_cast(*first++) << 16; + n += static_cast(*first++) << 8; + temp[0] = CHAR_TABLE[n >> 18]; + temp[1] = CHAR_TABLE[(n >> 12) & 0x3fu]; + temp[2] = CHAR_TABLE[(n >> 6) & 0x3fu]; + temp[3] = '='; + res.append(temp, sizeof(temp)); } else if (r == 1) { - uint32_t n = static_cast(*first++) << 16; - *p++ = CHAR_TABLE[n >> 18]; - *p++ = CHAR_TABLE[(n >> 12) & 0x3fu]; - *p++ = '='; - *p++ = '='; + int n = static_cast(*first++) << 16; + temp[0] = CHAR_TABLE[n >> 18]; + temp[1] = CHAR_TABLE[(n >> 12) & 0x3fu]; + temp[2] = '='; + temp[3] = '='; + res.append(temp, sizeof(temp)); } return res; } -template -InputIt next_decode_input(InputIt first, InputIt last, const int *tbl) { +template +InputIterator getNext(InputIterator first, InputIterator last, const int *tbl) { for (; first != last; ++first) { if (tbl[static_cast(*first)] != -1 || *first == '=') { break; @@ -87,8 +89,9 @@ return first; } -template std::string decode(InputIt first, InputIt last) { - static constexpr int INDEX_TABLE[] = { +template +std::string decode(InputIterator first, InputIterator last) { + static const int INDEX_TABLE[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, @@ -104,47 +107,59 @@ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - auto len = last - first; - if (len % 4 != 0) { - return ""; - } std::string res; - res.resize(len / 4 * 3); - - auto p = std::begin(res); + InputIterator k[4]; + int eq = 0; for (; first != last;) { - uint32_t n = 0; - for (int i = 1; i <= 4; ++i, ++first) { - auto idx = INDEX_TABLE[static_cast(*first)]; - if (idx == -1) { - if (i <= 2) { - return ""; + for (int i = 1; i <= 4; ++i) { + k[i - 1] = getNext(first, last, INDEX_TABLE); + if (k[i - 1] == last) { + // If i == 1, input may look like this: "TWFu\n" (i.e., + // garbage at the end) + if (i != 1) { + res.clear(); } - if (i == 3) { - if (*first == '=' && *(first + 1) == '=' && first + 2 == last) { - *p++ = n >> 16; - res.resize(p - std::begin(res)); - return res; - } - return ""; - } - if (*first == '=' && first + 1 == last) { - *p++ = n >> 16; - *p++ = n >> 8 & 0xffu; - res.resize(p - std::begin(res)); + return res; + } else if (*k[i - 1] == '=' && eq == 0) { + eq = i; + } + first = k[i - 1] + 1; + } + if (eq) { + break; + } + int n = (INDEX_TABLE[static_cast(*k[0])] << 18) + + (INDEX_TABLE[static_cast(*k[1])] << 12) + + (INDEX_TABLE[static_cast(*k[2])] << 6) + + INDEX_TABLE[static_cast(*k[3])]; + res += n >> 16; + res += n >> 8 & 0xffu; + res += n & 0xffu; + } + if (eq) { + if (eq <= 2) { + res.clear(); + return res; + } else { + for (int i = eq; i <= 4; ++i) { + if (*k[i - 1] != '=') { + res.clear(); return res; } - return ""; } - - n += idx << (24 - i * 6); + if (eq == 3) { + int n = (INDEX_TABLE[static_cast(*k[0])] << 18) + + (INDEX_TABLE[static_cast(*k[1])] << 12); + res += n >> 16; + } else if (eq == 4) { + int n = (INDEX_TABLE[static_cast(*k[0])] << 18) + + (INDEX_TABLE[static_cast(*k[1])] << 12) + + (INDEX_TABLE[static_cast(*k[2])] << 6); + res += n >> 16; + res += n >> 8 & 0xffu; + } } - - *p++ = n >> 16; - *p++ = n >> 8 & 0xffu; - *p++ = n & 0xffu; } - return res; } diff -Nru nghttp2-1.13.0/src/base64_test.cc nghttp2-0.6.7/src/base64_test.cc --- nghttp2-1.13.0/src/base64_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/base64_test.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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. - */ -#include "base64_test.h" - -#include -#include - -#include - -#include - -#include "base64.h" - -namespace nghttp2 { - -void test_base64_encode(void) { - { - std::string in = "\xff"; - auto out = base64::encode(std::begin(in), std::end(in)); - CU_ASSERT("/w==" == out); - } - { - std::string in = "\xff\xfe"; - auto out = base64::encode(std::begin(in), std::end(in)); - CU_ASSERT("//4=" == out); - } - { - std::string in = "\xff\xfe\xfd"; - auto out = base64::encode(std::begin(in), std::end(in)); - CU_ASSERT("//79" == out); - } - { - std::string in = "\xff\xfe\xfd\xfc"; - auto out = base64::encode(std::begin(in), std::end(in)); - CU_ASSERT("//79/A==" == out); - } -} - -void test_base64_decode(void) { - { - std::string in = "/w=="; - auto out = base64::decode(std::begin(in), std::end(in)); - CU_ASSERT("\xff" == out); - } - { - std::string in = "//4="; - auto out = base64::decode(std::begin(in), std::end(in)); - CU_ASSERT("\xff\xfe" == out); - } - { - std::string in = "//79"; - auto out = base64::decode(std::begin(in), std::end(in)); - CU_ASSERT("\xff\xfe\xfd" == out); - } - { - std::string in = "//79/A=="; - auto out = base64::decode(std::begin(in), std::end(in)); - CU_ASSERT("\xff\xfe\xfd\xfc" == out); - } - { - // we check the number of valid input must be multiples of 4 - std::string in = "//79="; - auto out = base64::decode(std::begin(in), std::end(in)); - CU_ASSERT("" == out); - } - { - // ending invalid character at the boundary of multiples of 4 is - // bad - std::string in = "bmdodHRw\n"; - auto out = base64::decode(std::begin(in), std::end(in)); - CU_ASSERT("" == out); - } - { - // after seeing '=', subsequent input must be also '='. - std::string in = "//79/A=A"; - auto out = base64::decode(std::begin(in), std::end(in)); - CU_ASSERT("" == out); - } - { - // additional '=' at the end is bad - std::string in = "//79/A======"; - auto out = base64::decode(std::begin(in), std::end(in)); - CU_ASSERT("" == out); - } -} - -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/base64_test.h nghttp2-0.6.7/src/base64_test.h --- nghttp2-1.13.0/src/base64_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/base64_test.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 BASE64_TEST_H -#define BASE64_TEST_H - -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - -namespace nghttp2 { - -void test_base64_encode(void); -void test_base64_decode(void); - -} // namespace nghttp2 - -#endif // BASE64_TEST_H diff -Nru nghttp2-1.13.0/src/buffer.h nghttp2-0.6.7/src/buffer.h --- nghttp2-1.13.0/src/buffer.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/buffer.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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 BUFFER_H -#define BUFFER_H - -#include "nghttp2_config.h" - -#include -#include -#include - -namespace nghttp2 { - -template struct Buffer { - Buffer() : pos(std::begin(buf)), last(pos) {} - // Returns the number of bytes to read. - size_t rleft() const { return last - pos; } - // Returns the number of bytes this buffer can store. - size_t wleft() const { return std::end(buf) - last; } - // Writes up to min(wleft(), |count|) bytes from buffer pointed by - // |src|. Returns number of bytes written. - size_t write(const void *src, size_t count) { - count = std::min(count, wleft()); - auto p = static_cast(src); - last = std::copy_n(p, count, last); - return count; - } - size_t write(size_t count) { - count = std::min(count, wleft()); - last += count; - return count; - } - // Drains min(rleft(), |count|) bytes from start of the buffer. - size_t drain(size_t count) { - count = std::min(count, rleft()); - pos += count; - return count; - } - size_t drain_reset(size_t count) { - count = std::min(count, rleft()); - std::copy(pos + count, last, std::begin(buf)); - last = std::begin(buf) + (last - (pos + count)); - pos = std::begin(buf); - return count; - } - void reset() { pos = last = std::begin(buf); } - uint8_t *begin() { return std::begin(buf); } - uint8_t &operator[](size_t n) { return buf[n]; } - const uint8_t &operator[](size_t n) const { return buf[n]; } - std::array buf; - uint8_t *pos, *last; -}; - -} // namespace nghttp2 - -#endif // BUFFER_H diff -Nru nghttp2-1.13.0/src/buffer_test.cc nghttp2-0.6.7/src/buffer_test.cc --- nghttp2-1.13.0/src/buffer_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/buffer_test.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "buffer_test.h" - -#include -#include -#include - -#include - -#include - -#include "buffer.h" - -namespace nghttp2 { - -void test_buffer_write(void) { - Buffer<16> b; - CU_ASSERT(0 == b.rleft()); - CU_ASSERT(16 == b.wleft()); - - b.write("012", 3); - - CU_ASSERT(3 == b.rleft()); - CU_ASSERT(13 == b.wleft()); - CU_ASSERT(b.pos == std::begin(b.buf)); - - b.drain(3); - - CU_ASSERT(0 == b.rleft()); - CU_ASSERT(13 == b.wleft()); - CU_ASSERT(3 == b.pos - std::begin(b.buf)); - - auto n = b.write("0123456789ABCDEF", 16); - - CU_ASSERT(n == 13); - - CU_ASSERT(13 == b.rleft()); - CU_ASSERT(0 == b.wleft()); - CU_ASSERT(3 == b.pos - std::begin(b.buf)); - CU_ASSERT(0 == memcmp(b.pos, "0123456789ABC", 13)); - - b.reset(); - - CU_ASSERT(0 == b.rleft()); - CU_ASSERT(16 == b.wleft()); - CU_ASSERT(b.pos == std::begin(b.buf)); - - b.write(5); - - CU_ASSERT(5 == b.rleft()); - CU_ASSERT(11 == b.wleft()); - CU_ASSERT(b.pos == std::begin(b.buf)); -} - -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/buffer_test.h nghttp2-0.6.7/src/buffer_test.h --- nghttp2-1.13.0/src/buffer_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/buffer_test.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 BUFFER_TEST_H -#define BUFFER_TEST_H - -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - -namespace nghttp2 { - -void test_buffer_write(void); - -} // namespace nghttp2 - -#endif // BUFFER_TEST_H diff -Nru nghttp2-1.13.0/src/CMakeLists.txt nghttp2-0.6.7/src/CMakeLists.txt --- nghttp2-1.13.0/src/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,261 +0,0 @@ -add_subdirectory(includes) - -file(GLOB c_sources *.c) -set_source_files_properties(${c_sources} PROPERTIES - COMPILE_FLAGS "${WARNCFLAGS}") -file(GLOB cxx_sources *.cc) -set_source_files_properties(${cxx_sources} PROPERTIES - COMPILE_FLAGS "${WARNCXXFLAGS} ${CXX1XCXXFLAGS}") - -include_directories( - "${CMAKE_SOURCE_DIR}/lib/includes" - "${CMAKE_BINARY_DIR}/lib/includes" - "${CMAKE_SOURCE_DIR}/lib" - "${CMAKE_SOURCE_DIR}/src/includes" - "${CMAKE_SOURCE_DIR}/third-party" - - ${JEMALLOC_INCLUDE_DIRS} - ${SPDYLAY_INCLUDE_DIRS} - ${LIBXML2_INCLUDE_DIRS} - ${LIBEV_INCLUDE_DIRS} - ${OPENSSL_INCLUDE_DIRS} - ${JANSSON_INCLUDE_DIRS} - ${ZLIB_INCLUDE_DIRS} -) - -# XXX per-target? -link_libraries( - nghttp2 - ${JEMALLOC_LIBRARIES} - ${SPDYLAY_LIBRARIES} - ${LIBXML2_LIBRARIES} - ${LIBEV_LIBRARIES} - ${OPENSSL_LIBRARIES} - ${JANSSON_LIBRARIES} - ${ZLIB_LIBRARIES} - ${APP_LIBRARIES} -) - -if(ENABLE_APP) - set(HELPER_OBJECTS - util.cc - http2.cc timegm.c app_helper.cc nghttp2_gzip.c - ) - - # nghttp client - set(NGHTTP_SOURCES - ${HELPER_OBJECTS} - nghttp.cc - ssl.cc - ) - if(HAVE_LIBXML2) - list(APPEND NGHTTP_SOURCES HtmlParser.cc) - endif() - - # nghttpd - set(NGHTTPD_SOURCES - ${HELPER_OBJECTS} - nghttpd.cc - ssl.cc - HttpServer.cc - ) - - # h2load - set(H2LOAD_SOURCES - util.cc - http2.cc h2load.cc - timegm.c - ssl.cc - h2load_http2_session.cc - h2load_http1_session.cc - ) - if(HAVE_SPDYLAY) - list(APPEND H2LOAD_SOURCES - h2load_spdy_session.cc - ) - endif() - - - # Common libnhttpx sources (used for nghttpx and unit tests) - set(NGHTTPX_SRCS - util.cc http2.cc timegm.c - app_helper.cc - ssl.cc - shrpx_config.cc - shrpx_accept_handler.cc - shrpx_connection_handler.cc - shrpx_client_handler.cc - shrpx_http2_upstream.cc - shrpx_https_upstream.cc - shrpx_downstream.cc - shrpx_downstream_connection.cc - shrpx_http_downstream_connection.cc - shrpx_http2_downstream_connection.cc - shrpx_http2_session.cc - shrpx_downstream_queue.cc - shrpx_log.cc - shrpx_http.cc - shrpx_io_control.cc - shrpx_ssl.cc - shrpx_worker.cc - shrpx_log_config.cc - shrpx_connect_blocker.cc - shrpx_live_check.cc - shrpx_downstream_connection_pool.cc - shrpx_rate_limit.cc - shrpx_connection.cc - shrpx_memcached_dispatcher.cc - shrpx_memcached_connection.cc - shrpx_worker_process.cc - shrpx_signal.cc - shrpx_router.cc - shrpx_api_downstream_connection.cc - shrpx_health_monitor_downstream_connection.cc - ) - if(HAVE_SPDYLAY) - list(APPEND NGHTTPX_SRCS - shrpx_spdy_upstream.cc - ) - endif() - if(HAVE_MRUBY) - list(APPEND NGHTTPX_SRCS - shrpx_mruby.cc - shrpx_mruby_module.cc - shrpx_mruby_module_env.cc - shrpx_mruby_module_request.cc - shrpx_mruby_module_response.cc - ) - endif() - add_library(nghttpx_static STATIC ${NGHTTPX_SRCS}) - set_target_properties(nghttpx_static PROPERTIES ARCHIVE_OUTPUT_NAME nghttpx) - - set(NGHTTPX-bin_SOURCES - shrpx.cc - ) - - if(HAVE_MRUBY) - target_link_libraries(nghttpx_static mruby-lib) - endif() - - if(HAVE_NEVERBLEED) - target_link_libraries(nghttpx_static neverbleed) - endif() - - - if(HAVE_CUNIT) - set(NGHTTPX_UNITTEST_SOURCES - shrpx-unittest.cc - shrpx_ssl_test.cc - shrpx_downstream_test.cc - shrpx_config_test.cc - shrpx_worker_test.cc - shrpx_http_test.cc - shrpx_router_test.cc - http2_test.cc - util_test.cc - nghttp2_gzip_test.c - nghttp2_gzip.c - buffer_test.cc - memchunk_test.cc - template_test.cc - base64_test.cc - ) - add_executable(nghttpx-unittest EXCLUDE_FROM_ALL - ${NGHTTPX_UNITTEST_SOURCES} - $ - ) - target_include_directories(nghttpx-unittest PRIVATE ${CUNIT_INCLUDE_DIRS}) - target_compile_definitions(nghttpx-unittest - PRIVATE "-DNGHTTP2_SRC_DIR=\"${CMAKE_SOURCE_DIR}/src\"" - ) - target_link_libraries(nghttpx-unittest nghttpx_static ${CUNIT_LIBRARIES}) - if(HAVE_MRUBY) - target_link_libraries(nghttpx-unittest mruby-lib) - endif() - if(HAVE_NEVERBLEED) - target_link_libraries(nghttpx-unittest neverbleed) - endif() - - add_test(nghttpx-unittest nghttpx-unittest) - add_dependencies(check nghttpx-unittest) - endif() - - add_executable(nghttp ${NGHTTP_SOURCES} $) - add_executable(nghttpd ${NGHTTPD_SOURCES} $) - add_executable(nghttpx ${NGHTTPX-bin_SOURCES} $) - target_compile_definitions(nghttpx PRIVATE "-DPKGDATADIR=\"${PKGDATADIR}\"") - target_link_libraries(nghttpx nghttpx_static) - add_executable(h2load ${H2LOAD_SOURCES} $) - - install(TARGETS nghttp nghttpd nghttpx h2load - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") -endif() - -if(ENABLE_HPACK_TOOLS) - set(inflatehd_SOURCES - inflatehd.cc - comp_helper.c - ) - set(deflatehd_SOURCES - deflatehd.cc - comp_helper.c - ) - add_executable(inflatehd ${inflatehd_SOURCES}) - add_executable(deflatehd ${deflatehd_SOURCES}) - install(TARGETS inflatehd deflatehd - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") -endif() - -if(ENABLE_ASIO_LIB) - set(NGHTTP2_ASIO_SOURCES - util.cc http2.cc - ssl.cc - timegm.c - asio_common.cc - asio_io_service_pool.cc - asio_server_http2.cc - asio_server_http2_impl.cc - asio_server.cc - asio_server_http2_handler.cc - asio_server_request.cc - asio_server_request_impl.cc - asio_server_response.cc - asio_server_response_impl.cc - asio_server_stream.cc - asio_server_serve_mux.cc - asio_server_request_handler.cc - asio_server_tls_context.cc - asio_client_session.cc - asio_client_session_impl.cc - asio_client_session_tcp_impl.cc - asio_client_session_tls_impl.cc - asio_client_response.cc - asio_client_response_impl.cc - asio_client_request.cc - asio_client_request_impl.cc - asio_client_stream.cc - asio_client_tls_context.cc - ) - - add_library(nghttp2_asio SHARED - ${NGHTTP2_ASIO_SOURCES} - $ - ) - target_include_directories(nghttp2_asio PRIVATE - ${OPENSSL_INCLUDE_DIRS} - ${Boost_INCLUDE_DIRS} - ) - target_link_libraries(nghttp2_asio - nghttp2 - ${OPENSSL_LIBRARIES} - ${Boost_LIBRARIES} - ) - set_target_properties(nghttp2_asio PROPERTIES - VERSION 1.0.0 SOVERSION 1) - - install(TARGETS nghttp2_asio - DESTINATION "${CMAKE_INSTALL_LIBDIR}") - - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2_asio.pc" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") -endif() diff -Nru nghttp2-1.13.0/src/comp_helper.c nghttp2-0.6.7/src/comp_helper.c --- nghttp2-1.13.0/src/comp_helper.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/comp_helper.c 2014-11-30 14:15:07.000000000 +0000 @@ -29,69 +29,27 @@ json_object_set_new(jent, key, json_pack("s#", val, len)); } -#define NGHTTP2_HD_ENTRY_OVERHEAD 32 - -json_t *dump_deflate_header_table(nghttp2_hd_deflater *deflater) { +json_t *dump_header_table(nghttp2_hd_context *context) { json_t *obj, *entries; size_t i; - size_t len = nghttp2_hd_deflate_get_num_table_entries(deflater); obj = json_object(); entries = json_array(); - /* The first index of dynamic table is 62 */ - for (i = 62; i <= len; ++i) { - const nghttp2_nv *nv = nghttp2_hd_deflate_get_table_entry(deflater, i); + for (i = 0; i < context->hd_table.len; ++i) { + nghttp2_hd_entry *ent = nghttp2_hd_table_get(context, i); json_t *outent = json_object(); - json_object_set_new(outent, "index", json_integer((json_int_t)i)); - dump_val(outent, "name", nv->name, nv->namelen); - dump_val(outent, "value", nv->value, nv->valuelen); + json_object_set_new(outent, "index", json_integer(i + 1)); + dump_val(outent, "name", ent->nv.name, ent->nv.namelen); + dump_val(outent, "value", ent->nv.value, ent->nv.valuelen); json_object_set_new(outent, "size", - json_integer((json_int_t)(nv->namelen + nv->valuelen + - NGHTTP2_HD_ENTRY_OVERHEAD))); + json_integer(ent->nv.namelen + ent->nv.valuelen + + NGHTTP2_HD_ENTRY_OVERHEAD)); json_array_append_new(entries, outent); } json_object_set_new(obj, "entries", entries); - json_object_set_new( - obj, "size", - json_integer( - (json_int_t)nghttp2_hd_deflate_get_dynamic_table_size(deflater))); - json_object_set_new( - obj, "max_size", - json_integer( - (json_int_t)nghttp2_hd_deflate_get_max_dynamic_table_size(deflater))); - - return obj; -} - -json_t *dump_inflate_header_table(nghttp2_hd_inflater *inflater) { - json_t *obj, *entries; - size_t i; - size_t len = nghttp2_hd_inflate_get_num_table_entries(inflater); - - obj = json_object(); - entries = json_array(); - /* The first index of dynamic table is 62 */ - for (i = 62; i <= len; ++i) { - const nghttp2_nv *nv = nghttp2_hd_inflate_get_table_entry(inflater, i); - json_t *outent = json_object(); - json_object_set_new(outent, "index", json_integer((json_int_t)i)); - dump_val(outent, "name", nv->name, nv->namelen); - dump_val(outent, "value", nv->value, nv->valuelen); - json_object_set_new(outent, "size", - json_integer((json_int_t)(nv->namelen + nv->valuelen + - NGHTTP2_HD_ENTRY_OVERHEAD))); - json_array_append_new(entries, outent); - } - json_object_set_new(obj, "entries", entries); - json_object_set_new( - obj, "size", - json_integer( - (json_int_t)nghttp2_hd_inflate_get_dynamic_table_size(inflater))); - json_object_set_new( - obj, "max_size", - json_integer( - (json_int_t)nghttp2_hd_inflate_get_max_dynamic_table_size(inflater))); - + json_object_set_new(obj, "size", json_integer(context->hd_table_bufsize)); + json_object_set_new(obj, "max_size", + json_integer(context->hd_table_bufsize_max)); return obj; } @@ -99,9 +57,6 @@ size_t valuelen) { json_t *nv_pair = json_object(); char *cname = malloc(namelen + 1); - if (cname == NULL) { - return NULL; - } memcpy(cname, name, namelen); cname[namelen] = '\0'; json_object_set_new(nv_pair, cname, json_pack("s#", value, valuelen)); diff -Nru nghttp2-1.13.0/src/comp_helper.h nghttp2-0.6.7/src/comp_helper.h --- nghttp2-1.13.0/src/comp_helper.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/comp_helper.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,19 +27,13 @@ #ifdef HAVE_CONFIG_H #include -#endif /* HAVE_CONFIG_H */ +#endif // HAVE_CONFIG_H #include -#include +#include "nghttp2_hd.h" -#ifdef __cplusplus -extern "C" { -#endif - -json_t *dump_deflate_header_table(nghttp2_hd_deflater *deflater); - -json_t *dump_inflate_header_table(nghttp2_hd_inflater *inflater); +json_t *dump_header_table(nghttp2_hd_context *context); json_t *dump_header(const uint8_t *name, size_t namelen, const uint8_t *value, size_t vlauelen); @@ -50,8 +44,4 @@ void output_json_footer(void); -#ifdef __cplusplus -} -#endif - -#endif /* NGHTTP2_COMP_HELPER_H */ +#endif // NGHTTP2_COMP_HELPER_H diff -Nru nghttp2-1.13.0/src/deflatehd.cc nghttp2-0.6.7/src/deflatehd.cc --- nghttp2-1.13.0/src/deflatehd.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/deflatehd.cc 2014-11-30 14:15:07.000000000 +0000 @@ -26,9 +26,7 @@ #include #endif // HAVE_CONFIG_H -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H #include #include @@ -41,12 +39,13 @@ #include -#include +extern "C" { -#include "template.h" -#include "comp_helper.h" +#include "nghttp2_hd.h" +#include "nghttp2_frame.h" -namespace nghttp2 { +#include "comp_helper.h" +} typedef struct { size_t table_size; @@ -75,23 +74,30 @@ } } -static void output_to_json(nghttp2_hd_deflater *deflater, const uint8_t *buf, - size_t buflen, size_t inputlen, - const std::vector &nva, int seq) { - auto hex = std::vector(buflen * 2); +static void output_to_json(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, + size_t inputlen, const std::vector &nva, + int seq) { + auto len = nghttp2_bufs_len(bufs); + auto hex = std::vector(len * 2); auto obj = json_object(); - auto comp_ratio = inputlen == 0 ? 0.0 : (double)buflen / inputlen * 100; + auto comp_ratio = inputlen == 0 ? 0.0 : (double)len / inputlen * 100; json_object_set_new(obj, "seq", json_integer(seq)); json_object_set_new(obj, "input_length", json_integer(inputlen)); - json_object_set_new(obj, "output_length", json_integer(buflen)); + json_object_set_new(obj, "output_length", json_integer(len)); json_object_set_new(obj, "percentage_of_original_size", json_real(comp_ratio)); - if (buflen == 0) { + auto hexp = hex.data(); + for (auto ci = bufs->head; ci; ci = ci->next) { + auto buf = &ci->buf; + to_hex(hexp, buf->pos, nghttp2_buf_len(buf)); + hexp += nghttp2_buf_len(buf); + } + + if (len == 0) { json_object_set_new(obj, "wire", json_string("")); } else { - to_hex(hex.data(), buf, buflen); json_object_set_new(obj, "wire", json_pack("s#", hex.data(), hex.size())); } json_object_set_new(obj, "headers", dump_headers(nva.data(), nva.size())); @@ -101,8 +107,7 @@ json_integer(config.table_size)); } if (config.dump_header_table) { - json_object_set_new(obj, "header_table", - dump_deflate_header_table(deflater)); + json_object_set_new(obj, "header_table", dump_header_table(&deflater->ctx)); } json_dumpf(obj, stdout, JSON_PRESERVE_ORDER | JSON_INDENT(2)); printf("\n"); @@ -113,19 +118,22 @@ const std::vector &nva, size_t inputlen, int seq) { ssize_t rv; - std::array buf; + nghttp2_bufs bufs; - rv = nghttp2_hd_deflate_hd(deflater, buf.data(), buf.size(), - (nghttp2_nv *)nva.data(), nva.size()); + nghttp2_bufs_init2(&bufs, 4096, 16, 0); + + rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, (nghttp2_nv *)nva.data(), + nva.size()); if (rv < 0) { fprintf(stderr, "deflate failed with error code %zd at %d\n", rv, seq); exit(EXIT_FAILURE); } input_sum += inputlen; - output_sum += rv; + output_sum += nghttp2_bufs_len(&bufs); - output_to_json(deflater, buf.data(), rv, inputlen, nva, seq); + output_to_json(deflater, &bufs, inputlen, nva, seq); + nghttp2_bufs_free(&bufs); } static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, @@ -178,19 +186,18 @@ return 0; } -static nghttp2_hd_deflater *init_deflater() { - nghttp2_hd_deflater *deflater; - nghttp2_hd_deflate_new(&deflater, config.deflate_table_size); +static void init_deflater(nghttp2_hd_deflater *deflater) { + nghttp2_hd_deflate_init2(deflater, config.deflate_table_size); nghttp2_hd_deflate_change_table_size(deflater, config.table_size); - return deflater; } static void deinit_deflater(nghttp2_hd_deflater *deflater) { - nghttp2_hd_deflate_del(deflater); + nghttp2_hd_deflate_free(deflater); } static int perform(void) { json_error_t error; + nghttp2_hd_deflater deflater; auto json = json_loadf(stdin, 0, &error); @@ -211,7 +218,7 @@ exit(EXIT_FAILURE); } - auto deflater = init_deflater(); + init_deflater(&deflater); output_json_header(); auto len = json_array_size(cases); @@ -221,7 +228,7 @@ fprintf(stderr, "Unexpected JSON type at %zu. It should be object.\n", i); continue; } - if (deflate_hd_json(obj, deflater, i) != 0) { + if (deflate_hd_json(obj, &deflater, i) != 0) { continue; } if (i + 1 < len) { @@ -229,7 +236,7 @@ } } output_json_footer(); - deinit_deflater(deflater); + deinit_deflater(&deflater); json_decref(json); return 0; } @@ -237,8 +244,8 @@ static int perform_from_http1text(void) { char line[1 << 14]; int seq = 0; - - auto deflater = init_deflater(); + nghttp2_hd_deflater deflater; + init_deflater(&deflater); output_json_header(); for (;;) { std::vector nva; @@ -285,7 +292,7 @@ if (seq > 0) { printf(",\n"); } - deflate_hd(deflater, nva, inputlen, seq); + deflate_hd(&deflater, nva, inputlen, seq); } for (auto &nv : nva) { @@ -298,7 +305,7 @@ ++seq; } output_json_footer(); - deinit_deflater(deflater); + deinit_deflater(&deflater); return 0; } @@ -380,8 +387,8 @@ int main(int argc, char **argv) { char *end; - config.table_size = 4_k; - config.deflate_table_size = 4_k; + config.table_size = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE; + config.deflate_table_size = NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE; config.http1text = 0; config.dump_header_table = 0; while (1) { @@ -438,9 +445,3 @@ output_sum, comp_ratio); return 0; } - -} // namespace nghttp2 - -int main(int argc, char **argv) { - return nghttp2::run_app(nghttp2::main, argc, argv); -} diff -Nru nghttp2-1.13.0/src/h2load.cc nghttp2-0.6.7/src/h2load.cc --- nghttp2-1.13.0/src/h2load.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/h2load.cc 2014-11-30 14:15:07.000000000 +0000 @@ -26,35 +26,29 @@ #include #include -#ifdef HAVE_NETINET_IN_H #include -#endif // HAVE_NETINET_IN_H #include -#include -#ifdef HAVE_FCNTL_H -#include -#endif // HAVE_FCNTL_H #include #include #include #include -#include #include #include #include #include -#include #ifdef HAVE_SPDYLAY #include #endif // HAVE_SPDYLAY +#include + #include +#include #include "http-parser/http_parser.h" -#include "h2load_http1_session.h" #include "h2load_http2_session.h" #ifdef HAVE_SPDYLAY #include "h2load_spdy_session.h" @@ -62,321 +56,56 @@ #include "ssl.h" #include "http2.h" #include "util.h" -#include "template.h" - -#ifndef O_BINARY -#define O_BINARY (0) -#endif // O_BINARY using namespace nghttp2; namespace h2load { -namespace { -bool recorded(const std::chrono::steady_clock::time_point &t) { - return std::chrono::steady_clock::duration::zero() != t.time_since_epoch(); -} -} // namespace - Config::Config() - : data_length(-1), - addrs(nullptr), - nreqs(1), - nclients(1), - nthreads(1), - max_concurrent_streams(1), - window_bits(30), - connection_window_bits(30), - rate(0), - rate_period(1.0), - conn_active_timeout(0.), - conn_inactivity_timeout(0.), - no_tls_proto(PROTO_HTTP2), - data_fd(-1), - port(0), - default_port(0), - verbose(false), - timing_script(false), - base_uri_unix(false), - unix_addr{} {} - -Config::~Config() { - if (addrs) { - if (base_uri_unix) { - delete addrs; - } else { - freeaddrinfo(addrs); - } - } + : addrs(nullptr), nreqs(1), nclients(1), nthreads(1), + max_concurrent_streams(-1), window_bits(16), connection_window_bits(16), + no_tls_proto(PROTO_HTTP2), port(0), default_port(0), verbose(false) {} - if (data_fd != -1) { - close(data_fd); - } -} +Config::~Config() { freeaddrinfo(addrs); } -bool Config::is_rate_mode() const { return (this->rate != 0); } -bool Config::has_base_uri() const { return (!this->base_uri.empty()); } Config config; namespace { -constexpr size_t MAX_SAMPLES = 1000000; -} // namespace - -Stats::Stats(size_t req_todo, size_t nclients) - : req_todo(req_todo), - req_started(0), - req_done(0), - req_success(0), - req_status_success(0), - req_failed(0), - req_error(0), - req_timedout(0), - bytes_total(0), - bytes_head(0), - bytes_head_decomp(0), - bytes_body(0), - status() {} - -Stream::Stream() : req_stat{}, status_success(-1) {} - -namespace { -std::random_device rd; -} // namespace - -namespace { -std::mt19937 gen(rd()); -} // namespace - -namespace { -void sampling_init(Sampling &smp, size_t total, size_t max_samples) { - smp.n = 0; - - if (total <= max_samples) { - smp.interval = 0.; - smp.point = 0.; - return; - } - - smp.interval = static_cast(total) / max_samples; - - std::uniform_real_distribution<> dis(0., smp.interval); - - smp.point = dis(gen); -} -} // namespace - -namespace { -bool sampling_should_pick(Sampling &smp) { - return smp.interval == 0. || smp.n == ceil(smp.point); -} -} // namespace - -namespace { -void sampling_advance_point(Sampling &smp) { smp.point += smp.interval; } -} // namespace - -namespace { -void writecb(struct ev_loop *loop, ev_io *w, int revents) { - auto client = static_cast(w->data); - client->restart_timeout(); - auto rv = client->do_write(); - if (rv == Client::ERR_CONNECT_FAIL) { - client->disconnect(); - // Try next address - client->current_addr = nullptr; - rv = client->connect(); - if (rv != 0) { - client->fail(); - delete client; - return; - } - return; - } - if (rv != 0) { - client->fail(); - delete client; - } -} -} // namespace - -namespace { -void readcb(struct ev_loop *loop, ev_io *w, int revents) { - auto client = static_cast(w->data); - client->restart_timeout(); - if (client->do_read() != 0) { - if (client->try_again_or_fail() == 0) { - return; - } - delete client; - return; - } - writecb(loop, &client->wev, revents); - // client->disconnect() and client->fail() may be called -} -} // namespace - -namespace { -// Called every rate_period when rate mode is being used -void rate_period_timeout_w_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto worker = static_cast(w->data); - auto nclients_per_second = worker->rate; - auto conns_remaining = worker->nclients - worker->nconns_made; - auto nclients = std::min(nclients_per_second, conns_remaining); - - for (size_t i = 0; i < nclients; ++i) { - auto req_todo = worker->nreqs_per_client; - if (worker->nreqs_rem > 0) { - ++req_todo; - --worker->nreqs_rem; - } - auto client = - make_unique(worker->next_client_id++, worker, req_todo); - - ++worker->nconns_made; - - if (client->connect() != 0) { - std::cerr << "client could not connect to host" << std::endl; - client->fail(); - } else { - client.release(); - } - worker->report_rate_progress(); - } - if (worker->nconns_made >= worker->nclients) { - ev_timer_stop(worker->loop, w); - } -} +void eventcb(bufferevent *bev, short events, void *ptr); } // namespace namespace { -// Called when an a connection has been inactive for a set period of time -// or a fixed amount of time after all requests have been made on a -// connection -void conn_timeout_cb(EV_P_ ev_timer *w, int revents) { - auto client = static_cast(w->data); - - ev_timer_stop(client->worker->loop, &client->conn_inactivity_watcher); - ev_timer_stop(client->worker->loop, &client->conn_active_watcher); - - if (util::check_socket_connected(client->fd)) { - client->timeout(); - } -} +void readcb(bufferevent *bev, void *ptr); } // namespace namespace { -bool check_stop_client_request_timeout(Client *client, ev_timer *w) { - auto nreq = client->req_todo - client->req_started; - - if (nreq == 0 || - client->streams.size() >= client->session->max_concurrent_streams()) { - // no more requests to make, stop timer - ev_timer_stop(client->worker->loop, w); - return true; - } - - return false; -} +void writecb(bufferevent *bev, void *ptr); } // namespace namespace { -void client_request_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto client = static_cast(w->data); - - if (client->submit_request() != 0) { - ev_timer_stop(client->worker->loop, w); - client->process_request_failure(); - return; - } - client->signal_write(); - - if (check_stop_client_request_timeout(client, w)) { - return; - } - - ev_tstamp duration = - config.timings[client->reqidx] - config.timings[client->reqidx - 1]; - - while (duration < 1e-9) { - if (client->submit_request() != 0) { - ev_timer_stop(client->worker->loop, w); - client->process_request_failure(); - return; - } - client->signal_write(); - if (check_stop_client_request_timeout(client, w)) { - return; - } - - duration = - config.timings[client->reqidx] - config.timings[client->reqidx - 1]; +void debug(const char *format, ...) { + if (config.verbose) { + fprintf(stderr, "[DEBUG] "); + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); } - - client->request_timeout_watcher.repeat = duration; - ev_timer_again(client->worker->loop, &client->request_timeout_watcher); } } // namespace -Client::Client(uint32_t id, Worker *worker, size_t req_todo) - : wb(&worker->mcpool), - cstat{}, - worker(worker), - ssl(nullptr), - next_addr(config.addrs), - current_addr(nullptr), - reqidx(0), - state(CLIENT_IDLE), - req_todo(req_todo), - req_started(0), - req_done(0), - id(id), - fd(-1), - new_connection_requested(false), - final(false) { - ev_io_init(&wev, writecb, 0, EV_WRITE); - ev_io_init(&rev, readcb, 0, EV_READ); - - wev.data = this; - rev.data = this; - - ev_timer_init(&conn_inactivity_watcher, conn_timeout_cb, 0., - worker->config->conn_inactivity_timeout); - conn_inactivity_watcher.data = this; - - ev_timer_init(&conn_active_watcher, conn_timeout_cb, - worker->config->conn_active_timeout, 0.); - conn_active_watcher.data = this; +Stream::Stream() : status_success(-1) {} - ev_timer_init(&request_timeout_watcher, client_request_timeout_cb, 0., 0.); - request_timeout_watcher.data = this; -} +Client::Client(Worker *worker, size_t req_todo) + : worker(worker), ssl(nullptr), bev(nullptr), next_addr(config.addrs), + reqidx(0), state(CLIENT_IDLE), req_todo(req_todo), req_started(0), + req_done(0) {} -Client::~Client() { - disconnect(); +Client::~Client() { disconnect(); } - if (ssl) { - SSL_free(ssl); - } - - if (sampling_should_pick(worker->client_smp)) { - sampling_advance_point(worker->client_smp); - worker->sample_client_stat(&cstat); - } - ++worker->client_smp.n; -} - -int Client::do_read() { return readfn(*this); } -int Client::do_write() { return writefn(*this); } - -int Client::make_socket(addrinfo *addr) { - fd = util::create_nonblock_socket(addr->ai_family); - if (fd == -1) { - return -1; - } +int Client::connect() { if (config.scheme == "https") { - if (!ssl) { - ssl = SSL_new(worker->ssl_ctx); - } + ssl = SSL_new(worker->ssl_ctx); auto config = worker->config; @@ -384,174 +113,65 @@ SSL_set_tlsext_host_name(ssl, config->host.c_str()); } - SSL_set_fd(ssl, fd); - SSL_set_connect_state(ssl); + bev = bufferevent_openssl_socket_new(worker->evbase, -1, ssl, + BUFFEREVENT_SSL_CONNECTING, + BEV_OPT_DEFER_CALLBACKS); + } else { + bev = bufferevent_socket_new(worker->evbase, -1, BEV_OPT_DEFER_CALLBACKS); } - auto rv = ::connect(fd, addr->ai_addr, addr->ai_addrlen); - if (rv != 0 && errno != EINPROGRESS) { - if (ssl) { - SSL_free(ssl); - ssl = nullptr; + int rv = -1; + while (next_addr) { + rv = bufferevent_socket_connect(bev, next_addr->ai_addr, + next_addr->ai_addrlen); + next_addr = next_addr->ai_next; + if (rv == 0) { + break; } - close(fd); - fd = -1; - return -1; - } - return 0; -} - -int Client::connect() { - int rv; - - record_client_start_time(); - clear_connect_times(); - record_connect_start_time(); - - if (worker->config->conn_inactivity_timeout > 0.) { - ev_timer_again(worker->loop, &conn_inactivity_watcher); } - - if (current_addr) { - rv = make_socket(current_addr); - if (rv == -1) { - return -1; - } - } else { - addrinfo *addr = nullptr; - while (next_addr) { - addr = next_addr; - next_addr = next_addr->ai_next; - rv = make_socket(addr); - if (rv == 0) { - break; - } - } - - if (fd == -1) { - return -1; - } - - assert(addr); - - current_addr = addr; + if (rv != 0) { + return -1; } - - writefn = &Client::connected; - - ev_io_set(&rev, fd, EV_READ); - ev_io_set(&wev, fd, EV_WRITE); - - ev_io_start(worker->loop, &wev); - + bufferevent_enable(bev, EV_READ); + bufferevent_setcb(bev, readcb, writecb, eventcb, this); return 0; } -void Client::timeout() { - process_timedout_streams(); - - disconnect(); -} - -void Client::restart_timeout() { - if (worker->config->conn_inactivity_timeout > 0.) { - ev_timer_again(worker->loop, &conn_inactivity_watcher); - } -} - -int Client::try_again_or_fail() { - disconnect(); - - if (new_connection_requested) { - new_connection_requested = false; - if (req_started < req_todo) { - // At the moment, we don't have a facility to re-start request - // already in in-flight. Make them fail. - auto req_abandoned = req_started - req_done; - - worker->stats.req_failed += req_abandoned; - worker->stats.req_error += req_abandoned; - worker->stats.req_done += req_abandoned; - - req_done = req_started; - - // Keep using current address - if (connect() == 0) { - return 0; - } - std::cerr << "client could not connect to host" << std::endl; - } - } - +void Client::fail() { process_abandoned_streams(); - return -1; -} - -void Client::fail() { disconnect(); - - process_abandoned_streams(); } void Client::disconnect() { - record_client_end_time(); - - ev_timer_stop(worker->loop, &conn_inactivity_watcher); - ev_timer_stop(worker->loop, &conn_active_watcher); - ev_timer_stop(worker->loop, &request_timeout_watcher); + int fd = -1; streams.clear(); session.reset(); - wb.reset(); state = CLIENT_IDLE; - ev_io_stop(worker->loop, &wev); - ev_io_stop(worker->loop, &rev); if (ssl) { + fd = SSL_get_fd(ssl); SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); - ERR_clear_error(); - - if (SSL_shutdown(ssl) != 1) { - SSL_free(ssl); - ssl = nullptr; - } + SSL_shutdown(ssl); + } + if (bev) { + bufferevent_disable(bev, EV_READ | EV_WRITE); + bufferevent_free(bev); + bev = nullptr; + } + if (ssl) { + SSL_free(ssl); + ssl = nullptr; } if (fd != -1) { shutdown(fd, SHUT_WR); close(fd); - fd = -1; } - - final = false; } -int Client::submit_request() { +void Client::submit_request() { + session->submit_request(); ++worker->stats.req_started; - if (session->submit_request() != 0) { - return -1; - } - ++req_started; - - // if an active timeout is set and this is the last request to be submitted - // on this connection, start the active timeout. - if (worker->config->conn_active_timeout > 0. && req_started >= req_todo) { - ev_timer_start(worker->loop, &conn_active_watcher); - } - - return 0; -} - -void Client::process_timedout_streams() { - for (auto &req_stat : worker->stats.req_stats) { - if (!req_stat.completed) { - req_stat.stream_close_time = std::chrono::steady_clock::now(); - } - } - - auto req_timed_out = req_todo - req_done; - worker->stats.req_timedout += req_timed_out; - - process_abandoned_streams(); } void Client::process_abandoned_streams() { @@ -564,32 +184,46 @@ req_done = req_todo; } -void Client::process_request_failure() { - auto req_abandoned = req_todo - req_started; - - worker->stats.req_failed += req_abandoned; - worker->stats.req_error += req_abandoned; - worker->stats.req_done += req_abandoned; - - req_done += req_abandoned; +void Client::report_progress() { + if (worker->id == 0 && + worker->stats.req_done % worker->progress_interval == 0) { + std::cout << "progress: " + << worker->stats.req_done * 100 / worker->stats.req_todo + << "% done" << std::endl; + } +} - if (req_done == req_todo) { - terminate_session(); - return; +namespace { +const char *get_tls_protocol(SSL *ssl) { + auto session = SSL_get_session(ssl); + + switch (session->ssl_version) { + case SSL2_VERSION: + return "SSLv2"; + case SSL3_VERSION: + return "SSLv3"; + case TLS1_2_VERSION: + return "TLSv1.2"; + case TLS1_1_VERSION: + return "TLSv1.1"; + case TLS1_VERSION: + return "TLSv1"; + default: + return "unknown"; } } +} // namespace namespace { void print_server_tmp_key(SSL *ssl) { -// libressl does not have SSL_get_server_tmp_key -#if OPENSSL_VERSION_NUMBER >= 0x10002000L && defined(SSL_get_server_tmp_key) +#if OPENSSL_VERSION_NUMBER >= 0x10002000L EVP_PKEY *key; if (!SSL_get_server_tmp_key(ssl, &key)) { return; } - auto key_del = defer(EVP_PKEY_free, key); + auto key_del = util::defer(key, EVP_PKEY_free); std::cout << "Server Temp Key: "; @@ -602,7 +236,7 @@ break; case EVP_PKEY_EC: { auto ec = EVP_PKEY_get1_EC_KEY(key); - auto ec_del = defer(EC_KEY_free, ec); + auto ec_del = util::defer(ec, EC_KEY_free); auto nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); auto cname = EC_curve_nid2nist(nid); if (!cname) { @@ -622,24 +256,13 @@ if (worker->id == 0 && !worker->tls_info_report_done) { worker->tls_info_report_done = true; auto cipher = SSL_get_current_cipher(ssl); - std::cout << "TLS Protocol: " << ssl::get_tls_protocol(ssl) << "\n" + std::cout << "Protocol: " << get_tls_protocol(ssl) << "\n" << "Cipher: " << SSL_CIPHER_get_name(cipher) << std::endl; print_server_tmp_key(ssl); } } -void Client::report_app_info() { - if (worker->id == 0 && !worker->app_info_report_done) { - worker->app_info_report_done = true; - std::cout << "Application protocol: " << selected_proto << std::endl; - } -} - -void Client::terminate_session() { - session->terminate(); - // http1 session needs writecb to tear down session. - signal_write(); -} +void Client::terminate_session() { session->terminate(); } void Client::on_request(int32_t stream_id) { streams[stream_id] = Stream(); } @@ -651,7 +274,7 @@ } auto &stream = (*itr).second; if (stream.status_success == -1 && namelen == 7 && - util::streq_l(":status", name, namelen)) { + util::streq(":status", 7, name, namelen)) { int status = 0; for (size_t i = 0; i < valuelen; ++i) { if ('0' <= value[i] && value[i] <= '9') { @@ -681,721 +304,225 @@ } } -void Client::on_status_code(int32_t stream_id, uint16_t status) { - auto itr = streams.find(stream_id); - if (itr == std::end(streams)) { - return; - } - auto &stream = (*itr).second; - - if (status >= 200 && status < 300) { - ++worker->stats.status[2]; - stream.status_success = 1; - } else if (status < 400) { - ++worker->stats.status[3]; - stream.status_success = 1; - } else if (status < 600) { - ++worker->stats.status[status / 100]; - stream.status_success = 0; - } else { - stream.status_success = 0; - } -} - -void Client::on_stream_close(int32_t stream_id, bool success, bool final) { - auto req_stat = get_req_stat(stream_id); - if (!req_stat) { - return; - } - - req_stat->stream_close_time = std::chrono::steady_clock::now(); - if (success) { - req_stat->completed = true; +void Client::on_stream_close(int32_t stream_id, bool success) { + ++worker->stats.req_done; + ++req_done; + if (success && streams[stream_id].status_success == 1) { ++worker->stats.req_success; - ++cstat.req_success; - - if (streams[stream_id].status_success == 1) { - ++worker->stats.req_status_success; - } else { - ++worker->stats.req_failed; - } - - if (sampling_should_pick(worker->request_times_smp)) { - sampling_advance_point(worker->request_times_smp); - worker->sample_req_stat(req_stat); - } - - // Count up in successful cases only - ++worker->request_times_smp.n; } else { ++worker->stats.req_failed; - ++worker->stats.req_error; } - - ++worker->stats.req_done; - ++req_done; - - worker->report_progress(); + report_progress(); streams.erase(stream_id); if (req_done == req_todo) { terminate_session(); return; } - if (!config.timing_script && !final) { - if (req_started < req_todo) { - if (submit_request() != 0) { - process_request_failure(); - } - return; - } - } -} - -RequestStat *Client::get_req_stat(int32_t stream_id) { - auto it = streams.find(stream_id); - if (it == std::end(streams)) { - return nullptr; + if (req_started < req_todo) { + submit_request(); + return; } - - return &(*it).second.req_stat; } -int Client::connection_made() { - if (ssl) { - report_tls_info(); - - const unsigned char *next_proto = nullptr; - unsigned int next_proto_len; - - SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (next_proto == nullptr) { - SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - if (next_proto) { - auto proto = StringRef{next_proto, next_proto_len}; - if (util::check_h2_is_selected(proto)) { - session = make_unique(this); - } else if (util::streq(NGHTTP2_H1_1, proto)) { - session = make_unique(this); - } -#ifdef HAVE_SPDYLAY - else { - auto spdy_version = spdylay_npn_get_version(next_proto, next_proto_len); - if (spdy_version) { - session = make_unique(this, spdy_version); - } - } -#endif // HAVE_SPDYLAY - - // Just assign next_proto to selected_proto anyway to show the - // negotiation result. - selected_proto = proto.str(); - } else { - std::cout << "No protocol negotiated. Fallback behaviour may be activated" - << std::endl; - - for (const auto &proto : config.npn_list) { - if (util::streq(NGHTTP2_H1_1_ALPN, StringRef{proto})) { - std::cout - << "Server does not support NPN/ALPN. Falling back to HTTP/1.1." - << std::endl; - session = make_unique(this); - selected_proto = NGHTTP2_H1_1.str(); - break; - } - } - } - - if (!selected_proto.empty()) { - report_app_info(); - } - - if (!session) { - std::cout - << "No supported protocol was negotiated. Supported protocols were:" - << std::endl; - for (const auto &proto : config.npn_list) { - std::cout << proto.substr(1) << std::endl; - } - disconnect(); - return -1; - } - } else { - switch (config.no_tls_proto) { - case Config::PROTO_HTTP2: - session = make_unique(this); - selected_proto = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID; - break; - case Config::PROTO_HTTP1_1: - session = make_unique(this); - selected_proto = NGHTTP2_H1_1.str(); - break; -#ifdef HAVE_SPDYLAY - case Config::PROTO_SPDY2: - session = make_unique(this, SPDYLAY_PROTO_SPDY2); - selected_proto = "spdy/2"; - break; - case Config::PROTO_SPDY3: - session = make_unique(this, SPDYLAY_PROTO_SPDY3); - selected_proto = "spdy/3"; - break; - case Config::PROTO_SPDY3_1: - session = make_unique(this, SPDYLAY_PROTO_SPDY3_1); - selected_proto = "spdy/3.1"; - break; -#endif // HAVE_SPDYLAY - default: - // unreachable - assert(0); - } - - report_app_info(); - } - - state = CLIENT_CONNECTED; - +int Client::on_connect() { session->on_connect(); - record_connect_time(); - - if (!config.timing_script) { - auto nreq = - std::min(req_todo - req_started, session->max_concurrent_streams()); - for (; nreq > 0; --nreq) { - if (submit_request() != 0) { - process_request_failure(); - break; - } - } - } else { - - ev_tstamp duration = config.timings[reqidx]; + auto nreq = + std::min(req_todo - req_started, (size_t)config.max_concurrent_streams); - while (duration < 1e-9) { - if (submit_request() != 0) { - process_request_failure(); - break; - } - duration = config.timings[reqidx]; - if (reqidx == 0) { - // if reqidx wraps around back to 0, we uses up all lines and - // should break - break; - } - } - - if (duration >= 1e-9) { - // double check since we may have break due to reqidx wraps - // around back to 0 - request_timeout_watcher.repeat = duration; - ev_timer_again(worker->loop, &request_timeout_watcher); - } + for (; nreq > 0; --nreq) { + submit_request(); } - signal_write(); - - return 0; + return session->on_write(); } -int Client::on_read(const uint8_t *data, size_t len) { - auto rv = session->on_read(data, len); - if (rv != 0) { +int Client::on_read() { + ssize_t rv = session->on_read(); + if (rv < 0) { return -1; } - worker->stats.bytes_total += len; - signal_write(); - return 0; -} + worker->stats.bytes_total += rv; -int Client::on_write() { - if (wb.rleft() >= BACKOFF_WRITE_BUFFER_THRES) { - return 0; - } - - if (session->on_write() != 0) { - return -1; - } - return 0; + return on_write(); } -int Client::read_clear() { - uint8_t buf[8_k]; +int Client::on_write() { return session->on_write(); } - for (;;) { - ssize_t nread; - while ((nread = read(fd, buf, sizeof(buf))) == -1 && errno == EINTR) - ; - if (nread == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - return 0; - } - return -1; - } +Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients, + Config *config) + : stats{0}, evbase(event_base_new()), ssl_ctx(ssl_ctx), config(config), + id(id), tls_info_report_done(false) { + stats.req_todo = req_todo; + progress_interval = std::max((size_t)1, req_todo / 10); - if (nread == 0) { - return -1; - } + auto nreqs_per_client = req_todo / nclients; + auto nreqs_rem = req_todo % nclients; - if (on_read(buf, nread) != 0) { - return -1; + for (size_t i = 0; i < nclients; ++i) { + auto req_todo = nreqs_per_client; + if (nreqs_rem > 0) { + ++req_todo; + --nreqs_rem; } + clients.push_back(util::make_unique(this, req_todo)); } - - return 0; } -int Client::write_clear() { - std::array iov; - - for (;;) { - if (on_write() != 0) { - return -1; - } - - auto iovcnt = wb.riovec(iov.data(), iov.size()); +Worker::~Worker() { event_base_free(evbase); } - if (iovcnt == 0) { - break; - } - - ssize_t nwrite; - while ((nwrite = writev(fd, iov.data(), iovcnt)) == -1 && errno == EINTR) - ; - - if (nwrite == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - ev_io_start(worker->loop, &wev); - return 0; - } - return -1; +void Worker::run() { + for (auto &client : clients) { + if (client->connect() != 0) { + std::cerr << "client could not connect to host" << std::endl; + client->fail(); } - - wb.drain(nwrite); - } - - ev_io_stop(worker->loop, &wev); - - return 0; -} - -int Client::connected() { - if (!util::check_socket_connected(fd)) { - return ERR_CONNECT_FAIL; - } - ev_io_start(worker->loop, &rev); - ev_io_stop(worker->loop, &wev); - - if (ssl) { - readfn = &Client::tls_handshake; - writefn = &Client::tls_handshake; - - return do_write(); - } - - readfn = &Client::read_clear; - writefn = &Client::write_clear; - - if (connection_made() != 0) { - return -1; } - - return 0; + event_base_loop(evbase, 0); } -int Client::tls_handshake() { - ERR_clear_error(); - - auto rv = SSL_do_handshake(ssl); - - if (rv <= 0) { - auto err = SSL_get_error(ssl, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - ev_io_stop(worker->loop, &wev); - return 0; - case SSL_ERROR_WANT_WRITE: - ev_io_start(worker->loop, &wev); - return 0; - default: - return -1; - } - } - - ev_io_stop(worker->loop, &wev); - - readfn = &Client::read_tls; - writefn = &Client::write_tls; - - if (connection_made() != 0) { - return -1; - } - - return 0; +namespace { +void debug_nextproto_error() { +#ifdef HAVE_SPDYLAY + debug("no supported protocol was negotiated, expected: %s, " + "spdy/2, spdy/3, spdy/3.1\n", + NGHTTP2_PROTO_VERSION_ID); +#else // !HAVE_SPDYLAY + debug("no supported protocol was negotiated, expected: %s\n", + NGHTTP2_PROTO_VERSION_ID); +#endif // !HAVE_SPDYLAY } +} // namespace -int Client::read_tls() { - uint8_t buf[8_k]; - - ERR_clear_error(); - - for (;;) { - auto rv = SSL_read(ssl, buf, sizeof(buf)); +namespace { +void eventcb(bufferevent *bev, short events, void *ptr) { + int rv; + auto client = static_cast(ptr); + if (events & BEV_EVENT_CONNECTED) { + if (client->ssl) { + client->report_tls_info(); + + const unsigned char *next_proto = nullptr; + unsigned int next_proto_len; + SSL_get0_next_proto_negotiated(client->ssl, &next_proto, &next_proto_len); + for (int i = 0; i < 2; ++i) { + if (next_proto) { + if (util::check_h2_is_selected(next_proto, next_proto_len)) { + client->session = util::make_unique(client); + } else { +#ifdef HAVE_SPDYLAY + auto spdy_version = + spdylay_npn_get_version(next_proto, next_proto_len); + if (spdy_version) { + client->session = + util::make_unique(client, spdy_version); + } else { + debug_nextproto_error(); + client->fail(); + return; + } +#else // !HAVE_SPDYLAY + debug_nextproto_error(); + client->fail(); + return; +#endif // !HAVE_SPDYLAY + } + } - if (rv <= 0) { - auto err = SSL_get_error(ssl, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - return 0; - case SSL_ERROR_WANT_WRITE: - // renegotiation started - return -1; - default: - return -1; +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + SSL_get0_alpn_selected(client->ssl, &next_proto, &next_proto_len); +#else // OPENSSL_VERSION_NUMBER < 0x10002000L + break; +#endif // OPENSSL_VERSION_NUMBER < 0x10002000L } - } - - if (on_read(buf, rv) != 0) { - return -1; - } - } -} - -int Client::write_tls() { - ERR_clear_error(); - - struct iovec iov; - - for (;;) { - if (on_write() != 0) { - return -1; - } - - auto iovcnt = wb.riovec(&iov, 1); - - if (iovcnt == 0) { - break; - } - auto rv = SSL_write(ssl, iov.iov_base, iov.iov_len); - - if (rv <= 0) { - auto err = SSL_get_error(ssl, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - // renegotiation started - return -1; - case SSL_ERROR_WANT_WRITE: - ev_io_start(worker->loop, &wev); - return 0; + if (!next_proto) { + debug_nextproto_error(); + client->fail(); + return; + } + } else { + switch (config.no_tls_proto) { + case Config::PROTO_HTTP2: + client->session = util::make_unique(client); + break; +#ifdef HAVE_SPDYLAY + case Config::PROTO_SPDY2: + client->session = + util::make_unique(client, SPDYLAY_PROTO_SPDY2); + break; + case Config::PROTO_SPDY3: + client->session = + util::make_unique(client, SPDYLAY_PROTO_SPDY3); + break; + case Config::PROTO_SPDY3_1: + client->session = + util::make_unique(client, SPDYLAY_PROTO_SPDY3_1); + break; +#endif // HAVE_SPDYLAY default: - return -1; + // unreachable + assert(0); } } - - wb.drain(rv); - } - - ev_io_stop(worker->loop, &wev); - - return 0; -} - -void Client::record_request_time(RequestStat *req_stat) { - req_stat->request_time = std::chrono::steady_clock::now(); -} - -void Client::record_connect_start_time() { - cstat.connect_start_time = std::chrono::steady_clock::now(); -} - -void Client::record_connect_time() { - cstat.connect_time = std::chrono::steady_clock::now(); -} - -void Client::record_ttfb() { - if (recorded(cstat.ttfb)) { + int fd = bufferevent_getfd(bev); + int val = 1; + (void)setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast(&val), sizeof(val)); + client->state = CLIENT_CONNECTED; + client->on_connect(); return; } - - cstat.ttfb = std::chrono::steady_clock::now(); -} - -void Client::clear_connect_times() { - cstat.connect_start_time = std::chrono::steady_clock::time_point(); - cstat.connect_time = std::chrono::steady_clock::time_point(); - cstat.ttfb = std::chrono::steady_clock::time_point(); -} - -void Client::record_client_start_time() { - // Record start time only once at the very first connection is going - // to be made. - if (recorded(cstat.client_start_time)) { + if (events & BEV_EVENT_EOF) { + client->fail(); return; } - - cstat.client_start_time = std::chrono::steady_clock::now(); -} - -void Client::record_client_end_time() { - // Unlike client_start_time, we overwrite client_end_time. This - // handles multiple connect/disconnect for HTTP/1.1 benchmark. - cstat.client_end_time = std::chrono::steady_clock::now(); -} - -void Client::signal_write() { ev_io_start(worker->loop, &wev); } - -void Client::try_new_connection() { new_connection_requested = true; } - -namespace { -int get_ev_loop_flags() { - if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) { - return ev_recommended_backends() | EVBACKEND_KQUEUE; - } - - return 0; -} -} // namespace - -Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients, - size_t rate, size_t max_samples, Config *config) - : stats(req_todo, nclients), - loop(ev_loop_new(get_ev_loop_flags())), - ssl_ctx(ssl_ctx), - config(config), - id(id), - tls_info_report_done(false), - app_info_report_done(false), - nconns_made(0), - nclients(nclients), - nreqs_per_client(req_todo / nclients), - nreqs_rem(req_todo % nclients), - rate(rate), - max_samples(max_samples), - next_client_id(0) { - if (!config->is_rate_mode()) { - progress_interval = std::max(static_cast(1), req_todo / 10); - } else { - progress_interval = std::max(static_cast(1), nclients / 10); - } - - // create timer that will go off every rate_period - ev_timer_init(&timeout_watcher, rate_period_timeout_w_cb, 0., - config->rate_period); - timeout_watcher.data = this; - - stats.req_stats.reserve(std::min(req_todo, max_samples)); - stats.client_stats.reserve(std::min(nclients, max_samples)); - - sampling_init(request_times_smp, req_todo, max_samples); - sampling_init(client_smp, nclients, max_samples); -} - -Worker::~Worker() { - ev_timer_stop(loop, &timeout_watcher); - ev_loop_destroy(loop); -} - -void Worker::run() { - if (!config->is_rate_mode()) { - for (size_t i = 0; i < nclients; ++i) { - auto req_todo = nreqs_per_client; - if (nreqs_rem > 0) { - ++req_todo; - --nreqs_rem; - } - auto client = make_unique(next_client_id++, this, req_todo); - if (client->connect() != 0) { - std::cerr << "client could not connect to host" << std::endl; - client->fail(); - } else { - client.release(); + if (events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { + if (client->state == CLIENT_IDLE) { + client->disconnect(); + rv = client->connect(); + if (rv == 0) { + return; } } - } else { - ev_timer_again(loop, &timeout_watcher); - - // call callback so that we don't waste the first rate_period - rate_period_timeout_w_cb(loop, &timeout_watcher, 0); - } - ev_run(loop, 0); -} - -void Worker::sample_req_stat(RequestStat *req_stat) { - stats.req_stats.push_back(*req_stat); - assert(stats.req_stats.size() <= max_samples); -} - -void Worker::sample_client_stat(ClientStat *cstat) { - stats.client_stats.push_back(*cstat); - assert(stats.client_stats.size() <= max_samples); -} - -void Worker::report_progress() { - if (id != 0 || config->is_rate_mode() || stats.req_done % progress_interval) { - return; - } - - std::cout << "progress: " << stats.req_done * 100 / stats.req_todo << "% done" - << std::endl; -} - -void Worker::report_rate_progress() { - if (id != 0 || nconns_made % progress_interval) { + debug("error/eof\n"); + client->fail(); return; } - - std::cout << "progress: " << nconns_made * 100 / nclients - << "% of clients started" << std::endl; -} - -namespace { -// Returns percentage of number of samples within mean +/- sd. -double within_sd(const std::vector &samples, double mean, double sd) { - if (samples.size() == 0) { - return 0.0; - } - auto lower = mean - sd; - auto upper = mean + sd; - auto m = std::count_if( - std::begin(samples), std::end(samples), - [&lower, &upper](double t) { return lower <= t && t <= upper; }); - return (m / static_cast(samples.size())) * 100; } } // namespace namespace { -// Computes statistics using |samples|. The min, max, mean, sd, and -// percentage of number of samples within mean +/- sd are computed. -// If |sampling| is true, this computes sample variance. Otherwise, -// population variance. -SDStat compute_time_stat(const std::vector &samples, - bool sampling = false) { - if (samples.empty()) { - return {0.0, 0.0, 0.0, 0.0, 0.0}; - } - // standard deviation calculated using Rapid calculation method: - // https://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods - double a = 0, q = 0; - size_t n = 0; - double sum = 0; - auto res = SDStat{std::numeric_limits::max(), - std::numeric_limits::min()}; - for (const auto &t : samples) { - ++n; - res.min = std::min(res.min, t); - res.max = std::max(res.max, t); - sum += t; - - auto na = a + (t - a) / n; - q += (t - a) * (t - na); - a = na; - } - - assert(n > 0); - res.mean = sum / n; - res.sd = sqrt(q / (sampling && n > 1 ? n - 1 : n)); - res.within_sd = within_sd(samples, res.mean, res.sd); - - return res; +void readcb(bufferevent *bev, void *ptr) { + int rv; + auto client = static_cast(ptr); + rv = client->on_read(); + if (rv != 0) { + client->fail(); + } } } // namespace -namespace { -SDStats -process_time_stats(const std::vector> &workers) { - auto request_times_sampling = false; - auto client_times_sampling = false; - size_t nrequest_times = 0; - size_t nclient_times = 0; - for (const auto &w : workers) { - nrequest_times += w->stats.req_stats.size(); - if (w->request_times_smp.interval != 0.) { - request_times_sampling = true; - } - - nclient_times += w->stats.client_stats.size(); - if (w->client_smp.interval != 0.) { - client_times_sampling = true; - } - } - - std::vector request_times; - request_times.reserve(nrequest_times); - - std::vector connect_times, ttfb_times, rps_values; - connect_times.reserve(nclient_times); - ttfb_times.reserve(nclient_times); - rps_values.reserve(nclient_times); - - for (const auto &w : workers) { - for (const auto &req_stat : w->stats.req_stats) { - if (!req_stat.completed) { - continue; - } - request_times.push_back( - std::chrono::duration_cast>( - req_stat.stream_close_time - req_stat.request_time).count()); - } - - const auto &stat = w->stats; - - for (const auto &cstat : stat.client_stats) { - if (recorded(cstat.client_start_time) && - recorded(cstat.client_end_time)) { - auto t = std::chrono::duration_cast>( - cstat.client_end_time - cstat.client_start_time).count(); - if (t > 1e-9) { - rps_values.push_back(cstat.req_success / t); - } - } - - // We will get connect event before FFTB. - if (!recorded(cstat.connect_start_time) || - !recorded(cstat.connect_time)) { - continue; - } - - connect_times.push_back( - std::chrono::duration_cast>( - cstat.connect_time - cstat.connect_start_time).count()); - - if (!recorded(cstat.ttfb)) { - continue; - } - - ttfb_times.push_back( - std::chrono::duration_cast>( - cstat.ttfb - cstat.connect_start_time).count()); - } - } - - return {compute_time_stat(request_times, request_times_sampling), - compute_time_stat(connect_times, client_times_sampling), - compute_time_stat(ttfb_times, client_times_sampling), - compute_time_stat(rps_values, client_times_sampling)}; +namespace { +void writecb(bufferevent *bev, void *ptr) { + if (evbuffer_get_length(bufferevent_get_output(bev)) > 0) { + return; + } + int rv; + auto client = static_cast(ptr); + rv = client->on_write(); + if (rv != 0) { + client->fail(); + } } } // namespace namespace { void resolve_host() { - if (config.base_uri_unix) { - auto res = make_unique(); - res->ai_family = config.unix_addr.sun_family; - res->ai_socktype = SOCK_STREAM; - res->ai_addrlen = sizeof(config.unix_addr); - res->ai_addr = - static_cast(static_cast(&config.unix_addr)); - - config.addrs = res.release(); - return; - }; - int rv; - addrinfo hints{}, *res; + addrinfo hints, *res; + memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; @@ -1420,13 +547,13 @@ std::string reqline; if (util::has_uri_field(u, UF_PATH)) { - reqline = util::get_uri_field(uri, u, UF_PATH).str(); + reqline = util::get_uri_field(uri, u, UF_PATH); } else { reqline = "/"; } if (util::has_uri_field(u, UF_QUERY)) { - reqline += '?'; + reqline += "?"; reqline += util::get_uri_field(uri, u, UF_QUERY); } @@ -1438,69 +565,60 @@ int client_select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { - if (util::select_protocol(const_cast(out), outlen, in, - inlen, config.npn_list)) { + if (nghttp2_select_next_protocol(out, outlen, in, inlen) > 0) { return SSL_TLSEXT_ERR_OK; } - - // OpenSSL will terminate handshake with fatal alert if we return - // NOACK. So there is no way to fallback. +#ifdef HAVE_SPDYLAY + else if (spdylay_select_next_protocol(out, outlen, in, inlen) > 0) { + return SSL_TLSEXT_ERR_OK; + } +#endif return SSL_TLSEXT_ERR_NOACK; } } // namespace namespace { -constexpr char UNIX_PATH_PREFIX[] = "unix:"; -} // namespace - -namespace { -bool parse_base_uri(const StringRef &base_uri) { - http_parser_url u{}; - if (http_parser_parse_url(base_uri.c_str(), base_uri.size(), 0, &u) != 0 || - !util::has_uri_field(u, UF_SCHEMA) || !util::has_uri_field(u, UF_HOST)) { - return false; - } - - config.scheme = util::get_uri_field(base_uri.c_str(), u, UF_SCHEMA).str(); - config.host = util::get_uri_field(base_uri.c_str(), u, UF_HOST).str(); - config.default_port = util::get_default_port(base_uri.c_str(), u); - if (util::has_uri_field(u, UF_PORT)) { - config.port = u.port; - } else { - config.port = config.default_port; - } - - return true; -} -} // namespace -namespace { -// Use std::vector::iterator explicitly, without that, -// http_parser_url u{} fails with clang-3.4. -std::vector parse_uris(std::vector::iterator first, - std::vector::iterator last) { +template +std::vector parse_uris(Iterator first, Iterator last) { std::vector reqlines; + // First URI is treated specially. We use scheme, host and port of + // this URI and ignore those in the remaining URIs if present. + http_parser_url u; + memset(&u, 0, sizeof(u)); + if (first == last) { std::cerr << "no URI available" << std::endl; exit(EXIT_FAILURE); } - if (!config.has_base_uri()) { + auto uri = (*first).c_str(); + ++first; - if (!parse_base_uri(StringRef{*first})) { - std::cerr << "invalid URI: " << *first << std::endl; - exit(EXIT_FAILURE); - } + if (http_parser_parse_url(uri, strlen(uri), 0, &u) != 0 || + !util::has_uri_field(u, UF_SCHEMA) || !util::has_uri_field(u, UF_HOST)) { + std::cerr << "invalid URI: " << uri << std::endl; + exit(EXIT_FAILURE); + } - config.base_uri = *first; + config.scheme = util::get_uri_field(uri, u, UF_SCHEMA); + config.host = util::get_uri_field(uri, u, UF_HOST); + config.default_port = util::get_default_port(uri, u); + if (util::has_uri_field(u, UF_PORT)) { + config.port = u.port; + } else { + config.port = config.default_port; } + reqlines.push_back(get_reqline(uri, u)); + for (; first != last; ++first) { - http_parser_url u{}; + http_parser_url u; + memset(&u, 0, sizeof(u)); auto uri = (*first).c_str(); - if (http_parser_parse_url(uri, (*first).size(), 0, &u) != 0) { + if (http_parser_parse_url(uri, strlen(uri), 0, &u) != 0) { std::cerr << "invalid URI: " << uri << std::endl; exit(EXIT_FAILURE); } @@ -1525,67 +643,6 @@ } // namespace namespace { -void read_script_from_file(std::istream &infile, - std::vector &timings, - std::vector &uris) { - std::string script_line; - int line_count = 0; - while (std::getline(infile, script_line)) { - line_count++; - if (script_line.empty()) { - std::cerr << "Empty line detected at line " << line_count - << ". Ignoring and continuing." << std::endl; - continue; - } - - std::size_t pos = script_line.find("\t"); - if (pos == std::string::npos) { - std::cerr << "Invalid line format detected, no tab character at line " - << line_count << ". \n\t" << script_line << std::endl; - exit(EXIT_FAILURE); - } - - const char *start = script_line.c_str(); - char *end; - auto v = std::strtod(start, &end); - - errno = 0; - if (v < 0.0 || !std::isfinite(v) || end == start || errno != 0) { - auto error = errno; - std::cerr << "Time value error at line " << line_count << ". \n\t" - << "value = " << script_line.substr(0, pos) << std::endl; - if (error != 0) { - std::cerr << "\t" << strerror(error) << std::endl; - } - exit(EXIT_FAILURE); - } - - timings.push_back(v / 1000.0); - uris.push_back(script_line.substr(pos + 1, script_line.size())); - } -} -} // namespace - -namespace { -std::unique_ptr create_worker(uint32_t id, SSL_CTX *ssl_ctx, - size_t nreqs, size_t nclients, - size_t rate, size_t max_samples) { - std::stringstream rate_report; - if (config.is_rate_mode() && nclients > rate) { - rate_report << "Up to " << rate << " client(s) will be created every " - << util::duration_str(config.rate_period) << " "; - } - - std::cout << "spawning thread #" << id << ": " << nclients - << " total client(s). " << rate_report.str() << nreqs - << " total requests" << std::endl; - - return make_unique(id, ssl_ctx, nreqs, nclients, rate, max_samples, - &config); -} -} // namespace - -namespace { void print_version(std::ostream &out) { out << "h2load nghttp2/" NGHTTP2_VERSION << std::endl; } @@ -1593,197 +650,79 @@ namespace { void print_usage(std::ostream &out) { - out << R"(Usage: h2load [OPTIONS]... [URI]... + out << R"( +Usage: h2load [OPTIONS]... [URI]... benchmarking tool for HTTP/2 and SPDY server)" << std::endl; } } // namespace namespace { -constexpr char DEFAULT_NPN_LIST[] = "h2,h2-16,h2-14" -#ifdef HAVE_SPDYLAY - ",spdy/3.1,spdy/3,spdy/2" -#endif // HAVE_SPDYLAY - ",http/1.1"; -} // namespace - -namespace { void print_help(std::ostream &out) { print_usage(out); - auto config = Config(); - out << R"( - Specify URI to access. Multiple URIs can be specified. - URIs are used in this order for each client. All URIs - are used, then first URI is used and then 2nd URI, and - so on. The scheme, host and port in the subsequent - URIs, if present, are ignored. Those in the first URI - are used solely. Definition of a base URI overrides all - scheme, host or port values. + Specify URI to access. Multiple URIs can be + specified. URIs are used in this order for each + client. All URIs are used, then first URI is + used and then 2nd URI, and so on. The scheme, + host and port in the subsequent URIs, if present, + are ignored. Those in the first URI are used + solely. Options: - -n, --requests= - Number of requests across all clients. If it is used - with --timing-script-file option, this option specifies - the number of requests each client performs rather than - the number of requests across all clients. - Default: )" << config.nreqs << R"( - -c, --clients= - Number of concurrent clients. With -r option, this - specifies the maximum number of connections to be made. - Default: )" << config.nclients << R"( - -t, --threads= - Number of native threads. - Default: )" << config.nthreads << R"( - -i, --input-file= - Path of a file with multiple URIs are separated by EOLs. - This option will disable URIs getting from command-line. - If '-' is given as , URIs will be read from stdin. - URIs are used in this order for each client. All URIs - are used, then first URI is used and then 2nd URI, and - so on. The scheme, host and port in the subsequent - URIs, if present, are ignored. Those in the first URI - are used solely. Definition of a base URI overrides all - scheme, host or port values. - -m, --max-concurrent-streams= - Max concurrent streams to issue per session. When - http/1.1 is used, this specifies the number of HTTP - pipelining requests in-flight. - Default: 1 + -n, --requests= Number of requests. Default: )" << config.nreqs << R"( + -c, --clients= Number of concurrent clients. Default: )" + << config.nclients << R"( + -t, --threads= Number of native threads. Default: )" << config.nthreads + << R"( + -i, --input-file= + Path of a file with multiple URIs are seperated + by EOLs. This option will disable URIs getting + from command-line. If '-' is given as , + URIs will be read from stdin. URIs are used in + this order for each client. All URIs are used, + then first URI is used and then 2nd URI, and so + on. The scheme, host and port in the subsequent + URIs, if present, are ignored. Those in the + first URI are used solely. + -m, --max-concurrent-streams=(auto|) + Max concurrent streams to issue per session. If + "auto" is given, the number of given URIs is + used. Default: auto -w, --window-bits= - Sets the stream level initial window size to (2**)-1. - For SPDY, 2** is used instead. - Default: )" << config.window_bits << R"( + Sets the stream level initial window size to + (2**)-1. For SPDY, 2** is used instead. -W, --connection-window-bits= - Sets the connection level initial window size to - (2**)-1. For SPDY, if is strictly less than 16, - this option is ignored. Otherwise 2** is used for - SPDY. - Default: )" << config.connection_window_bits << R"( + Sets the connection level initial window size to + (2**)-1. For SPDY, if is strictly less + than 16, this option is ignored. Otherwise + 2** is used for SPDY. -H, --header=
- Add/Override a header to the requests. - --ciphers= - Set allowed cipher list. The format of the string is - described in OpenSSL ciphers(1). + Add/Override a header to the requests. -p, --no-tls-proto= - Specify ALPN identifier of the protocol to be used when - accessing http URI without SSL/TLS.)"; - + Specify ALPN identifier of the protocol to be + used when accessing http URI without SSL/TLS.)"; #ifdef HAVE_SPDYLAY out << R"( - Available protocols: spdy/2, spdy/3, spdy/3.1, )"; -#else // !HAVE_SPDYLAY + Available protocols: spdy/2, spdy/3, spdy/3.1 and + )"; +#else // !HAVE_SPDYLAY out << R"( - Available protocols: )"; + Available protocol: )"; #endif // !HAVE_SPDYLAY - out << NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"( and - )" << NGHTTP2_H1_1 << R"( - Default: )" << NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"( - -d, --data= - Post FILE to server. The request method is changed to - POST. For http/1.1 connection, if -d is used, the - maximum number of in-flight pipelined requests is set to - 1. - -r, --rate= - Specifies the fixed rate at which connections are - created. The rate must be a positive integer, - representing the number of connections to be made per - rate period. The maximum number of connections to be - made is given in -c option. This rate will be - distributed among threads as evenly as possible. For - example, with -t2 and -r4, each thread gets 2 - connections per period. When the rate is 0, the program - will run as it normally does, creating connections at - whatever variable rate it wants. The default value for - this option is 0. - --rate-period= - Specifies the time period between creating connections. - The period must be a positive number, representing the - length of the period in time. This option is ignored if - the rate option is not used. The default value for this - option is 1s. - -T, --connection-active-timeout= - Specifies the maximum time that h2load is willing to - keep a connection open, regardless of the activity on - said connection. must be a positive integer, - specifying the amount of time to wait. When no timeout - value is set (either active or inactive), h2load will - keep a connection open indefinitely, waiting for a - response. - -N, --connection-inactivity-timeout= - Specifies the amount of time that h2load is willing to - wait to see activity on a given connection. - must be a positive integer, specifying the amount of - time to wait. When no timeout value is set (either - active or inactive), h2load will keep a connection open - indefinitely, waiting for a response. - --timing-script-file= - Path of a file containing one or more lines separated by - EOLs. Each script line is composed of two tab-separated - fields. The first field represents the time offset from - the start of execution, expressed as a positive value of - milliseconds with microsecond resolution. The second - field represents the URI. This option will disable URIs - getting from command-line. If '-' is given as , - script lines will be read from stdin. Script lines are - used in order for each client. If -n is given, it must - be less than or equal to the number of script lines, - larger values are clamped to the number of script lines. - If -n is not given, the number of requests will default - to the number of script lines. The scheme, host and - port defined in the first URI are used solely. Values - contained in other URIs, if present, are ignored. - Definition of a base URI overrides all scheme, host or - port values. - -B, --base-uri=(|unix:) - Specify URI from which the scheme, host and port will be - used for all requests. The base URI overrides all - values defined either at the command line or inside - input files. If argument starts with "unix:", then the - rest of the argument will be treated as UNIX domain - socket path. The connection is made through that path - instead of TCP. In this case, scheme is inferred from - the first URI appeared in the command line or inside - input files as usual. - --npn-list= - Comma delimited list of ALPN protocol identifier sorted - in the order of preference. That means most desirable - protocol comes first. This is used in both ALPN and - NPN. The parameter must be delimited by a single comma - only and any white spaces are treated as a part of - protocol string. - Default: )" << DEFAULT_NPN_LIST << R"( - --h1 Short hand for --npn-list=http/1.1 - --no-tls-proto=http/1.1, which effectively force - http/1.1 for both http and https URI. - -v, --verbose - Output debug information. - --version Display version information and exit. - -h, --help Display this help and exit. - --- - - The 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.)" << std::endl; + out << NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"( + Default: )" << NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"( + -v, --verbose Output debug information. + --version Display version information and exit. + -h, --help Display this help and exit.)" << std::endl; } } // namespace int main(int argc, char **argv) { - ssl::libssl_init(); - -#ifndef NOTHREADS - ssl::LibsslGlobalLock lock; -#endif // NOTHREADS - - std::string datafile; - bool nreqs_set_manually = false; while (1) { static int flag = 0; static option long_options[] = { {"requests", required_argument, nullptr, 'n'}, {"clients", required_argument, nullptr, 'c'}, - {"data", required_argument, nullptr, 'd'}, {"threads", required_argument, nullptr, 't'}, {"max-concurrent-streams", required_argument, nullptr, 'm'}, {"window-bits", required_argument, nullptr, 'w'}, @@ -1794,33 +733,20 @@ {"verbose", no_argument, nullptr, 'v'}, {"help", no_argument, nullptr, 'h'}, {"version", no_argument, &flag, 1}, - {"ciphers", required_argument, &flag, 2}, - {"rate", required_argument, nullptr, 'r'}, - {"connection-active-timeout", required_argument, nullptr, 'T'}, - {"connection-inactivity-timeout", required_argument, nullptr, 'N'}, - {"timing-script-file", required_argument, &flag, 3}, - {"base-uri", required_argument, nullptr, 'B'}, - {"npn-list", required_argument, &flag, 4}, - {"rate-period", required_argument, &flag, 5}, - {"h1", no_argument, &flag, 6}, {nullptr, 0, nullptr, 0}}; int option_index = 0; - auto c = getopt_long(argc, argv, "hvW:c:d:m:n:p:t:w:H:i:r:T:N:B:", - long_options, &option_index); + auto c = getopt_long(argc, argv, "hvW:c:m:n:p:t:w:H:i:", long_options, + &option_index); if (c == -1) { break; } switch (c) { case 'n': config.nreqs = strtoul(optarg, nullptr, 10); - nreqs_set_manually = true; break; case 'c': config.nclients = strtoul(optarg, nullptr, 10); break; - case 'd': - datafile = optarg; - break; case 't': #ifdef NOTHREADS std::cerr << "-t: WARNING: Threading disabled at build time, " @@ -1830,7 +756,11 @@ #endif // NOTHREADS break; case 'm': - config.max_concurrent_streams = strtoul(optarg, nullptr, 10); + if (util::strieq("auto", optarg)) { + config.max_concurrent_streams = -1; + } else { + config.max_concurrent_streams = strtoul(optarg, nullptr, 10); + } break; case 'w': case 'W': { @@ -1877,90 +807,26 @@ util::inp_strlower(config.custom_headers.back().name); break; } - case 'i': - config.ifile = optarg; + case 'i': { + config.ifile = std::string(optarg); break; - case 'p': { - auto proto = StringRef{optarg}; - if (util::strieq(StringRef::from_lit(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID), - proto)) { + } + case 'p': + if (util::strieq(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, optarg)) { config.no_tls_proto = Config::PROTO_HTTP2; - } else if (util::strieq(NGHTTP2_H1_1, proto)) { - config.no_tls_proto = Config::PROTO_HTTP1_1; #ifdef HAVE_SPDYLAY - } else if (util::strieq_l("spdy/2", proto)) { + } else if (util::strieq("spdy/2", optarg)) { config.no_tls_proto = Config::PROTO_SPDY2; - } else if (util::strieq_l("spdy/3", proto)) { + } else if (util::strieq("spdy/3", optarg)) { config.no_tls_proto = Config::PROTO_SPDY3; - } else if (util::strieq_l("spdy/3.1", proto)) { + } else if (util::strieq("spdy/3.1", optarg)) { config.no_tls_proto = Config::PROTO_SPDY3_1; #endif // HAVE_SPDYLAY } else { - std::cerr << "-p: unsupported protocol " << proto << std::endl; - exit(EXIT_FAILURE); - } - break; - } - case 'r': - config.rate = strtoul(optarg, nullptr, 10); - if (config.rate == 0) { - std::cerr << "-r: the rate at which connections are made " - << "must be positive." << std::endl; - exit(EXIT_FAILURE); - } - break; - case 'T': - config.conn_active_timeout = util::parse_duration_with_unit(optarg); - if (!std::isfinite(config.conn_active_timeout)) { - std::cerr << "-T: bad value for the conn_active_timeout wait time: " - << optarg << std::endl; - exit(EXIT_FAILURE); - } - break; - case 'N': - config.conn_inactivity_timeout = util::parse_duration_with_unit(optarg); - if (!std::isfinite(config.conn_inactivity_timeout)) { - std::cerr << "-N: bad value for the conn_inactivity_timeout wait time: " - << optarg << std::endl; - exit(EXIT_FAILURE); - } - break; - case 'B': { - auto arg = StringRef{optarg}; - config.base_uri = ""; - config.base_uri_unix = false; - - if (util::istarts_with_l(arg, UNIX_PATH_PREFIX)) { - // UNIX domain socket path - sockaddr_un un; - - auto path = StringRef{std::begin(arg) + str_size(UNIX_PATH_PREFIX), - std::end(arg)}; - - if (path.size() == 0 || path.size() + 1 > sizeof(un.sun_path)) { - std::cerr << "--base-uri: invalid UNIX domain socket path: " << arg - << std::endl; - exit(EXIT_FAILURE); - } - - config.base_uri_unix = true; - - auto &unix_addr = config.unix_addr; - std::copy(std::begin(path), std::end(path), unix_addr.sun_path); - unix_addr.sun_path[path.size()] = '\0'; - unix_addr.sun_family = AF_UNIX; - - break; - } - - if (!parse_base_uri(arg)) { - std::cerr << "--base-uri: invalid base URI: " << arg << std::endl; + std::cerr << "-p: unsupported protocol " << optarg << std::endl; exit(EXIT_FAILURE); } - - config.base_uri = arg.str(); break; - } case 'v': config.verbose = true; break; @@ -1976,33 +842,6 @@ // version option print_version(std::cout); exit(EXIT_SUCCESS); - case 2: - // ciphers option - config.ciphers = optarg; - break; - case 3: - // timing-script option - config.ifile = optarg; - config.timing_script = true; - break; - case 4: - // npn-list option - config.npn_list = util::parse_config_str_list(StringRef{optarg}); - break; - case 5: - // rate-period - config.rate_period = util::parse_duration_with_unit(optarg); - if (!std::isfinite(config.rate_period)) { - std::cerr << "--rate-period: value error " << optarg << std::endl; - exit(EXIT_FAILURE); - } - break; - case 6: - // --h1 - config.npn_list = - util::parse_config_str_list(StringRef::from_lit("http/1.1")); - config.no_tls_proto = Config::PROTO_HTTP1_1; - break; } break; default: @@ -2017,76 +856,6 @@ } } - if (config.nclients == 0) { - std::cerr << "-c: the number of clients must be strictly greater than 0." - << std::endl; - exit(EXIT_FAILURE); - } - - if (config.npn_list.empty()) { - config.npn_list = - util::parse_config_str_list(StringRef::from_lit(DEFAULT_NPN_LIST)); - } - - // serialize the APLN tokens - for (auto &proto : config.npn_list) { - proto.insert(proto.begin(), static_cast(proto.size())); - } - - std::vector reqlines; - - if (config.ifile.empty()) { - std::vector uris; - std::copy(&argv[optind], &argv[argc], std::back_inserter(uris)); - reqlines = parse_uris(std::begin(uris), std::end(uris)); - } else { - std::vector uris; - if (!config.timing_script) { - if (config.ifile == "-") { - uris = read_uri_from_file(std::cin); - } else { - std::ifstream infile(config.ifile); - if (!infile) { - std::cerr << "cannot read input file: " << config.ifile << std::endl; - exit(EXIT_FAILURE); - } - - uris = read_uri_from_file(infile); - } - } else { - if (config.ifile == "-") { - read_script_from_file(std::cin, config.timings, uris); - } else { - std::ifstream infile(config.ifile); - if (!infile) { - std::cerr << "cannot read input file: " << config.ifile << std::endl; - exit(EXIT_FAILURE); - } - - read_script_from_file(infile, config.timings, uris); - } - - if (nreqs_set_manually) { - if (config.nreqs > uris.size()) { - std::cerr << "-n: the number of requests must be less than or equal " - "to the number of timing script entries. Setting number " - "of requests to " << uris.size() << std::endl; - - config.nreqs = uris.size(); - } - } else { - config.nreqs = uris.size(); - } - } - - reqlines = parse_uris(std::begin(uris), std::end(uris)); - } - - if (reqlines.empty()) { - std::cerr << "No URI given" << std::endl; - exit(EXIT_FAILURE); - } - if (config.nreqs == 0) { std::cerr << "-n: the number of requests must be strictly greater than 0." << std::endl; @@ -2105,56 +874,29 @@ exit(EXIT_FAILURE); } - if (config.nthreads > std::thread::hardware_concurrency()) { - std::cerr << "-t: warning: the number of threads is greater than hardware " - << "cores." << std::endl; - } - - // With timing script, we don't distribute config.nreqs to each - // client or thread. - if (!config.timing_script && config.nreqs < config.nclients) { + if (config.nreqs < config.nclients) { std::cerr << "-n, -c: the number of requests must be greater than or " - << "equal to the clients." << std::endl; - exit(EXIT_FAILURE); - } - - if (config.nclients < config.nthreads) { - std::cerr << "-c, -t: the number of clients must be greater than or equal " - "to the number of threads." << std::endl; + << "equal to the concurrent clients." << std::endl; exit(EXIT_FAILURE); } - if (config.is_rate_mode()) { - if (config.rate < config.nthreads) { - std::cerr << "-r, -t: the connection rate must be greater than or equal " - << "to the number of threads." << std::endl; - exit(EXIT_FAILURE); - } - - if (config.rate > config.nclients) { - std::cerr << "-r, -c: the connection rate must be smaller than or equal " - "to the number of clients." << std::endl; - exit(EXIT_FAILURE); - } - } - - if (!datafile.empty()) { - config.data_fd = open(datafile.c_str(), O_RDONLY | O_BINARY); - if (config.data_fd == -1) { - std::cerr << "-d: Could not open file " << datafile << std::endl; - exit(EXIT_FAILURE); - } - struct stat data_stat; - if (fstat(config.data_fd, &data_stat) == -1) { - std::cerr << "-d: Could not stat file " << datafile << std::endl; - exit(EXIT_FAILURE); - } - config.data_length = data_stat.st_size; + if (config.nthreads > std::thread::hardware_concurrency()) { + std::cerr << "-t: warning: the number of threads is greater than hardware " + << "cores." << std::endl; } - struct sigaction act {}; + struct sigaction act; + memset(&act, 0, sizeof(struct sigaction)); act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, nullptr); + OPENSSL_config(nullptr); + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); + SSL_library_init(); + +#ifndef NOTHREADS + ssl::LibsslGlobalLock lock; +#endif // NOTHREADS auto ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if (!ssl_ctx) { @@ -2162,42 +904,46 @@ << ERR_error_string(ERR_get_error(), nullptr) << std::endl; exit(EXIT_FAILURE); } - - auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | - SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; - - SSL_CTX_set_options(ssl_ctx, ssl_opts); - SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY); - SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS); - - const char *ciphers; - if (config.ciphers.empty()) { - ciphers = ssl::DEFAULT_CIPHER_LIST; - } else { - ciphers = config.ciphers.c_str(); - } - - if (SSL_CTX_set_cipher_list(ssl_ctx, ciphers) == 0) { - std::cerr << "SSL_CTX_set_cipher_list with " << ciphers - << " failed: " << ERR_error_string(ERR_get_error(), nullptr) - << std::endl; - exit(EXIT_FAILURE); - } - SSL_CTX_set_next_proto_select_cb(ssl_ctx, client_select_next_proto_cb, nullptr); #if OPENSSL_VERSION_NUMBER >= 0x10002000L - std::vector proto_list; - for (const auto &proto : config.npn_list) { - std::copy_n(proto.c_str(), proto.size(), std::back_inserter(proto_list)); - } - + auto proto_list = util::get_default_alpn(); +#ifdef HAVE_SPDYLAY + static const char spdy_proto_list[] = "\x8spdy/3.1\x6spdy/3\x6spdy/2"; + std::copy(spdy_proto_list, spdy_proto_list + sizeof(spdy_proto_list) - 1, + std::back_inserter(proto_list)); +#endif // HAVE_SPDYLAY SSL_CTX_set_alpn_protos(ssl_ctx, proto_list.data(), proto_list.size()); #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - std::string user_agent = "h2load nghttp2/" NGHTTP2_VERSION; + std::vector reqlines; + + if (config.ifile.empty()) { + std::vector uris; + std::copy(&argv[optind], &argv[argc], std::back_inserter(uris)); + reqlines = parse_uris(std::begin(uris), std::end(uris)); + } else { + std::vector uris; + if (config.ifile == "-") { + uris = read_uri_from_file(std::cin); + } else { + std::ifstream infile(config.ifile); + if (!infile) { + std::cerr << "cannot read input file: " << config.ifile << std::endl; + exit(EXIT_FAILURE); + } + + uris = read_uri_from_file(infile); + } + + reqlines = parse_uris(std::begin(uris), std::end(uris)); + } + + if (config.max_concurrent_streams == -1) { + config.max_concurrent_streams = reqlines.size(); + } + Headers shared_nva; shared_nva.emplace_back(":scheme", config.scheme); if (config.port != config.default_port) { @@ -2206,12 +952,11 @@ } else { shared_nva.emplace_back(":authority", config.host); } - shared_nva.emplace_back(":method", config.data_fd == -1 ? "GET" : "POST"); - shared_nva.emplace_back("user-agent", user_agent); + shared_nva.emplace_back(":method", "GET"); // list overridalbe headers - auto override_hdrs = make_array(":authority", ":host", ":method", - ":scheme", "user-agent"); + auto override_hdrs = + std::vector{":authority", ":host", ":method", ":scheme"}; for (auto &kv : config.custom_headers) { if (std::find(std::begin(override_hdrs), std::end(override_hdrs), @@ -2229,55 +974,9 @@ } } - std::string content_length_str; - if (config.data_fd != -1) { - content_length_str = util::utos(config.data_length); - } - - auto method_it = - std::find_if(std::begin(shared_nva), std::end(shared_nva), - [](const Header &nv) { return nv.name == ":method"; }); - assert(method_it != std::end(shared_nva)); - - config.h1reqs.reserve(reqlines.size()); - config.nva.reserve(reqlines.size()); - config.nv.reserve(reqlines.size()); - for (auto &req : reqlines) { - // For HTTP/1.1 - auto h1req = (*method_it).value; - h1req += ' '; - h1req += req; - h1req += " HTTP/1.1\r\n"; - for (auto &nv : shared_nva) { - if (nv.name == ":authority") { - h1req += "Host: "; - h1req += nv.value; - h1req += "\r\n"; - continue; - } - if (nv.name[0] == ':') { - continue; - } - h1req += nv.name; - h1req += ": "; - h1req += nv.value; - h1req += "\r\n"; - } - - if (!content_length_str.empty()) { - h1req += "Content-Length: "; - h1req += content_length_str; - h1req += "\r\n"; - } - h1req += "\r\n"; - - config.h1reqs.push_back(std::move(h1req)); - // For nghttp2 std::vector nva; - // 2 for :path, and possible content-length - nva.reserve(2 + shared_nva.size()); nva.push_back(http2::make_nv_ls(":path", req)); @@ -2285,18 +984,10 @@ nva.push_back(http2::make_nv(nv.name, nv.value, false)); } - if (!content_length_str.empty()) { - nva.push_back(http2::make_nv(StringRef::from_lit("content-length"), - StringRef{content_length_str})); - } - config.nva.push_back(std::move(nva)); // For spdylay std::vector cva; - // 3 for :path, :version, and possible content-length, 1 for - // terminal nullptr - cva.reserve(2 * (3 + shared_nva.size()) + 1); cva.push_back(":path"); cva.push_back(req.c_str()); @@ -2311,212 +1002,119 @@ } cva.push_back(":version"); cva.push_back("HTTP/1.1"); - - if (!content_length_str.empty()) { - cva.push_back("content-length"); - cva.push_back(content_length_str.c_str()); - } - cva.push_back(nullptr); config.nv.push_back(std::move(cva)); } - // Don't DOS our server! - if (config.host == "nghttp2.org") { - std::cerr << "Using h2load against public server " << config.host - << " should be prohibited." << std::endl; - exit(EXIT_FAILURE); - } - resolve_host(); - std::cout << "starting benchmark..." << std::endl; - - std::vector> workers; - workers.reserve(config.nthreads); - -#ifndef NOTHREADS - size_t nreqs_per_thread = 0; - ssize_t nreqs_rem = 0; - - if (!config.timing_script) { - nreqs_per_thread = config.nreqs / config.nthreads; - nreqs_rem = config.nreqs % config.nthreads; + if (config.nclients == 1) { + config.nthreads = 1; } + size_t nreqs_per_thread = config.nreqs / config.nthreads; + ssize_t nreqs_rem = config.nreqs % config.nthreads; + size_t nclients_per_thread = config.nclients / config.nthreads; ssize_t nclients_rem = config.nclients % config.nthreads; - size_t rate_per_thread = config.rate / config.nthreads; - ssize_t rate_per_thread_rem = config.rate % config.nthreads; - - size_t max_samples_per_thread = - std::max(static_cast(256), MAX_SAMPLES / config.nthreads); - - std::mutex mu; - std::condition_variable cv; - auto ready = false; - - std::vector> futures; - for (size_t i = 0; i < config.nthreads; ++i) { - auto rate = rate_per_thread; - if (rate_per_thread_rem > 0) { - --rate_per_thread_rem; - ++rate; - } - auto nclients = nclients_per_thread; - if (nclients_rem > 0) { - --nclients_rem; - ++nclients; - } - - size_t nreqs; - if (config.timing_script) { - // With timing script, each client issues config.nreqs requests. - // We divide nreqs by number of clients in Worker ctor to - // distribute requests to those clients evenly, so multiply - // config.nreqs here by config.nclients. - nreqs = config.nreqs * nclients; - } else { - nreqs = nreqs_per_thread; - if (nreqs_rem > 0) { - --nreqs_rem; - ++nreqs; - } - } - - workers.push_back(create_worker(i, ssl_ctx, nreqs, nclients, rate, - max_samples_per_thread)); - auto &worker = workers.back(); - futures.push_back( - std::async(std::launch::async, [&worker, &mu, &cv, &ready]() { - { - std::unique_lock ulk(mu); - cv.wait(ulk, [&ready] { return ready; }); - } - worker->run(); - })); - } - - { - std::lock_guard lg(mu); - ready = true; - cv.notify_all(); - } + std::cout << "starting benchmark..." << std::endl; auto start = std::chrono::steady_clock::now(); - for (auto &fut : futures) { - fut.get(); +#ifndef NOTHREADS + std::vector> futures; + for (size_t i = 0; i < config.nthreads - 1; ++i) { + auto nreqs = nreqs_per_thread + (nreqs_rem-- > 0); + auto nclients = nclients_per_thread + (nclients_rem-- > 0); + std::cout << "spawning thread #" << i << ": " << nclients + << " concurrent clients, " << nreqs << " total requests" + << std::endl; + auto worker = + util::make_unique(i, ssl_ctx, nreqs, nclients, &config); + futures.push_back(std::async(std::launch::async, + [](std::unique_ptr worker) { + worker->run(); + + return worker->stats; + }, + std::move(worker))); } - -#else // NOTHREADS - auto rate = config.rate; - auto nclients = config.nclients; - auto nreqs = - config.timing_script ? config.nreqs * config.nclients : config.nreqs; - - workers.push_back( - create_worker(0, ssl_ctx, nreqs, nclients, rate, MAX_SAMPLES)); - - auto start = std::chrono::steady_clock::now(); - - workers.back()->run(); #endif // NOTHREADS - auto end = std::chrono::steady_clock::now(); - auto duration = - std::chrono::duration_cast(end - start); + auto nreqs_last = nreqs_per_thread + (nreqs_rem-- > 0); + auto nclients_last = nclients_per_thread + (nclients_rem-- > 0); + std::cout << "spawning thread #" << (config.nthreads - 1) << ": " + << nclients_last << " concurrent clients, " << nreqs_last + << " total requests" << std::endl; + Worker worker(config.nthreads - 1, ssl_ctx, nreqs_last, nclients_last, + &config); + worker.run(); - Stats stats(0, 0); - for (const auto &w : workers) { - const auto &s = w->stats; - - stats.req_todo += s.req_todo; - stats.req_started += s.req_started; - stats.req_done += s.req_done; - stats.req_timedout += s.req_timedout; - stats.req_success += s.req_success; - stats.req_status_success += s.req_status_success; - stats.req_failed += s.req_failed; - stats.req_error += s.req_error; - stats.bytes_total += s.bytes_total; - stats.bytes_head += s.bytes_head; - stats.bytes_head_decomp += s.bytes_head_decomp; - stats.bytes_body += s.bytes_body; +#ifndef NOTHREADS + for (auto &fut : futures) { + auto stats = fut.get(); - for (size_t i = 0; i < stats.status.size(); ++i) { - stats.status[i] += s.status[i]; + worker.stats.req_todo += stats.req_todo; + worker.stats.req_started += stats.req_started; + worker.stats.req_done += stats.req_done; + worker.stats.req_success += stats.req_success; + worker.stats.req_failed += stats.req_failed; + worker.stats.req_error += stats.req_error; + worker.stats.bytes_total += stats.bytes_total; + worker.stats.bytes_head += stats.bytes_head; + worker.stats.bytes_body += stats.bytes_body; + + for (size_t i = 0; i < util::array_size(stats.status); ++i) { + worker.stats.status[i] += stats.status[i]; } } +#endif // NOTHREADS - auto ts = process_time_stats(workers); + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast( + end - start).count(); // Requests which have not been issued due to connection errors, are // counted towards req_failed and req_error. - auto req_not_issued = - stats.req_todo - stats.req_status_success - stats.req_failed; - stats.req_failed += req_not_issued; - stats.req_error += req_not_issued; - - // UI is heavily inspired by weighttp[1] and wrk[2] - // - // [1] https://github.com/lighttpd/weighttp - // [2] https://github.com/wg/wrk - double rps = 0; - int64_t bps = 0; - if (duration.count() > 0) { - auto secd = std::chrono::duration_cast< - std::chrono::duration>(duration); - rps = stats.req_success / secd.count(); - bps = stats.bytes_total / secd.count(); - } - - double header_space_savings = 0.; - if (stats.bytes_head_decomp > 0) { - header_space_savings = - 1. - static_cast(stats.bytes_head) / stats.bytes_head_decomp; - } - - std::cout << std::fixed << std::setprecision(2) << R"( -finished in )" << util::format_duration(duration) << ", " << rps << " req/s, " - << util::utos_funit(bps) << R"(B/s -requests: )" << stats.req_todo << " total, " << stats.req_started - << " started, " << stats.req_done << " done, " - << stats.req_status_success << " succeeded, " << stats.req_failed - << " failed, " << stats.req_error << " errored, " - << stats.req_timedout << R"( timeout -status codes: )" << stats.status[2] << " 2xx, " << stats.status[3] << " 3xx, " - << stats.status[4] << " 4xx, " << stats.status[5] << R"( 5xx -traffic: )" << util::utos_funit(stats.bytes_total) << "B (" << stats.bytes_total - << ") total, " << util::utos_funit(stats.bytes_head) << "B (" - << stats.bytes_head << ") headers (space savings " - << header_space_savings * 100 << "%), " - << util::utos_funit(stats.bytes_body) << "B (" << stats.bytes_body - << R"() data - min max mean sd +/- sd -time for request: )" << std::setw(10) << util::format_duration(ts.request.min) - << " " << std::setw(10) << util::format_duration(ts.request.max) - << " " << std::setw(10) << util::format_duration(ts.request.mean) - << " " << std::setw(10) << util::format_duration(ts.request.sd) - << std::setw(9) << util::dtos(ts.request.within_sd) << "%" - << "\ntime for connect: " << std::setw(10) - << util::format_duration(ts.connect.min) << " " << std::setw(10) - << util::format_duration(ts.connect.max) << " " << std::setw(10) - << util::format_duration(ts.connect.mean) << " " << std::setw(10) - << util::format_duration(ts.connect.sd) << std::setw(9) - << util::dtos(ts.connect.within_sd) << "%" - << "\ntime to 1st byte: " << std::setw(10) - << util::format_duration(ts.ttfb.min) << " " << std::setw(10) - << util::format_duration(ts.ttfb.max) << " " << std::setw(10) - << util::format_duration(ts.ttfb.mean) << " " << std::setw(10) - << util::format_duration(ts.ttfb.sd) << std::setw(9) - << util::dtos(ts.ttfb.within_sd) << "%" - << "\nreq/s : " << std::setw(10) << ts.rps.min << " " - << std::setw(10) << ts.rps.max << " " << std::setw(10) - << ts.rps.mean << " " << std::setw(10) << ts.rps.sd << std::setw(9) - << util::dtos(ts.rps.within_sd) << "%" << std::endl; + auto req_not_issued = worker.stats.req_todo - worker.stats.req_success - + worker.stats.req_failed; + worker.stats.req_failed += req_not_issued; + worker.stats.req_error += req_not_issued; + + // UI is heavily inspired by weighttp + // https://github.com/lighttpd/weighttp + size_t rps; + int64_t kbps; + if (duration > 0) { + auto secd = static_cast(duration) / (1000 * 1000); + rps = worker.stats.req_todo / secd; + kbps = worker.stats.bytes_total / secd / 1024; + } else { + rps = 0; + kbps = 0; + } + + auto sec = duration / (1000 * 1000); + auto millisec = (duration / 1000) % 1000; + auto microsec = duration % 1000; + + std::cout << "\n" + << "finished in " << sec << " sec, " << millisec << " millisec and " + << microsec << " microsec, " << rps << " req/s, " << kbps + << " kbytes/s\n" + << "requests: " << worker.stats.req_todo << " total, " + << worker.stats.req_started << " started, " << worker.stats.req_done + << " done, " << worker.stats.req_success << " succeeded, " + << worker.stats.req_failed << " failed, " << worker.stats.req_error + << " errored\n" + << "status codes: " << worker.stats.status[2] << " 2xx, " + << worker.stats.status[3] << " 3xx, " << worker.stats.status[4] + << " 4xx, " << worker.stats.status[5] << " 5xx\n" + << "traffic: " << worker.stats.bytes_total << " bytes total, " + << worker.stats.bytes_head << " bytes headers, " + << worker.stats.bytes_body << " bytes data" << std::endl; SSL_CTX_free(ssl_ctx); diff -Nru nghttp2-1.13.0/src/h2load.h nghttp2-0.6.7/src/h2load.h --- nghttp2-1.13.0/src/h2load.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/h2load.h 2014-11-30 14:15:07.000000000 +0000 @@ -28,52 +28,34 @@ #include "nghttp2_config.h" #include -#ifdef HAVE_SYS_SOCKET_H #include -#endif // HAVE_SYS_SOCKET_H -#ifdef HAVE_NETDB_H #include -#endif // HAVE_NETDB_H -#include #include #include #include #include -#include -#include #include -#include +#include +#include #include #include "http2.h" -#include "memchunk.h" -#include "template.h" - -using namespace nghttp2; namespace h2load { -constexpr auto BACKOFF_WRITE_BUFFER_THRES = 16_k; - class Session; -struct Worker; struct Config { std::vector> nva; std::vector> nv; - std::vector h1reqs; - std::vector timings; nghttp2::Headers custom_headers; std::string scheme; std::string host; std::string ifile; - std::string ciphers; - // length of upload data - int64_t data_length; addrinfo *addrs; size_t nreqs; size_t nclients; @@ -82,210 +64,74 @@ ssize_t max_concurrent_streams; size_t window_bits; size_t connection_window_bits; - // rate at which connections should be made - size_t rate; - ev_tstamp rate_period; - // amount of time to wait for activity on a given connection - ev_tstamp conn_active_timeout; - // amount of time to wait after the last request is made on a connection - ev_tstamp conn_inactivity_timeout; - enum { - PROTO_HTTP2, - PROTO_SPDY2, - PROTO_SPDY3, - PROTO_SPDY3_1, - PROTO_HTTP1_1 - } no_tls_proto; - // file descriptor for upload data - int data_fd; + enum { PROTO_HTTP2, PROTO_SPDY2, PROTO_SPDY3, PROTO_SPDY3_1 } no_tls_proto; uint16_t port; uint16_t default_port; bool verbose; - bool timing_script; - std::string base_uri; - // true if UNIX domain socket is used. In this case, base_uri is - // not used in usual way. - bool base_uri_unix; - // used when UNIX domain socket is used (base_uri_unix is true). - sockaddr_un unix_addr; - // list of supported NPN/ALPN protocol strings in the order of - // preference. - std::vector npn_list; Config(); ~Config(); - - bool is_rate_mode() const; - bool has_base_uri() const; -}; - -struct RequestStat { - // time point when request was sent - std::chrono::steady_clock::time_point request_time; - // time point when stream was closed - std::chrono::steady_clock::time_point stream_close_time; - // upload data length sent so far - int64_t data_offset; - // true if stream was successfully closed. This means stream was - // not reset, but it does not mean HTTP level error (e.g., 404). - bool completed; -}; - -struct ClientStat { - // time client started (i.e., first connect starts) - std::chrono::steady_clock::time_point client_start_time; - // time client end (i.e., client somehow processed all requests it - // is responsible for, and disconnected) - std::chrono::steady_clock::time_point client_end_time; - // The number of requests completed successfull, but not necessarily - // means successful HTTP status code. - size_t req_success; - - // The following 3 numbers are overwritten each time when connection - // is made. - - // time connect starts - std::chrono::steady_clock::time_point connect_start_time; - // time to connect - std::chrono::steady_clock::time_point connect_time; - // time to first byte (TTFB) - std::chrono::steady_clock::time_point ttfb; -}; - -struct SDStat { - // min, max, mean and sd (standard deviation) - double min, max, mean, sd; - // percentage of samples inside mean -/+ sd - double within_sd; -}; - -struct SDStats { - // time for request - SDStat request; - // time for connect - SDStat connect; - // time to first byte (TTFB) - SDStat ttfb; - // request per second for each client - SDStat rps; }; struct Stats { - Stats(size_t req_todo, size_t nclients); // The total number of requests size_t req_todo; // The number of requests issued so far size_t req_started; // The number of requests finished size_t req_done; - // The number of requests completed successfull, but not necessarily - // means successful HTTP status code. + // The number of requests marked as success. This is subset of + // req_done. size_t req_success; - // The number of requests marked as success. HTTP status code is - // also considered as success. This is subset of req_done. - size_t req_status_success; // The number of requests failed. This is subset of req_done. size_t req_failed; // The number of requests failed due to network errors. This is // subset of req_failed. size_t req_error; - // The number of requests that failed due to timeout. - size_t req_timedout; // The number of bytes received on the "wire". If SSL/TLS is used, // this is the number of decrypted bytes the application received. int64_t bytes_total; - // The number of bytes received for header fields. This is - // compressed version. + // The number of bytes received in HEADERS frame payload. int64_t bytes_head; - // The number of bytes received for header fields after they are - // decompressed. - int64_t bytes_head_decomp; // The number of bytes received in DATA frame. int64_t bytes_body; // The number of each HTTP status category, status[i] is status code // in the range [i*100, (i+1)*100). - std::array status; - // The statistics per request - std::vector req_stats; - // THe statistics per client - std::vector client_stats; + size_t status[6]; }; enum ClientState { CLIENT_IDLE, CLIENT_CONNECTED }; struct Client; -// We use systematic sampling method -struct Sampling { - // sampling interval - double interval; - // cumulative value of interval, and the next point is the integer - // rounded up from this value. - double point; - // number of samples seen, including discarded samples. - size_t n; -}; - struct Worker { - MemchunkPool mcpool; + std::vector> clients; Stats stats; - Sampling request_times_smp; - Sampling client_smp; - struct ev_loop *loop; + event_base *evbase; SSL_CTX *ssl_ctx; Config *config; size_t progress_interval; uint32_t id; bool tls_info_report_done; - bool app_info_report_done; - size_t nconns_made; - // number of clients this worker handles - size_t nclients; - // number of requests each client issues - size_t nreqs_per_client; - // at most nreqs_rem clients get an extra request - size_t nreqs_rem; - size_t rate; - // maximum number of samples in this worker thread - size_t max_samples; - ev_timer timeout_watcher; - // The next client ID this worker assigns - uint32_t next_client_id; Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients, - size_t rate, size_t max_samples, Config *config); + Config *config); ~Worker(); - Worker(Worker &&o) = default; void run(); - void sample_req_stat(RequestStat *req_stat); - void sample_client_stat(ClientStat *cstat); - void report_progress(); - void report_rate_progress(); }; struct Stream { - RequestStat req_stat; int status_success; Stream(); }; struct Client { - DefaultMemchunks wb; std::unordered_map streams; - ClientStat cstat; std::unique_ptr session; - ev_io wev; - ev_io rev; - std::function readfn, writefn; Worker *worker; SSL *ssl; - ev_timer request_timeout_watcher; + bufferevent *bev; addrinfo *next_addr; - // Address for the current address. When try_new_connection() is - // used and current_addr is not nullptr, it is used instead of - // trying next address though next_addr. To try new address, set - // nullptr to current_addr before calling connect(). - addrinfo *current_addr; size_t reqidx; ClientState state; // The number of requests this client has to issue. @@ -294,82 +140,24 @@ size_t req_started; // The number of requests this client has done so far. size_t req_done; - // The client id per worker - uint32_t id; - int fd; - ev_timer conn_active_watcher; - ev_timer conn_inactivity_watcher; - std::string selected_proto; - bool new_connection_requested; - // true if the current connection will be closed, and no more new - // request cannot be processed. - bool final; - - enum { ERR_CONNECT_FAIL = -100 }; - Client(uint32_t id, Worker *worker, size_t req_todo); + Client(Worker *worker, size_t req_todo); ~Client(); - int make_socket(addrinfo *addr); int connect(); void disconnect(); void fail(); - // Call this function when do_read() returns -1. This function - // tries to connect to the remote host again if it is requested. If - // so, this function returns 0, and this object should be retained. - // Otherwise, this function returns -1, and this object should be - // deleted. - int try_again_or_fail(); - void timeout(); - void restart_timeout(); - int submit_request(); - void process_request_failure(); - void process_timedout_streams(); + void submit_request(); void process_abandoned_streams(); + void report_progress(); void report_tls_info(); - void report_app_info(); void terminate_session(); - // Asks client to create new connection, instead of just fail. - void try_new_connection(); - - int do_read(); - int do_write(); - - // low-level I/O callback functions called by do_read/do_write - int connected(); - int read_clear(); - int write_clear(); - int tls_handshake(); - int read_tls(); - int write_tls(); - - int on_read(const uint8_t *data, size_t len); + int on_connect(); + int on_read(); int on_write(); - - int connection_made(); - void on_request(int32_t stream_id); void on_header(int32_t stream_id, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen); - void on_status_code(int32_t stream_id, uint16_t status); - // |success| == true means that the request/response was exchanged - // |successfully, but it does not mean response carried successful - // |HTTP status code. - void on_stream_close(int32_t stream_id, bool success, bool final = false); - // Returns RequestStat for |stream_id|. This function must be - // called after on_request(stream_id), and before - // on_stream_close(stream_id, ...). Otherwise, this will return - // nullptr. - RequestStat *get_req_stat(int32_t stream_id); - - void record_request_time(RequestStat *req_stat); - void record_connect_start_time(); - void record_connect_time(); - void record_ttfb(); - void clear_connect_times(); - void record_client_start_time(); - void record_client_end_time(); - - void signal_write(); + void on_stream_close(int32_t stream_id, bool success); }; } // namespace h2load diff -Nru nghttp2-1.13.0/src/h2load_http1_session.cc nghttp2-0.6.7/src/h2load_http1_session.cc --- nghttp2-1.13.0/src/h2load_http1_session.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/h2load_http1_session.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,276 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 British Broadcasting Corporation - * - * 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. - */ -#include "h2load_http1_session.h" - -#include -#include - -#include "h2load.h" -#include "util.h" -#include "template.h" - -#include -#include - -#include "http-parser/http_parser.h" - -using namespace nghttp2; - -namespace h2load { - -Http1Session::Http1Session(Client *client) - : stream_req_counter_(1), - stream_resp_counter_(1), - client_(client), - htp_(), - complete_(false) { - http_parser_init(&htp_, HTTP_RESPONSE); - htp_.data = this; -} - -Http1Session::~Http1Session() {} - -namespace { -// HTTP response message begin -int htp_msg_begincb(http_parser *htp) { - auto session = static_cast(htp->data); - - if (session->stream_resp_counter_ > session->stream_req_counter_) { - return -1; - } - - return 0; -} -} // namespace - -namespace { -// HTTP response status code -int htp_statuscb(http_parser *htp, const char *at, size_t length) { - auto session = static_cast(htp->data); - auto client = session->get_client(); - client->on_status_code(session->stream_resp_counter_, htp->status_code); - - return 0; -} -} // namespace - -namespace { -// HTTP response message complete -int htp_msg_completecb(http_parser *htp) { - auto session = static_cast(htp->data); - auto client = session->get_client(); - - client->final = http_should_keep_alive(htp) == 0; - auto req_stat = client->get_req_stat(session->stream_resp_counter_); - - assert(req_stat); - - auto config = client->worker->config; - if (req_stat->data_offset >= config->data_length) { - client->on_stream_close(session->stream_resp_counter_, true, client->final); - } - - session->stream_resp_counter_ += 2; - - if (client->final) { - session->stream_req_counter_ = session->stream_resp_counter_; - - http_parser_pause(htp, 1); - // Connection is going down. If we have still request to do, - // create new connection and keep on doing the job. - if (client->req_started < client->req_todo) { - client->try_new_connection(); - } - - return 0; - } - - return 0; -} -} // namespace - -namespace { -int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) { - auto session = static_cast(htp->data); - auto client = session->get_client(); - - client->worker->stats.bytes_head += len; - client->worker->stats.bytes_head_decomp += len; - return 0; -} -} // namespace - -namespace { -int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) { - auto session = static_cast(htp->data); - auto client = session->get_client(); - - client->worker->stats.bytes_head += len; - client->worker->stats.bytes_head_decomp += len; - return 0; -} -} // namespace - -namespace { -int htp_body_cb(http_parser *htp, const char *data, size_t len) { - auto session = static_cast(htp->data); - auto client = session->get_client(); - - client->record_ttfb(); - client->worker->stats.bytes_body += len; - - return 0; -} -} // namespace - -namespace { -http_parser_settings htp_hooks = { - htp_msg_begincb, // http_cb on_message_begin; - nullptr, // http_data_cb on_url; - htp_statuscb, // http_data_cb on_status; - htp_hdr_keycb, // http_data_cb on_header_field; - htp_hdr_valcb, // http_data_cb on_header_value; - nullptr, // http_cb on_headers_complete; - htp_body_cb, // http_data_cb on_body; - htp_msg_completecb // http_cb on_message_complete; -}; -} // namespace - -void Http1Session::on_connect() { client_->signal_write(); } - -int Http1Session::submit_request() { - auto config = client_->worker->config; - const auto &req = config->h1reqs[client_->reqidx]; - client_->reqidx++; - - if (client_->reqidx == config->h1reqs.size()) { - client_->reqidx = 0; - } - - client_->on_request(stream_req_counter_); - - auto req_stat = client_->get_req_stat(stream_req_counter_); - - client_->record_request_time(req_stat); - client_->wb.append(req); - - if (config->data_fd == -1 || config->data_length == 0) { - // increment for next request - stream_req_counter_ += 2; - - return 0; - } - - return on_write(); -} - -int Http1Session::on_read(const uint8_t *data, size_t len) { - auto nread = http_parser_execute(&htp_, &htp_hooks, - reinterpret_cast(data), len); - - if (client_->worker->config->verbose) { - std::cout.write(reinterpret_cast(data), nread); - } - - auto htperr = HTTP_PARSER_ERRNO(&htp_); - - if (htperr == HPE_PAUSED) { - // pause is done only when connection: close is requested - return -1; - } - - if (htperr != HPE_OK) { - std::cerr << "[ERROR] HTTP parse error: " - << "(" << http_errno_name(htperr) << ") " - << http_errno_description(htperr) << std::endl; - return -1; - } - - return 0; -} - -int Http1Session::on_write() { - if (complete_) { - return -1; - } - - auto config = client_->worker->config; - auto req_stat = client_->get_req_stat(stream_req_counter_); - if (!req_stat) { - return 0; - } - - if (req_stat->data_offset < config->data_length) { - auto req_stat = client_->get_req_stat(stream_req_counter_); - auto &wb = client_->wb; - - // TODO unfortunately, wb has no interface to use with read(2) - // family functions. - std::array buf; - - ssize_t nread; - while ((nread = pread(config->data_fd, buf.data(), buf.size(), - req_stat->data_offset)) == -1 && - errno == EINTR) - ; - - if (nread == -1) { - return -1; - } - - req_stat->data_offset += nread; - - wb.append(buf.data(), nread); - - if (client_->worker->config->verbose) { - std::cout << "[send " << nread << " byte(s)]" << std::endl; - } - - if (req_stat->data_offset == config->data_length) { - // increment for next request - stream_req_counter_ += 2; - - if (stream_resp_counter_ == stream_req_counter_) { - // Response has already been received - client_->on_stream_close(stream_resp_counter_ - 2, true, - client_->final); - } - } - } - - return 0; -} - -void Http1Session::terminate() { complete_ = true; } - -Client *Http1Session::get_client() { return client_; } - -size_t Http1Session::max_concurrent_streams() { - auto config = client_->worker->config; - - return config->data_fd == -1 ? config->max_concurrent_streams : 1; -} - -} // namespace h2load diff -Nru nghttp2-1.13.0/src/h2load_http1_session.h nghttp2-0.6.7/src/h2load_http1_session.h --- nghttp2-1.13.0/src/h2load_http1_session.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/h2load_http1_session.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 British Broadcasting Corporation - * - * 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 H2LOAD_HTTP1_SESSION_H -#define H2LOAD_HTTP1_SESSION_H - -#include "h2load_session.h" - -#include - -namespace h2load { - -struct Client; - -class Http1Session : public Session { -public: - Http1Session(Client *client); - virtual ~Http1Session(); - virtual void on_connect(); - virtual int submit_request(); - virtual int on_read(const uint8_t *data, size_t len); - virtual int on_write(); - virtual void terminate(); - virtual size_t max_concurrent_streams(); - Client *get_client(); - int32_t stream_req_counter_; - int32_t stream_resp_counter_; - -private: - Client *client_; - http_parser htp_; - bool complete_; -}; - -} // namespace h2load - -#endif // H2LOAD_HTTP1_SESSION_H diff -Nru nghttp2-1.13.0/src/h2load_http2_session.cc nghttp2-0.6.7/src/h2load_http2_session.cc --- nghttp2-1.13.0/src/h2load_http2_session.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/h2load_http2_session.cc 2014-11-30 14:15:07.000000000 +0000 @@ -25,11 +25,10 @@ #include "h2load_http2_session.h" #include -#include #include "h2load.h" #include "util.h" -#include "template.h" +#include "libevent_util.h" using namespace nghttp2; @@ -51,7 +50,6 @@ return 0; } client->on_header(frame->hd.stream_id, name, namelen, value, valuelen); - client->worker->stats.bytes_head_decomp += namelen + valuelen; return 0; } } // namespace @@ -64,12 +62,7 @@ frame->headers.cat != NGHTTP2_HCAT_RESPONSE) { return 0; } - client->worker->stats.bytes_head += - frame->hd.length - frame->headers.padlen - - ((frame->hd.flags & NGHTTP2_FLAG_PRIORITY) ? 5 : 0); - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - client->record_ttfb(); - } + client->worker->stats.bytes_head += frame->hd.length; return 0; } } // namespace @@ -79,7 +72,6 @@ int32_t stream_id, const uint8_t *data, size_t len, void *user_data) { auto client = static_cast(user_data); - client->record_ttfb(); client->worker->stats.bytes_body += len; return 0; } @@ -90,93 +82,10 @@ uint32_t error_code, void *user_data) { auto client = static_cast(user_data); client->on_stream_close(stream_id, error_code == NGHTTP2_NO_ERROR); - - return 0; -} -} // namespace - -namespace { -int on_frame_not_send_callback(nghttp2_session *session, - const nghttp2_frame *frame, int lib_error_code, - void *user_data) { - if (frame->hd.type != NGHTTP2_HEADERS || - frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - return 0; - } - - auto client = static_cast(user_data); - // request was not sent. Mark it as error. - client->on_stream_close(frame->hd.stream_id, false); - return 0; } } // namespace -namespace { -int before_frame_send_callback(nghttp2_session *session, - const nghttp2_frame *frame, void *user_data) { - if (frame->hd.type != NGHTTP2_HEADERS || - frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - return 0; - } - - auto client = static_cast(user_data); - auto req_stat = client->get_req_stat(frame->hd.stream_id); - assert(req_stat); - client->record_request_time(req_stat); - - return 0; -} -} // namespace - -namespace { -ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id, - uint8_t *buf, size_t length, uint32_t *data_flags, - nghttp2_data_source *source, void *user_data) { - auto client = static_cast(user_data); - auto config = client->worker->config; - auto req_stat = client->get_req_stat(stream_id); - assert(req_stat); - ssize_t nread; - while ((nread = pread(config->data_fd, buf, length, req_stat->data_offset)) == - -1 && - errno == EINTR) - ; - - if (nread == -1) { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - - req_stat->data_offset += nread; - - if (req_stat->data_offset == config->data_length) { - *data_flags |= NGHTTP2_DATA_FLAG_EOF; - return nread; - } - - if (req_stat->data_offset > config->data_length || nread == 0) { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - - return nread; -} - -} // namespace - -namespace { -ssize_t send_callback(nghttp2_session *session, const uint8_t *data, - size_t length, int flags, void *user_data) { - auto client = static_cast(user_data); - auto &wb = client->wb; - - if (wb.rleft() >= BACKOFF_WRITE_BUFFER_THRES) { - return NGHTTP2_ERR_WOULDBLOCK; - } - - return wb.append(data, length); -} -} // namespace - void Http2Session::on_connect() { int rv; @@ -184,7 +93,8 @@ nghttp2_session_callbacks_new(&callbacks); - auto callbacks_deleter = defer(nghttp2_session_callbacks_del, callbacks); + auto callbacks_deleter = + util::defer(callbacks, nghttp2_session_callbacks_del); nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, on_frame_recv_callback); @@ -198,40 +108,32 @@ nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header_callback); - nghttp2_session_callbacks_set_on_frame_not_send_callback( - callbacks, on_frame_not_send_callback); - - nghttp2_session_callbacks_set_before_frame_send_callback( - callbacks, before_frame_send_callback); - - nghttp2_session_callbacks_set_send_callback(callbacks, send_callback); - nghttp2_session_client_new(&session_, callbacks, client_); - std::array iv; + nghttp2_settings_entry iv[2]; iv[0].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; iv[0].value = 0; iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; iv[1].value = (1 << client_->worker->config->window_bits) - 1; - rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, iv.data(), - iv.size()); + rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, iv, + util::array_size(iv)); assert(rv == 0); - auto connection_window = - (1 << client_->worker->config->connection_window_bits) - 1; - nghttp2_session_set_local_window_size(session_, NGHTTP2_FLAG_NONE, 0, - connection_window); + auto extra_connection_window = + (1 << client_->worker->config->connection_window_bits) - 1 - + NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; + if (extra_connection_window != 0) { + nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, + extra_connection_window); + } - client_->signal_write(); + bufferevent_write(client_->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE, + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); } -int Http2Session::submit_request() { - if (nghttp2_session_check_request_allowed(session_) == 0) { - return -1; - } - +void Http2Session::submit_request() { auto config = client_->worker->config; auto &nva = config->nva[client_->reqidx++]; @@ -239,49 +141,73 @@ client_->reqidx = 0; } - nghttp2_data_provider prd{{0}, file_read_callback}; - - auto stream_id = - nghttp2_submit_request(session_, nullptr, nva.data(), nva.size(), - config->data_fd == -1 ? nullptr : &prd, nullptr); - if (stream_id < 0) { - return -1; - } + auto stream_id = nghttp2_submit_request(session_, nullptr, nva.data(), + nva.size(), nullptr, nullptr); + assert(stream_id > 0); client_->on_request(stream_id); - - return 0; } -int Http2Session::on_read(const uint8_t *data, size_t len) { - auto rv = nghttp2_session_mem_recv(session_, data, len); - if (rv < 0) { - return -1; - } +ssize_t Http2Session::on_read() { + int rv; + size_t nread = 0; - assert(static_cast(rv) == len); + auto input = bufferevent_get_input(client_->bev); - if (nghttp2_session_want_read(session_) == 0 && - nghttp2_session_want_write(session_) == 0 && client_->wb.rleft() == 0) { - return -1; - } + for (;;) { + auto inputlen = evbuffer_get_contiguous_space(input); - client_->signal_write(); + if (inputlen == 0) { + assert(evbuffer_get_length(input) == 0); - return 0; + return nread; + } + + auto mem = evbuffer_pullup(input, inputlen); + + rv = nghttp2_session_mem_recv(session_, mem, inputlen); + + if (rv < 0) { + return -1; + } + + nread += rv; + + if (evbuffer_drain(input, rv) != 0) { + return -1; + } + } } int Http2Session::on_write() { - auto rv = nghttp2_session_send(session_); + int rv; + uint8_t buf[16384]; + auto output = bufferevent_get_output(client_->bev); + util::EvbufferBuffer evbbuf(output, buf, sizeof(buf)); + for (;;) { + const uint8_t *data; + auto datalen = nghttp2_session_mem_send(session_, &data); + + if (datalen < 0) { + return -1; + } + if (datalen == 0) { + break; + } + rv = evbbuf.add(data, datalen); + if (rv != 0) { + return -1; + } + } + rv = evbbuf.flush(); if (rv != 0) { return -1; } - if (nghttp2_session_want_read(session_) == 0 && - nghttp2_session_want_write(session_) == 0 && client_->wb.rleft() == 0) { + nghttp2_session_want_write(session_) == 0 && + evbuffer_get_length(output) == 0) { return -1; } - return 0; } @@ -289,8 +215,4 @@ nghttp2_session_terminate_session(session_, NGHTTP2_NO_ERROR); } -size_t Http2Session::max_concurrent_streams() { - return (size_t)client_->worker->config->max_concurrent_streams; -} - } // namespace h2load diff -Nru nghttp2-1.13.0/src/h2load_http2_session.h nghttp2-0.6.7/src/h2load_http2_session.h --- nghttp2-1.13.0/src/h2load_http2_session.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/h2load_http2_session.h 2014-11-30 14:15:07.000000000 +0000 @@ -38,11 +38,10 @@ Http2Session(Client *client); virtual ~Http2Session(); virtual void on_connect(); - virtual int submit_request(); - virtual int on_read(const uint8_t *data, size_t len); + virtual void submit_request(); + virtual ssize_t on_read(); virtual int on_write(); virtual void terminate(); - virtual size_t max_concurrent_streams(); private: Client *client_; diff -Nru nghttp2-1.13.0/src/h2load_session.h nghttp2-0.6.7/src/h2load_session.h --- nghttp2-1.13.0/src/h2load_session.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/h2load_session.h 2014-11-30 14:15:07.000000000 +0000 @@ -29,10 +29,6 @@ #include -#include - -#include "h2load.h" - namespace h2load { class Session { @@ -41,17 +37,15 @@ // Called when the connection was made. virtual void on_connect() = 0; // Called when one request must be issued. - virtual int submit_request() = 0; + virtual void submit_request() = 0; // Called when incoming bytes are available. The subclass has to // return the number of bytes read. - virtual int on_read(const uint8_t *data, size_t len) = 0; + virtual ssize_t on_read() = 0; // Called when write is available. Returns 0 on success, otherwise // return -1. virtual int on_write() = 0; // Called when the underlying session must be terminated. virtual void terminate() = 0; - // Return the maximum concurrency per connection - virtual size_t max_concurrent_streams() = 0; }; } // namespace h2load diff -Nru nghttp2-1.13.0/src/h2load_spdy_session.cc nghttp2-0.6.7/src/h2load_spdy_session.cc --- nghttp2-1.13.0/src/h2load_spdy_session.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/h2load_spdy_session.cc 2014-11-30 14:15:07.000000000 +0000 @@ -25,7 +25,6 @@ #include "h2load_spdy_session.h" #include -#include #include "h2load.h" #include "util.h" @@ -48,8 +47,6 @@ return; } client->on_request(frame->syn_stream.stream_id); - auto req_stat = client->get_req_stat(frame->syn_stream.stream_id); - client->record_request_time(req_stat); } } // namespace @@ -63,22 +60,11 @@ for (auto p = frame->syn_reply.nv; *p; p += 2) { auto name = *p; auto value = *(p + 1); - auto namelen = strlen(name); - auto valuelen = strlen(value); client->on_header(frame->syn_reply.stream_id, - reinterpret_cast(name), namelen, - reinterpret_cast(value), valuelen); - client->worker->stats.bytes_head_decomp += namelen + valuelen; - } - - // Strictly speaking, we have to subtract 2 (unused field) if SPDY - // version is 2. But it is already deprecated, and we don't do - // extra work for it. - client->worker->stats.bytes_head += frame->syn_reply.hd.length - 4; - - if (frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN) { - client->record_ttfb(); + reinterpret_cast(name), strlen(name), + reinterpret_cast(value), strlen(value)); } + client->worker->stats.bytes_head += frame->syn_reply.hd.length; } } // namespace @@ -87,8 +73,6 @@ int32_t stream_id, const uint8_t *data, size_t len, void *user_data) { auto client = static_cast(user_data); - - client->record_ttfb(); client->worker->stats.bytes_body += len; auto spdy_session = static_cast(client->session.get()); @@ -110,41 +94,14 @@ ssize_t send_callback(spdylay_session *session, const uint8_t *data, size_t length, int flags, void *user_data) { auto client = static_cast(user_data); - auto &wb = client->wb; - - if (wb.rleft() >= BACKOFF_WRITE_BUFFER_THRES) { - return SPDYLAY_ERR_DEFERRED; - } - - return wb.append(data, length); -} -} // namespace - -namespace { -ssize_t file_read_callback(spdylay_session *session, int32_t stream_id, - uint8_t *buf, size_t length, int *eof, - spdylay_data_source *source, void *user_data) { - auto client = static_cast(user_data); - auto config = client->worker->config; - auto req_stat = client->get_req_stat(stream_id); - - ssize_t nread; - while ((nread = pread(config->data_fd, buf, length, req_stat->data_offset)) == - -1 && - errno == EINTR) - ; - - if (nread == -1) { - return SPDYLAY_ERR_TEMPORAL_CALLBACK_FAILURE; - } - - req_stat->data_offset += nread; + auto spdy_session = static_cast(client->session.get()); + int rv; - if (nread == 0 || req_stat->data_offset == config->data_length) { - *eof = 1; + rv = spdy_session->sendbuf.add(data, length); + if (rv != 0) { + return SPDYLAY_ERR_CALLBACK_FAILURE; } - - return nread; + return length; } } // namespace @@ -162,11 +119,12 @@ spdylay_session_set_option(session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE, &val, sizeof(val)); - spdylay_settings_entry iv; - iv.settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE; - iv.flags = SPDYLAY_ID_FLAG_SETTINGS_NONE; - iv.value = (1 << client_->worker->config->window_bits); - spdylay_submit_settings(session_, SPDYLAY_FLAG_SETTINGS_NONE, &iv, 1); + spdylay_settings_entry iv[1]; + iv[0].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE; + iv[0].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE; + iv[0].value = (1 << client_->worker->config->window_bits); + spdylay_submit_settings(session_, SPDYLAY_FLAG_SETTINGS_NONE, iv, + util::array_size(iv)); auto config = client_->worker->config; @@ -176,12 +134,9 @@ (1 << config->connection_window_bits) - SPDYLAY_INITIAL_WINDOW_SIZE; spdylay_submit_window_update(session_, 0, delta); } - - client_->signal_write(); } -int SpdySession::submit_request() { - int rv; +void SpdySession::submit_request() { auto config = client_->worker->config; auto &nv = config->nv[client_->reqidx++]; @@ -189,44 +144,58 @@ client_->reqidx = 0; } - spdylay_data_provider prd{{0}, file_read_callback}; + spdylay_submit_request(session_, 0, nv.data(), nullptr, nullptr); +} + +ssize_t SpdySession::on_read() { + int rv; + size_t nread = 0; + auto input = bufferevent_get_input(client_->bev); - rv = spdylay_submit_request(session_, 0, nv.data(), - config->data_fd == -1 ? nullptr : &prd, nullptr); + for (;;) { + auto inputlen = evbuffer_get_contiguous_space(input); - if (rv != 0) { - return -1; - } + if (inputlen == 0) { + assert(evbuffer_get_length(input) == 0); - return 0; -} + return nread; + } -int SpdySession::on_read(const uint8_t *data, size_t len) { - auto rv = spdylay_session_mem_recv(session_, data, len); - if (rv < 0) { - return -1; - } + auto mem = evbuffer_pullup(input, inputlen); - assert(static_cast(rv) == len); + rv = spdylay_session_mem_recv(session_, mem, inputlen); - if (spdylay_session_want_read(session_) == 0 && - spdylay_session_want_write(session_) == 0 && client_->wb.rleft() == 0) { - return -1; - } + if (rv < 0) { + return -1; + } - client_->signal_write(); + nread += rv; - return 0; + if (evbuffer_drain(input, rv) != 0) { + return -1; + } + } } int SpdySession::on_write() { - auto rv = spdylay_session_send(session_); + int rv; + uint8_t buf[16384]; + + sendbuf.reset(bufferevent_get_output(client_->bev), buf, sizeof(buf)); + + rv = spdylay_session_send(session_); + if (rv != 0) { + return -1; + } + + rv = sendbuf.flush(); if (rv != 0) { return -1; } if (spdylay_session_want_read(session_) == 0 && - spdylay_session_want_write(session_) == 0 && client_->wb.rleft() == 0) { + spdylay_session_want_write(session_) == 0 && + evbuffer_get_length(bufferevent_get_output(client_->bev)) == 0) { return -1; } return 0; @@ -282,8 +251,4 @@ } } -size_t SpdySession::max_concurrent_streams() { - return (size_t)client_->worker->config->max_concurrent_streams; -} - } // namespace h2load diff -Nru nghttp2-1.13.0/src/h2load_spdy_session.h nghttp2-0.6.7/src/h2load_spdy_session.h --- nghttp2-1.13.0/src/h2load_spdy_session.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/h2load_spdy_session.h 2014-11-30 14:15:07.000000000 +0000 @@ -30,6 +30,7 @@ #include #include "util.h" +#include "libevent_util.h" namespace h2load { @@ -40,13 +41,14 @@ SpdySession(Client *client, uint16_t spdy_version); virtual ~SpdySession(); virtual void on_connect(); - virtual int submit_request(); - virtual int on_read(const uint8_t *data, size_t len); + virtual void submit_request(); + virtual ssize_t on_read(); virtual int on_write(); virtual void terminate(); - virtual size_t max_concurrent_streams(); void handle_window_update(int32_t stream_id, size_t recvlen); + nghttp2::util::EvbufferBuffer sendbuf; + private: Client *client_; spdylay_session *session_; diff -Nru nghttp2-1.13.0/src/HtmlParser.cc nghttp2-0.6.7/src/HtmlParser.cc --- nghttp2-1.13.0/src/HtmlParser.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/HtmlParser.cc 2014-11-30 14:15:07.000000000 +0000 @@ -30,8 +30,7 @@ namespace nghttp2 { -ParserData::ParserData(const std::string &base_uri) - : base_uri(base_uri), inside_head(0) {} +ParserData::ParserData(const std::string &base_uri) : base_uri(base_uri) {} HtmlParser::HtmlParser(const std::string &base_uri) : base_uri_(base_uri), parser_ctx_(nullptr), parser_data_(base_uri) {} @@ -39,83 +38,59 @@ HtmlParser::~HtmlParser() { htmlFreeParserCtxt(parser_ctx_); } namespace { -StringRef get_attr(const xmlChar **attrs, const StringRef &name) { +const char *get_attr(const xmlChar **attrs, const char *name) { if (attrs == nullptr) { - return StringRef{}; + return nullptr; } for (; *attrs; attrs += 2) { - if (util::strieq(StringRef{attrs[0], strlen(reinterpret_cast( - attrs[0]))}, - name)) { - return StringRef{attrs[1], - strlen(reinterpret_cast(attrs[1]))}; + if (util::strieq(reinterpret_cast(attrs[0]), name)) { + return reinterpret_cast(attrs[1]); } } - return StringRef{}; + return nullptr; } } // namespace namespace { -void add_link(ParserData *parser_data, const StringRef &uri, - ResourceType res_type) { +void add_link(ParserData *parser_data, const char *uri, RequestPriority pri) { auto u = xmlBuildURI( - reinterpret_cast(uri.c_str()), + reinterpret_cast(uri), reinterpret_cast(parser_data->base_uri.c_str())); if (u) { parser_data->links.push_back( - std::make_pair(reinterpret_cast(u), res_type)); + std::make_pair(reinterpret_cast(u), pri)); free(u); } } } // namespace namespace { -void start_element_func(void *user_data, const xmlChar *src_name, +void start_element_func(void *user_data, const xmlChar *name, const xmlChar **attrs) { auto parser_data = static_cast(user_data); - auto name = - StringRef{src_name, strlen(reinterpret_cast(src_name))}; - if (util::strieq_l("head", name)) { - ++parser_data->inside_head; - } - if (util::strieq_l("link", name)) { - auto rel_attr = get_attr(attrs, StringRef::from_lit("rel")); - auto href_attr = get_attr(attrs, StringRef::from_lit("href")); - if (rel_attr.empty() || href_attr.empty()) { + if (util::strieq(reinterpret_cast(name), "link")) { + auto rel_attr = get_attr(attrs, "rel"); + auto href_attr = get_attr(attrs, "href"); + if (!href_attr) { return; } - if (util::strieq_l("shortcut icon", rel_attr)) { - add_link(parser_data, href_attr, REQ_OTHERS); - } else if (util::strieq_l("stylesheet", rel_attr)) { - add_link(parser_data, href_attr, REQ_CSS); - } - } else if (util::strieq_l("img", name)) { - auto src_attr = get_attr(attrs, StringRef::from_lit("src")); - if (src_attr.empty()) { + if (util::strieq(rel_attr, "shortcut icon")) { + add_link(parser_data, href_attr, REQ_PRI_LOWEST); + } else if (util::strieq(rel_attr, "stylesheet")) { + add_link(parser_data, href_attr, REQ_PRI_MEDIUM); + } + } else if (util::strieq(reinterpret_cast(name), "img")) { + auto src_attr = get_attr(attrs, "src"); + if (!src_attr) { return; } - add_link(parser_data, src_attr, REQ_IMG); - } else if (util::strieq_l("script", name)) { - auto src_attr = get_attr(attrs, StringRef::from_lit("src")); - if (src_attr.empty()) { + add_link(parser_data, src_attr, REQ_PRI_LOWEST); + } else if (util::strieq(reinterpret_cast(name), "script")) { + auto src_attr = get_attr(attrs, "src"); + if (!src_attr) { return; } - if (parser_data->inside_head) { - add_link(parser_data, src_attr, REQ_JS); - } else { - add_link(parser_data, src_attr, REQ_UNBLOCK_JS); - } - } -} -} // namespace - -namespace { -void end_element_func(void *user_data, const xmlChar *name) { - auto parser_data = static_cast(user_data); - if (util::strieq_l( - "head", - StringRef{name, strlen(reinterpret_cast(name))})) { - --parser_data->inside_head; + add_link(parser_data, src_attr, REQ_PRI_LOW); } } } // namespace @@ -137,7 +112,7 @@ nullptr, // startDocumentSAXFunc nullptr, // endDocumentSAXFunc &start_element_func, // startElementSAXFunc - &end_element_func, // endElementSAXFunc + nullptr, // endElementSAXFunc nullptr, // referenceSAXFunc nullptr, // charactersSAXFunc nullptr, // ignorableWhitespaceSAXFunc @@ -185,7 +160,7 @@ } } -const std::vector> & +const std::vector> & HtmlParser::get_links() const { return parser_data_.links; } diff -Nru nghttp2-1.13.0/src/HtmlParser.h nghttp2-0.6.7/src/HtmlParser.h --- nghttp2-1.13.0/src/HtmlParser.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/HtmlParser.h 2014-11-30 14:15:07.000000000 +0000 @@ -38,19 +38,16 @@ namespace nghttp2 { -enum ResourceType { - REQ_CSS = 1, - REQ_JS, - REQ_UNBLOCK_JS, - REQ_IMG, - REQ_OTHERS, +enum RequestPriority { + REQ_PRI_HIGH = 0, + REQ_PRI_MEDIUM = 1, + REQ_PRI_LOW = 2, + REQ_PRI_LOWEST = 3 }; struct ParserData { std::string base_uri; - std::vector> links; - // > 0 if we are inside "head" element. - int inside_head; + std::vector> links; ParserData(const std::string &base_uri); }; @@ -61,7 +58,7 @@ HtmlParser(const std::string &base_uri); ~HtmlParser(); int parse_chunk(const char *chunk, size_t size, int fin); - const std::vector> &get_links() const; + const std::vector> &get_links() const; void clear_links(); private: @@ -78,13 +75,14 @@ public: HtmlParser(const std::string &base_uri) {} int parse_chunk(const char *chunk, size_t size, int fin) { return 0; } - const std::vector> &get_links() const { + const std::vector> & + get_links() const { return links_; } void clear_links() {} private: - std::vector> links_; + std::vector> links_; }; #endif // !HAVE_LIBXML2 diff -Nru nghttp2-1.13.0/src/http2.cc nghttp2-0.6.7/src/http2.cc --- nghttp2-1.13.0/src/http2.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/http2.cc 2014-11-30 14:15:07.000000000 +0000 @@ -30,221 +30,115 @@ namespace http2 { -StringRef get_status_string(BlockAllocator &balloc, unsigned int status_code) { +std::string get_status_string(unsigned int status_code) { switch (status_code) { case 100: - return StringRef::from_lit("100 Continue"); + return "100 Continue"; case 101: - return StringRef::from_lit("101 Switching Protocols"); + return "101 Switching Protocols"; case 200: - return StringRef::from_lit("200 OK"); + return "200 OK"; case 201: - return StringRef::from_lit("201 Created"); + return "201 Created"; case 202: - return StringRef::from_lit("202 Accepted"); + return "202 Accepted"; case 203: - return StringRef::from_lit("203 Non-Authoritative Information"); + return "203 Non-Authoritative Information"; case 204: - return StringRef::from_lit("204 No Content"); + return "204 No Content"; case 205: - return StringRef::from_lit("205 Reset Content"); + return "205 Reset Content"; case 206: - return StringRef::from_lit("206 Partial Content"); + return "206 Partial Content"; case 300: - return StringRef::from_lit("300 Multiple Choices"); + return "300 Multiple Choices"; case 301: - return StringRef::from_lit("301 Moved Permanently"); + return "301 Moved Permanently"; case 302: - return StringRef::from_lit("302 Found"); + return "302 Found"; case 303: - return StringRef::from_lit("303 See Other"); + return "303 See Other"; case 304: - return StringRef::from_lit("304 Not Modified"); + return "304 Not Modified"; case 305: - return StringRef::from_lit("305 Use Proxy"); - // case 306: return StringRef::from_lit("306 (Unused)"); + return "305 Use Proxy"; + // case 306: return "306 (Unused)"; case 307: - return StringRef::from_lit("307 Temporary Redirect"); + return "307 Temporary Redirect"; case 308: - return StringRef::from_lit("308 Permanent Redirect"); + return "308 Permanent Redirect"; case 400: - return StringRef::from_lit("400 Bad Request"); + return "400 Bad Request"; case 401: - return StringRef::from_lit("401 Unauthorized"); + return "401 Unauthorized"; case 402: - return StringRef::from_lit("402 Payment Required"); + return "402 Payment Required"; case 403: - return StringRef::from_lit("403 Forbidden"); + return "403 Forbidden"; case 404: - return StringRef::from_lit("404 Not Found"); + return "404 Not Found"; case 405: - return StringRef::from_lit("405 Method Not Allowed"); + return "405 Method Not Allowed"; case 406: - return StringRef::from_lit("406 Not Acceptable"); + return "406 Not Acceptable"; case 407: - return StringRef::from_lit("407 Proxy Authentication Required"); + return "407 Proxy Authentication Required"; case 408: - return StringRef::from_lit("408 Request Timeout"); + return "408 Request Timeout"; case 409: - return StringRef::from_lit("409 Conflict"); + return "409 Conflict"; case 410: - return StringRef::from_lit("410 Gone"); + return "410 Gone"; case 411: - return StringRef::from_lit("411 Length Required"); + return "411 Length Required"; case 412: - return StringRef::from_lit("412 Precondition Failed"); + return "412 Precondition Failed"; case 413: - return StringRef::from_lit("413 Payload Too Large"); + return "413 Payload Too Large"; case 414: - return StringRef::from_lit("414 URI Too Long"); + return "414 URI Too Long"; case 415: - return StringRef::from_lit("415 Unsupported Media Type"); + return "415 Unsupported Media Type"; case 416: - return StringRef::from_lit("416 Requested Range Not Satisfiable"); + return "416 Requested Range Not Satisfiable"; case 417: - return StringRef::from_lit("417 Expectation Failed"); + return "417 Expectation Failed"; case 421: - return StringRef::from_lit("421 Misdirected Request"); + return "421 Misdirected Request"; case 426: - return StringRef::from_lit("426 Upgrade Required"); + return "426 Upgrade Required"; case 428: - return StringRef::from_lit("428 Precondition Required"); + return "428 Precondition Required"; case 429: - return StringRef::from_lit("429 Too Many Requests"); + return "429 Too Many Requests"; case 431: - return StringRef::from_lit("431 Request Header Fields Too Large"); - case 451: - return StringRef::from_lit("451 Unavailable For Legal Reasons"); + return "431 Request Header Fields Too Large"; case 500: - return StringRef::from_lit("500 Internal Server Error"); + return "500 Internal Server Error"; case 501: - return StringRef::from_lit("501 Not Implemented"); + return "501 Not Implemented"; case 502: - return StringRef::from_lit("502 Bad Gateway"); + return "502 Bad Gateway"; case 503: - return StringRef::from_lit("503 Service Unavailable"); + return "503 Service Unavailable"; case 504: - return StringRef::from_lit("504 Gateway Timeout"); + return "504 Gateway Timeout"; case 505: - return StringRef::from_lit("505 HTTP Version Not Supported"); + return "505 HTTP Version Not Supported"; case 511: - return StringRef::from_lit("511 Network Authentication Required"); + return "511 Network Authentication Required"; default: - return util::make_string_ref_uint(balloc, status_code); + return util::utos(status_code); } } -StringRef stringify_status(BlockAllocator &balloc, unsigned int status_code) { - switch (status_code) { - case 100: - return StringRef::from_lit("100"); - case 101: - return StringRef::from_lit("101"); - case 200: - return StringRef::from_lit("200"); - case 201: - return StringRef::from_lit("201"); - case 202: - return StringRef::from_lit("202"); - case 203: - return StringRef::from_lit("203"); - case 204: - return StringRef::from_lit("204"); - case 205: - return StringRef::from_lit("205"); - case 206: - return StringRef::from_lit("206"); - case 300: - return StringRef::from_lit("300"); - case 301: - return StringRef::from_lit("301"); - case 302: - return StringRef::from_lit("302"); - case 303: - return StringRef::from_lit("303"); - case 304: - return StringRef::from_lit("304"); - case 305: - return StringRef::from_lit("305"); - // case 306: return StringRef::from_lit("306"); - case 307: - return StringRef::from_lit("307"); - case 308: - return StringRef::from_lit("308"); - case 400: - return StringRef::from_lit("400"); - case 401: - return StringRef::from_lit("401"); - case 402: - return StringRef::from_lit("402"); - case 403: - return StringRef::from_lit("403"); - case 404: - return StringRef::from_lit("404"); - case 405: - return StringRef::from_lit("405"); - case 406: - return StringRef::from_lit("406"); - case 407: - return StringRef::from_lit("407"); - case 408: - return StringRef::from_lit("408"); - case 409: - return StringRef::from_lit("409"); - case 410: - return StringRef::from_lit("410"); - case 411: - return StringRef::from_lit("411"); - case 412: - return StringRef::from_lit("412"); - case 413: - return StringRef::from_lit("413"); - case 414: - return StringRef::from_lit("414"); - case 415: - return StringRef::from_lit("415"); - case 416: - return StringRef::from_lit("416"); - case 417: - return StringRef::from_lit("417"); - case 421: - return StringRef::from_lit("421"); - case 426: - return StringRef::from_lit("426"); - case 428: - return StringRef::from_lit("428"); - case 429: - return StringRef::from_lit("429"); - case 431: - return StringRef::from_lit("431"); - case 451: - return StringRef::from_lit("451"); - case 500: - return StringRef::from_lit("500"); - case 501: - return StringRef::from_lit("501"); - case 502: - return StringRef::from_lit("502"); - case 503: - return StringRef::from_lit("503"); - case 504: - return StringRef::from_lit("504"); - case 505: - return StringRef::from_lit("505"); - case 511: - return StringRef::from_lit("511"); - default: - return util::make_string_ref_uint(balloc, status_code); - } -} - -void capitalize(DefaultMemchunks *buf, const StringRef &s) { - buf->append(util::upcase(s[0])); - for (size_t i = 1; i < s.size(); ++i) { +void capitalize(std::string &s, size_t offset) { + s[offset] = util::upcase(s[offset]); + for (size_t i = offset + 1, eoi = s.size(); i < eoi; ++i) { if (s[i - 1] == '-') { - buf->append(util::upcase(s[i])); + s[i] = util::upcase(s[i]); } else { - buf->append(s[i]); + s[i] = util::lowcase(s[i]); } } } @@ -262,6 +156,17 @@ return true; } +void sanitize_header_value(std::string &s, size_t offset) { + // Since both nghttp2 and spdylay do not allow \n and \r in header + // values, we don't have to do this anymore. + + // for(size_t i = offset, eoi = s.size(); i < eoi; ++i) { + // if(s[i] == '\r' || s[i] == '\n') { + // s[i] = ' '; + // } + // } +} + void copy_url_component(std::string &dest, const http_parser_url *u, int field, const char *url) { if (u->field_set & (1 << field)) { @@ -269,158 +174,257 @@ } } -Headers::value_type to_header(const uint8_t *name, size_t namelen, - const uint8_t *value, size_t valuelen, - bool no_index, int32_t token) { - return Header(std::string(reinterpret_cast(name), namelen), - std::string(reinterpret_cast(value), valuelen), - no_index, token); +bool check_http2_allowed_header(const char *name) { + return check_http2_allowed_header(reinterpret_cast(name), + strlen(name)); } -void add_header(Headers &nva, const uint8_t *name, size_t namelen, - const uint8_t *value, size_t valuelen, bool no_index, - int32_t token) { - if (valuelen > 0) { - size_t i, j; - for (i = 0; i < valuelen && (value[i] == ' ' || value[i] == '\t'); ++i) - ; - for (j = valuelen - 1; j > i && (value[j] == ' ' || value[j] == '\t'); --j) - ; - value += i; - valuelen -= i + (valuelen - j - 1); +bool check_http2_allowed_header(const uint8_t *name, size_t namelen) { + return !util::strieq("connection", name, namelen) && + !util::strieq("host", name, namelen) && + !util::strieq("keep-alive", name, namelen) && + !util::strieq("proxy-connection", name, namelen) && + !util::strieq("te", name, namelen) && + !util::strieq("transfer-encoding", name, namelen) && + !util::strieq("upgrade", name, namelen); +} + +namespace { +const char *DISALLOWED_HD[] = { + "connection", "keep-alive", "proxy-connection", + "te", "transfer-encoding", "upgrade", +}; +} // namespace + +namespace { +auto DISALLOWED_HDLEN = util::array_size(DISALLOWED_HD); +} // namespace + +namespace { +const char *REQUEST_PSEUDO_HD[] = { + ":authority", ":method", ":path", ":scheme", +}; +} // namespace + +namespace { +auto REQUEST_PSEUDO_HDLEN = util::array_size(REQUEST_PSEUDO_HD); +} // namespace + +namespace { +const char *RESPONSE_PSEUDO_HD[] = { + ":status", +}; +} // namespace + +namespace { +auto RESPONSE_PSEUDO_HDLEN = util::array_size(RESPONSE_PSEUDO_HD); +} // namespace + +namespace { +const char *IGN_HD[] = { + "connection", "http2-settings", "keep-alive", "proxy-connection", + "server", "te", "transfer-encoding", "upgrade", + "via", "x-forwarded-for", "x-forwarded-proto", +}; +} // namespace + +namespace { +auto IGN_HDLEN = util::array_size(IGN_HD); +} // namespace + +namespace { +const char *HTTP1_IGN_HD[] = { + "connection", "cookie", "http2-settings", "keep-alive", + "proxy-connection", "server", "upgrade", "via", + "x-forwarded-for", "x-forwarded-proto", +}; +} // namespace + +namespace { +auto HTTP1_IGN_HDLEN = util::array_size(HTTP1_IGN_HD); +} // namespace + +bool name_less(const Headers::value_type &lhs, const Headers::value_type &rhs) { + if (lhs.name.c_str()[0] == ':') { + if (rhs.name.c_str()[0] != ':') { + return true; + } + } else if (rhs.name.c_str()[0] == ':') { + return false; } - nva.push_back(to_header(name, namelen, value, valuelen, no_index, token)); + + return lhs.name < rhs.name; } -const Headers::value_type *get_header(const Headers &nva, const char *name) { - const Headers::value_type *res = nullptr; - for (auto &nv : nva) { - if (nv.name == name) { - res = &nv; +bool check_http2_headers(const Headers &nva) { + for (size_t i = 0; i < DISALLOWED_HDLEN; ++i) { + if (std::binary_search(std::begin(nva), std::end(nva), + Header(DISALLOWED_HD[i], ""), name_less)) { + return false; } } - return res; + return true; } -bool non_empty_value(const HeaderRefs::value_type *nv) { - return nv && !nv->value.empty(); +bool check_http2_request_headers(const Headers &nva) { + return check_http2_headers(nva); } -namespace { -nghttp2_nv make_nv_internal(const std::string &name, const std::string &value, - bool no_index, uint8_t nv_flags) { - uint8_t flags; +bool check_http2_response_headers(const Headers &nva) { + return check_http2_headers(nva); +} - flags = - nv_flags | (no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE); +namespace { +template +bool check_pseudo_header(const uint8_t *name, size_t namelen, + InputIterator allowed_first, + InputIterator allowed_last) { + for (auto i = allowed_first; i != allowed_last; ++i) { + if (util::streq(*i, name, namelen)) { + return true; + } + } - return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(), - value.size(), flags}; + return false; } } // namespace -namespace { -nghttp2_nv make_nv_internal(const StringRef &name, const StringRef &value, - bool no_index, uint8_t nv_flags) { - uint8_t flags; +bool check_http2_request_pseudo_header(const uint8_t *name, size_t namelen) { + return check_pseudo_header(name, namelen, REQUEST_PSEUDO_HD, + REQUEST_PSEUDO_HD + REQUEST_PSEUDO_HDLEN); +} - flags = - nv_flags | (no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE); +bool check_http2_response_pseudo_header(const uint8_t *name, size_t namelen) { + return check_pseudo_header(name, namelen, RESPONSE_PSEUDO_HD, + RESPONSE_PSEUDO_HD + RESPONSE_PSEUDO_HDLEN); +} - return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(), - value.size(), flags}; +void normalize_headers(Headers &nva) { + for (auto &kv : nva) { + util::inp_strlower(kv.name); + } + std::stable_sort(std::begin(nva), std::end(nva), name_less); } -} // namespace -nghttp2_nv make_nv(const std::string &name, const std::string &value, - bool no_index) { - return make_nv_internal(name, value, no_index, NGHTTP2_NV_FLAG_NONE); +Headers::value_type to_header(const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, + bool no_index) { + return Header(std::string(reinterpret_cast(name), namelen), + std::string(reinterpret_cast(value), valuelen), + no_index); } -nghttp2_nv make_nv(const StringRef &name, const StringRef &value, - bool no_index) { - return make_nv_internal(name, value, no_index, NGHTTP2_NV_FLAG_NONE); +void add_header(Headers &nva, const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, bool no_index) { + nva.push_back(to_header(name, namelen, value, valuelen, no_index)); } -nghttp2_nv make_nv_nocopy(const std::string &name, const std::string &value, - bool no_index) { - return make_nv_internal(name, value, no_index, - NGHTTP2_NV_FLAG_NO_COPY_NAME | - NGHTTP2_NV_FLAG_NO_COPY_VALUE); +const Headers::value_type *get_unique_header(const Headers &nva, + const char *name) { + auto nv = Headers::value_type(name, ""); + auto i = std::lower_bound(std::begin(nva), std::end(nva), nv, name_less); + if (i != std::end(nva) && (*i).name == nv.name) { + auto j = i + 1; + if (j == std::end(nva) || (*j).name != nv.name) { + return &(*i); + } + } + return nullptr; } -nghttp2_nv make_nv_nocopy(const StringRef &name, const StringRef &value, - bool no_index) { - return make_nv_internal(name, value, no_index, - NGHTTP2_NV_FLAG_NO_COPY_NAME | - NGHTTP2_NV_FLAG_NO_COPY_VALUE); +const Headers::value_type *get_header(const Headers &nva, const char *name) { + auto nv = Headers::value_type(name, ""); + auto i = std::lower_bound(std::begin(nva), std::end(nva), nv, name_less); + if (i != std::end(nva) && (*i).name == nv.name) { + return &(*i); + } + return nullptr; } -namespace { -void copy_headers_to_nva_internal(std::vector &nva, - const HeaderRefs &headers, uint8_t nv_flags) { - for (auto &kv : headers) { - if (kv.name.empty() || kv.name[0] == ':') { - continue; - } - switch (kv.token) { - case HD_COOKIE: - case HD_CONNECTION: - case HD_FORWARDED: - case HD_HOST: - case HD_HTTP2_SETTINGS: - case HD_KEEP_ALIVE: - case HD_PROXY_CONNECTION: - case HD_SERVER: - case HD_TE: - case HD_TRANSFER_ENCODING: - case HD_UPGRADE: - case HD_VIA: - case HD_X_FORWARDED_FOR: - case HD_X_FORWARDED_PROTO: - continue; - } - nva.push_back(make_nv_internal(kv.name, kv.value, kv.no_index, nv_flags)); +std::string value_to_str(const Headers::value_type *nv) { + if (nv) { + return nv->value; } + return ""; } -} // namespace -void copy_headers_to_nva(std::vector &nva, - const HeaderRefs &headers) { - copy_headers_to_nva_internal(nva, headers, NGHTTP2_NV_FLAG_NONE); +bool value_lws(const Headers::value_type *nv) { + return (*nv).value.find_first_not_of("\t ") == std::string::npos; } -void copy_headers_to_nva_nocopy(std::vector &nva, - const HeaderRefs &headers) { - copy_headers_to_nva_internal(nva, headers, NGHTTP2_NV_FLAG_NO_COPY_NAME | - NGHTTP2_NV_FLAG_NO_COPY_VALUE); +bool non_empty_value(const Headers::value_type *nv) { + return nv && !value_lws(nv); } -void build_http1_headers_from_headers(DefaultMemchunks *buf, - const HeaderRefs &headers) { - for (auto &kv : headers) { - if (kv.name.empty() || kv.name[0] == ':') { - continue; +nghttp2_nv make_nv(const std::string &name, const std::string &value, + bool no_index) { + uint8_t flags; + + flags = no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE; + + return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(), + value.size(), flags}; +} + +void copy_norm_headers_to_nva(std::vector &nva, + const Headers &headers) { + size_t i, j; + for (i = 0, j = 0; i < headers.size() && j < IGN_HDLEN;) { + auto &kv = headers[i]; + int rv = strcmp(kv.name.c_str(), IGN_HD[j]); + if (rv < 0) { + if (!kv.name.empty() && kv.name.c_str()[0] != ':') { + nva.push_back(make_nv(kv.name, kv.value, kv.no_index)); + } + ++i; + } else if (rv > 0) { + ++j; + } else { + ++i; } - switch (kv.token) { - case HD_CONNECTION: - case HD_COOKIE: - case HD_FORWARDED: - case HD_HOST: - case HD_HTTP2_SETTINGS: - case HD_KEEP_ALIVE: - case HD_PROXY_CONNECTION: - case HD_SERVER: - case HD_UPGRADE: - case HD_VIA: - case HD_X_FORWARDED_FOR: - case HD_X_FORWARDED_PROTO: - continue; + } + for (; i < headers.size(); ++i) { + auto &kv = headers[i]; + if (!kv.name.empty() && kv.name.c_str()[0] != ':') { + nva.push_back(make_nv(kv.name, kv.value, kv.no_index)); + } + } +} + +void build_http1_headers_from_norm_headers(std::string &hdrs, + const Headers &headers) { + size_t i, j; + for (i = 0, j = 0; i < headers.size() && j < HTTP1_IGN_HDLEN;) { + auto &kv = headers[i]; + auto rv = strcmp(kv.name.c_str(), HTTP1_IGN_HD[j]); + + if (rv < 0) { + if (!kv.name.empty() && kv.name.c_str()[0] != ':') { + hdrs += kv.name; + capitalize(hdrs, hdrs.size() - kv.name.size()); + hdrs += ": "; + hdrs += kv.value; + sanitize_header_value(hdrs, hdrs.size() - kv.value.size()); + hdrs += "\r\n"; + } + ++i; + } else if (rv > 0) { + ++j; + } else { + ++i; + } + } + for (; i < headers.size(); ++i) { + auto &kv = headers[i]; + + if (!kv.name.empty() && kv.name.c_str()[0] != ':') { + hdrs += kv.name; + capitalize(hdrs, hdrs.size() - kv.name.size()); + hdrs += ": "; + hdrs += kv.value; + sanitize_header_value(hdrs, hdrs.size() - kv.value.size()); + hdrs += "\r\n"; } - capitalize(buf, kv.name); - buf->append(": "); - buf->append(kv.value); - buf->append("\r\n"); } } @@ -446,100 +450,89 @@ void dump_nv(FILE *out, const char **nv) { for (size_t i = 0; nv[i]; i += 2) { - fprintf(out, "%s: %s\n", nv[i], nv[i + 1]); + fwrite(nv[i], strlen(nv[i]), 1, out); + fwrite(": ", 2, 1, out); + fwrite(nv[i + 1], strlen(nv[i + 1]), 1, out); + fwrite("\n", 1, 1, out); } - fputc('\n', out); + fwrite("\n", 1, 1, out); fflush(out); } void dump_nv(FILE *out, const nghttp2_nv *nva, size_t nvlen) { auto end = nva + nvlen; for (; nva != end; ++nva) { - fprintf(out, "%s: %s\n", nva->name, nva->value); + fwrite(nva->name, nva->namelen, 1, out); + fwrite(": ", 2, 1, out); + fwrite(nva->value, nva->valuelen, 1, out); + fwrite("\n", 1, 1, out); } - fputc('\n', out); + fwrite("\n", 1, 1, out); fflush(out); } void dump_nv(FILE *out, const Headers &nva) { for (auto &nv : nva) { - fprintf(out, "%s: %s\n", nv.name.c_str(), nv.value.c_str()); + fwrite(nv.name.c_str(), nv.name.size(), 1, out); + fwrite(": ", 2, 1, out); + fwrite(nv.value.c_str(), nv.value.size(), 1, out); + fwrite("\n", 1, 1, out); } - fputc('\n', out); + fwrite("\n", 1, 1, out); fflush(out); } -void dump_nv(FILE *out, const HeaderRefs &nva) { - for (auto &nv : nva) { - fprintf(out, "%s: %s\n", nv.name.c_str(), nv.value.c_str()); +std::string rewrite_location_uri(const std::string &uri, + const http_parser_url &u, + const std::string &request_host, + const std::string &upstream_scheme, + uint16_t upstream_port) { + // We just rewrite host and optionally port. We don't rewrite https + // link. Not sure it happens in practice. + if (u.field_set & (1 << UF_SCHEMA)) { + auto field = &u.field_data[UF_SCHEMA]; + if (!util::streq("http", &uri[field->off], field->len)) { + return ""; + } } - fputc('\n', out); - fflush(out); -} - -StringRef rewrite_location_uri(BlockAllocator &balloc, const StringRef &uri, - const http_parser_url &u, - const StringRef &match_host, - const StringRef &request_authority, - const StringRef &upstream_scheme) { - // We just rewrite scheme and authority. if ((u.field_set & (1 << UF_HOST)) == 0) { - return StringRef{}; + return ""; } auto field = &u.field_data[UF_HOST]; - if (!util::starts_with(std::begin(match_host), std::end(match_host), - &uri[field->off], &uri[field->off] + field->len) || - (match_host.size() != field->len && match_host[field->len] != ':')) { - return StringRef{}; - } - - auto len = 0; - if (!request_authority.empty()) { - len += upstream_scheme.size() + str_size("://") + request_authority.size(); - } - - if (u.field_set & (1 << UF_PATH)) { - field = &u.field_data[UF_PATH]; - len += field->len; - } - - if (u.field_set & (1 << UF_QUERY)) { - field = &u.field_data[UF_QUERY]; - len += 1 + field->len; - } - - if (u.field_set & (1 << UF_FRAGMENT)) { - field = &u.field_data[UF_FRAGMENT]; - len += 1 + field->len; - } - - auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; - - if (!request_authority.empty()) { - p = std::copy(std::begin(upstream_scheme), std::end(upstream_scheme), p); - p = util::copy_lit(p, "://"); - p = std::copy(std::begin(request_authority), std::end(request_authority), - p); + if (!util::startsWith(std::begin(request_host), std::end(request_host), + &uri[field->off], &uri[field->off] + field->len) || + (request_host.size() != field->len && request_host[field->len] != ':')) { + return ""; + } + std::string res = upstream_scheme; + res += "://"; + res.append(&uri[field->off], field->len); + if (upstream_scheme == "http") { + if (upstream_port != 80) { + res += ":"; + res += util::utos(upstream_port); + } + } else if (upstream_scheme == "https") { + if (upstream_port != 443) { + res += ":"; + res += util::utos(upstream_port); + } } if (u.field_set & (1 << UF_PATH)) { field = &u.field_data[UF_PATH]; - p = std::copy_n(&uri[field->off], field->len, p); + res.append(&uri[field->off], field->len); } if (u.field_set & (1 << UF_QUERY)) { field = &u.field_data[UF_QUERY]; - *p++ = '?'; - p = std::copy_n(&uri[field->off], field->len, p); + res += "?"; + res.append(&uri[field->off], field->len); } if (u.field_set & (1 << UF_FRAGMENT)) { field = &u.field_data[UF_FRAGMENT]; - *p++ = '#'; - p = std::copy_n(&uri[field->off], field->len, p); + res += "#"; + res.append(&uri[field->off], field->len); } - - *p = '\0'; - - return StringRef{iov.base, p}; + return res; } int check_nv(const uint8_t *name, size_t namelen, const uint8_t *value, @@ -553,7 +546,7 @@ return 1; } -int parse_http_status_code(const StringRef &src) { +int parse_http_status_code(const std::string &src) { if (src.size() != 3) { return -1; } @@ -574,1097 +567,6 @@ return status; } -int lookup_token(const StringRef &name) { - return lookup_token(name.byte(), name.size()); -} - -// This function was generated by genheaderfunc.py. Inspired by h2o -// header lookup. https://github.com/h2o/h2o -int lookup_token(const uint8_t *name, size_t namelen) { - switch (namelen) { - case 2: - switch (name[1]) { - case 'e': - if (util::streq_l("t", name, 1)) { - return HD_TE; - } - break; - } - break; - case 3: - switch (name[2]) { - case 'a': - if (util::streq_l("vi", name, 2)) { - return HD_VIA; - } - break; - } - break; - case 4: - switch (name[3]) { - case 'e': - if (util::streq_l("dat", name, 3)) { - return HD_DATE; - } - break; - case 'k': - if (util::streq_l("lin", name, 3)) { - return HD_LINK; - } - break; - case 't': - if (util::streq_l("hos", name, 3)) { - return HD_HOST; - } - break; - } - break; - case 5: - switch (name[4]) { - case 'h': - if (util::streq_l(":pat", name, 4)) { - return HD__PATH; - } - break; - case 't': - if (util::streq_l(":hos", name, 4)) { - return HD__HOST; - } - break; - } - break; - case 6: - switch (name[5]) { - case 'e': - if (util::streq_l("cooki", name, 5)) { - return HD_COOKIE; - } - break; - case 'r': - if (util::streq_l("serve", name, 5)) { - return HD_SERVER; - } - break; - case 't': - if (util::streq_l("expec", name, 5)) { - return HD_EXPECT; - } - break; - } - break; - case 7: - switch (name[6]) { - case 'c': - if (util::streq_l("alt-sv", name, 6)) { - return HD_ALT_SVC; - } - break; - case 'd': - if (util::streq_l(":metho", name, 6)) { - return HD__METHOD; - } - break; - case 'e': - if (util::streq_l(":schem", name, 6)) { - return HD__SCHEME; - } - if (util::streq_l("upgrad", name, 6)) { - return HD_UPGRADE; - } - break; - case 'r': - if (util::streq_l("traile", name, 6)) { - return HD_TRAILER; - } - break; - case 's': - if (util::streq_l(":statu", name, 6)) { - return HD__STATUS; - } - break; - } - break; - case 8: - switch (name[7]) { - case 'n': - if (util::streq_l("locatio", name, 7)) { - return HD_LOCATION; - } - break; - } - break; - case 9: - switch (name[8]) { - case 'd': - if (util::streq_l("forwarde", name, 8)) { - return HD_FORWARDED; - } - break; - } - break; - case 10: - switch (name[9]) { - case 'e': - if (util::streq_l("keep-aliv", name, 9)) { - return HD_KEEP_ALIVE; - } - break; - case 'n': - if (util::streq_l("connectio", name, 9)) { - return HD_CONNECTION; - } - break; - case 't': - if (util::streq_l("user-agen", name, 9)) { - return HD_USER_AGENT; - } - break; - case 'y': - if (util::streq_l(":authorit", name, 9)) { - return HD__AUTHORITY; - } - break; - } - break; - case 12: - switch (name[11]) { - case 'e': - if (util::streq_l("content-typ", name, 11)) { - return HD_CONTENT_TYPE; - } - break; - } - break; - case 13: - switch (name[12]) { - case 'l': - if (util::streq_l("cache-contro", name, 12)) { - return HD_CACHE_CONTROL; - } - break; - } - break; - case 14: - switch (name[13]) { - case 'h': - if (util::streq_l("content-lengt", name, 13)) { - return HD_CONTENT_LENGTH; - } - break; - case 's': - if (util::streq_l("http2-setting", name, 13)) { - return HD_HTTP2_SETTINGS; - } - break; - } - break; - case 15: - switch (name[14]) { - case 'e': - if (util::streq_l("accept-languag", name, 14)) { - return HD_ACCEPT_LANGUAGE; - } - break; - case 'g': - if (util::streq_l("accept-encodin", name, 14)) { - return HD_ACCEPT_ENCODING; - } - break; - case 'r': - if (util::streq_l("x-forwarded-fo", name, 14)) { - return HD_X_FORWARDED_FOR; - } - break; - } - break; - case 16: - switch (name[15]) { - case 'n': - if (util::streq_l("proxy-connectio", name, 15)) { - return HD_PROXY_CONNECTION; - } - break; - } - break; - case 17: - switch (name[16]) { - case 'e': - if (util::streq_l("if-modified-sinc", name, 16)) { - return HD_IF_MODIFIED_SINCE; - } - break; - case 'g': - if (util::streq_l("transfer-encodin", name, 16)) { - return HD_TRANSFER_ENCODING; - } - break; - case 'o': - if (util::streq_l("x-forwarded-prot", name, 16)) { - return HD_X_FORWARDED_PROTO; - } - break; - } - break; - } - return -1; -} - -void init_hdidx(HeaderIndex &hdidx) { - std::fill(std::begin(hdidx), std::end(hdidx), -1); -} - -void index_header(HeaderIndex &hdidx, int32_t token, size_t idx) { - if (token == -1) { - return; - } - assert(token < HD_MAXIDX); - hdidx[token] = idx; -} - -const Headers::value_type *get_header(const HeaderIndex &hdidx, int32_t token, - const Headers &nva) { - auto i = hdidx[token]; - if (i == -1) { - return nullptr; - } - return &nva[i]; -} - -Headers::value_type *get_header(const HeaderIndex &hdidx, int32_t token, - Headers &nva) { - auto i = hdidx[token]; - if (i == -1) { - return nullptr; - } - return &nva[i]; -} - -namespace { -template InputIt skip_lws(InputIt first, InputIt last) { - for (; first != last; ++first) { - switch (*first) { - case ' ': - case '\t': - continue; - default: - return first; - } - } - return first; -} -} // namespace - -namespace { -template -InputIt skip_to_next_field(InputIt first, InputIt last) { - for (; first != last; ++first) { - switch (*first) { - case ' ': - case '\t': - case ',': - continue; - default: - return first; - } - } - return first; -} -} // namespace - -namespace { -// Skip to the right dquote ('"'), handling backslash escapes. -// Returns |last| if input is not terminated with '"'. -template -InputIt skip_to_right_dquote(InputIt first, InputIt last) { - for (; first != last;) { - switch (*first) { - case '"': - return first; - case '\\': - ++first; - if (first == last) { - return first; - } - break; - } - ++first; - } - return first; -} -} // namespace - -namespace { -// Returns true if link-param does not match pattern |pat| of length -// |patlen| or it has empty value (""). |pat| should be parmname -// followed by "=". -bool check_link_param_empty(const char *first, const char *last, - const char *pat, size_t patlen) { - if (first + patlen <= last) { - if (std::equal(pat, pat + patlen, first, util::CaseCmp())) { - // we only accept URI if pat is followd by "" (e.g., - // loadpolicy="") here. - if (first + patlen + 2 <= last) { - if (*(first + patlen) != '"' || *(first + patlen + 1) != '"') { - return false; - } - } else { - // here we got invalid production (anchor=") or anchor=? - return false; - } - } - } - return true; -} -} // namespace - -namespace { -// Returns true if link-param consists of only parmname, and it -// matches string [pat, pat + patlen). -bool check_link_param_without_value(const char *first, const char *last, - const char *pat, size_t patlen) { - if (first + patlen > last) { - return false; - } - - if (first + patlen == last) { - return std::equal(pat, pat + patlen, first, util::CaseCmp()); - } - - switch (*(first + patlen)) { - case ';': - case ',': - return std::equal(pat, pat + patlen, first, util::CaseCmp()); - } - - return false; -} -} // namespace - -namespace { -std::pair -parse_next_link_header_once(const char *first, const char *last) { - first = skip_to_next_field(first, last); - if (first == last || *first != '<') { - return {{StringRef{}}, last}; - } - auto url_first = ++first; - first = std::find(first, last, '>'); - if (first == last) { - return {{StringRef{}}, first}; - } - auto url_last = first++; - if (first == last) { - return {{StringRef{}}, first}; - } - // we expect ';' or ',' here - switch (*first) { - case ',': - return {{StringRef{}}, ++first}; - case ';': - ++first; - break; - default: - return {{StringRef{}}, last}; - } - - auto ok = false; - auto ign = false; - for (;;) { - first = skip_lws(first, last); - if (first == last) { - return {{StringRef{}}, first}; - } - // we expect link-param - - if (!ign) { - if (!ok) { - // rel can take several relations using quoted form. - static constexpr char PLP[] = "rel=\""; - static constexpr size_t PLPLEN = str_size(PLP); - - static constexpr char PLT[] = "preload"; - static constexpr size_t PLTLEN = str_size(PLT); - if (first + PLPLEN < last && *(first + PLPLEN - 1) == '"' && - std::equal(PLP, PLP + PLPLEN, first, util::CaseCmp())) { - // we have to search preload in whitespace separated list: - // rel="preload something http://example.org/foo" - first += PLPLEN; - auto start = first; - for (; first != last;) { - if (*first != ' ' && *first != '"') { - ++first; - continue; - } - - if (start == first) { - return {{StringRef{}}, last}; - } - - if (!ok && start + PLTLEN == first && - std::equal(PLT, PLT + PLTLEN, start, util::CaseCmp())) { - ok = true; - } - - if (*first == '"') { - break; - } - first = skip_lws(first, last); - start = first; - } - if (first == last) { - return {{StringRef{}}, last}; - } - assert(*first == '"'); - ++first; - if (first == last || *first == ',') { - goto almost_done; - } - if (*first == ';') { - ++first; - // parse next link-param - continue; - } - return {{StringRef{}}, last}; - } - } - // we are only interested in rel=preload parameter. Others are - // simply skipped. - static constexpr char PL[] = "rel=preload"; - static constexpr size_t PLLEN = str_size(PL); - if (first + PLLEN == last) { - if (std::equal(PL, PL + PLLEN, first, util::CaseCmp())) { - // ok = true; - // this is the end of sequence - return {{{url_first, url_last}}, last}; - } - } else if (first + PLLEN + 1 <= last) { - switch (*(first + PLLEN)) { - case ',': - if (!std::equal(PL, PL + PLLEN, first, util::CaseCmp())) { - break; - } - // ok = true; - // skip including ',' - first += PLLEN + 1; - return {{{url_first, url_last}}, first}; - case ';': - if (!std::equal(PL, PL + PLLEN, first, util::CaseCmp())) { - break; - } - ok = true; - // skip including ';' - first += PLLEN + 1; - // continue parse next link-param - continue; - } - } - // we have to reject URI if we have nonempty anchor parameter. - static constexpr char ANCHOR[] = "anchor="; - static constexpr size_t ANCHORLEN = str_size(ANCHOR); - if (!ign && !check_link_param_empty(first, last, ANCHOR, ANCHORLEN)) { - ign = true; - } - - // reject URI if we have non-empty loadpolicy. This could be - // tightened up to just pick up "next" or "insert". - static constexpr char LOADPOLICY[] = "loadpolicy="; - static constexpr size_t LOADPOLICYLEN = str_size(LOADPOLICY); - if (!ign && - !check_link_param_empty(first, last, LOADPOLICY, LOADPOLICYLEN)) { - ign = true; - } - - // reject URI if we have nopush attribute. - static constexpr char NOPUSH[] = "nopush"; - static constexpr size_t NOPUSHLEN = str_size(NOPUSH); - if (!ign && - check_link_param_without_value(first, last, NOPUSH, NOPUSHLEN)) { - ign = true; - } - } - - auto param_first = first; - for (; first != last;) { - if (util::in_attr_char(*first)) { - ++first; - continue; - } - // '*' is only allowed at the end of parameter name and must be - // followed by '=' - if (last - first >= 2 && first != param_first) { - if (*first == '*' && *(first + 1) == '=') { - ++first; - break; - } - } - if (*first == '=' || *first == ';' || *first == ',') { - break; - } - return {{StringRef{}}, last}; - } - if (param_first == first) { - // empty parmname - return {{StringRef{}}, last}; - } - // link-param without value is acceptable (see link-extension) if - // it is not followed by '=' - if (first == last || *first == ',') { - goto almost_done; - } - if (*first == ';') { - ++first; - // parse next link-param - continue; - } - // now parsing link-param value - assert(*first == '='); - ++first; - if (first == last) { - // empty value is not acceptable - return {{StringRef{}}, first}; - } - if (*first == '"') { - // quoted-string - first = skip_to_right_dquote(first + 1, last); - if (first == last) { - return {{StringRef{}}, first}; - } - ++first; - if (first == last || *first == ',') { - goto almost_done; - } - if (*first == ';') { - ++first; - // parse next link-param - continue; - } - return {{StringRef{}}, last}; - } - // not quoted-string, skip to next ',' or ';' - if (*first == ',' || *first == ';') { - // empty value - return {{StringRef{}}, last}; - } - for (; first != last; ++first) { - if (*first == ',' || *first == ';') { - break; - } - } - if (first == last || *first == ',') { - goto almost_done; - } - assert(*first == ';'); - ++first; - // parse next link-param - } - -almost_done: - assert(first == last || *first == ','); - - if (first != last) { - ++first; - } - if (ok && !ign) { - return {{{url_first, url_last}}, first}; - } - return {{StringRef{}}, first}; -} -} // namespace - -std::vector parse_link_header(const StringRef &src) { - std::vector res; - for (auto first = std::begin(src); first != std::end(src);) { - auto rv = parse_next_link_header_once(first, std::end(src)); - first = rv.second; - auto &link = rv.first; - if (!link.uri.empty()) { - res.push_back(link); - } - } - return res; -} - -std::string path_join(const StringRef &base_path, const StringRef &base_query, - const StringRef &rel_path, const StringRef &rel_query) { - BlockAllocator balloc(1024, 1024); - - return path_join(balloc, base_path, base_query, rel_path, rel_query).str(); -} - -bool expect_response_body(int status_code) { - return status_code / 100 != 1 && status_code != 304 && status_code != 204; -} - -bool expect_response_body(const std::string &method, int status_code) { - return method != "HEAD" && expect_response_body(status_code); -} - -bool expect_response_body(int method_token, int status_code) { - return method_token != HTTP_HEAD && expect_response_body(status_code); -} - -int lookup_method_token(const StringRef &name) { - return lookup_method_token(name.byte(), name.size()); -} - -// This function was generated by genmethodfunc.py. -int lookup_method_token(const uint8_t *name, size_t namelen) { - switch (namelen) { - case 3: - switch (name[2]) { - case 'T': - if (util::streq_l("GE", name, 2)) { - return HTTP_GET; - } - if (util::streq_l("PU", name, 2)) { - return HTTP_PUT; - } - break; - } - break; - case 4: - switch (name[3]) { - case 'D': - if (util::streq_l("HEA", name, 3)) { - return HTTP_HEAD; - } - break; - case 'E': - if (util::streq_l("MOV", name, 3)) { - return HTTP_MOVE; - } - break; - case 'K': - if (util::streq_l("LOC", name, 3)) { - return HTTP_LOCK; - } - break; - case 'T': - if (util::streq_l("POS", name, 3)) { - return HTTP_POST; - } - break; - case 'Y': - if (util::streq_l("COP", name, 3)) { - return HTTP_COPY; - } - break; - } - break; - case 5: - switch (name[4]) { - case 'E': - if (util::streq_l("MERG", name, 4)) { - return HTTP_MERGE; - } - if (util::streq_l("PURG", name, 4)) { - return HTTP_PURGE; - } - if (util::streq_l("TRAC", name, 4)) { - return HTTP_TRACE; - } - break; - case 'H': - if (util::streq_l("PATC", name, 4)) { - return HTTP_PATCH; - } - break; - case 'L': - if (util::streq_l("MKCO", name, 4)) { - return HTTP_MKCOL; - } - break; - } - break; - case 6: - switch (name[5]) { - case 'E': - if (util::streq_l("DELET", name, 5)) { - return HTTP_DELETE; - } - break; - case 'H': - if (util::streq_l("SEARC", name, 5)) { - return HTTP_SEARCH; - } - break; - case 'K': - if (util::streq_l("UNLOC", name, 5)) { - return HTTP_UNLOCK; - } - break; - case 'T': - if (util::streq_l("REPOR", name, 5)) { - return HTTP_REPORT; - } - break; - case 'Y': - if (util::streq_l("NOTIF", name, 5)) { - return HTTP_NOTIFY; - } - break; - } - break; - case 7: - switch (name[6]) { - case 'H': - if (util::streq_l("MSEARC", name, 6)) { - return HTTP_MSEARCH; - } - break; - case 'S': - if (util::streq_l("OPTION", name, 6)) { - return HTTP_OPTIONS; - } - break; - case 'T': - if (util::streq_l("CONNEC", name, 6)) { - return HTTP_CONNECT; - } - break; - } - break; - case 8: - switch (name[7]) { - case 'D': - if (util::streq_l("PROPFIN", name, 7)) { - return HTTP_PROPFIND; - } - break; - case 'T': - if (util::streq_l("CHECKOU", name, 7)) { - return HTTP_CHECKOUT; - } - break; - } - break; - case 9: - switch (name[8]) { - case 'E': - if (util::streq_l("SUBSCRIB", name, 8)) { - return HTTP_SUBSCRIBE; - } - break; - case 'H': - if (util::streq_l("PROPPATC", name, 8)) { - return HTTP_PROPPATCH; - } - break; - } - break; - case 10: - switch (name[9]) { - case 'R': - if (util::streq_l("MKCALENDA", name, 9)) { - return HTTP_MKCALENDAR; - } - break; - case 'Y': - if (util::streq_l("MKACTIVIT", name, 9)) { - return HTTP_MKACTIVITY; - } - break; - } - break; - case 11: - switch (name[10]) { - case 'E': - if (util::streq_l("UNSUBSCRIB", name, 10)) { - return HTTP_UNSUBSCRIBE; - } - break; - } - break; - } - return -1; -} - -StringRef to_method_string(int method_token) { - // we happened to use same value for method with http-parser. - return StringRef{http_method_str(static_cast(method_token))}; -} - -StringRef get_pure_path_component(const StringRef &uri) { - int rv; - - http_parser_url u{}; - rv = http_parser_parse_url(uri.c_str(), uri.size(), 0, &u); - if (rv != 0) { - return StringRef{}; - } - - if (u.field_set & (1 << UF_PATH)) { - auto &f = u.field_data[UF_PATH]; - return StringRef{uri.c_str() + f.off, f.len}; - } - - return StringRef::from_lit("/"); -} - -int construct_push_component(BlockAllocator &balloc, StringRef &scheme, - StringRef &authority, StringRef &path, - const StringRef &base, const StringRef &uri) { - int rv; - StringRef rel, relq; - - http_parser_url u{}; - - rv = http_parser_parse_url(uri.c_str(), uri.size(), 0, &u); - - if (rv != 0) { - if (uri[0] == '/') { - return -1; - } - - // treat link_url as relative URI. - auto end = std::find(std::begin(uri), std::end(uri), '#'); - auto q = std::find(std::begin(uri), end, '?'); - - rel = StringRef{std::begin(uri), q}; - if (q != end) { - relq = StringRef{q + 1, std::end(uri)}; - } - } else { - if (u.field_set & (1 << UF_SCHEMA)) { - scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA); - } - - if (u.field_set & (1 << UF_HOST)) { - auto auth = util::get_uri_field(uri.c_str(), u, UF_HOST); - auto len = auth.size(); - auto port_exists = u.field_set & (1 << UF_PORT); - if (port_exists) { - len += 1 + str_size("65535"); - } - auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; - p = std::copy(std::begin(auth), std::end(auth), p); - if (port_exists) { - *p++ = ':'; - p = util::utos(p, u.port); - } - *p = '\0'; - - authority = StringRef{iov.base, p}; - } - - if (u.field_set & (1 << UF_PATH)) { - auto &f = u.field_data[UF_PATH]; - rel = StringRef{uri.c_str() + f.off, f.len}; - } else { - rel = StringRef::from_lit("/"); - } - - if (u.field_set & (1 << UF_QUERY)) { - auto &f = u.field_data[UF_QUERY]; - relq = StringRef{uri.c_str() + f.off, f.len}; - } - } - - path = http2::path_join(balloc, base, StringRef{}, rel, relq); - - return 0; -} - -namespace { -template InputIt eat_file(InputIt first, InputIt last) { - if (first == last) { - *first++ = '/'; - return first; - } - - if (*(last - 1) == '/') { - return last; - } - - auto p = last; - for (; p != first && *(p - 1) != '/'; --p) - ; - if (p == first) { - // this should not happend in normal case, where we expect path - // starts with '/' - *first++ = '/'; - return first; - } - - return p; -} -} // namespace - -namespace { -template InputIt eat_dir(InputIt first, InputIt last) { - auto p = eat_file(first, last); - - --p; - - assert(*p == '/'); - - return eat_file(first, p); -} -} // namespace - -StringRef path_join(BlockAllocator &balloc, const StringRef &base_path, - const StringRef &base_query, const StringRef &rel_path, - const StringRef &rel_query) { - auto res = make_byte_ref( - balloc, std::max(static_cast(1), base_path.size()) + - rel_path.size() + 1 + - std::max(base_query.size(), rel_query.size()) + 1); - auto p = res.base; - - if (rel_path.empty()) { - if (base_path.empty()) { - *p++ = '/'; - } else { - p = std::copy(std::begin(base_path), std::end(base_path), p); - } - if (rel_query.empty()) { - if (!base_query.empty()) { - *p++ = '?'; - p = std::copy(std::begin(base_query), std::end(base_query), p); - } - *p = '\0'; - return StringRef{res.base, p}; - } - *p++ = '?'; - p = std::copy(std::begin(rel_query), std::end(rel_query), p); - *p = '\0'; - return StringRef{res.base, p}; - } - - auto first = std::begin(rel_path); - auto last = std::end(rel_path); - - if (rel_path[0] == '/') { - *p++ = '/'; - ++first; - for (; first != last && *first == '/'; ++first) - ; - } else if (base_path.empty()) { - *p++ = '/'; - } else { - p = std::copy(std::begin(base_path), std::end(base_path), p); - } - - for (; first != last;) { - if (*first == '.') { - if (first + 1 == last) { - break; - } - if (*(first + 1) == '/') { - first += 2; - continue; - } - if (*(first + 1) == '.') { - if (first + 2 == last) { - p = eat_dir(res.base, p); - break; - } - if (*(first + 2) == '/') { - p = eat_dir(res.base, p); - first += 3; - continue; - } - } - } - if (*(p - 1) != '/') { - p = eat_file(res.base, p); - } - auto slash = std::find(first, last, '/'); - if (slash == last) { - p = std::copy(first, last, p); - break; - } - p = std::copy(first, slash + 1, p); - first = slash + 1; - for (; first != last && *first == '/'; ++first) - ; - } - if (!rel_query.empty()) { - *p++ = '?'; - p = std::copy(std::begin(rel_query), std::end(rel_query), p); - } - *p = '\0'; - return StringRef{res.base, p}; -} - -StringRef normalize_path(BlockAllocator &balloc, const StringRef &path, - const StringRef &query) { - // First, decode %XX for unreserved characters, then do - // http2::path_join - - // We won't find %XX if length is less than 3. - if (path.size() < 3 || - std::find(std::begin(path), std::end(path), '%') == std::end(path)) { - return path_join(balloc, StringRef{}, StringRef{}, path, query); - } - - // includes last terminal NULL. - auto result = make_byte_ref(balloc, path.size() + 1); - auto p = result.base; - - auto it = std::begin(path); - for (; it + 2 < std::end(path);) { - if (*it == '%') { - if (util::is_hex_digit(*(it + 1)) && util::is_hex_digit(*(it + 2))) { - auto c = - (util::hex_to_uint(*(it + 1)) << 4) + util::hex_to_uint(*(it + 2)); - if (util::in_rfc3986_unreserved_chars(c)) { - *p++ = c; - - it += 3; - - continue; - } - *p++ = '%'; - *p++ = util::upcase(*(it + 1)); - *p++ = util::upcase(*(it + 2)); - - it += 3; - - continue; - } - } - *p++ = *it++; - } - - p = std::copy(it, std::end(path), p); - *p = '\0'; - - return path_join(balloc, StringRef{}, StringRef{}, StringRef{result.base, p}, - query); -} - -std::string normalize_path(const StringRef &path, const StringRef &query) { - BlockAllocator balloc(1024, 1024); - - return normalize_path(balloc, path, query).str(); -} - -StringRef rewrite_clean_path(BlockAllocator &balloc, const StringRef &src) { - if (src.empty() || src[0] != '/') { - return src; - } - // probably, not necessary most of the case, but just in case. - auto fragment = std::find(std::begin(src), std::end(src), '#'); - auto raw_query = std::find(std::begin(src), fragment, '?'); - auto query = raw_query; - if (query != fragment) { - ++query; - } - return normalize_path(balloc, StringRef{std::begin(src), raw_query}, - StringRef{query, fragment}); -} - -StringRef copy_lower(BlockAllocator &balloc, const StringRef &src) { - auto iov = make_byte_ref(balloc, src.size() + 1); - auto p = iov.base; - p = std::copy(std::begin(src), std::end(src), p); - *p = '\0'; - util::inp_strlower(iov.base, p); - return StringRef{iov.base, p}; -} - } // namespace http2 } // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/http2.h nghttp2-0.6.7/src/http2.h --- nghttp2-1.13.0/src/http2.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/http2.h 2014-11-30 14:15:07.000000000 +0000 @@ -31,28 +31,18 @@ #include #include #include -#include #include #include "http-parser/http_parser.h" -#include "util.h" -#include "memchunk.h" -#include "template.h" -#include "allocator.h" - namespace nghttp2 { struct Header { - Header(std::string name, std::string value, bool no_index = false, - int32_t token = -1) - : name(std::move(name)), - value(std::move(value)), - token(token), - no_index(no_index) {} + Header(std::string name, std::string value, bool no_index = false) + : name(std::move(name)), value(std::move(value)), no_index(no_index) {} - Header() : token(-1), no_index(false) {} + Header() : no_index(false) {} bool operator==(const Header &other) const { return name == other.name && value == other.value; @@ -64,72 +54,88 @@ std::string name; std::string value; - int32_t token; bool no_index; }; -struct HeaderRef { - HeaderRef(const StringRef &name, const StringRef &value, - bool no_index = false, int32_t token = -1) - : name(name), value(value), token(token), no_index(no_index) {} - - HeaderRef() : token(-1), no_index(false) {} - - bool operator==(const HeaderRef &other) const { - return name == other.name && value == other.value; - } - - bool operator<(const HeaderRef &rhs) const { - return name < rhs.name || (name == rhs.name && value < rhs.value); - } - - StringRef name; - StringRef value; - int32_t token; - bool no_index; -}; - -using Headers = std::vector
; -using HeaderRefs = std::vector; +typedef std::vector
Headers; namespace http2 { -// Returns string version of |status code| followed by reason -// string. (e.g., "404 Not Found"). -StringRef get_status_string(BlockAllocator &balloc, unsigned int status_code); - -// Returns string version of |status_code|. (e.g., "404") -StringRef stringify_status(BlockAllocator &balloc, unsigned int status_code); +std::string get_status_string(unsigned int status_code); -void capitalize(DefaultMemchunks *buf, const StringRef &s); +void capitalize(std::string &s, size_t offset); // Returns true if |value| is LWS bool lws(const char *value); +void sanitize_header_value(std::string &s, size_t offset); + // Copies the |field| component value from |u| and |url| to the // |dest|. If |u| does not have |field|, then this function does // nothing. void copy_url_component(std::string &dest, const http_parser_url *u, int field, const char *url); +// Returns true if the header field |name| with length |namelen| bytes +// is valid for HTTP/2. +bool check_http2_allowed_header(const uint8_t *name, size_t namelen); + +// Calls check_http2_allowed_header with |name| and strlen(name), +// assuming |name| is null-terminated string. +bool check_http2_allowed_header(const char *name); + +// Checks that headers |nva| do not contain disallowed header fields +// in HTTP/2 spec. This function returns true if |nva| does not +// contains such headers. +bool check_http2_headers(const Headers &nva); + +// Calls check_http2_headers() +bool check_http2_request_headers(const Headers &nva); + +// Calls check_http2_headers() +bool check_http2_response_headers(const Headers &nva); + +// Returns true if |name| is allowed pusedo header for request. +bool check_http2_request_pseudo_header(const uint8_t *name, size_t namelen); + +// Returns true if |name| is allowed pusedo header for response. +bool check_http2_response_pseudo_header(const uint8_t *name, size_t namelen); + +bool name_less(const Headers::value_type &lhs, const Headers::value_type &rhs); + +void normalize_headers(Headers &nva); + Headers::value_type to_header(const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, - bool no_index, int32_t token); + bool no_index); // Add name/value pairs to |nva|. If |no_index| is true, this // name/value pair won't be indexed when it is forwarded to the next -// hop. This function strips white spaces around |value|. +// hop. void add_header(Headers &nva, const uint8_t *name, size_t namelen, - const uint8_t *value, size_t valuelen, bool no_index, - int32_t token); + const uint8_t *value, size_t valuelen, bool no_index); -// Returns pointer to the entry in |nva| which has name |name|. If -// more than one entries which have the name |name|, last occurrence -// in |nva| is returned. If no such entry exist, returns nullptr. +// Returns the iterator to the entry in |nva| which has name |name| +// and the |name| is uinque in the |nva|. If no such entry exist, +// returns nullptr. +const Headers::value_type *get_unique_header(const Headers &nva, + const char *name); + +// Returns the iterator to the entry in |nva| which has name +// |name|. If more than one entries which have the name |name|, first +// occurrence in |nva| is returned. If no such entry exist, returns +// nullptr. const Headers::value_type *get_header(const Headers &nva, const char *name); -// Returns true if the value of |nv| is not empty. -bool non_empty_value(const HeaderRefs::value_type *nv); +// Returns nv->second if nv is not nullptr. Otherwise, returns "". +std::string value_to_str(const Headers::value_type *nv); + +// Returns true if the value of |nv| includes only ' ' (0x20) or '\t'. +bool value_lws(const Headers::value_type *nv); + +// Returns true if the value of |nv| is not empty value and not LWS +// and not contain illegal characters. +bool non_empty_value(const Headers::value_type *nv); // Creates nghttp2_nv using |name| and |value| and returns it. The // returned value only references the data pointer to name.c_str() and @@ -138,73 +144,39 @@ nghttp2_nv make_nv(const std::string &name, const std::string &value, bool no_index = false); -nghttp2_nv make_nv(const StringRef &name, const StringRef &value, - bool no_index = false); - -nghttp2_nv make_nv_nocopy(const std::string &name, const std::string &value, - bool no_index = false); - -nghttp2_nv make_nv_nocopy(const StringRef &name, const StringRef &value, - bool no_index = false); - // Create nghttp2_nv from string literal |name| and |value|. template -constexpr nghttp2_nv make_nv_ll(const char(&name)[N], const char(&value)[M]) { +nghttp2_nv make_nv_ll(const char (&name)[N], const char (&value)[M]) { return {(uint8_t *)name, (uint8_t *)value, N - 1, M - 1, - NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE}; + NGHTTP2_NV_FLAG_NONE}; } // Create nghttp2_nv from string literal |name| and c-string |value|. template -nghttp2_nv make_nv_lc(const char(&name)[N], const char *value) { +nghttp2_nv make_nv_lc(const char (&name)[N], const char *value) { return {(uint8_t *)name, (uint8_t *)value, N - 1, strlen(value), - NGHTTP2_NV_FLAG_NO_COPY_NAME}; -} - -template -nghttp2_nv make_nv_lc_nocopy(const char(&name)[N], const char *value) { - return {(uint8_t *)name, (uint8_t *)value, N - 1, strlen(value), - NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE}; + NGHTTP2_NV_FLAG_NONE}; } // Create nghttp2_nv from string literal |name| and std::string // |value|. template -nghttp2_nv make_nv_ls(const char(&name)[N], const std::string &value) { +nghttp2_nv make_nv_ls(const char (&name)[N], const std::string &value) { return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), - NGHTTP2_NV_FLAG_NO_COPY_NAME}; + NGHTTP2_NV_FLAG_NONE}; } -template -nghttp2_nv make_nv_ls_nocopy(const char(&name)[N], const std::string &value) { - return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), - NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE}; -} - -template -nghttp2_nv make_nv_ls_nocopy(const char(&name)[N], const StringRef &value) { - return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), - NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE}; -} - -// Appends headers in |headers| to |nv|. |headers| must be indexed -// before this call (its element's token field is assigned). Certain -// headers, including disallowed headers in HTTP/2 spec and headers -// which require special handling (i.e. via), are not copied. -void copy_headers_to_nva(std::vector &nva, - const HeaderRefs &headers); - -// Just like copy_headers_to_nva(), but this adds -// NGHTTP2_NV_FLAG_NO_COPY_NAME and NGHTTP2_NV_FLAG_NO_COPY_VALUE. -void copy_headers_to_nva_nocopy(std::vector &nva, - const HeaderRefs &headers); - -// Appends HTTP/1.1 style header lines to |buf| from headers in -// |headers|. |headers| must be indexed before this call (its -// element's token field is assigned). Certain headers, which -// requires special handling (i.e. via and cookie), are not appended. -void build_http1_headers_from_headers(DefaultMemchunks *buf, - const HeaderRefs &headers); +// Appends headers in |headers| to |nv|. Certain headers, including +// disallowed headers in HTTP/2 spec and headers which require +// special handling (i.e. via), are not copied. +void copy_norm_headers_to_nva(std::vector &nva, + const Headers &headers); + +// Appends HTTP/1.1 style header lines to |hdrs| from headers in +// |headers|. Certain headers, which requires special handling +// (i.e. via and cookie), are not appended. +void build_http1_headers_from_norm_headers(std::string &hdrs, + const Headers &headers); // Return positive window_size_increment if WINDOW_UPDATE should be // sent for the stream |stream_id|. If |stream_id| == 0, this function @@ -225,26 +197,21 @@ // Dumps name/value pairs in |nva| to |out|. void dump_nv(FILE *out, const Headers &nva); -void dump_nv(FILE *out, const HeaderRefs &nva); - // Rewrites redirection URI which usually appears in location header // field. The |uri| is the URI in the location header field. The |u| -// stores the result of parsed |uri|. The |request_authority| is the -// host or :authority header field value in the request. The +// stores the result of parsed |uri|. The |request_host| is the host +// or :authority header field value in the request. The // |upstream_scheme| is either "https" or "http" in the upstream -// interface. Rewrite is done only if location header field value -// contains |match_host| as host excluding port. The |match_host| and -// |request_authority| could be different. If |request_authority| is -// empty, strip authority. +// interface. // // This function returns the new rewritten URI on success. If the // location URI is not subject to the rewrite, this function returns // emtpy string. -StringRef rewrite_location_uri(BlockAllocator &balloc, const StringRef &uri, - const http_parser_url &u, - const StringRef &match_host, - const StringRef &request_authority, - const StringRef &upstream_scheme); +std::string rewrite_location_uri(const std::string &uri, + const http_parser_url &u, + const std::string &request_host, + const std::string &upstream_scheme, + uint16_t upstream_port); // Checks the header name/value pair using nghttp2_check_header_name() // and nghttp2_check_header_value(). If both function returns nonzero, @@ -253,136 +220,7 @@ size_t valuelen); // Returns parsed HTTP status code. Returns -1 on failure. -int parse_http_status_code(const StringRef &src); - -// Header fields to be indexed, except HD_MAXIDX which is convenient -// member to get maximum value. -// -// generated by genheaderfunc.py -enum { - HD__AUTHORITY, - HD__HOST, - HD__METHOD, - HD__PATH, - HD__SCHEME, - HD__STATUS, - HD_ACCEPT_ENCODING, - HD_ACCEPT_LANGUAGE, - HD_ALT_SVC, - HD_CACHE_CONTROL, - HD_CONNECTION, - HD_CONTENT_LENGTH, - HD_CONTENT_TYPE, - HD_COOKIE, - HD_DATE, - HD_EXPECT, - HD_FORWARDED, - HD_HOST, - HD_HTTP2_SETTINGS, - HD_IF_MODIFIED_SINCE, - HD_KEEP_ALIVE, - HD_LINK, - HD_LOCATION, - HD_PROXY_CONNECTION, - HD_SERVER, - HD_TE, - HD_TRAILER, - HD_TRANSFER_ENCODING, - HD_UPGRADE, - HD_USER_AGENT, - HD_VIA, - HD_X_FORWARDED_FOR, - HD_X_FORWARDED_PROTO, - HD_MAXIDX, -}; - -using HeaderIndex = std::array; - -// Looks up header token for header name |name| of length |namelen|. -// Only headers we are interested in are tokenized. If header name -// cannot be tokenized, returns -1. -int lookup_token(const uint8_t *name, size_t namelen); -int lookup_token(const StringRef &name); - -// Initializes |hdidx|, header index. The |hdidx| must point to the -// array containing at least HD_MAXIDX elements. -void init_hdidx(HeaderIndex &hdidx); -// Indexes header |token| using index |idx|. -void index_header(HeaderIndex &hdidx, int32_t token, size_t idx); - -// Returns header denoted by |token| using index |hdidx|. -const Headers::value_type *get_header(const HeaderIndex &hdidx, int32_t token, - const Headers &nva); - -Headers::value_type *get_header(const HeaderIndex &hdidx, int32_t token, - Headers &nva); - -struct LinkHeader { - // The region of URI. This might not be NULL-terminated. - StringRef uri; -}; - -// Returns next URI-reference in Link header field value |src|. If no -// URI-reference found after searching all input, returned uri field -// is empty. This imply that empty URI-reference is ignored during -// parsing. -std::vector parse_link_header(const StringRef &src); - -// Constructs path by combining base path |base_path| with another -// path |rel_path|. The base path and another path can have optional -// query component. This function assumes |base_path| is normalized. -// In other words, it does not contain ".." or "." path components -// and starts with "/" if it is not empty. -std::string path_join(const StringRef &base, const StringRef &base_query, - const StringRef &rel_path, const StringRef &rel_query); - -StringRef path_join(BlockAllocator &balloc, const StringRef &base_path, - const StringRef &base_query, const StringRef &rel_path, - const StringRef &rel_query); - -// true if response has body, taking into account the request method -// and status code. -bool expect_response_body(const std::string &method, int status_code); -bool expect_response_body(int method_token, int status_code); - -// true if response has body, taking into account status code only. -bool expect_response_body(int status_code); - -// Looks up method token for method name |name| of length |namelen|. -// Only methods defined in http-parser/http-parser.h (http_method) are -// tokenized. If method name cannot be tokenized, returns -1. -int lookup_method_token(const uint8_t *name, size_t namelen); -int lookup_method_token(const StringRef &name); - -// Returns string representation of |method_token|. This is wrapper -// function over http_method_str from http-parser. If |method_token| -// is not known to http-parser, "" is returned. The returned -// StringRef is guaranteed to be NULL-terminated. -StringRef to_method_string(int method_token); - -StringRef normalize_path(BlockAllocator &balloc, const StringRef &path, - const StringRef &query); - -std::string normalize_path(const StringRef &path, const StringRef &query); - -StringRef rewrite_clean_path(BlockAllocator &balloc, const StringRef &src); - -// Returns path component of |uri|. The returned path does not -// include query component. This function returns empty string if it -// fails. -StringRef get_pure_path_component(const StringRef &uri); - -// Deduces scheme, authority and path from given |uri|, and stores -// them in |scheme|, |authority|, and |path| respectively. If |uri| -// is relative path, path resolution takes place using path given in -// |base| of length |baselen|. This function returns 0 if it -// succeeds, or -1. -int construct_push_component(BlockAllocator &balloc, StringRef &scheme, - StringRef &authority, StringRef &path, - const StringRef &base, const StringRef &uri); - -// Copies |src| and return its lower-cased version. -StringRef copy_lower(BlockAllocator &balloc, const StringRef &src); +int parse_http_status_code(const std::string &src); } // namespace http2 diff -Nru nghttp2-1.13.0/src/http2_test.cc nghttp2-0.6.7/src/http2_test.cc --- nghttp2-1.13.0/src/http2_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/http2_test.cc 2014-11-30 14:15:07.000000000 +0000 @@ -46,7 +46,7 @@ namespace shrpx { namespace { -void check_nv(const HeaderRef &a, const nghttp2_nv *b) { +void check_nv(const Header &a, const nghttp2_nv *b) { CU_ASSERT(a.name.size() == b->namelen); CU_ASSERT(a.value.size() == b->valuelen); CU_ASSERT(memcmp(a.name.c_str(), b->name, b->namelen) == 0); @@ -58,52 +58,58 @@ auto nva = Headers(); http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"123", 3, - false, -1); + false); CU_ASSERT(Headers::value_type("alpha", "123") == nva[0]); CU_ASSERT(!nva[0].no_index); nva.clear(); http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"", 0, - true, -1); + true); CU_ASSERT(Headers::value_type("alpha", "") == nva[0]); CU_ASSERT(nva[0].no_index); +} - nva.clear(); - - http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b", 2, - false, -1); - CU_ASSERT(Headers::value_type("a", "b") == nva[0]); - - nva.clear(); +void test_http2_check_http2_headers(void) { + auto nva1 = Headers{{"alpha", "1"}, {"bravo", "2"}, {"upgrade", "http2"}}; + CU_ASSERT(!http2::check_http2_headers(nva1)); - http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)"b ", 2, - false, -1); - CU_ASSERT(Headers::value_type("a", "b") == nva[0]); + auto nva2 = Headers{{"connection", "1"}, {"delta", "2"}, {"echo", "3"}}; + CU_ASSERT(!http2::check_http2_headers(nva2)); - nva.clear(); + auto nva3 = Headers{{"alpha", "1"}, {"bravo", "2"}, {"te2", "3"}}; + CU_ASSERT(http2::check_http2_headers(nva3)); - http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b ", 5, - false, -1); - CU_ASSERT(Headers::value_type("a", "b") == nva[0]); + auto n1 = ":authority"; + auto n1u8 = reinterpret_cast(n1); - nva.clear(); + CU_ASSERT(http2::check_http2_request_pseudo_header(n1u8, strlen(n1))); + CU_ASSERT(!http2::check_http2_response_pseudo_header(n1u8, strlen(n1))); - http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" bravo ", - 9, false, -1); - CU_ASSERT(Headers::value_type("a", "bravo") == nva[0]); + auto n2 = ":status"; + auto n2u8 = reinterpret_cast(n2); - nva.clear(); + CU_ASSERT(!http2::check_http2_request_pseudo_header(n2u8, strlen(n2))); + CU_ASSERT(http2::check_http2_response_pseudo_header(n2u8, strlen(n2))); +} - http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" ", 4, - false, -1); - CU_ASSERT(Headers::value_type("a", "") == nva[0]); +void test_http2_get_unique_header(void) { + auto nva = Headers{{"alpha", "1"}, + {"bravo", "2"}, + {"bravo", "3"}, + {"charlie", "4"}, + {"delta", "5"}, + {"echo", "6"}}; + const Headers::value_type *rv; + rv = http2::get_unique_header(nva, "delta"); + CU_ASSERT(rv != nullptr); + CU_ASSERT("delta" == rv->name); - nva.clear(); + rv = http2::get_unique_header(nva, "bravo"); + CU_ASSERT(rv == nullptr); - http2::add_header(nva, (const uint8_t *)"te", 2, (const uint8_t *)"trailers", - 8, false, http2::HD_TE); - CU_ASSERT(http2::HD_TE == nva[0].token); + rv = http2::get_unique_header(nva, "foxtrot"); + CU_ASSERT(rv == nullptr); } void test_http2_get_header(void) { @@ -112,8 +118,7 @@ {"bravo", "3"}, {"charlie", "4"}, {"delta", "5"}, - {"echo", "6"}, - {"content-length", "7"}}; + {"echo", "6"}}; const Headers::value_type *rv; rv = http2::get_header(nva, "delta"); CU_ASSERT(rv != nullptr); @@ -125,56 +130,39 @@ rv = http2::get_header(nva, "foxtrot"); CU_ASSERT(rv == nullptr); +} - http2::HeaderIndex hdidx; - http2::init_hdidx(hdidx); - hdidx[http2::HD_CONTENT_LENGTH] = 6; - rv = http2::get_header(hdidx, http2::HD_CONTENT_LENGTH, nva); - CU_ASSERT("content-length" == rv->name); +void test_http2_value_lws(void) { + auto nva = Headers{ + {"0", "alpha"}, {"1", " alpha"}, {"2", ""}, {" 3", " "}, {" 4", " a "}}; + CU_ASSERT(!http2::value_lws(&nva[0])); + CU_ASSERT(!http2::value_lws(&nva[1])); + CU_ASSERT(http2::value_lws(&nva[2])); + CU_ASSERT(http2::value_lws(&nva[3])); + CU_ASSERT(!http2::value_lws(&nva[4])); } namespace { -auto headers = HeaderRefs{ - {StringRef::from_lit("alpha"), StringRef::from_lit("0"), true}, - {StringRef::from_lit("bravo"), StringRef::from_lit("1")}, - {StringRef::from_lit("connection"), StringRef::from_lit("2"), false, - http2::HD_CONNECTION}, - {StringRef::from_lit("connection"), StringRef::from_lit("3"), false, - http2::HD_CONNECTION}, - {StringRef::from_lit("delta"), StringRef::from_lit("4")}, - {StringRef::from_lit("expect"), StringRef::from_lit("5")}, - {StringRef::from_lit("foxtrot"), StringRef::from_lit("6")}, - {StringRef::from_lit("tango"), StringRef::from_lit("7")}, - {StringRef::from_lit("te"), StringRef::from_lit("8"), false, http2::HD_TE}, - {StringRef::from_lit("te"), StringRef::from_lit("9"), false, http2::HD_TE}, - {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("10"), false, - http2::HD_X_FORWARDED_FOR}, - {StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("11"), false, - http2::HD_X_FORWARDED_FOR}, - {StringRef::from_lit("zulu"), StringRef::from_lit("12")}}; +auto headers = Headers{{"alpha", "0", true}, + {"bravo", "1"}, + {"connection", "2"}, + {"connection", "3"}, + {"delta", "4"}, + {"expect", "5"}, + {"foxtrot", "6"}, + {"tango", "7"}, + {"te", "8"}, + {"te", "9"}, + {"x-forwarded-proto", "10"}, + {"x-forwarded-proto", "11"}, + {"zulu", "12"}}; } // namespace -void test_http2_copy_headers_to_nva(void) { - auto ans = std::vector{0, 1, 4, 5, 6, 7, 12}; +void test_http2_copy_norm_headers_to_nva(void) { std::vector nva; - - http2::copy_headers_to_nva_nocopy(nva, headers); - CU_ASSERT(7 == nva.size()); - for (size_t i = 0; i < ans.size(); ++i) { - check_nv(headers[ans[i]], &nva[i]); - - if (ans[i] == 0) { - CU_ASSERT((NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE | - NGHTTP2_NV_FLAG_NO_INDEX) == nva[i].flags); - } else { - CU_ASSERT((NGHTTP2_NV_FLAG_NO_COPY_NAME | - NGHTTP2_NV_FLAG_NO_COPY_VALUE) == nva[i].flags); - } - } - - nva.clear(); - http2::copy_headers_to_nva(nva, headers); + http2::copy_norm_headers_to_nva(nva, headers); CU_ASSERT(7 == nva.size()); + auto ans = std::vector{0, 1, 4, 5, 6, 7, 12}; for (size_t i = 0; i < ans.size(); ++i) { check_nv(headers[ans[i]], &nva[i]); @@ -186,20 +174,27 @@ } } -void test_http2_build_http1_headers_from_headers(void) { - MemchunkPool pool; - DefaultMemchunks buf(&pool); - http2::build_http1_headers_from_headers(&buf, headers); - auto hdrs = std::string(buf.head->pos, buf.head->last); - CU_ASSERT("Alpha: 0\r\n" - "Bravo: 1\r\n" - "Delta: 4\r\n" - "Expect: 5\r\n" - "Foxtrot: 6\r\n" - "Tango: 7\r\n" - "Te: 8\r\n" - "Te: 9\r\n" - "Zulu: 12\r\n" == hdrs); +void test_http2_build_http1_headers_from_norm_headers(void) { + std::string hdrs; + http2::build_http1_headers_from_norm_headers(hdrs, headers); + CU_ASSERT(hdrs == "Alpha: 0\r\n" + "Bravo: 1\r\n" + "Delta: 4\r\n" + "Expect: 5\r\n" + "Foxtrot: 6\r\n" + "Tango: 7\r\n" + "Te: 8\r\n" + "Te: 9\r\n" + "Zulu: 12\r\n"); + + hdrs.clear(); + // Both nghttp2 and spdylay do not allow \r and \n in header value + // now. + + // auto hd2 = std::vector> + // {{"alpha", "bravo\r\ncharlie\r\n"}}; + // http2::build_http1_headers_from_norm_headers(hdrs, hd2); + // CU_ASSERT(hdrs == "Alpha: bravo charlie \r\n"); } void test_http2_lws(void) { @@ -209,761 +204,50 @@ } namespace { -void check_rewrite_location_uri(const std::string &want, const std::string &uri, - const std::string &match_host, - const std::string &req_authority, - const std::string &upstream_scheme) { - BlockAllocator balloc(4096, 4096); - http_parser_url u{}; +void check_rewrite_location_uri(const std::string &new_uri, + const std::string &uri, + const std::string &req_host, + const std::string &upstream_scheme, + uint16_t upstream_port) { + http_parser_url u; + memset(&u, 0, sizeof(u)); CU_ASSERT(0 == http_parser_parse_url(uri.c_str(), uri.size(), 0, &u)); - auto got = http2::rewrite_location_uri( - balloc, StringRef{uri}, u, StringRef{match_host}, - StringRef{req_authority}, StringRef{upstream_scheme}); - CU_ASSERT(want == got); + CU_ASSERT(new_uri == http2::rewrite_location_uri( + uri, u, req_host, upstream_scheme, upstream_port)); } } // namespace void test_http2_rewrite_location_uri(void) { check_rewrite_location_uri("https://localhost:3000/alpha?bravo#charlie", "http://localhost:3001/alpha?bravo#charlie", - "localhost:3001", "localhost:3000", "https"); + "localhost:3001", "https", 3000); check_rewrite_location_uri("https://localhost/", "http://localhost:3001/", - "localhost", "localhost", "https"); + "localhost:3001", "https", 443); check_rewrite_location_uri("http://localhost/", "http://localhost:3001/", - "localhost", "localhost", "http"); + "localhost:3001", "http", 80); check_rewrite_location_uri("http://localhost:443/", "http://localhost:3001/", - "localhost", "localhost:443", "http"); + "localhost:3001", "http", 443); check_rewrite_location_uri("https://localhost:80/", "http://localhost:3001/", - "localhost", "localhost:80", "https"); - check_rewrite_location_uri("", "http://localhost:3001/", "127.0.0.1", - "127.0.0.1", "https"); + "localhost:3001", "https", 80); + check_rewrite_location_uri("", "http://localhost:3001/", "127.0.0.1", "https", + 3000); check_rewrite_location_uri("https://localhost:3000/", - "http://localhost:3001/", "localhost", - "localhost:3000", "https"); + "http://localhost:3001/", "localhost", "https", + 3000); + check_rewrite_location_uri("", "https://localhost:3001/", "localhost", + "https", 3000); check_rewrite_location_uri("https://localhost:3000/", "http://localhost/", - "localhost", "localhost:3000", "https"); - - // match_host != req_authority - check_rewrite_location_uri("https://example.org", "http://127.0.0.1:8080", - "127.0.0.1", "example.org", "https"); - check_rewrite_location_uri("", "http://example.org", "127.0.0.1", - "example.org", "https"); + "localhost", "https", 3000); } void test_http2_parse_http_status_code(void) { - CU_ASSERT(200 == http2::parse_http_status_code(StringRef::from_lit("200"))); - CU_ASSERT(102 == http2::parse_http_status_code(StringRef::from_lit("102"))); - CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("099"))); - CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("99"))); - CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("-1"))); - CU_ASSERT(-1 == http2::parse_http_status_code(StringRef::from_lit("20a"))); - CU_ASSERT(-1 == http2::parse_http_status_code(StringRef{})); -} - -void test_http2_index_header(void) { - http2::HeaderIndex hdidx; - http2::init_hdidx(hdidx); - - http2::index_header(hdidx, http2::HD__AUTHORITY, 0); - http2::index_header(hdidx, -1, 1); - - CU_ASSERT(0 == hdidx[http2::HD__AUTHORITY]); -} - -void test_http2_lookup_token(void) { - CU_ASSERT(http2::HD__AUTHORITY == - http2::lookup_token(StringRef::from_lit(":authority"))); - CU_ASSERT(-1 == http2::lookup_token(StringRef::from_lit(":authorit"))); - CU_ASSERT(-1 == http2::lookup_token(StringRef::from_lit(":Authority"))); - CU_ASSERT(http2::HD_EXPECT == - http2::lookup_token(StringRef::from_lit("expect"))); -} - -void test_http2_parse_link_header(void) { - { - // only URI appears; we don't extract URI unless it bears rel=preload - auto res = http2::parse_link_header(StringRef::from_lit("")); - CU_ASSERT(0 == res.size()); - } - { - // URI url should be extracted - auto res = - http2::parse_link_header(StringRef::from_lit("; rel=preload")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // With extra link-param. URI url should be extracted - auto res = http2::parse_link_header( - StringRef::from_lit("; rel=preload; as=file")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // With extra link-param. URI url should be extracted - auto res = http2::parse_link_header( - StringRef::from_lit("; as=file; rel=preload")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // With extra link-param and quote-string. URI url should be - // extracted - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel=preload; title="foo,bar")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // With extra link-param and quote-string. URI url should be - // extracted - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; title="foo,bar"; rel=preload)")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // ',' after quote-string - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; title="foo,bar", ; rel=preload)")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url2" == res[0].uri); - } - { - // Only first URI should be extracted. - auto res = http2::parse_link_header( - StringRef::from_lit("; rel=preload, ")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // Both have rel=preload, so both urls should be extracted - auto res = http2::parse_link_header( - StringRef::from_lit("; rel=preload, ; rel=preload")); - CU_ASSERT(2 == res.size()); - CU_ASSERT("url" == res[0].uri); - CU_ASSERT("url2" == res[1].uri); - } - { - // Second URI uri should be extracted. - auto res = http2::parse_link_header( - StringRef::from_lit(", ;rel=preload")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url2" == res[0].uri); - } - { - // Error if input ends with ';' - auto res = - http2::parse_link_header(StringRef::from_lit(";rel=preload;")); - CU_ASSERT(0 == res.size()); - } - { - // Error if link header ends with ';' - auto res = http2::parse_link_header( - StringRef::from_lit(";rel=preload;, ")); - CU_ASSERT(0 == res.size()); - } - { - // OK if input ends with ',' - auto res = - http2::parse_link_header(StringRef::from_lit(";rel=preload,")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // Multiple repeated ','s between fields is OK - auto res = http2::parse_link_header( - StringRef::from_lit(",,,;rel=preload")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url2" == res[0].uri); - } - { - // Error if url is not enclosed by <> - auto res = - http2::parse_link_header(StringRef::from_lit("url>;rel=preload")); - CU_ASSERT(0 == res.size()); - } - { - // Error if url is not enclosed by <> - auto res = - http2::parse_link_header(StringRef::from_lit(";rel=preload; as=")); - CU_ASSERT(0 == res.size()); - } - { - // Empty parameter value is not allowed - auto res = - http2::parse_link_header(StringRef::from_lit(";as=;rel=preload")); - CU_ASSERT(0 == res.size()); - } - { - // Empty parameter value is not allowed - auto res = http2::parse_link_header( - StringRef::from_lit(";as=, ;rel=preload")); - CU_ASSERT(0 == res.size()); - } - { - // Empty parameter name is not allowed - auto res = http2::parse_link_header( - StringRef::from_lit("; =file; rel=preload")); - CU_ASSERT(0 == res.size()); - } - { - // Without whitespaces - auto res = http2::parse_link_header( - StringRef::from_lit(";as=file;rel=preload,;rel=preload")); - CU_ASSERT(2 == res.size()); - CU_ASSERT("url" == res[0].uri); - CU_ASSERT("url2" == res[1].uri); - } - { - // link-extension may have no value - auto res = - http2::parse_link_header(StringRef::from_lit("; as; rel=preload")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // ext-name-star - auto res = http2::parse_link_header( - StringRef::from_lit("; foo*=bar; rel=preload")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // '*' is not allowed expect for trailing one - auto res = http2::parse_link_header( - StringRef::from_lit("; *=bar; rel=preload")); - CU_ASSERT(0 == res.size()); - } - { - // '*' is not allowed expect for trailing one - auto res = http2::parse_link_header( - StringRef::from_lit("; foo*bar=buzz; rel=preload")); - CU_ASSERT(0 == res.size()); - } - { - // ext-name-star must be followed by '=' - auto res = http2::parse_link_header( - StringRef::from_lit("; foo*; rel=preload")); - CU_ASSERT(0 == res.size()); - } - { - // '>' is not followed by ';' - auto res = - http2::parse_link_header(StringRef::from_lit(" rel=preload")); - CU_ASSERT(0 == res.size()); - } - { - // Starting with whitespace is no problem. - auto res = - http2::parse_link_header(StringRef::from_lit(" ; rel=preload")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // preload is a prefix of bogus rel parameter value - auto res = - http2::parse_link_header(StringRef::from_lit("; rel=preloadx")); - CU_ASSERT(0 == res.size()); - } - { - // preload in relation-types list - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="preload")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // preload in relation-types list followed by another parameter - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="preload foo")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // preload in relation-types list following another parameter - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="foo preload")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // preload in relation-types list between other parameters - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="foo preload bar")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // preload in relation-types list between other parameters - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="foo preload bar")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // no preload in relation-types list - auto res = - http2::parse_link_header(StringRef::from_lit(R"(; rel="foo")")); - CU_ASSERT(0 == res.size()); - } - { - // no preload in relation-types list, multiple unrelated elements. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="foo bar")")); - CU_ASSERT(0 == res.size()); - } - { - // preload in relation-types list, followed by another link-value. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="preload", )")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // preload in relation-types list, following another link-value. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(, ; rel="preload")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url2" == res[0].uri); - } - { - // preload in relation-types list, followed by another link-param. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="preload"; as="font")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // preload in relation-types list, followed by character other - // than ';' or ',' - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="preload".)")); - CU_ASSERT(0 == res.size()); - } - { - // preload in relation-types list, followed by ';' but it - // terminates input - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="preload";)")); - CU_ASSERT(0 == res.size()); - } - { - // preload in relation-types list, followed by ',' but it - // terminates input - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="preload",)")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // preload in relation-types list but there is preceding white - // space. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel=" preload")")); - CU_ASSERT(0 == res.size()); - } - { - // preload in relation-types list but there is trailing white - // space. - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel="preload ")")); - CU_ASSERT(0 == res.size()); - } - { - // backslash escaped characters in quoted-string - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel=preload; title="foo\"baz\"bar")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // anchor="" is acceptable - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel=preload; anchor="")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // With anchor="#foo", url should be ignored - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel=preload; anchor="#foo")")); - CU_ASSERT(0 == res.size()); - } - { - // With anchor=f, url should be ignored - auto res = http2::parse_link_header( - StringRef::from_lit("; rel=preload; anchor=f")); - CU_ASSERT(0 == res.size()); - } - { - // First url is ignored With anchor="#foo", but url should be - // accepted. - auto res = http2::parse_link_header(StringRef::from_lit( - R"(; rel=preload; anchor="#foo", ; rel=preload)")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url2" == res[0].uri); - } - { - // With loadpolicy="next", url should be ignored - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel=preload; loadpolicy="next")")); - CU_ASSERT(0 == res.size()); - } - { - // url should be picked up if empty loadpolicy is specified - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel=preload; loadpolicy="")")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // case-insensitive match - auto res = http2::parse_link_header( - StringRef::from_lit(R"(; rel=preload; ANCHOR="#foo", ; )" - R"(REL=PRELOAD, ; REL="foo PRELOAD bar")")); - CU_ASSERT(2 == res.size()); - CU_ASSERT("url2" == res[0].uri); - CU_ASSERT("url3" == res[1].uri); - } - { - // nopush at the end of input - auto res = http2::parse_link_header( - StringRef::from_lit("; rel=preload; nopush")); - CU_ASSERT(0 == res.size()); - } - { - // nopush followed by ';' - auto res = http2::parse_link_header( - StringRef::from_lit("; rel=preload; nopush; foo")); - CU_ASSERT(0 == res.size()); - } - { - // nopush followed by ',' - auto res = http2::parse_link_header( - StringRef::from_lit("; nopush; rel=preload")); - CU_ASSERT(0 == res.size()); - } - { - // string whose prefix is nopush - auto res = http2::parse_link_header( - StringRef::from_lit("; nopushyes; rel=preload")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } - { - // rel=preload twice - auto res = http2::parse_link_header( - StringRef::from_lit("; rel=preload; rel=preload")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("url" == res[0].uri); - } -} - -void test_http2_path_join(void) { - { - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/"); - CU_ASSERT("/" == http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/alpha"); - CU_ASSERT("/alpha" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // rel ends with trailing '/' - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/alpha/"); - CU_ASSERT("/alpha/" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // rel contains multiple components - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/alpha/bravo"); - CU_ASSERT("/alpha/bravo" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // rel is relative - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("alpha/bravo"); - CU_ASSERT("/alpha/bravo" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // rel is relative and base ends without /, which means it refers - // to file. - auto base = StringRef::from_lit("/alpha"); - auto rel = StringRef::from_lit("bravo/charlie"); - CU_ASSERT("/bravo/charlie" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // rel contains repeated '/'s - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/alpha/////bravo/////"); - CU_ASSERT("/alpha/bravo/" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // base ends with '/', so '..' eats 'bravo' - auto base = StringRef::from_lit("/alpha/bravo/"); - auto rel = StringRef::from_lit("../charlie/delta"); - CU_ASSERT("/alpha/charlie/delta" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // base does not end with '/', so '..' eats 'alpha/bravo' - auto base = StringRef::from_lit("/alpha/bravo"); - auto rel = StringRef::from_lit("../charlie"); - CU_ASSERT("/charlie" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // 'charlie' is eaten by following '..' - auto base = StringRef::from_lit("/alpha/bravo/"); - auto rel = StringRef::from_lit("../charlie/../delta"); - CU_ASSERT("/alpha/delta" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // excessive '..' results in '/' - auto base = StringRef::from_lit("/alpha/bravo/"); - auto rel = StringRef::from_lit("../../../"); - CU_ASSERT("/" == http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // excessive '..' and path component - auto base = StringRef::from_lit("/alpha/bravo/"); - auto rel = StringRef::from_lit("../../../charlie"); - CU_ASSERT("/charlie" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // rel ends with '..' - auto base = StringRef::from_lit("/alpha/bravo/"); - auto rel = StringRef::from_lit("charlie/.."); - CU_ASSERT("/alpha/bravo/" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // base empty and rel contains '..' - auto base = StringRef{}; - auto rel = StringRef::from_lit("charlie/.."); - CU_ASSERT("/" == http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // '.' is ignored - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("charlie/././././delta"); - CU_ASSERT("/charlie/delta" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // trailing '.' is ignored - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("charlie/."); - CU_ASSERT("/charlie/" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // query - auto base = StringRef::from_lit("/"); - auto rel = StringRef::from_lit("/"); - auto relq = StringRef::from_lit("q"); - CU_ASSERT("/?q" == http2::path_join(base, StringRef{}, rel, relq)); - } - { - // empty rel and query - auto base = StringRef::from_lit("/alpha"); - auto rel = StringRef{}; - auto relq = StringRef::from_lit("q"); - CU_ASSERT("/alpha?q" == http2::path_join(base, StringRef{}, rel, relq)); - } - { - // both rel and query are empty - auto base = StringRef::from_lit("/alpha"); - auto baseq = StringRef::from_lit("r"); - auto rel = StringRef{}; - auto relq = StringRef{}; - CU_ASSERT("/alpha?r" == http2::path_join(base, baseq, rel, relq)); - } - { - // empty base - auto base = StringRef{}; - auto rel = StringRef::from_lit("/alpha"); - CU_ASSERT("/alpha" == - http2::path_join(base, StringRef{}, rel, StringRef{})); - } - { - // everything is empty - CU_ASSERT("/" == http2::path_join(StringRef{}, StringRef{}, StringRef{}, - StringRef{})); - } - { - // only baseq is not empty - auto base = StringRef{}; - auto baseq = StringRef::from_lit("r"); - auto rel = StringRef{}; - CU_ASSERT("/?r" == http2::path_join(base, baseq, rel, StringRef{})); - } - { - // path starts with multiple '/'s. - auto base = StringRef{}; - auto baseq = StringRef{}; - auto rel = StringRef::from_lit("//alpha//bravo"); - auto relq = StringRef::from_lit("charlie"); - CU_ASSERT("/alpha/bravo?charlie" == - http2::path_join(base, baseq, rel, relq)); - } -} - -void test_http2_normalize_path(void) { - CU_ASSERT("/alpha/charlie" == - http2::normalize_path( - StringRef::from_lit("/alpha/bravo/../charlie"), StringRef{})); - - CU_ASSERT("/alpha" == - http2::normalize_path(StringRef::from_lit("/a%6c%70%68%61"), - StringRef{})); - - CU_ASSERT( - "/alpha%2F%3A" == - http2::normalize_path(StringRef::from_lit("/alpha%2f%3a"), StringRef{})); - - CU_ASSERT("/%2F" == - http2::normalize_path(StringRef::from_lit("%2f"), StringRef{})); - - CU_ASSERT("/%f" == - http2::normalize_path(StringRef::from_lit("%f"), StringRef{})); - - CU_ASSERT("/%" == - http2::normalize_path(StringRef::from_lit("%"), StringRef{})); - - CU_ASSERT("/" == http2::normalize_path(StringRef{}, StringRef{})); - - CU_ASSERT("/alpha?bravo" == - http2::normalize_path(StringRef::from_lit("/alpha"), - StringRef::from_lit("bravo"))); -} - -void test_http2_rewrite_clean_path(void) { - BlockAllocator balloc(4096, 4096); - - // unreserved characters - CU_ASSERT("/alpha/bravo/" == - http2::rewrite_clean_path(balloc, - StringRef::from_lit("/alpha/%62ravo/"))); - - // percent-encoding is converted to upper case. - CU_ASSERT("/delta%3A" == http2::rewrite_clean_path( - balloc, StringRef::from_lit("/delta%3a"))); - - // path component is normalized before mathcing - CU_ASSERT( - "/alpha/bravo/" == - http2::rewrite_clean_path( - balloc, StringRef::from_lit("/alpha/charlie/%2e././bravo/delta/.."))); - - CU_ASSERT("alpha%3a" == - http2::rewrite_clean_path(balloc, StringRef::from_lit("alpha%3a"))); - - CU_ASSERT("" == http2::rewrite_clean_path(balloc, StringRef{})); - - CU_ASSERT( - "/alpha?bravo" == - http2::rewrite_clean_path(balloc, StringRef::from_lit("//alpha?bravo"))); -} - -void test_http2_get_pure_path_component(void) { - CU_ASSERT("/" == http2::get_pure_path_component(StringRef::from_lit("/"))); - - CU_ASSERT("/foo" == - http2::get_pure_path_component(StringRef::from_lit("/foo"))); - - CU_ASSERT("/bar" == http2::get_pure_path_component( - StringRef::from_lit("https://example.org/bar"))); - - CU_ASSERT("/alpha" == http2::get_pure_path_component(StringRef::from_lit( - "https://example.org/alpha?q=a"))); - - CU_ASSERT("/bravo" == http2::get_pure_path_component(StringRef::from_lit( - "https://example.org/bravo?q=a#fragment"))); - - CU_ASSERT("" == - http2::get_pure_path_component(StringRef::from_lit("\x01\x02"))); -} - -void test_http2_construct_push_component(void) { - BlockAllocator balloc(4096, 4096); - StringRef base, uri; - StringRef scheme, authority, path; - - base = StringRef::from_lit("/b/"); - uri = StringRef::from_lit("https://example.org/foo"); - - CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority, - path, base, uri)); - CU_ASSERT("https" == scheme); - CU_ASSERT("example.org" == authority); - CU_ASSERT("/foo" == path); - - scheme = StringRef{}; - authority = StringRef{}; - path = StringRef{}; - - uri = StringRef::from_lit("/foo/bar?q=a"); - - CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority, - path, base, uri)); - CU_ASSERT("" == scheme); - CU_ASSERT("" == authority); - CU_ASSERT("/foo/bar?q=a" == path); - - scheme = StringRef{}; - authority = StringRef{}; - path = StringRef{}; - - uri = StringRef::from_lit("foo/../bar?q=a"); - - CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority, - path, base, uri)); - CU_ASSERT("" == scheme); - CU_ASSERT("" == authority); - CU_ASSERT("/b/bar?q=a" == path); - - scheme = StringRef{}; - authority = StringRef{}; - path = StringRef{}; - - uri = StringRef{}; - - CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority, - path, base, uri)); - CU_ASSERT("" == scheme); - CU_ASSERT("" == authority); - CU_ASSERT("/" == path); - - scheme = StringRef{}; - authority = StringRef{}; - path = StringRef{}; - - uri = StringRef::from_lit("?q=a"); - - CU_ASSERT(0 == http2::construct_push_component(balloc, scheme, authority, - path, base, uri)); - CU_ASSERT("" == scheme); - CU_ASSERT("" == authority); - CU_ASSERT("/b/?q=a" == path); + CU_ASSERT(200 == http2::parse_http_status_code("200")); + CU_ASSERT(102 == http2::parse_http_status_code("102")); + CU_ASSERT(-1 == http2::parse_http_status_code("099")); + CU_ASSERT(-1 == http2::parse_http_status_code("99")); + CU_ASSERT(-1 == http2::parse_http_status_code("-1")); + CU_ASSERT(-1 == http2::parse_http_status_code("20a")); + CU_ASSERT(-1 == http2::parse_http_status_code("")); } } // namespace shrpx diff -Nru nghttp2-1.13.0/src/http2_test.h nghttp2-0.6.7/src/http2_test.h --- nghttp2-1.13.0/src/http2_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/http2_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,27 +25,18 @@ #ifndef SHRPX_HTTP2_TEST_H #define SHRPX_HTTP2_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - namespace shrpx { void test_http2_add_header(void); +void test_http2_check_http2_headers(void); +void test_http2_get_unique_header(void); void test_http2_get_header(void); -void test_http2_copy_headers_to_nva(void); -void test_http2_build_http1_headers_from_headers(void); +void test_http2_value_lws(void); +void test_http2_copy_norm_headers_to_nva(void); +void test_http2_build_http1_headers_from_norm_headers(void); void test_http2_lws(void); void test_http2_rewrite_location_uri(void); void test_http2_parse_http_status_code(void); -void test_http2_index_header(void); -void test_http2_lookup_token(void); -void test_http2_parse_link_header(void); -void test_http2_path_join(void); -void test_http2_normalize_path(void); -void test_http2_rewrite_clean_path(void); -void test_http2_get_pure_path_component(void); -void test_http2_construct_push_component(void); } // namespace shrpx diff -Nru nghttp2-1.13.0/src/HttpServer.cc nghttp2-0.6.7/src/HttpServer.cc --- nghttp2-1.13.0/src/HttpServer.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/HttpServer.cc 2014-11-30 14:15:07.000000000 +0000 @@ -25,43 +25,41 @@ #include "HttpServer.h" #include -#ifdef HAVE_SYS_SOCKET_H #include -#endif // HAVE_SYS_SOCKET_H -#ifdef HAVE_NETDB_H #include -#endif // HAVE_NETDB_H -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H -#ifdef HAVE_FCNTL_H #include -#endif // HAVE_FCNTL_H -#ifdef HAVE_NETINET_IN_H #include -#endif // HAVE_NETINET_IN_H #include -#ifdef HAVE_ARPA_INET_H -#include -#endif // HAVE_ARPA_INET_H #include #include #include #include -#include -#include #include -#include #include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nghttp2_helper.h" + +#ifdef __cplusplus +} +#endif + #include "app_helper.h" #include "http2.h" #include "util.h" +#include "libevent_util.h" #include "ssl.h" -#include "template.h" #ifndef O_BINARY #define O_BINARY (0) @@ -70,10 +68,13 @@ namespace nghttp2 { namespace { -// TODO could be constexpr -constexpr auto DEFAULT_HTML = StringRef::from_lit("index.html"); -constexpr auto NGHTTPD_SERVER = - StringRef::from_lit("nghttpd nghttp2/" NGHTTP2_VERSION); +const std::string STATUS_200 = "200"; +const std::string STATUS_301 = "301"; +const std::string STATUS_304 = "304"; +const std::string STATUS_400 = "400"; +const std::string STATUS_404 = "404"; +const std::string DEFAULT_HTML = "index.html"; +const std::string NGHTTPD_SERVER = "nghttpd nghttp2/" NGHTTP2_VERSION; } // namespace namespace { @@ -87,40 +88,52 @@ void print_session_id(int64_t id) { std::cout << "[id=" << id << "] "; } } // namespace +namespace { +void append_nv(Stream *stream, const std::vector &nva) { + for (auto &nv : nva) { + http2::add_header(stream->headers, nv.name, nv.namelen, nv.value, + nv.valuelen, nv.flags & NGHTTP2_NV_FLAG_NO_INDEX); + } +} +} // namespace + Config::Config() - : mime_types_file("/etc/mime.types"), - stream_read_timeout(1_min), - stream_write_timeout(1_min), - data_ptr(nullptr), - padding(0), - num_worker(1), - max_concurrent_streams(100), - header_table_size(-1), - window_bits(-1), - connection_window_bits(-1), - port(0), - verbose(false), - daemon(false), - verify_client(false), - no_tls(false), - error_gzip(false), - early_response(false), - hexdump(false), - echo_upload(false), - no_content_length(false) {} + : stream_read_timeout{60, 0}, stream_write_timeout{60, 0}, + session_option(nullptr), data_ptr(nullptr), padding(0), num_worker(1), + header_table_size(-1), port(0), verbose(false), daemon(false), + verify_client(false), no_tls(false), error_gzip(false), + early_response(false) { + nghttp2_option_new(&session_option); + nghttp2_option_set_recv_client_preface(session_option, 1); +} + +Config::~Config() { nghttp2_option_del(session_option); } + +Stream::Stream(Http2Handler *handler, int32_t stream_id) + : handler(handler), rtimer(nullptr), wtimer(nullptr), stream_id(stream_id), + file(-1) {} + +Stream::~Stream() { + if (file != -1) { + close(file); + } -Config::~Config() {} + if (wtimer) { + event_free(wtimer); + } + + if (rtimer) { + event_free(rtimer); + } +} namespace { -void stream_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) { +void stream_timeout_cb(evutil_socket_t fd, short what, void *arg) { int rv; - auto stream = static_cast(w->data); + auto stream = static_cast(arg); auto hd = stream->handler; auto config = hd->get_config(); - ev_timer_stop(hd->get_loop(), &stream->rtimer); - ev_timer_stop(hd->get_loop(), &stream->wtimer); - if (config->verbose) { print_session_id(hd->session_id()); print_timer(); @@ -139,15 +152,19 @@ namespace { void add_stream_read_timeout(Stream *stream) { auto hd = stream->handler; - ev_timer_again(hd->get_loop(), &stream->rtimer); + auto config = hd->get_config(); + + evtimer_add(stream->rtimer, &config->stream_read_timeout); } } // namespace namespace { void add_stream_read_timeout_if_pending(Stream *stream) { auto hd = stream->handler; - if (ev_is_active(&stream->rtimer)) { - ev_timer_again(hd->get_loop(), &stream->rtimer); + auto config = hd->get_config(); + + if (evtimer_pending(stream->rtimer, nullptr)) { + evtimer_add(stream->rtimer, &config->stream_read_timeout); } } } // namespace @@ -155,106 +172,59 @@ namespace { void add_stream_write_timeout(Stream *stream) { auto hd = stream->handler; - ev_timer_again(hd->get_loop(), &stream->wtimer); + auto config = hd->get_config(); + + evtimer_add(stream->wtimer, &config->stream_write_timeout); } } // namespace namespace { void remove_stream_read_timeout(Stream *stream) { - auto hd = stream->handler; - ev_timer_stop(hd->get_loop(), &stream->rtimer); + if (stream->rtimer) { + evtimer_del(stream->rtimer); + } } } // namespace namespace { void remove_stream_write_timeout(Stream *stream) { - auto hd = stream->handler; - ev_timer_stop(hd->get_loop(), &stream->wtimer); + if (stream->wtimer) { + evtimer_del(stream->wtimer); + } } } // namespace namespace { -void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config); -} // namespace - -namespace { -constexpr ev_tstamp RELEASE_FD_TIMEOUT = 2.; -} // namespace - -namespace { -void release_fd_cb(struct ev_loop *loop, ev_timer *w, int revents); -} // namespace - -namespace { -constexpr ev_tstamp FILE_ENTRY_MAX_AGE = 10.; -} // namespace - -namespace { -constexpr size_t FILE_ENTRY_EVICT_THRES = 2048; +std::shared_ptr cached_date; } // namespace namespace { -bool need_validation_file_entry(const FileEntry *ent, ev_tstamp now) { - return ent->last_valid + FILE_ENTRY_MAX_AGE < now; +void refresh_cb(evutil_socket_t sig, short events, void *arg) { + cached_date = std::make_shared(util::http_date(time(nullptr))); } } // namespace namespace { -bool validate_file_entry(FileEntry *ent, ev_tstamp now) { - struct stat stbuf; - int rv; - - rv = fstat(ent->fd, &stbuf); - if (rv != 0) { - ent->stale = true; - return false; - } - - if (stbuf.st_nlink == 0 || ent->mtime != stbuf.st_mtime) { - ent->stale = true; - return false; - } - - ent->mtime = stbuf.st_mtime; - ent->last_valid = now; - - return true; -} +void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config); } // namespace class Sessions { public: - Sessions(HttpServer *sv, struct ev_loop *loop, const Config *config, - SSL_CTX *ssl_ctx) - : sv_(sv), - loop_(loop), - config_(config), - ssl_ctx_(ssl_ctx), - callbacks_(nullptr), - next_session_id_(1), - tstamp_cached_(ev_now(loop)), - cached_date_(util::http_date(tstamp_cached_)) { + Sessions(event_base *evbase, const Config *config, SSL_CTX *ssl_ctx) + : evbase_(evbase), config_(config), ssl_ctx_(ssl_ctx), + callbacks_(nullptr), next_session_id_(1) { nghttp2_session_callbacks_new(&callbacks_); fill_callback(callbacks_, config_); - - ev_timer_init(&release_fd_timer_, release_fd_cb, 0., RELEASE_FD_TIMEOUT); - release_fd_timer_.data = this; } ~Sessions() { - ev_timer_stop(loop_, &release_fd_timer_); for (auto handler : handlers_) { delete handler; } nghttp2_session_callbacks_del(callbacks_); } void add_handler(Http2Handler *handler) { handlers_.insert(handler); } - void remove_handler(Http2Handler *handler) { - handlers_.erase(handler); - if (handlers_.empty() && !fd_cache_.empty()) { - ev_timer_again(loop_, &release_fd_timer_); - } - } + void remove_handler(Http2Handler *handler) { handlers_.erase(handler); } SSL_CTX *get_ssl_ctx() const { return ssl_ctx_; } SSL *ssl_session_new(int fd) { SSL *ssl = SSL_new(ssl_ctx_); @@ -270,21 +240,19 @@ return ssl; } const Config *get_config() const { return config_; } - struct ev_loop *get_loop() const { - return loop_; - } + event_base *get_evbase() const { return evbase_; } int64_t get_next_session_id() { auto session_id = next_session_id_; if (next_session_id_ == std::numeric_limits::max()) { next_session_id_ = 1; - } else { - ++next_session_id_; } return session_id; } const nghttp2_session_callbacks *get_callbacks() const { return callbacks_; } void accept_connection(int fd) { - util::make_socket_nodelay(fd); + int val = 1; + (void)setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast(&val), sizeof(val)); SSL *ssl = nullptr; if (ssl_ctx_) { ssl = ssl_session_new(fd); @@ -294,178 +262,26 @@ } } auto handler = - make_unique(this, fd, ssl, get_next_session_id()); + util::make_unique(this, fd, ssl, get_next_session_id()); + handler->setup_bev(); if (!ssl) { - if (handler->connection_made() != 0) { + if (handler->on_connect() != 0) { return; } } add_handler(handler.release()); } - void update_cached_date() { cached_date_ = util::http_date(tstamp_cached_); } - const std::string &get_cached_date() { - auto t = ev_now(loop_); - if (t != tstamp_cached_) { - tstamp_cached_ = t; - update_cached_date(); - } - return cached_date_; - } - FileEntry *get_cached_fd(const std::string &path) { - auto range = fd_cache_.equal_range(path); - if (range.first == range.second) { - return nullptr; - } - - auto now = ev_now(loop_); - - for (auto it = range.first; it != range.second;) { - auto &ent = (*it).second; - if (ent->stale) { - ++it; - continue; - } - if (need_validation_file_entry(ent.get(), now) && - !validate_file_entry(ent.get(), now)) { - if (ent->usecount == 0) { - fd_cache_lru_.remove(ent.get()); - close(ent->fd); - it = fd_cache_.erase(it); - continue; - } - ++it; - continue; - } - - fd_cache_lru_.remove(ent.get()); - fd_cache_lru_.append(ent.get()); - - ++ent->usecount; - return ent.get(); - } - return nullptr; - } - FileEntry *cache_fd(const std::string &path, const FileEntry &ent) { -#ifdef HAVE_STD_MAP_EMPLACE - auto rv = fd_cache_.emplace(path, make_unique(ent)); -#else // !HAVE_STD_MAP_EMPLACE - // for gcc-4.7 - auto rv = - fd_cache_.insert(std::make_pair(path, make_unique(ent))); -#endif // !HAVE_STD_MAP_EMPLACE - auto &res = (*rv).second; - res->it = rv; - fd_cache_lru_.append(res.get()); - - while (fd_cache_.size() > FILE_ENTRY_EVICT_THRES) { - auto ent = fd_cache_lru_.head; - if (ent->usecount) { - break; - } - fd_cache_lru_.remove(ent); - close(ent->fd); - fd_cache_.erase(ent->it); - } - - return res.get(); - } - void release_fd(FileEntry *target) { - --target->usecount; - - if (target->usecount == 0 && target->stale) { - fd_cache_lru_.remove(target); - close(target->fd); - fd_cache_.erase(target->it); - return; - } - - // We use timer to close file descriptor and delete the entry from - // cache. The timer will be started when there is no handler. - } - void release_unused_fd() { - for (auto i = std::begin(fd_cache_); i != std::end(fd_cache_);) { - auto &ent = (*i).second; - if (ent->usecount != 0) { - ++i; - continue; - } - - fd_cache_lru_.remove(ent.get()); - close(ent->fd); - i = fd_cache_.erase(i); - } - } - const HttpServer *get_server() const { return sv_; } - bool handlers_empty() const { return handlers_.empty(); } private: std::set handlers_; - // cache for file descriptors to read file. - std::multimap> fd_cache_; - DList fd_cache_lru_; - HttpServer *sv_; - struct ev_loop *loop_; + event_base *evbase_; const Config *config_; SSL_CTX *ssl_ctx_; nghttp2_session_callbacks *callbacks_; - ev_timer release_fd_timer_; int64_t next_session_id_; - ev_tstamp tstamp_cached_; - std::string cached_date_; }; namespace { -void release_fd_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto sessions = static_cast(w->data); - - ev_timer_stop(loop, w); - - if (!sessions->handlers_empty()) { - return; - } - - sessions->release_unused_fd(); -} -} // namespace - -Stream::Stream(Http2Handler *handler, int32_t stream_id) - : balloc(1024, 1024), - header{}, - handler(handler), - file_ent(nullptr), - body_length(0), - body_offset(0), - header_buffer_size(0), - stream_id(stream_id), - echo_upload(false) { - auto config = handler->get_config(); - ev_timer_init(&rtimer, stream_timeout_cb, 0., config->stream_read_timeout); - ev_timer_init(&wtimer, stream_timeout_cb, 0., config->stream_write_timeout); - rtimer.data = this; - wtimer.data = this; -} - -Stream::~Stream() { - if (file_ent != nullptr) { - auto sessions = handler->get_sessions(); - sessions->release_fd(file_ent); - } - - auto &rcbuf = header.rcbuf; - nghttp2_rcbuf_decref(rcbuf.method); - nghttp2_rcbuf_decref(rcbuf.scheme); - nghttp2_rcbuf_decref(rcbuf.authority); - nghttp2_rcbuf_decref(rcbuf.host); - nghttp2_rcbuf_decref(rcbuf.path); - nghttp2_rcbuf_decref(rcbuf.ims); - nghttp2_rcbuf_decref(rcbuf.expect); - - auto loop = handler->get_loop(); - ev_timer_stop(loop, &rtimer); - ev_timer_stop(loop, &wtimer); -} - -namespace { void on_session_closed(Http2Handler *hd, int64_t session_id) { if (hd->get_config()->verbose) { print_session_id(session_id); @@ -475,84 +291,25 @@ } } // namespace -namespace { -void settings_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) { - int rv; - auto hd = static_cast(w->data); - hd->terminate_session(NGHTTP2_SETTINGS_TIMEOUT); - rv = hd->on_write(); - if (rv == -1) { - delete_handler(hd); - } -} -} // namespace - -namespace { -void readcb(struct ev_loop *loop, ev_io *w, int revents) { - int rv; - auto handler = static_cast(w->data); - - rv = handler->on_read(); - if (rv == -1) { - delete_handler(handler); - } -} -} // namespace - -namespace { -void writecb(struct ev_loop *loop, ev_io *w, int revents) { - int rv; - auto handler = static_cast(w->data); - - rv = handler->on_write(); - if (rv == -1) { - delete_handler(handler); - } -} -} // namespace - Http2Handler::Http2Handler(Sessions *sessions, int fd, SSL *ssl, int64_t session_id) - : session_id_(session_id), - session_(nullptr), - sessions_(sessions), - ssl_(ssl), - data_pending_(nullptr), - data_pendinglen_(0), - fd_(fd) { - ev_timer_init(&settings_timerev_, settings_timeout_cb, 10., 0.); - ev_io_init(&wev_, writecb, fd, EV_WRITE); - ev_io_init(&rev_, readcb, fd, EV_READ); - - settings_timerev_.data = this; - wev_.data = this; - rev_.data = this; - - auto loop = sessions_->get_loop(); - ev_io_start(loop, &rev_); - - if (ssl) { - SSL_set_accept_state(ssl); - read_ = &Http2Handler::tls_handshake; - write_ = &Http2Handler::tls_handshake; - } else { - read_ = &Http2Handler::read_clear; - write_ = &Http2Handler::write_clear; - } -} + : session_id_(session_id), session_(nullptr), sessions_(sessions), + ssl_(ssl), bev_(nullptr), settings_timerev_(nullptr), fd_(fd) {} Http2Handler::~Http2Handler() { on_session_closed(this, session_id_); + if (settings_timerev_) { + event_free(settings_timerev_); + } nghttp2_session_del(session_); if (ssl_) { SSL_set_shutdown(ssl_, SSL_RECEIVED_SHUTDOWN); - ERR_clear_error(); SSL_shutdown(ssl_); } - auto loop = sessions_->get_loop(); - ev_timer_stop(loop, &settings_timerev_); - ev_io_stop(loop, &rev_); - ev_io_stop(loop, &wev_); + if (bev_) { + bufferevent_disable(bev_, EV_READ | EV_WRITE); + bufferevent_free(bev_); + } if (ssl_) { SSL_free(ssl_); } @@ -562,311 +319,189 @@ void Http2Handler::remove_self() { sessions_->remove_handler(this); } -struct ev_loop *Http2Handler::get_loop() const { - return sessions_->get_loop(); +namespace { +void readcb(bufferevent *bev, void *arg) { + int rv; + auto handler = static_cast(arg); + + rv = handler->on_read(); + if (rv == -1) { + delete_handler(handler); + } } +} // namespace -Http2Handler::WriteBuf *Http2Handler::get_wb() { return &wb_; } +namespace { +void writecb(bufferevent *bev, void *arg) { + int rv; + auto handler = static_cast(arg); -void Http2Handler::start_settings_timer() { - ev_timer_start(sessions_->get_loop(), &settings_timerev_); + rv = handler->on_write(); + if (rv == -1) { + delete_handler(handler); + } } +} // namespace -int Http2Handler::fill_wb() { - if (data_pending_) { - auto n = std::min(wb_.wleft(), data_pendinglen_); - wb_.write(data_pending_, n); - if (n < data_pendinglen_) { - data_pending_ += n; - data_pendinglen_ -= n; - return 0; - } +namespace { +void eventcb(bufferevent *bev, short events, void *arg) { + auto handler = static_cast(arg); - data_pending_ = nullptr; - data_pendinglen_ = 0; - } + if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { + delete_handler(handler); - for (;;) { - const uint8_t *data; - auto datalen = nghttp2_session_mem_send(session_, &data); + return; + } - if (datalen < 0) { - std::cerr << "nghttp2_session_mem_send() returned error: " - << nghttp2_strerror(datalen) << std::endl; - return -1; - } - if (datalen == 0) { - break; - } - auto n = wb_.write(data, datalen); - if (n < static_cast(datalen)) { - data_pending_ = data + n; - data_pendinglen_ = datalen - n; - break; + if (events & BEV_EVENT_CONNECTED) { + if (handler->get_sessions()->get_config()->verbose) { + std::cerr << "SSL/TLS handshake completed" << std::endl; } - } - return 0; -} -int Http2Handler::read_clear() { - int rv; - std::array buf; + if (handler->verify_npn_result() != 0) { + delete_handler(handler); - for (;;) { - ssize_t nread; - while ((nread = read(fd_, buf.data(), buf.size())) == -1 && errno == EINTR) - ; - if (nread == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - break; - } - return -1; - } - if (nread == 0) { - return -1; + return; } - if (get_config()->hexdump) { - util::hexdump(stdout, buf.data(), nread); - } + if (handler->on_connect() != 0) { + delete_handler(handler); - rv = nghttp2_session_mem_recv(session_, buf.data(), nread); - if (rv < 0) { - if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) { - std::cerr << "nghttp2_session_mem_recv() returned error: " - << nghttp2_strerror(rv) << std::endl; - } - return -1; + return; } } - - return write_(*this); } +} // namespace -int Http2Handler::write_clear() { - auto loop = sessions_->get_loop(); - for (;;) { - if (wb_.rleft() > 0) { - ssize_t nwrite; - while ((nwrite = write(fd_, wb_.pos, wb_.rleft())) == -1 && - errno == EINTR) - ; - if (nwrite == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - ev_io_start(loop, &wev_); - return 0; - } - return -1; - } - wb_.drain(nwrite); - continue; - } - wb_.reset(); - if (fill_wb() != 0) { - return -1; - } - if (wb_.rleft() == 0) { - break; - } - } +int Http2Handler::setup_bev() { + auto evbase = sessions_->get_evbase(); - if (wb_.rleft() == 0) { - ev_io_stop(loop, &wev_); + if (ssl_) { + bev_ = bufferevent_openssl_socket_new( + evbase, fd_, ssl_, BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_DEFER_CALLBACKS); } else { - ev_io_start(loop, &wev_); + bev_ = bufferevent_socket_new(evbase, fd_, BEV_OPT_DEFER_CALLBACKS); } - if (nghttp2_session_want_read(session_) == 0 && - nghttp2_session_want_write(session_) == 0 && wb_.rleft() == 0) { - return -1; - } + bufferevent_enable(bev_, EV_READ); + bufferevent_setcb(bev_, readcb, writecb, eventcb, this); return 0; } -int Http2Handler::tls_handshake() { - ev_io_stop(sessions_->get_loop(), &wev_); - - ERR_clear_error(); +int Http2Handler::send() { + int rv; + uint8_t buf[16384]; + auto output = bufferevent_get_output(bev_); + util::EvbufferBuffer evbbuf(output, buf, sizeof(buf)); + for (;;) { + // Check buffer length and break if it is large enough. + if (evbuffer_get_length(output) + evbbuf.get_buflen() >= 65536) { + break; + } - auto rv = SSL_do_handshake(ssl_); + const uint8_t *data; + auto datalen = nghttp2_session_mem_send(session_, &data); - if (rv <= 0) { - auto err = SSL_get_error(ssl_, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - return 0; - case SSL_ERROR_WANT_WRITE: - ev_io_start(sessions_->get_loop(), &wev_); - return 0; - default: + if (datalen < 0) { + std::cerr << "nghttp2_session_mem_send() returned error: " + << nghttp2_strerror(datalen) << std::endl; + return -1; + } + if (datalen == 0) { + break; + } + rv = evbbuf.add(data, datalen); + if (rv != 0) { + std::cerr << "evbuffer_add() failed" << std::endl; return -1; } } - if (sessions_->get_config()->verbose) { - std::cerr << "SSL/TLS handshake completed" << std::endl; - } - - if (verify_npn_result() != 0) { + rv = evbbuf.flush(); + if (rv != 0) { + std::cerr << "evbuffer_add() failed" << std::endl; return -1; } - read_ = &Http2Handler::read_tls; - write_ = &Http2Handler::write_tls; + if (nghttp2_session_want_read(session_) == 0 && + nghttp2_session_want_write(session_) == 0 && + evbuffer_get_length(output) == 0) { - if (connection_made() != 0) { return -1; } - if (sessions_->get_config()->verbose) { - if (SSL_session_reused(ssl_)) { - std::cerr << "SSL/TLS session reused" << std::endl; - } - } - return 0; } -int Http2Handler::read_tls() { - std::array buf; +int Http2Handler::on_read() { + int rv; - ERR_clear_error(); + auto input = bufferevent_get_input(bev_); for (;;) { - auto rv = SSL_read(ssl_, buf.data(), buf.size()); + auto len = evbuffer_get_contiguous_space(input); - if (rv <= 0) { - auto err = SSL_get_error(ssl_, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - goto fin; - case SSL_ERROR_WANT_WRITE: - // renegotiation started - return -1; - default: - return -1; - } + if (len == 0) { + break; } - auto nread = rv; - - if (get_config()->hexdump) { - util::hexdump(stdout, buf.data(), nread); - } + auto data = evbuffer_pullup(input, len); - rv = nghttp2_session_mem_recv(session_, buf.data(), nread); + rv = nghttp2_session_mem_recv(session_, data, len); if (rv < 0) { - if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) { - std::cerr << "nghttp2_session_mem_recv() returned error: " - << nghttp2_strerror(rv) << std::endl; - } + std::cerr << "nghttp2_session_mem_recv() returned error: " + << nghttp2_strerror(rv) << std::endl; return -1; } - } - -fin: - return write_(*this); -} - -int Http2Handler::write_tls() { - auto loop = sessions_->get_loop(); - - ERR_clear_error(); - - for (;;) { - if (wb_.rleft() > 0) { - auto rv = SSL_write(ssl_, wb_.pos, wb_.rleft()); - if (rv <= 0) { - auto err = SSL_get_error(ssl_, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - // renegotiation started - return -1; - case SSL_ERROR_WANT_WRITE: - ev_io_start(sessions_->get_loop(), &wev_); - return 0; - default: - return -1; - } - } - - wb_.drain(rv); - continue; + if (evbuffer_drain(input, len) == -1) { + std::cerr << "evbuffer_drain() failed" << std::endl; } - wb_.reset(); - if (fill_wb() != 0) { - return -1; - } - if (wb_.rleft() == 0) { - break; - } - } - - if (wb_.rleft() == 0) { - ev_io_stop(loop, &wev_); - } else { - ev_io_start(loop, &wev_); - } - - if (nghttp2_session_want_read(session_) == 0 && - nghttp2_session_want_write(session_) == 0 && wb_.rleft() == 0) { - return -1; } - return 0; + return send(); } -int Http2Handler::on_read() { return read_(*this); } +int Http2Handler::on_write() { return send(); } -int Http2Handler::on_write() { return write_(*this); } +namespace { +void settings_timeout_cb(evutil_socket_t fd, short what, void *arg) { + auto hd = static_cast(arg); + hd->terminate_session(NGHTTP2_SETTINGS_TIMEOUT); + hd->on_write(); +} +} // namespace -int Http2Handler::connection_made() { +int Http2Handler::on_connect() { int r; - r = nghttp2_session_server_new(&session_, sessions_->get_callbacks(), this); - + r = nghttp2_session_server_new2(&session_, sessions_->get_callbacks(), this, + sessions_->get_config()->session_option); if (r != 0) { return r; } - - auto config = sessions_->get_config(); - std::array entry; + nghttp2_settings_entry entry[4]; size_t niv = 1; entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; - entry[0].value = config->max_concurrent_streams; + entry[0].value = 100; - if (config->header_table_size >= 0) { + if (sessions_->get_config()->header_table_size >= 0) { entry[niv].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; - entry[niv].value = config->header_table_size; - ++niv; - } - - if (config->window_bits != -1) { - entry[niv].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; - entry[niv].value = (1 << config->window_bits) - 1; + entry[niv].value = sessions_->get_config()->header_table_size; ++niv; } - - r = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(), niv); + r = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry, niv); if (r != 0) { return r; } - - if (config->connection_window_bits != -1) { - r = nghttp2_session_set_local_window_size( - session_, NGHTTP2_FLAG_NONE, 0, - (1 << config->connection_window_bits) - 1); - if (r != 0) { - return r; - } - } - - if (ssl_ && !nghttp2::ssl::check_http2_requirement(ssl_)) { - terminate_session(NGHTTP2_INADEQUATE_SECURITY); - } + assert(settings_timerev_ == nullptr); + settings_timerev_ = + evtimer_new(sessions_->get_evbase(), settings_timeout_cb, this); + // SETTINGS ACK timeout is 10 seconds for now + timeval settings_timeout = {10, 0}; + evtimer_add(settings_timerev_, &settings_timeout); return on_write(); } @@ -878,11 +513,11 @@ SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len); for (int i = 0; i < 2; ++i) { if (next_proto) { - auto proto = StringRef{next_proto, next_proto_len}; if (sessions_->get_config()->verbose) { + std::string proto(next_proto, next_proto + next_proto_len); std::cout << "The negotiated protocol: " << proto << std::endl; } - if (util::check_h2_is_selected(proto)) { + if (util::check_h2_is_selected(next_proto, next_proto_len)) { return 0; } break; @@ -902,103 +537,77 @@ return -1; } -int Http2Handler::submit_file_response(const StringRef &status, Stream *stream, - time_t last_modified, off_t file_length, - const std::string *content_type, +int Http2Handler::submit_file_response(const std::string &status, + Stream *stream, time_t last_modified, + off_t file_length, nghttp2_data_provider *data_prd) { + auto date_str = cached_date; + std::string content_length = util::utos(file_length); std::string last_modified_str; - auto nva = make_array(http2::make_nv_ls_nocopy(":status", status), - http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER), - http2::make_nv_ll("cache-control", "max-age=3600"), - http2::make_nv_ls("date", sessions_->get_cached_date()), - http2::make_nv_ll("", ""), http2::make_nv_ll("", ""), - http2::make_nv_ll("", ""), http2::make_nv_ll("", "")); - size_t nvlen = 4; - if (!get_config()->no_content_length) { - nva[nvlen++] = http2::make_nv_ls_nocopy( - "content-length", - util::make_string_ref_uint(stream->balloc, file_length)); - } + auto nva = std::vector{ + http2::make_nv_ls(":status", status), + http2::make_nv_ls("server", NGHTTPD_SERVER), + http2::make_nv_ls("content-length", content_length), + http2::make_nv_ll("cache-control", "max-age=3600"), + http2::make_nv_ls("date", *date_str), + }; if (last_modified != 0) { last_modified_str = util::http_date(last_modified); - nva[nvlen++] = http2::make_nv_ls("last-modified", last_modified_str); - } - if (content_type) { - nva[nvlen++] = http2::make_nv_ls("content-type", *content_type); + nva.push_back(http2::make_nv_ls("last-modified", last_modified_str)); } - auto &trailer_names = get_config()->trailer_names; - if (!trailer_names.empty()) { - nva[nvlen++] = http2::make_nv_ls_nocopy("trailer", trailer_names); - } - return nghttp2_submit_response(session_, stream->stream_id, nva.data(), nvlen, - data_prd); + return nghttp2_submit_response(session_, stream->stream_id, nva.data(), + nva.size(), data_prd); } -int Http2Handler::submit_response(const StringRef &status, int32_t stream_id, - const HeaderRefs &headers, +int Http2Handler::submit_response(const std::string &status, int32_t stream_id, + const Headers &headers, nghttp2_data_provider *data_prd) { - auto nva = std::vector(); - nva.reserve(4 + headers.size()); - nva.push_back(http2::make_nv_ls_nocopy(":status", status)); - nva.push_back(http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER)); - nva.push_back(http2::make_nv_ls("date", sessions_->get_cached_date())); - - if (data_prd) { - auto &trailer_names = get_config()->trailer_names; - if (!trailer_names.empty()) { - nva.push_back(http2::make_nv_ls_nocopy("trailer", trailer_names)); - } - } - + auto date_str = cached_date; + auto nva = + std::vector{http2::make_nv_ls(":status", status), + http2::make_nv_ls("server", NGHTTPD_SERVER), + http2::make_nv_ls("date", *date_str)}; for (auto &nv : headers) { - nva.push_back(http2::make_nv_nocopy(nv.name, nv.value, nv.no_index)); + nva.push_back(http2::make_nv(nv.name, nv.value, nv.no_index)); } int r = nghttp2_submit_response(session_, stream_id, nva.data(), nva.size(), data_prd); return r; } -int Http2Handler::submit_response(const StringRef &status, int32_t stream_id, +int Http2Handler::submit_response(const std::string &status, int32_t stream_id, nghttp2_data_provider *data_prd) { - auto nva = make_array(http2::make_nv_ls_nocopy(":status", status), - http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER), - http2::make_nv_ls("date", sessions_->get_cached_date()), - http2::make_nv_ll("", "")); - size_t nvlen = 3; - - if (data_prd) { - auto &trailer_names = get_config()->trailer_names; - if (!trailer_names.empty()) { - nva[nvlen++] = http2::make_nv_ls_nocopy("trailer", trailer_names); - } - } - - return nghttp2_submit_response(session_, stream_id, nva.data(), nvlen, + auto nva = + std::vector{http2::make_nv_ls(":status", status), + http2::make_nv_ls("server", NGHTTPD_SERVER)}; + return nghttp2_submit_response(session_, stream_id, nva.data(), nva.size(), data_prd); } int Http2Handler::submit_non_final_response(const std::string &status, int32_t stream_id) { - auto nva = make_array(http2::make_nv_ls(":status", status)); + auto nva = std::vector{http2::make_nv_ls(":status", status)}; return nghttp2_submit_headers(session_, NGHTTP2_FLAG_NONE, stream_id, nullptr, nva.data(), nva.size(), nullptr); } int Http2Handler::submit_push_promise(Stream *stream, - const StringRef &push_path) { - auto authority = stream->header.authority; - - if (authority.empty()) { - authority = stream->header.host; - } - - auto scheme = get_config()->no_tls ? StringRef::from_lit("http") - : StringRef::from_lit("https"); - - auto nva = make_array(http2::make_nv_ll(":method", "GET"), - http2::make_nv_ls_nocopy(":path", push_path), - http2::make_nv_ls_nocopy(":scheme", scheme), - http2::make_nv_ls_nocopy(":authority", authority)); + const std::string &push_path) { + auto itr = + std::lower_bound(std::begin(stream->headers), std::end(stream->headers), + Header(":authority", "")); + + if (itr == std::end(stream->headers) || (*itr).name != ":authority") { + itr = std::lower_bound(std::begin(stream->headers), + std::end(stream->headers), Header("host", "")); + } + + auto nva = std::vector{ + http2::make_nv_ll(":method", "GET"), + http2::make_nv_ls(":path", push_path), + get_config()->no_tls ? http2::make_nv_ll(":scheme", "http") + : http2::make_nv_ll(":scheme", "https"), + http2::make_nv_ls(":authority", (*itr).value)}; auto promised_stream_id = nghttp2_submit_push_promise( session_, NGHTTP2_FLAG_END_HEADERS, stream->stream_id, nva.data(), @@ -1008,15 +617,9 @@ return promised_stream_id; } - auto promised_stream = make_unique(this, promised_stream_id); - - auto &promised_header = promised_stream->header; - promised_header.method = StringRef::from_lit("GET"); - promised_header.path = push_path; - promised_header.scheme = scheme; - promised_header.authority = - make_string_ref(promised_stream->balloc, authority); + auto promised_stream = util::make_unique(this, promised_stream_id); + append_nv(promised_stream.get(), nva); add_stream(promised_stream_id, std::move(promised_stream)); return 0; @@ -1057,7 +660,11 @@ } void Http2Handler::remove_settings_timer() { - ev_timer_stop(sessions_->get_loop(), &settings_timerev_); + if (settings_timerev_) { + evtimer_del(settings_timerev_); + event_free(settings_timerev_); + settings_timerev_ = nullptr; + } } void Http2Handler::terminate_session(uint32_t error_code) { @@ -1067,34 +674,24 @@ ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { - int rv; auto hd = static_cast(user_data); auto stream = hd->get_stream(stream_id); - auto nread = std::min(stream->body_length - stream->body_offset, - static_cast(length)); + int fd = source->fd; + ssize_t nread; - *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY; + while ((nread = read(fd, buf, length)) == -1 && errno == EINTR) + ; - if (nread == 0 || stream->body_length == stream->body_offset + nread) { - *data_flags |= NGHTTP2_DATA_FLAG_EOF; + if (nread == -1) { + remove_stream_read_timeout(stream); + remove_stream_write_timeout(stream); - auto config = hd->get_config(); - if (!config->trailer.empty()) { - std::vector nva; - nva.reserve(config->trailer.size()); - for (auto &kv : config->trailer) { - nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); - } - rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size()); - if (rv != 0) { - if (nghttp2_is_fatal(rv)) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - } else { - *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM; - } - } + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + + if (nread == 0) { + *data_flags |= NGHTTP2_DATA_FLAG_EOF; if (nghttp2_session_get_stream_remote_close(session, stream_id) == 0) { remove_stream_read_timeout(stream); @@ -1104,102 +701,76 @@ } } - return nread; -} - -namespace { -void prepare_status_response(Stream *stream, Http2Handler *hd, int status) { - auto sessions = hd->get_sessions(); - auto status_page = sessions->get_server()->get_status_page(status); - auto file_ent = &status_page->file_ent; - - // we don't set stream->file_ent since we don't want to expire it. - stream->body_length = file_ent->length; - nghttp2_data_provider data_prd; - data_prd.source.fd = file_ent->fd; - data_prd.read_callback = file_read_callback; - - HeaderRefs headers; - headers.reserve(2); - headers.emplace_back(StringRef::from_lit("content-type"), - StringRef::from_lit("text/html; charset=UTF-8")); - headers.emplace_back( - StringRef::from_lit("content-length"), - util::make_string_ref_uint(stream->balloc, file_ent->length)); - hd->submit_response(StringRef{status_page->status}, stream->stream_id, - headers, &data_prd); + return nread; } -} // namespace namespace { -void prepare_echo_response(Stream *stream, Http2Handler *hd) { - auto length = lseek(stream->file_ent->fd, 0, SEEK_END); - if (length == -1) { - hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR); - return; - } - stream->body_length = length; - if (lseek(stream->file_ent->fd, 0, SEEK_SET) == -1) { - hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR); +void prepare_status_response(Stream *stream, Http2Handler *hd, + const std::string &status) { + int pipefd[2]; + if (status == STATUS_304 || pipe(pipefd) == -1) { + hd->submit_response(status, stream->stream_id, 0); return; } - nghttp2_data_provider data_prd; - data_prd.source.fd = stream->file_ent->fd; - data_prd.read_callback = file_read_callback; - - HeaderRefs headers; - headers.emplace_back(StringRef::from_lit("nghttpd-response"), - StringRef::from_lit("echo")); - if (!hd->get_config()->no_content_length) { - headers.emplace_back(StringRef::from_lit("content-length"), - util::make_string_ref_uint(stream->balloc, length)); - } + std::string body; + body.reserve(256); + body = ""; + body += status; + body += "

"; + body += status; + body += "


"; + body += NGHTTPD_SERVER; + body += " at port "; + body += util::utos(hd->get_config()->port); + body += "
"; + body += ""; - hd->submit_response(StringRef::from_lit("200"), stream->stream_id, headers, - &data_prd); -} -} // namespace + Headers headers; + if (hd->get_config()->error_gzip) { + gzFile write_fd = gzdopen(pipefd[1], "w"); + gzwrite(write_fd, body.c_str(), body.size()); + gzclose(write_fd); + headers.emplace_back("content-encoding", "gzip"); + } else { + ssize_t rv; -namespace { -bool prepare_upload_temp_store(Stream *stream, Http2Handler *hd) { - auto sessions = hd->get_sessions(); + while ((rv = write(pipefd[1], body.c_str(), body.size())) == -1 && + errno == EINTR) + ; - char tempfn[] = "/tmp/nghttpd.temp.XXXXXX"; - auto fd = mkstemp(tempfn); - if (fd == -1) { - return false; + if (rv != static_cast(body.size())) { + std::cerr << "Could not write all response body: " << rv << std::endl; + } } - unlink(tempfn); - // Ordinary request never start with "echo:". The length is 0 for - // now. We will update it when we get whole request body. - auto path = std::string("echo:") + tempfn; - stream->file_ent = - sessions->cache_fd(path, FileEntry(path, 0, 0, fd, nullptr, 0, true)); - stream->echo_upload = true; - return true; + close(pipefd[1]); + + stream->file = pipefd[0]; + nghttp2_data_provider data_prd; + data_prd.source.fd = pipefd[0]; + data_prd.read_callback = file_read_callback; + headers.emplace_back("content-type", "text/html; charset=UTF-8"); + hd->submit_response(status, stream->stream_id, headers, &data_prd); } } // namespace namespace { void prepare_redirect_response(Stream *stream, Http2Handler *hd, - const StringRef &path, int status) { - auto scheme = stream->header.scheme; - - auto authority = stream->header.authority; - if (authority.empty()) { - authority = stream->header.host; - } + const std::string &path, + const std::string &status) { + auto scheme = http2::get_unique_header(stream->headers, ":scheme"); + auto authority = http2::get_unique_header(stream->headers, ":authority"); + if (!authority) { + authority = http2::get_unique_header(stream->headers, ":host"); + } + + auto redirect_url = scheme->value; + redirect_url += "://"; + redirect_url += authority->value; + redirect_url += path; - auto location = concat_string_ref( - stream->balloc, scheme, StringRef::from_lit("://"), authority, path); + auto headers = Headers{{"location", redirect_url}}; - auto headers = HeaderRefs{{StringRef::from_lit("location"), location}}; - - auto sessions = hd->get_sessions(); - auto status_page = sessions->get_server()->get_status_page(status); - - hd->submit_response(StringRef{status_page->status}, stream->stream_id, - headers, nullptr); + hd->submit_response(status, stream->stream_id, headers, nullptr); } } // namespace @@ -1207,188 +778,113 @@ void prepare_response(Stream *stream, Http2Handler *hd, bool allow_push = true) { int rv; - auto reqpath = stream->header.path; - if (reqpath.empty()) { - prepare_status_response(stream, hd, 405); - return; - } - - auto ims = stream->header.ims; + auto reqpath = + (*std::lower_bound(std::begin(stream->headers), std::end(stream->headers), + Header(":path", ""))).value; + auto ims = + std::lower_bound(std::begin(stream->headers), std::end(stream->headers), + Header("if-modified-since", "")); time_t last_mod = 0; bool last_mod_found = false; - if (!ims.empty()) { + if (ims != std::end(stream->headers) && (*ims).name == "if-modified-since") { last_mod_found = true; - last_mod = util::parse_http_date(ims); + last_mod = util::parse_http_date((*ims).value); } - - StringRef raw_path, raw_query; - auto query_pos = std::find(std::begin(reqpath), std::end(reqpath), '?'); - if (query_pos != std::end(reqpath)) { + auto query_pos = reqpath.find("?"); + std::string url; + if (query_pos != std::string::npos) { // Do not response to this request to allow clients to test timeouts. - if (util::streq_l("nghttpd_do_not_respond_to_req=yes", - StringRef{query_pos, std::end(reqpath)})) { + if (reqpath.find("nghttpd_do_not_respond_to_req=yes", query_pos) != + std::string::npos) { return; } - raw_path = StringRef{std::begin(reqpath), query_pos}; - raw_query = StringRef{query_pos, std::end(reqpath)}; - } else { - raw_path = reqpath; - } - - auto sessions = hd->get_sessions(); - - StringRef path; - if (std::find(std::begin(raw_path), std::end(raw_path), '%') == - std::end(raw_path)) { - path = raw_path; + url = reqpath.substr(0, query_pos); } else { - path = util::percent_decode(stream->balloc, raw_path); + url = reqpath; } - path = http2::path_join(stream->balloc, StringRef{}, StringRef{}, path, - StringRef{}); - - if (std::find(std::begin(path), std::end(path), '\\') != std::end(path)) { - if (stream->file_ent) { - sessions->release_fd(stream->file_ent); - stream->file_ent = nullptr; - } - prepare_status_response(stream, hd, 404); + url = util::percentDecode(url.begin(), url.end()); + if (!util::check_path(url)) { + prepare_status_response(stream, hd, STATUS_404); return; } - - if (!hd->get_config()->push.empty()) { - auto push_itr = hd->get_config()->push.find(path.str()); - if (allow_push && push_itr != std::end(hd->get_config()->push)) { - for (auto &push_path : (*push_itr).second) { - rv = hd->submit_push_promise(stream, StringRef{push_path}); - if (rv != 0) { - std::cerr << "nghttp2_submit_push_promise() returned error: " - << nghttp2_strerror(rv) << std::endl; - } + auto push_itr = hd->get_config()->push.find(url); + if (allow_push && push_itr != std::end(hd->get_config()->push)) { + for (auto &push_path : (*push_itr).second) { + rv = hd->submit_push_promise(stream, push_path); + if (rv != 0) { + std::cerr << "nghttp2_submit_push_promise() returned error: " + << nghttp2_strerror(rv) << std::endl; } } } + std::string path = hd->get_config()->htdocs + url; + if (path[path.size() - 1] == '/') { + path += DEFAULT_HTML; + } + int file = open(path.c_str(), O_RDONLY | O_BINARY); + if (file == -1) { + prepare_status_response(stream, hd, STATUS_404); - std::string file_path; - { - auto len = hd->get_config()->htdocs.size() + path.size(); - - auto trailing_slash = path[path.size() - 1] == '/'; - if (trailing_slash) { - len += DEFAULT_HTML.size(); - } - - file_path.resize(len); - - auto p = &file_path[0]; - - auto &htdocs = hd->get_config()->htdocs; - p = std::copy(std::begin(htdocs), std::end(htdocs), p); - p = std::copy(std::begin(path), std::end(path), p); - if (trailing_slash) { - std::copy(std::begin(DEFAULT_HTML), std::end(DEFAULT_HTML), p); - } - } - - if (stream->echo_upload) { - assert(stream->file_ent); - prepare_echo_response(stream, hd); return; } - auto file_ent = sessions->get_cached_fd(file_path); - - if (file_ent == nullptr) { - int file = open(file_path.c_str(), O_RDONLY | O_BINARY); - if (file == -1) { - prepare_status_response(stream, hd, 404); - - return; - } - - struct stat buf; - - if (fstat(file, &buf) == -1) { - close(file); - prepare_status_response(stream, hd, 404); - - return; - } - - if (buf.st_mode & S_IFDIR) { - close(file); - - auto reqpath = concat_string_ref(stream->balloc, raw_path, - StringRef::from_lit("/"), raw_query); - - prepare_redirect_response(stream, hd, reqpath, 301); + struct stat buf; - return; - } - - const std::string *content_type = nullptr; - - auto ext = file_path.c_str() + file_path.size() - 1; - for (; file_path.c_str() < ext && *ext != '.' && *ext != '/'; --ext) - ; - if (*ext == '.') { - ++ext; - - const auto &mime_types = hd->get_config()->mime_types; - auto content_type_itr = mime_types.find(ext); - if (content_type_itr != std::end(mime_types)) { - content_type = &(*content_type_itr).second; - } - } + if (fstat(file, &buf) == -1) { + close(file); + prepare_status_response(stream, hd, STATUS_404); - file_ent = sessions->cache_fd( - file_path, FileEntry(file_path, buf.st_size, buf.st_mtime, file, - content_type, ev_now(sessions->get_loop()))); + return; } - stream->file_ent = file_ent; + if (buf.st_mode & S_IFDIR) { + close(file); - if (last_mod_found && file_ent->mtime <= last_mod) { - hd->submit_response(StringRef::from_lit("304"), stream->stream_id, nullptr); + if (query_pos == std::string::npos) { + reqpath += "/"; + } else { + reqpath.insert(query_pos, "/"); + } - return; - } + prepare_redirect_response(stream, hd, reqpath, STATUS_301); - auto method = stream->header.method; - if (method == StringRef::from_lit("HEAD")) { - hd->submit_file_response(StringRef::from_lit("200"), stream, - file_ent->mtime, file_ent->length, - file_ent->content_type, nullptr); return; } - stream->body_length = file_ent->length; + stream->file = file; nghttp2_data_provider data_prd; - data_prd.source.fd = file_ent->fd; + data_prd.source.fd = file; data_prd.read_callback = file_read_callback; - hd->submit_file_response(StringRef::from_lit("200"), stream, file_ent->mtime, - file_ent->length, file_ent->content_type, &data_prd); + if (last_mod_found && buf.st_mtime <= last_mod) { + prepare_status_response(stream, hd, STATUS_304); + + return; + } + + hd->submit_file_response(STATUS_200, stream, buf.st_mtime, buf.st_size, + &data_prd); } } // namespace namespace { -int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame, - nghttp2_rcbuf *name, nghttp2_rcbuf *value, - uint8_t flags, void *user_data) { - auto hd = static_cast(user_data); - - auto namebuf = nghttp2_rcbuf_get_buf(name); - auto valuebuf = nghttp2_rcbuf_get_buf(value); +const char *REQUIRED_HEADERS[] = {":method", ":path", ":scheme", nullptr}; +} // namespace +namespace { +int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, + const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, uint8_t flags, + void *user_data) { + auto hd = static_cast(user_data); if (hd->get_config()->verbose) { print_session_id(hd->session_id()); - verbose_on_header_callback(session, frame, namebuf.base, namebuf.len, - valuebuf.base, valuebuf.len, flags, user_data); + verbose_on_header_callback(session, frame, name, namelen, value, valuelen, + flags, user_data); } if (frame->hd.type != NGHTTP2_HEADERS || frame->headers.cat != NGHTTP2_HCAT_REQUEST) { @@ -1398,54 +894,40 @@ if (!stream) { return 0; } - - if (stream->header_buffer_size + namebuf.len + valuebuf.len > 64_k) { - hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR); + if (!http2::check_nv(name, namelen, value, valuelen)) { return 0; } - stream->header_buffer_size += namebuf.len + valuebuf.len; + if (namelen > 0 && name[0] == ':') { + if ((!stream->headers.empty() && + stream->headers.back().name.c_str()[0] != ':') || + !http2::check_http2_request_pseudo_header(name, namelen)) { - auto token = http2::lookup_token(namebuf.base, namebuf.len); + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + } - auto &header = stream->header; + http2::add_header(stream->headers, name, namelen, value, valuelen, + flags & NGHTTP2_NV_FLAG_NO_INDEX); + return 0; +} +} // namespace - switch (token) { - case http2::HD__METHOD: - header.method = StringRef{valuebuf.base, valuebuf.len}; - header.rcbuf.method = value; - nghttp2_rcbuf_incref(value); - break; - case http2::HD__SCHEME: - header.scheme = StringRef{valuebuf.base, valuebuf.len}; - header.rcbuf.scheme = value; - nghttp2_rcbuf_incref(value); - break; - case http2::HD__AUTHORITY: - header.authority = StringRef{valuebuf.base, valuebuf.len}; - header.rcbuf.authority = value; - nghttp2_rcbuf_incref(value); - break; - case http2::HD_HOST: - header.host = StringRef{valuebuf.base, valuebuf.len}; - header.rcbuf.host = value; - nghttp2_rcbuf_incref(value); - break; - case http2::HD__PATH: - header.path = StringRef{valuebuf.base, valuebuf.len}; - header.rcbuf.path = value; - nghttp2_rcbuf_incref(value); - break; - case http2::HD_IF_MODIFIED_SINCE: - header.ims = StringRef{valuebuf.base, valuebuf.len}; - header.rcbuf.ims = value; - nghttp2_rcbuf_incref(value); - break; - case http2::HD_EXPECT: - header.expect = StringRef{valuebuf.base, valuebuf.len}; - header.rcbuf.expect = value; - nghttp2_rcbuf_incref(value); - break; +namespace { +int setup_stream_timeout(Stream *stream) { + auto hd = stream->handler; + auto evbase = hd->get_sessions()->get_evbase(); + + stream->rtimer = evtimer_new(evbase, stream_timeout_cb, stream); + if (!stream->rtimer) { + return -1; + } + + stream->wtimer = evtimer_new(evbase, stream_timeout_cb, stream); + if (!stream->wtimer) { + return -1; } return 0; @@ -1462,7 +944,11 @@ return 0; } - auto stream = make_unique(hd, frame->hd.stream_id); + auto stream = util::make_unique(hd, frame->hd.stream_id); + if (setup_stream_timeout(stream.get()) != 0) { + hd->submit_rst_stream(stream.get(), NGHTTP2_INTERNAL_ERROR); + return 0; + } add_stream_read_timeout(stream.get()); @@ -1490,7 +976,7 @@ if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { remove_stream_read_timeout(stream); - if (stream->echo_upload || !hd->get_config()->early_response) { + if (!hd->get_config()->early_response) { prepare_response(stream, hd); } } else { @@ -1507,28 +993,40 @@ if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { - auto expect100 = stream->header.expect; + http2::normalize_headers(stream->headers); + if (!http2::check_http2_request_headers(stream->headers)) { + hd->submit_rst_stream(stream, NGHTTP2_PROTOCOL_ERROR); + return 0; + } + for (size_t i = 0; REQUIRED_HEADERS[i]; ++i) { + if (!http2::get_unique_header(stream->headers, REQUIRED_HEADERS[i])) { + hd->submit_rst_stream(stream, NGHTTP2_PROTOCOL_ERROR); + return 0; + } + } + // intermediary translating from HTTP/1 request to HTTP/2 may + // not produce :authority header field. In this case, it should + // provide host HTTP/1.1 header field. + if (!http2::get_unique_header(stream->headers, ":authority") && + !http2::get_unique_header(stream->headers, "host")) { + hd->submit_rst_stream(stream, NGHTTP2_PROTOCOL_ERROR); + return 0; + } + + auto expect100 = http2::get_header(stream->headers, "expect"); - if (util::strieq_l("100-continue", expect100)) { + if (expect100 && util::strieq("100-continue", expect100->value.c_str())) { hd->submit_non_final_response("100", frame->hd.stream_id); } - auto method = stream->header.method; - if (hd->get_config()->echo_upload && - (method == StringRef::from_lit("POST") || - method == StringRef::from_lit("PUT"))) { - if (!prepare_upload_temp_store(stream, hd)) { - hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR); - return 0; - } - } else if (hd->get_config()->early_response) { + if (hd->get_config()->early_response) { prepare_response(stream, hd); } } if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { remove_stream_read_timeout(stream); - if (stream->echo_upload || !hd->get_config()->early_response) { + if (!hd->get_config()->early_response) { prepare_response(stream, hd); } } else { @@ -1542,6 +1040,11 @@ hd->remove_settings_timer(); } break; + case NGHTTP2_PUSH_PROMISE: + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->push_promise.promised_stream_id, + NGHTTP2_REFUSED_STREAM); + break; default: break; } @@ -1583,15 +1086,6 @@ break; } - case NGHTTP2_SETTINGS: { - if (frame->hd.flags & NGHTTP2_FLAG_ACK) { - return 0; - } - - hd->start_settings_timer(); - - break; - } case NGHTTP2_PUSH_PROMISE: { auto promised_stream_id = frame->push_promise.promised_stream_id; auto promised_stream = hd->get_stream(promised_stream_id); @@ -1601,6 +1095,13 @@ return 0; } + if (setup_stream_timeout(promised_stream) != 0) { + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, promised_stream_id, + NGHTTP2_INTERNAL_ERROR); + + return 0; + } + add_stream_read_timeout_if_pending(stream); add_stream_write_timeout(stream); @@ -1612,58 +1113,6 @@ } // namespace namespace { -int send_data_callback(nghttp2_session *session, nghttp2_frame *frame, - const uint8_t *framehd, size_t length, - nghttp2_data_source *source, void *user_data) { - auto hd = static_cast(user_data); - auto wb = hd->get_wb(); - auto padlen = frame->data.padlen; - auto stream = hd->get_stream(frame->hd.stream_id); - - if (wb->wleft() < 9 + length + padlen) { - return NGHTTP2_ERR_WOULDBLOCK; - } - - int fd = source->fd; - - auto p = wb->last; - - p = std::copy_n(framehd, 9, p); - - if (padlen) { - *p++ = padlen - 1; - } - - while (length) { - ssize_t nread; - while ((nread = pread(fd, p, length, stream->body_offset)) == -1 && - errno == EINTR) - ; - - if (nread == -1) { - remove_stream_read_timeout(stream); - remove_stream_write_timeout(stream); - - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - - stream->body_offset += nread; - length -= nread; - p += nread; - } - - if (padlen) { - std::fill(p, p + padlen - 1, 0); - p += padlen - 1; - } - - wb->last = p; - - return 0; -} -} // namespace - -namespace { ssize_t select_padding_callback(nghttp2_session *session, const nghttp2_frame *frame, size_t max_payload, void *user_data) { @@ -1683,21 +1132,6 @@ return 0; } - if (stream->echo_upload) { - assert(stream->file_ent); - while (len) { - ssize_t n; - while ((n = write(stream->file_ent->fd, data, len)) == -1 && - errno == EINTR) - ; - if (n == -1) { - hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR); - return 0; - } - len -= n; - data += n; - } - } // TODO Handle POST add_stream_read_timeout(stream); @@ -1735,23 +1169,17 @@ if (config->verbose) { nghttp2_session_callbacks_set_on_invalid_frame_recv_callback( callbacks, verbose_on_invalid_frame_recv_callback); - - nghttp2_session_callbacks_set_error_callback(callbacks, - verbose_error_callback); } nghttp2_session_callbacks_set_on_data_chunk_recv_callback( callbacks, on_data_chunk_recv_callback); - nghttp2_session_callbacks_set_on_header_callback2(callbacks, - on_header_callback2); + nghttp2_session_callbacks_set_on_header_callback(callbacks, + on_header_callback); nghttp2_session_callbacks_set_on_begin_headers_callback( callbacks, on_begin_headers_callback); - nghttp2_session_callbacks_set_send_data_callback(callbacks, - send_data_callback); - if (config->padding) { nghttp2_session_callbacks_set_select_padding_callback( callbacks, select_padding_callback); @@ -1763,53 +1191,38 @@ int fd; }; -struct Worker { - std::unique_ptr sessions; - ev_async w; - // protectes q - std::mutex m; - std::deque q; -}; - namespace { -void worker_acceptcb(struct ev_loop *loop, ev_async *w, int revents) { - auto worker = static_cast(w->data); - auto &sessions = worker->sessions; - - std::deque q; - { - std::lock_guard lock(worker->m); - q.swap(worker->q); - } - - for (auto c : q) { - sessions->accept_connection(c.fd); +void worker_readcb(bufferevent *bev, void *arg) { + auto sessions = static_cast(arg); + auto input = bufferevent_get_input(bev); + while (evbuffer_get_length(input) >= sizeof(ClientInfo)) { + ClientInfo client; + if (evbuffer_remove(input, &client, sizeof(client)) == -1) { + std::cerr << "evbuffer_remove() failed" << std::endl; + } + sessions->accept_connection(client.fd); } } } // namespace namespace { -void run_worker(Worker *worker) { - auto loop = worker->sessions->get_loop(); - - ev_run(loop, 0); -} -} // namespace - -namespace { -int get_ev_loop_flags() { - if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) { - return ev_recommended_backends() | EVBACKEND_KQUEUE; - } +void run_worker(int thread_id, int fd, SSL_CTX *ssl_ctx, const Config *config) { + auto evbase = event_base_new(); + auto bev = bufferevent_socket_new(evbase, fd, BEV_OPT_DEFER_CALLBACKS | + BEV_OPT_CLOSE_ON_FREE); + auto sessions = Sessions(evbase, config, ssl_ctx); - return 0; + bufferevent_enable(bev, EV_READ); + bufferevent_setcb(bev, worker_readcb, nullptr, nullptr, &sessions); + event_base_loop(evbase, 0); } } // namespace -class AcceptHandler { +class ListenEventHandler { public: - AcceptHandler(HttpServer *sv, Sessions *sessions, const Config *config) + ListenEventHandler(Sessions *sessions, const Config *config) : sessions_(sessions), config_(config), next_worker_(0) { + int rv; if (config_->num_worker == 1) { return; } @@ -1817,42 +1230,47 @@ if (config_->verbose) { std::cerr << "spawning thread #" << i << std::endl; } - auto worker = make_unique(); - auto loop = ev_loop_new(get_ev_loop_flags()); - worker->sessions = - make_unique(sv, loop, config_, sessions_->get_ssl_ctx()); - ev_async_init(&worker->w, worker_acceptcb); - worker->w.data = worker.get(); - ev_async_start(loop, &worker->w); - - auto t = std::thread(run_worker, worker.get()); + int socks[2]; + rv = socketpair(AF_UNIX, SOCK_STREAM, 0, socks); + if (rv == -1) { + std::cerr << "socketpair() failed: errno=" << errno << std::endl; + assert(0); + } + evutil_make_socket_nonblocking(socks[0]); + evutil_make_socket_nonblocking(socks[1]); + auto bev = bufferevent_socket_new(sessions_->get_evbase(), socks[0], + BEV_OPT_DEFER_CALLBACKS | + BEV_OPT_CLOSE_ON_FREE); + if (!bev) { + std::cerr << "bufferevent_socket_new() failed" << std::endl; + assert(0); + } + workers_.push_back(bev); + auto t = std::thread(run_worker, i, socks[1], sessions_->get_ssl_ctx(), + config_); t.detach(); - workers_.push_back(std::move(worker)); } } - void accept_connection(int fd) { + void accept_connection(int fd, sockaddr *addr, int addrlen) { if (config_->num_worker == 1) { sessions_->accept_connection(fd); return; } - // Dispatch client to the one of the worker threads, in a round // robin manner. - auto &worker = workers_[next_worker_]; + auto client = ClientInfo{fd}; + bufferevent_write(workers_[next_worker_], &client, sizeof(client)); if (next_worker_ == config_->num_worker - 1) { next_worker_ = 0; } else { ++next_worker_; } - { - std::lock_guard lock(worker->m); - worker->q.push_back({fd}); - } - ev_async_send(worker->sessions->get_loop(), &worker->w); } private: - std::vector> workers_; + // In multi threading mode, this includes bufferevent to dispatch + // client to the worker threads. + std::vector workers_; Sessions *sessions_; const Config *config_; // In multi threading mode, this points to the next thread that @@ -1860,109 +1278,7 @@ size_t next_worker_; }; -namespace { -void acceptcb(struct ev_loop *loop, ev_io *w, int revents); -} // namespace - -class ListenEventHandler { -public: - ListenEventHandler(Sessions *sessions, int fd, - std::shared_ptr acceptor) - : acceptor_(acceptor), sessions_(sessions), fd_(fd) { - ev_io_init(&w_, acceptcb, fd, EV_READ); - w_.data = this; - ev_io_start(sessions_->get_loop(), &w_); - } - void accept_connection() { - for (;;) { -#ifdef HAVE_ACCEPT4 - auto fd = accept4(fd_, nullptr, nullptr, SOCK_NONBLOCK); -#else // !HAVE_ACCEPT4 - auto fd = accept(fd_, nullptr, nullptr); -#endif // !HAVE_ACCEPT4 - if (fd == -1) { - break; - } -#ifndef HAVE_ACCEPT4 - util::make_socket_nonblocking(fd); -#endif // !HAVE_ACCEPT4 - acceptor_->accept_connection(fd); - } - } - -private: - ev_io w_; - std::shared_ptr acceptor_; - Sessions *sessions_; - int fd_; -}; - -namespace { -void acceptcb(struct ev_loop *loop, ev_io *w, int revents) { - auto handler = static_cast(w->data); - handler->accept_connection(); -} -} // namespace - -namespace { -FileEntry make_status_body(int status, uint16_t port) { - BlockAllocator balloc(1024, 1024); - - auto status_string = http2::get_status_string(balloc, status); - - std::string body; - body = ""; - body += status_string; - body += "

"; - body += status_string; - body += "


"; - body += NGHTTPD_SERVER; - body += " at port "; - body += util::utos(port); - body += "
"; - body += ""; - - char tempfn[] = "/tmp/nghttpd.temp.XXXXXX"; - int fd = mkstemp(tempfn); - if (fd == -1) { - auto error = errno; - std::cerr << "Could not open status response body file: errno=" << error; - assert(0); - } - unlink(tempfn); - ssize_t nwrite; - while ((nwrite = write(fd, body.c_str(), body.size())) == -1 && - errno == EINTR) - ; - if (nwrite == -1) { - auto error = errno; - std::cerr << "Could not write status response body into file: errno=" - << error; - assert(0); - } - - return FileEntry(util::utos(status), nwrite, 0, fd, nullptr, 0); -} -} // namespace - -// index into HttpServer::status_pages_ -enum { - IDX_200, - IDX_301, - IDX_400, - IDX_404, - IDX_405, -}; - -HttpServer::HttpServer(const Config *config) : config_(config) { - status_pages_ = std::vector{ - {"200", make_status_body(200, config_->port)}, - {"301", make_status_body(301, config_->port)}, - {"400", make_status_body(400, config_->port)}, - {"404", make_status_body(404, config_->port)}, - {"405", make_status_body(405, config_->port)}, - }; -} +HttpServer::HttpServer(const Config *config) : config_(config) {} namespace { int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len, @@ -1983,16 +1299,27 @@ } // namespace namespace { -int start_listen(HttpServer *sv, struct ev_loop *loop, Sessions *sessions, - const Config *config) { +void evlistener_acceptcb(evconnlistener *listener, int fd, sockaddr *addr, + int addrlen, void *arg) { + auto handler = static_cast(arg); + handler->accept_connection(fd, addr, addrlen); +} +} // namespace + +namespace { +void evlistener_errorcb(evconnlistener *listener, void *ptr) { + std::cerr << "Accepting incoming connection failed" << std::endl; +} +} // namespace + +namespace { +int start_listen(event_base *evbase, Sessions *sessions, const Config *config) { + addrinfo hints; int r; - bool ok = false; - const char *addr = nullptr; - std::shared_ptr acceptor; auto service = util::utos(config->port); - addrinfo hints{}; + memset(&hints, 0, sizeof(addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; @@ -2000,17 +1327,16 @@ hints.ai_flags |= AI_ADDRCONFIG; #endif // AI_ADDRCONFIG - if (!config->address.empty()) { - addr = config->address.c_str(); - } + auto listen_handler_store = + util::make_unique(sessions, config); + auto listen_handler = listen_handler_store.get(); addrinfo *res, *rp; - r = getaddrinfo(addr, service.c_str(), &hints, &res); + r = getaddrinfo(nullptr, service.c_str(), &hints, &res); if (r != 0) { std::cerr << "getaddrinfo() failed: " << gai_strerror(r) << std::endl; return -1; } - for (rp = res; rp; rp = rp->ai_next) { int fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (fd == -1) { @@ -2022,7 +1348,7 @@ close(fd); continue; } - (void)util::make_socket_nonblocking(fd); + evutil_make_socket_nonblocking(fd); #ifdef IPV6_V6ONLY if (rp->ai_family == AF_INET6) { if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, @@ -2032,18 +1358,18 @@ } } #endif // IPV6_V6ONLY - if (bind(fd, rp->ai_addr, rp->ai_addrlen) == 0 && listen(fd, 1000) == 0) { - if (!acceptor) { - acceptor = std::make_shared(sv, sessions, config); - } - new ListenEventHandler(sessions, fd, acceptor); + if (bind(fd, rp->ai_addr, rp->ai_addrlen) == 0) { + auto evlistener = + evconnlistener_new(evbase, evlistener_acceptcb, listen_handler, + LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1, fd); + evconnlistener_set_error_cb(evlistener, evlistener_errorcb); + + listen_handler_store.release(); if (config->verbose) { - std::string s = util::numeric_name(rp->ai_addr, rp->ai_addrlen); - std::cout << (rp->ai_family == AF_INET ? "IPv4" : "IPv6") << ": listen " - << s << ":" << config->port << std::endl; + std::cout << (rp->ai_family == AF_INET ? "IPv4" : "IPv6") + << ": listen on port " << config->port << std::endl; } - ok = true; continue; } else { std::cerr << strerror(errno) << std::endl; @@ -2051,10 +1377,6 @@ close(fd); } freeaddrinfo(res); - - if (!ok) { - return -1; - } return 0; } } // namespace @@ -2075,7 +1397,8 @@ std::cout << std::endl; } } - if (!util::select_h2(out, outlen, in, inlen)) { + if (nghttp2_select_next_protocol(const_cast(out), outlen, + in, inlen) <= 0) { return SSL_TLSEXT_ERR_NOACK; } return SSL_TLSEXT_ERR_OK; @@ -2094,20 +1417,16 @@ return -1; } - auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | - SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | - SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET | - SSL_OP_CIPHER_SERVER_PREFERENCE; - - SSL_CTX_set_options(ssl_ctx, ssl_opts); + SSL_CTX_set_options(ssl_ctx, + SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | + SSL_OP_NO_COMPRESSION | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | + SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET | + SSL_OP_CIPHER_SERVER_PREFERENCE); SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS); - if (SSL_CTX_set_cipher_list(ssl_ctx, ssl::DEFAULT_CIPHER_LIST) == 0) { - std::cerr << ERR_error_string(ERR_get_error(), nullptr) << std::endl; - return -1; - } + SSL_CTX_set_cipher_list(ssl_ctx, ssl::DEFAULT_CIPHER_LIST); const unsigned char sid_ctx[] = "nghttpd"; SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1); @@ -2186,39 +1505,35 @@ #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L } - auto loop = EV_DEFAULT; + auto evcfg = event_config_new(); + event_config_set_flag(evcfg, EVENT_BASE_FLAG_NOLOCK); + + auto evbase = event_base_new_with_config(evcfg); - Sessions sessions(this, loop, config_, ssl_ctx); - if (start_listen(this, loop, &sessions, config_) != 0) { + Sessions sessions(evbase, config_, ssl_ctx); + if (start_listen(evbase, &sessions, config_) != 0) { std::cerr << "Could not listen" << std::endl; - if (ssl_ctx) { - SSL_CTX_free(ssl_ctx); - } return -1; } - ev_run(loop, 0); + auto refresh_ev = event_new(evbase, -1, EV_PERSIST, refresh_cb, nullptr); + if (!refresh_ev) { + std::cerr << "Could not add refresh timer" << std::endl; + return -1; + } + + timeval refresh_timeout = {1, 0}; + if (event_add(refresh_ev, &refresh_timeout) == -1) { + std::cerr << "Adding refresh event failed" << std::endl; + return -1; + } + + cached_date = std::make_shared(util::http_date(time(nullptr))); + + event_base_loop(evbase, 0); return 0; } const Config *HttpServer::get_config() const { return config_; } -const StatusPage *HttpServer::get_status_page(int status) const { - switch (status) { - case 200: - return &status_pages_[IDX_200]; - case 301: - return &status_pages_[IDX_301]; - case 400: - return &status_pages_[IDX_400]; - case 404: - return &status_pages_[IDX_404]; - case 405: - return &status_pages_[IDX_405]; - default: - assert(0); - } - return nullptr; -} - } // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/HttpServer.h nghttp2-0.6.7/src/HttpServer.h --- nghttp2-1.13.0/src/HttpServer.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/HttpServer.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,9 +27,9 @@ #include "nghttp2_config.h" +#include #include -#include #include #include @@ -39,38 +39,39 @@ #include -#include +#include +#include #include +#ifdef __cplusplus +extern "C" { +#endif + +#include "nghttp2_buf.h" + +#ifdef __cplusplus +} +#endif + #include "http2.h" -#include "buffer.h" -#include "template.h" -#include "allocator.h" namespace nghttp2 { struct Config { std::map> push; - std::map mime_types; - Headers trailer; - std::string trailer_names; std::string htdocs; std::string host; std::string private_key_file; std::string cert_file; std::string dh_param_file; - std::string address; - std::string mime_types_file; - ev_tstamp stream_read_timeout; - ev_tstamp stream_write_timeout; + timeval stream_read_timeout; + timeval stream_write_timeout; + nghttp2_option *session_option; void *data_ptr; size_t padding; size_t num_worker; - size_t max_concurrent_streams; ssize_t header_table_size; - int window_bits; - int connection_window_bits; uint16_t port; bool verbose; bool daemon; @@ -78,75 +79,20 @@ bool no_tls; bool error_gzip; bool early_response; - bool hexdump; - bool echo_upload; - bool no_content_length; Config(); ~Config(); }; class Http2Handler; -struct FileEntry { - FileEntry(std::string path, int64_t length, int64_t mtime, int fd, - const std::string *content_type, ev_tstamp last_valid, - bool stale = false) - : path(std::move(path)), - length(length), - mtime(mtime), - last_valid(last_valid), - content_type(content_type), - dlnext(nullptr), - dlprev(nullptr), - fd(fd), - usecount(1), - stale(stale) {} - std::string path; - std::multimap>::iterator it; - int64_t length; - int64_t mtime; - ev_tstamp last_valid; - const std::string *content_type; - FileEntry *dlnext, *dlprev; - int fd; - int usecount; - bool stale; -}; - -struct RequestHeader { - StringRef method; - StringRef scheme; - StringRef authority; - StringRef host; - StringRef path; - StringRef ims; - StringRef expect; - - struct { - nghttp2_rcbuf *method; - nghttp2_rcbuf *scheme; - nghttp2_rcbuf *authority; - nghttp2_rcbuf *host; - nghttp2_rcbuf *path; - nghttp2_rcbuf *ims; - nghttp2_rcbuf *expect; - } rcbuf; -}; - struct Stream { - BlockAllocator balloc; - RequestHeader header; + Headers headers; + std::pair response_body; Http2Handler *handler; - FileEntry *file_ent; - ev_timer rtimer; - ev_timer wtimer; - int64_t body_length; - int64_t body_offset; - // Total amount of bytes (sum of name and value length) used in - // headers. - size_t header_buffer_size; + event *rtimer; + event *wtimer; int32_t stream_id; - bool echo_upload; + int file; Stream(Http2Handler *handler, int32_t stream_id); ~Stream(); }; @@ -159,27 +105,26 @@ ~Http2Handler(); void remove_self(); - void start_settings_timer(); + int setup_bev(); + int send(); int on_read(); int on_write(); - int connection_made(); + int on_connect(); int verify_npn_result(); - int submit_file_response(const StringRef &status, Stream *stream, + int submit_file_response(const std::string &status, Stream *stream, time_t last_modified, off_t file_length, - const std::string *content_type, nghttp2_data_provider *data_prd); - int submit_response(const StringRef &status, int32_t stream_id, + int submit_response(const std::string &status, int32_t stream_id, nghttp2_data_provider *data_prd); - int submit_response(const StringRef &status, int32_t stream_id, - const HeaderRefs &headers, - nghttp2_data_provider *data_prd); + int submit_response(const std::string &status, int32_t stream_id, + const Headers &headers, nghttp2_data_provider *data_prd); int submit_non_final_response(const std::string &status, int32_t stream_id); - int submit_push_promise(Stream *stream, const StringRef &push_path); + int submit_push_promise(Stream *stream, const std::string &push_path); int submit_rst_stream(Stream *stream, uint32_t error_code); @@ -192,51 +137,25 @@ void remove_settings_timer(); void terminate_session(uint32_t error_code); - int fill_wb(); - - int read_clear(); - int write_clear(); - int tls_handshake(); - int read_tls(); - int write_tls(); - - struct ev_loop *get_loop() const; - - using WriteBuf = Buffer<64_k>; - - WriteBuf *get_wb(); - private: - ev_io wev_; - ev_io rev_; - ev_timer settings_timerev_; std::map> id2stream_; - WriteBuf wb_; - std::function read_, write_; int64_t session_id_; nghttp2_session *session_; Sessions *sessions_; SSL *ssl_; - const uint8_t *data_pending_; - size_t data_pendinglen_; + bufferevent *bev_; + event *settings_timerev_; int fd_; }; -struct StatusPage { - std::string status; - FileEntry file_ent; -}; - class HttpServer { public: HttpServer(const Config *config); int listen(); int run(); const Config *get_config() const; - const StatusPage *get_status_page(int status) const; private: - std::vector status_pages_; const Config *config_; }; diff -Nru nghttp2-1.13.0/src/includes/CMakeLists.txt nghttp2-0.6.7/src/includes/CMakeLists.txt --- nghttp2-1.13.0/src/includes/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/includes/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -if(ENABLE_ASIO_LIB) - install(FILES - nghttp2/asio_http2.h - nghttp2/asio_http2_client.h - nghttp2/asio_http2_server.h - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/nghttp2") -endif() diff -Nru nghttp2-1.13.0/src/includes/Makefile.am nghttp2-0.6.7/src/includes/Makefile.am --- nghttp2-1.13.0/src/includes/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/includes/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -20,10 +20,4 @@ # 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. - -EXTRA_DIST = CMakeLists.txt - -if ENABLE_ASIO_LIB -nobase_include_HEADERS = nghttp2/asio_http2.h nghttp2/asio_http2_client.h \ - nghttp2/asio_http2_server.h -endif # ENABLE_ASIO_LIB +nobase_include_HEADERS = nghttp2/asio_http2.h diff -Nru nghttp2-1.13.0/src/includes/Makefile.in nghttp2-0.6.7/src/includes/Makefile.in --- nghttp2-1.13.0/src/includes/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/src/includes/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -29,26 +29,8 @@ # 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. - VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -113,6 +95,8 @@ host_triplet = @host@ target_triplet = @target@ subdir = src/includes +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(nobase_include_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -122,14 +106,11 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__nobase_include_HEADERS_DIST) \ - $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -153,8 +134,6 @@ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac -am__nobase_include_HEADERS_DIST = nghttp2/asio_http2.h \ - nghttp2/asio_http2_client.h nghttp2/asio_http2_server.h am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -203,12 +182,10 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -227,7 +204,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -243,7 +219,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -259,10 +234,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -274,7 +245,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -312,11 +282,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -371,7 +340,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -384,10 +352,15 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -EXTRA_DIST = CMakeLists.txt -@ENABLE_ASIO_LIB_TRUE@nobase_include_HEADERS = nghttp2/asio_http2.h nghttp2/asio_http2_client.h \ -@ENABLE_ASIO_LIB_TRUE@ nghttp2/asio_http2_server.h +# 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. +nobase_include_HEADERS = nghttp2/asio_http2.h all: all-am .SUFFIXES: @@ -403,6 +376,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/includes/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/includes/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -652,8 +626,6 @@ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-nobase_includeHEADERS -.PRECIOUS: Makefile - # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru nghttp2-1.13.0/src/includes/nghttp2/asio_http2_client.h nghttp2-0.6.7/src/includes/nghttp2/asio_http2_client.h --- nghttp2-1.13.0/src/includes/nghttp2/asio_http2_client.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/includes/nghttp2/asio_http2_client.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,216 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_HTTP2_CLIENT_H -#define ASIO_HTTP2_CLIENT_H - -#include - -namespace nghttp2 { - -namespace asio_http2 { - -namespace client { - -class response_impl; - -class response { -public: - // Application must not call this directly. - response(); - ~response(); - - // Sets callback which is invoked when chunk of response body is - // received. - void on_data(data_cb cb) const; - - // Returns status code. - int status_code() const; - - // Returns content-length. -1 if it is unknown. - int64_t content_length() const; - - // Returns the response header fields. The pusedo header fields, - // which start with colon (:), are exluced from this list. - const header_map &header() const; - - // Application must not call this directly. - response_impl &impl() const; - -private: - std::unique_ptr impl_; -}; - -class request; - -using response_cb = std::function; -using request_cb = std::function; -using connect_cb = - std::function; - -class request_impl; - -class request { -public: - // Application must not call this directly. - request(); - ~request(); - - // Sets callback which is invoked when response header is received. - void on_response(response_cb cb) const; - - // Sets callback which is invoked when push request header is - // received. - void on_push(request_cb cb) const; - - // Sets callback which is invoked when this request and response are - // finished. After the invocation of this callback, the application - // must not access request and response object. - void on_close(close_cb cb) const; - - // Write trailer part. This must be called after setting both - // NGHTTP2_DATA_FLAG_EOF and NGHTTP2_DATA_FLAG_NO_END_STREAM set in - // *data_flag parameter in generator_cb passed to session::submit() - // function. - void write_trailer(header_map h) const; - - // Cancels this request and response with given error code. - void cancel(uint32_t error_code = NGHTTP2_INTERNAL_ERROR) const; - - // Resumes deferred uploading. - void resume() const; - - // Returns method (e.g., GET). - const std::string &method() const; - - // Returns request URI, split into components. - const uri_ref &uri() const; - - // Returns request header fields. The pusedo header fields, which - // start with colon (:), are exluced from this list. - const header_map &header() const; - - // Application must not call this directly. - request_impl &impl() const; - -private: - std::unique_ptr impl_; -}; - -class session_impl; - -class session { -public: - // Starts HTTP/2 session by connecting to |host| and |service| - // (e.g., "80") using clear text TCP connection with connect timeout - // 60 seconds. - session(boost::asio::io_service &io_service, const std::string &host, - const std::string &service); - - // Starts HTTP/2 session by connecting to |host| and |service| - // (e.g., "80") using clear text TCP connection with given connect - // timeout. - session(boost::asio::io_service &io_service, const std::string &host, - const std::string &service, - const boost::posix_time::time_duration &connect_timeout); - - // Starts HTTP/2 session by connecting to |host| and |service| - // (e.g., "443") using encrypted SSL/TLS connection with connect - // timeout 60 seconds. - session(boost::asio::io_service &io_service, - boost::asio::ssl::context &tls_context, const std::string &host, - const std::string &service); - - // Starts HTTP/2 session by connecting to |host| and |service| - // (e.g., "443") using encrypted SSL/TLS connection with given - // connect timeout. - session(boost::asio::io_service &io_service, - boost::asio::ssl::context &tls_context, const std::string &host, - const std::string &service, - const boost::posix_time::time_duration &connect_timeout); - - ~session(); - - session(session &&other) noexcept; - session &operator=(session &&other) noexcept; - - // Sets callback which is invoked after connection is established. - void on_connect(connect_cb cb) const; - - // Sets callback which is invoked there is connection level error - // and session is terminated. - void on_error(error_cb cb) const; - - // Sets read timeout, which defaults to 60 seconds. - void read_timeout(const boost::posix_time::time_duration &t); - - // Shutdowns connection. - void shutdown() const; - - // Returns underlying io_service object. - boost::asio::io_service &io_service() const; - - // Submits request to server using |method| (e.g., "GET"), |uri| - // (e.g., "http://localhost/") and optionally additional header - // fields. This function returns pointer to request object if it - // succeeds, or nullptr and |ec| contains error message. - const request *submit(boost::system::error_code &ec, - const std::string &method, const std::string &uri, - header_map h = header_map{}) const; - - // Submits request to server using |method| (e.g., "GET"), |uri| - // (e.g., "http://localhost/") and optionally additional header - // fields. The |data| is request body. This function returns - // pointer to request object if it succeeds, or nullptr and |ec| - // contains error message. - const request *submit(boost::system::error_code &ec, - const std::string &method, const std::string &uri, - std::string data, header_map h = header_map{}) const; - - // Submits request to server using |method| (e.g., "GET"), |uri| - // (e.g., "http://localhost/") and optionally additional header - // fields. The |cb| is used to generate request body. This - // function returns pointer to request object if it succeeds, or - // nullptr and |ec| contains error message. - const request *submit(boost::system::error_code &ec, - const std::string &method, const std::string &uri, - generator_cb cb, header_map h = header_map{}) const; - -private: - std::shared_ptr impl_; -}; - -// configure |tls_ctx| for client use. Currently, we just set NPN -// callback for HTTP/2. -boost::system::error_code -configure_tls_context(boost::system::error_code &ec, - boost::asio::ssl::context &tls_ctx); - -} // namespace client - -} // namespace asio_http2 - -} // namespace nghttp2 - -#endif // ASIO_HTTP2_CLIENT_H diff -Nru nghttp2-1.13.0/src/includes/nghttp2/asio_http2.h nghttp2-0.6.7/src/includes/nghttp2/asio_http2.h --- nghttp2-1.13.0/src/includes/nghttp2/asio_http2.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/includes/nghttp2/asio_http2.h 2014-11-30 14:15:07.000000000 +0000 @@ -30,76 +30,205 @@ #include #include #include -#include - -#include -#include -#include - -#include namespace nghttp2 { namespace asio_http2 { -struct header_value { - // header field value +struct header { + std::string name; std::string value; - // true if the header field value is sensitive information, such as - // authorization information or short length secret cookies. If - // true, those header fields are not indexed by HPACK (but still - // huffman-encoded), which results in lesser compression. - bool sensitive; }; -// header fields. The header field name must be lower-cased. -using header_map = std::multimap; +typedef std::function data_cb; +typedef std::function void_cb; -const boost::system::error_category &nghttp2_category() noexcept; +// Callback function to generate response body. The implementation of +// this callback must fill at most |len| bytes data to |buf|. The +// return value is pair of written bytes and bool value indicating +// that this is the end of the body. If the end of the body was +// reached, return true. If there is error and application wants to +// terminate stream, return std::make_pair(-1, false). Returning +// std::make_pair(0, false) tells the library that don't call this +// callback until application calls response::resume(). This is +// useful when there is no data to send at the moment but there will +// be more to come in near future. +typedef std::function(uint8_t *buf, std::size_t len)> + read_cb; + +class channel_impl; + +class channel { +public: + // Application must not call this directly. + channel(); + + // Schedules the execution of callback |cb| in the same thread where + // request callback is called. Therefore, it is same to use request + // or response object in |cb|. The callbacks are executed in the + // same order they are posted though same channel object if they are + // posted from the same thread. + void post(void_cb cb); -struct uri_ref { - std::string scheme; - std::string host; - // form after percent-encoding decoded - std::string path; - // original path, percent-encoded - std::string raw_path; - // original query, percent-encoded - std::string raw_query; - std::string fragment; + // Application must not call this directly. + channel_impl &impl(); + +private: + std::unique_ptr impl_; }; -// Callback function when data is arrived. EOF is indicated by -// passing 0 to the second parameter. -typedef std::function data_cb; -typedef std::function void_cb; -typedef std::function error_cb; -// Callback function when request and response are finished. The -// parameter indicates the cause of closure. -typedef std::function close_cb; - -// Callback function to generate response body. This function has the -// same semantics with nghttp2_data_source_read_callback. Just source -// and user_data parameters are removed. -// -// Basically, write at most |len| bytes to |data| and returns the -// number of bytes written. If there is no data left to send, set -// NGHTTP2_DATA_FLAG_EOF to *data_flags (e.g., *data_flags |= -// NGHTTP2_DATA_FLAG_EOF). If there is still data to send but they -// are not available right now, return NGHTTP2_ERR_DEFERRED. In case -// of the error and request/response must be closed, return -// NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE. -typedef std::function generator_cb; +typedef std::function thread_cb; + +namespace server { + +class request_impl; +class response_impl; + +class request { +public: + // Application must not call this directly. + request(); + + // Returns request headers. The pusedo headers, which start with + // colon (;), are exluced from this list. + const std::vector
&headers() const; + + // Returns method (e.g., GET). + const std::string &method() const; + + // Returns scheme (e.g., https). + const std::string &scheme() const; + + // Returns authority (e.g., example.org). This could be empty + // string. In this case, check host(). + + const std::string &authority() const; + // Returns host (e.g., example.org). If host header field is not + // present, this value is copied from authority(). + + const std::string &host() const; + + // Returns path (e.g., /index.html). + const std::string &path() const; + + // Sets callback when chunk of request body is received. + void on_data(data_cb cb); + + // Sets callback when request was completed. + void on_end(void_cb cb); + + // Pushes resource denoted by |path| using |method|. The additional + // headers can be given in |headers|. request_cb will be called for + // pushed resource later on. This function returns true if it + // succeeds, or false. + bool push(std::string method, std::string path, + std::vector
headers = {}); + + // Returns true if this is pushed request. + bool pushed() const; + + // Returns true if stream has been closed. + bool closed() const; + + // Runs function |start| in one of background threads. Returns true + // if scheduling task was done successfully. + // + // Since |start| is called in different thread, calling any method + // of request or response object in the callback may cause undefined + // behavior. To safely use them, use channel::post(). A callback + // passed to channel::post() is executed in the same thread where + // request callback is called, so it is safe to use request or + // response object. Example:: + bool run_task(thread_cb start); + + // Application must not call this directly. + request_impl &impl(); + +private: + std::unique_ptr impl_; +}; + +class response { +public: + // Application must not call this directly. + response(); + + // Write response header using |status_code| (e.g., 200) and + // additional headers in |headers|. + void write_head(unsigned int status_code, std::vector
headers = {}); + + // Sends |data| as request body. No further call of end() is + // allowed. + void end(std::string data = ""); + + // Sets callback |cb| as a generator of the response body. No + // further call of end() is allowed. + void end(read_cb cb); + + // Resumes deferred response. + void resume(); + + // Returns status code. + unsigned int status_code() const; + + // Returns true if response has been started. + bool started() const; + + // Application must not call this directly. + response_impl &impl(); + +private: + std::unique_ptr impl_; +}; + +// This is so called request callback. Called every time request is +// received. +typedef std::function &, + const std::shared_ptr &)> request_cb; + +class http2_impl; + +class http2 { +public: + http2(); + ~http2(); + + // Starts listening connection on given address and port. The + // incoming requests are handled by given callback |cb|. + void listen(const std::string &address, uint16_t port, request_cb cb); + + // Sets number of native threads to handle incoming HTTP request. + // It defaults to 1. + void num_threads(size_t num_threads); + + // Sets TLS private key file and certificate file. Both files must + // be in PEM format. + void tls(std::string private_key_file, std::string certificate_file); + + // Sets number of background threads to run concurrent tasks (see + // request::run_task()). It defaults to 1. This is not the number + // of thread to handle incoming HTTP request. For this purpose, see + // num_threads(). + void num_concurrent_tasks(size_t num_concurrent_tasks); + + // Sets the maximum length to which the queue of pending + // connections. + void backlog(int backlog); + +private: + std::unique_ptr impl_; +}; + +} // namespace server // Convenient function to create function to read file denoted by // |path|. This can be passed to response::end(). -generator_cb file_generator(const std::string &path); +read_cb file_reader(const std::string &path); -// Like file_generator(const std::string&), but it takes opened file +// Like file_reader(const std::string&), but it takes opened file // descriptor. The passed descriptor will be closed when returned // function object is destroyed. -generator_cb file_generator_from_fd(int fd); +read_cb file_reader_from_fd(int fd); // Validates path so that it does not contain directory traversal // vector. Returns true if path is safe. The |path| must start with @@ -113,38 +242,8 @@ // Returns HTTP date representation of current posix time |t|. std::string http_date(int64_t t); -// Parses |uri| and extract scheme, host and service. The service is -// port component of URI (e.g., "8443") if available, otherwise it is -// scheme (e.g., "https"). -boost::system::error_code host_service_from_uri(boost::system::error_code &ec, - std::string &scheme, - std::string &host, - std::string &service, - const std::string &uri); - -enum nghttp2_asio_error { - NGHTTP2_ASIO_ERR_NO_ERROR = 0, - NGHTTP2_ASIO_ERR_TLS_NO_APP_PROTO_NEGOTIATED = 1, -}; - } // namespace asio_http2 } // namespace nghttp2 -namespace boost { - -namespace system { - -template <> struct is_error_code_enum { - BOOST_STATIC_CONSTANT(bool, value = true); -}; - -template <> struct is_error_code_enum { - BOOST_STATIC_CONSTANT(bool, value = true); -}; - -} // namespace system - -} // namespace boost - #endif // ASIO_HTTP2_H diff -Nru nghttp2-1.13.0/src/includes/nghttp2/asio_http2_server.h nghttp2-0.6.7/src/includes/nghttp2/asio_http2_server.h --- nghttp2-1.13.0/src/includes/nghttp2/asio_http2_server.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/includes/nghttp2/asio_http2_server.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,242 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 ASIO_HTTP2_SERVER_H -#define ASIO_HTTP2_SERVER_H - -#include - -namespace nghttp2 { - -namespace asio_http2 { - -namespace server { - -class request_impl; -class response_impl; - -class request { -public: - // Application must not call this directly. - request(); - ~request(); - - // Returns request header fields. The pusedo header fields, which - // start with colon (:), are exluced from this list. - const header_map &header() const; - - // Returns method (e.g., GET). - const std::string &method() const; - - // Returns request URI, split into components. - const uri_ref &uri() const; - - // Sets callback which is invoked when chunk of request body is - // received. - void on_data(data_cb cb) const; - - // Application must not call this directly. - request_impl &impl() const; - - // Returns the remote endpoint of the request - const boost::asio::ip::tcp::endpoint &remote_endpoint() const; - -private: - std::unique_ptr impl_; -}; - -class response { -public: - // Application must not call this directly. - response(); - ~response(); - - // Write response header using |status_code| (e.g., 200) and - // additional header fields in |h|. - void write_head(unsigned int status_code, header_map h = header_map{}) const; - - // Sends |data| as request body. No further call of end() is - // allowed. - void end(std::string data = "") const; - - // Sets callback as a generator of the response body. No further - // call of end() is allowed. - void end(generator_cb cb) const; - - // Write trailer part. This must be called after setting both - // NGHTTP2_DATA_FLAG_EOF and NGHTTP2_DATA_FLAG_NO_END_STREAM set in - // *data_flag parameter in generator_cb passed to end() function. - void write_trailer(header_map h) const; - - // Sets callback which is invoked when this request and response are - // finished. After the invocation of this callback, the application - // must not access request and response object. - void on_close(close_cb cb) const; - - // Cancels this request and response with given error code. - void cancel(uint32_t error_code = NGHTTP2_INTERNAL_ERROR) const; - - // Resumes deferred response. - void resume() const; - - // Pushes resource denoted by |raw_path_query| using |method|. The - // additional header fields can be given in |h|. This function - // returns pointer to response object for promised stream, otherwise - // nullptr and error code is filled in |ec|. Be aware that the - // header field name given in |h| must be lower-cased. - const response *push(boost::system::error_code &ec, std::string method, - std::string raw_path_query, - header_map h = header_map{}) const; - - // Returns status code. - unsigned int status_code() const; - - // Returns boost::asio::io_service this response is running on. - boost::asio::io_service &io_service() const; - - // Application must not call this directly. - response_impl &impl() const; - -private: - std::unique_ptr impl_; -}; - -// This is so called request callback. Called every time request is -// received. The life time of |request| and |response| objects end -// when callback set by response::on_close() is called. After that, -// the application must not access to those objects. -typedef std::function request_cb; - -class http2_impl; - -class http2 { -public: - http2(); - ~http2(); - - http2(http2 &&other) noexcept; - http2 &operator=(http2 &&other) noexcept; - - // Starts listening connection on given address and port and serves - // incoming requests in cleartext TCP connection. If |asynchronous| - // is false, this function blocks forever unless there is an error. - // If it is true, after server has started, this function returns - // immediately, and the caller should call join() to shutdown server - // gracefully. - boost::system::error_code listen_and_serve(boost::system::error_code &ec, - const std::string &address, - const std::string &port, - bool asynchronous = false); - - // Starts listening connection on given address and port and serves - // incoming requests in SSL/TLS encrypted connection. For - // |asynchronous| parameter, see cleartext version - // |listen_and_serve|. - boost::system::error_code - listen_and_serve(boost::system::error_code &ec, - boost::asio::ssl::context &tls_context, - const std::string &address, const std::string &port, - bool asynchronous = false); - - // Registers request handler |cb| with path pattern |pattern|. This - // function will fail and returns false if same pattern has been - // already registered or |pattern| is empty string. Otherwise - // returns true. The pattern match rule is the same as - // net/http/ServeMux in golang. Quoted from golang manual - // (http://golang.org/pkg/net/http/#ServeMux): - // - // Patterns name fixed, rooted paths, like "/favicon.ico", or - // rooted subtrees, like "/images/" (note the trailing - // slash). Longer patterns take precedence over shorter ones, so - // that if there are handlers registered for both "/images/" and - // "/images/thumbnails/", the latter handler will be called for - // paths beginning "/images/thumbnails/" and the former will - // receive requests for any other paths in the "/images/" subtree. - // - // Note that since a pattern ending in a slash names a rooted - // subtree, the pattern "/" matches all paths not matched by other - // registered patterns, not just the URL with Path == "/". - // - // Patterns may optionally begin with a host name, restricting - // matches to URLs on that host only. Host-specific patterns take - // precedence over general patterns, so that a handler might - // register for the two patterns "/codesearch" and - // "codesearch.google.com/" without also taking over requests for - // "http://www.google.com/". - // - // Just like ServeMux in golang, URL request path is sanitized and - // if they contains . or .. elements, they are redirected to an - // equivalent .- and ..-free URL. - bool handle(std::string pattern, request_cb cb); - - // Sets number of native threads to handle incoming HTTP request. - // It defaults to 1. - void num_threads(size_t num_threads); - - // Sets the maximum length to which the queue of pending - // connections. - void backlog(int backlog); - - // Sets TLS handshake timeout, which defaults to 60 seconds. - void tls_handshake_timeout(const boost::posix_time::time_duration &t); - - // Sets read timeout, which defaults to 60 seconds. - void read_timeout(const boost::posix_time::time_duration &t); - - // Gracefully stop http2 server - void stop(); - - // Join on http2 server and wait for it to fully stop - void join(); - - // Get access to the io_service objects. - const std::vector> & - io_services() const; - -private: - std::unique_ptr impl_; -}; - -// Configures |tls_context| for server use. This function sets couple -// of OpenSSL options (disables SSLv2 and SSLv3 and compression) and -// enables ECDHE ciphers. NPN callback is also configured. -boost::system::error_code -configure_tls_context_easy(boost::system::error_code &ec, - boost::asio::ssl::context &tls_context); - -// Returns request handler to do redirect to |uri| using -// |status_code|. The |uri| appears in "location" header field as is. -request_cb redirect_handler(int status_code, std::string uri); - -// Returns request handler to reply with given |status_code| and HTML -// including message about status code. -request_cb status_handler(int status_code); - -} // namespace server - -} // namespace asio_http2 - -} // namespace nghttp2 - -#endif // ASIO_HTTP2_SERVER_H diff -Nru nghttp2-1.13.0/src/inflatehd.cc nghttp2-0.6.7/src/inflatehd.cc --- nghttp2-1.13.0/src/inflatehd.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/inflatehd.cc 2014-11-30 14:15:07.000000000 +0000 @@ -26,9 +26,7 @@ #include #endif // HAVE_CONFIG_H -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H #include #include @@ -41,12 +39,13 @@ #include -#include +extern "C" { -#include "template.h" -#include "comp_helper.h" +#include "nghttp2_hd.h" +#include "nghttp2_frame.h" -namespace nghttp2 { +#include "comp_helper.h" +} typedef struct { int dump_header_table; } inflate_config; @@ -75,15 +74,12 @@ json_object_set_new(obj, "seq", json_integer(seq)); json_object_set(obj, "wire", wire); json_object_set(obj, "headers", headers); - auto max_dyn_table_size = - nghttp2_hd_inflate_get_max_dynamic_table_size(inflater); - if (old_settings_table_size != max_dyn_table_size) { + if (old_settings_table_size != inflater->settings_hd_table_bufsize_max) { json_object_set_new(obj, "header_table_size", - json_integer(max_dyn_table_size)); + json_integer(inflater->settings_hd_table_bufsize_max)); } if (config.dump_header_table) { - json_object_set_new(obj, "header_table", - dump_inflate_header_table(inflater)); + json_object_set_new(obj, "header_table", dump_header_table(&inflater->ctx)); } json_dumpf(obj, stdout, JSON_INDENT(2) | JSON_PRESERVE_ORDER); json_decref(obj); @@ -94,8 +90,7 @@ ssize_t rv; nghttp2_nv nv; int inflate_flags; - size_t old_settings_table_size = - nghttp2_hd_inflate_get_max_dynamic_table_size(inflater); + size_t old_settings_table_size = inflater->settings_hd_table_bufsize_max; auto wire = json_object_get(obj, "wire"); @@ -104,11 +99,6 @@ return -1; } - if (!json_is_string(wire)) { - fprintf(stderr, "'wire' value is not string at %d\n", seq); - return -1; - } - auto table_size = json_object_get(obj, "header_table_size"); if (table_size) { @@ -169,7 +159,7 @@ } static int perform(void) { - nghttp2_hd_inflater *inflater = NULL; + nghttp2_hd_inflater inflater; json_error_t error; auto json = json_loadf(stdin, 0, &error); @@ -191,7 +181,7 @@ exit(EXIT_FAILURE); } - nghttp2_hd_inflate_new(&inflater); + nghttp2_hd_inflate_init(&inflater); output_json_header(); auto len = json_array_size(cases); @@ -201,7 +191,7 @@ fprintf(stderr, "Unexpected JSON type at %zu. It should be object.\n", i); continue; } - if (inflate_hd(obj, inflater, i) != 0) { + if (inflate_hd(obj, &inflater, i) != 0) { continue; } if (i + 1 < len) { @@ -209,7 +199,7 @@ } } output_json_footer(); - nghttp2_hd_inflate_del(inflater); + nghttp2_hd_inflate_free(&inflater); json_decref(json); return 0; @@ -278,9 +268,3 @@ perform(); return 0; } - -} // namespace nghttp2 - -int main(int argc, char **argv) { - return nghttp2::run_app(nghttp2::main, argc, argv); -} diff -Nru nghttp2-1.13.0/src/libevent_util.cc nghttp2-0.6.7/src/libevent_util.cc --- nghttp2-1.13.0/src/libevent_util.cc 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/libevent_util.cc 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,152 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 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. + */ +#include "libevent_util.h" + +#include +#include + +namespace nghttp2 { + +namespace util { + +EvbufferBuffer::EvbufferBuffer() + : evbuffer_(nullptr), bucket_(nullptr), buf_(nullptr), bufmax_(0), + buflen_(0), limit_(0), writelen_(0) {} + +EvbufferBuffer::EvbufferBuffer(evbuffer *evbuffer, uint8_t *buf, size_t bufmax, + ssize_t limit) + : evbuffer_(evbuffer), bucket_(limit == -1 ? nullptr : evbuffer_new()), + buf_(buf), bufmax_(bufmax), buflen_(0), limit_(limit), writelen_(0) {} + +void EvbufferBuffer::reset(evbuffer *evbuffer, uint8_t *buf, size_t bufmax, + ssize_t limit) { + evbuffer_ = evbuffer; + buf_ = buf; + if (limit != -1 && !bucket_) { + bucket_ = evbuffer_new(); + } + bufmax_ = bufmax; + buflen_ = 0; + limit_ = limit; + writelen_ = 0; +} + +EvbufferBuffer::~EvbufferBuffer() { + if (bucket_) { + evbuffer_free(bucket_); + } +} + +int EvbufferBuffer::write_buffer() { + for (auto pos = buf_, end = buf_ + buflen_; pos < end;) { + // To avoid merging chunks in evbuffer, we first add to temporal + // buffer bucket_ and then move its chain to evbuffer_. + auto nwrite = std::min(end - pos, limit_); + auto rv = evbuffer_add(bucket_, pos, nwrite); + if (rv == -1) { + return -1; + } + rv = evbuffer_add_buffer(evbuffer_, bucket_); + if (rv == -1) { + return -1; + } + pos += nwrite; + } + return 0; +} + +int EvbufferBuffer::flush() { + int rv; + if (buflen_ > 0) { + if (limit_ == -1) { + rv = evbuffer_add(evbuffer_, buf_, buflen_); + } else { + rv = write_buffer(); + } + if (rv == -1) { + return -1; + } + writelen_ += buflen_; + buflen_ = 0; + } + return 0; +} + +int EvbufferBuffer::add(const uint8_t *data, size_t datalen) { + int rv; + if (buflen_ + datalen > bufmax_) { + if (buflen_ > 0) { + if (limit_ == -1) { + rv = evbuffer_add(evbuffer_, buf_, buflen_); + } else { + rv = write_buffer(); + } + if (rv == -1) { + return -1; + } + writelen_ += buflen_; + buflen_ = 0; + } + if (datalen > bufmax_) { + if (limit_ == -1) { + rv = evbuffer_add(evbuffer_, data, datalen); + } else { + rv = write_buffer(); + } + if (rv == -1) { + return -1; + } + writelen_ += buflen_; + return 0; + } + } + memcpy(buf_ + buflen_, data, datalen); + buflen_ += datalen; + return 0; +} + +size_t EvbufferBuffer::get_buflen() const { return buflen_; } + +size_t EvbufferBuffer::get_writelen() const { return writelen_; } + +void bev_enable_unless(bufferevent *bev, int events) { + if ((bufferevent_get_enabled(bev) & events) == events) { + return; + } + + bufferevent_enable(bev, events); +} + +void bev_disable_unless(bufferevent *bev, int events) { + if ((bufferevent_get_enabled(bev) & events) == 0) { + return; + } + + bufferevent_disable(bev, events); +} + +} // namespace util + +} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/libevent_util.h nghttp2-0.6.7/src/libevent_util.h --- nghttp2-1.13.0/src/libevent_util.h 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/libevent_util.h 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 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 LIBEVENT_UTIL_H +#define LIBEVENT_UTIL_H + +#include "nghttp2_config.h" + +#include +#include + +namespace nghttp2 { + +namespace util { + +class EvbufferBuffer { +public: + EvbufferBuffer(); + // If |limit| is not -1, at most min(limit, bufmax) size bytes are + // added to evbuffer_. + EvbufferBuffer(evbuffer *evbuffer, uint8_t *buf, size_t bufmax, + ssize_t limit = -1); + ~EvbufferBuffer(); + void reset(evbuffer *evbuffer, uint8_t *buf, size_t bufmax, + ssize_t limit = -1); + int flush(); + int add(const uint8_t *data, size_t datalen); + size_t get_buflen() const; + int write_buffer(); + // Returns the number of written bytes to evbuffer_ so far. reset() + // resets this value to 0. + size_t get_writelen() const; + +private: + evbuffer *evbuffer_; + evbuffer *bucket_; + uint8_t *buf_; + size_t bufmax_; + size_t buflen_; + ssize_t limit_; + size_t writelen_; +}; + +// These functions are provided to reduce epoll_ctl syscall. Avoid +// calling bufferevent_enable/disable() unless it is required by +// sniffing current enabled events. +void bev_enable_unless(bufferevent *bev, int events); +void bev_disable_unless(bufferevent *bev, int events); + +} // namespace util + +} // namespace nghttp2 + +#endif // LIBEVENT_UTIL_H diff -Nru nghttp2-1.13.0/src/Makefile.am nghttp2-0.6.7/src/Makefile.am --- nghttp2-1.13.0/src/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -22,19 +22,12 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = includes -EXTRA_DIST = \ - CMakeLists.txt \ - test.example.com.pem \ - test.nghttp2.org.pem - bin_PROGRAMS = check_PROGRAMS = TESTS = -AM_CFLAGS = $(WARNCFLAGS) -AM_CXXFLAGS = $(WARNCXXFLAGS) $(CXX1XCXXFLAGS) AM_CPPFLAGS = \ - -DPKGDATADIR='"$(pkgdatadir)"' \ + -Wall \ -I$(top_srcdir)/lib/includes \ -I$(top_builddir)/lib/includes \ -I$(top_srcdir)/lib \ @@ -42,32 +35,34 @@ -I$(top_srcdir)/third-party \ @LIBSPDYLAY_CFLAGS@ \ @XML_CPPFLAGS@ \ - @LIBEV_CFLAGS@ \ + @LIBEVENT_OPENSSL_CFLAGS@ \ @OPENSSL_CFLAGS@ \ @JANSSON_CFLAGS@ \ @ZLIB_CFLAGS@ \ @DEFS@ - -LDADD = $(top_builddir)/lib/libnghttp2.la \ - $(top_builddir)/third-party/libhttp-parser.la \ +AM_LDFLAGS = \ @JEMALLOC_LIBS@ \ @LIBSPDYLAY_LIBS@ \ @XML_LIBS@ \ - @LIBEV_LIBS@ \ + @LIBEVENT_OPENSSL_LIBS@ \ @OPENSSL_LIBS@ \ @JANSSON_LIBS@ \ @ZLIB_LIBS@ \ - @APPLDFLAGS@ + @SRC_LIBS@ + +LDADD = \ + $(top_builddir)/lib/libnghttp2.la \ + $(top_builddir)/third-party/libhttp-parser.la if ENABLE_APP bin_PROGRAMS += nghttp nghttpd nghttpx -HELPER_OBJECTS = util.cc \ +HELPER_OBJECTS = util.cc libevent_util.cc \ http2.cc timegm.c app_helper.cc nghttp2_gzip.c -HELPER_HFILES = util.h \ +HELPER_HFILES = util.h libevent_util.h \ http2.h timegm.h app_helper.h nghttp2_config.h \ - nghttp2_gzip.h network.h + nghttp2_gzip.h HTML_PARSER_OBJECTS = HTML_PARSER_HFILES = HtmlParser.h @@ -76,9 +71,8 @@ HTML_PARSER_OBJECTS += HtmlParser.cc endif # HAVE_LIBXML2 -nghttp_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttp.cc nghttp.h \ - ${HTML_PARSER_OBJECTS} ${HTML_PARSER_HFILES} \ - ssl.cc ssl.h +nghttp_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttp.cc \ + ${HTML_PARSER_OBJECTS} ${HTML_PARSER_HFILES} nghttpd_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttpd.cc \ ssl.cc ssl.h \ @@ -86,13 +80,12 @@ bin_PROGRAMS += h2load -h2load_SOURCES = util.cc util.h \ +h2load_SOURCES = util.cc util.h libevent_util.cc libevent_util.h \ http2.cc http2.h h2load.cc h2load.h \ timegm.c timegm.h \ ssl.cc ssl.h \ h2load_session.h \ - h2load_http2_session.cc h2load_http2_session.h \ - h2load_http1_session.cc h2load_http1_session.h + h2load_http2_session.cc h2load_http2_session.h if HAVE_SPDYLAY h2load_SOURCES += h2load_spdy_session.cc h2load_spdy_session.h @@ -100,77 +93,42 @@ NGHTTPX_SRCS = \ util.cc util.h http2.cc http2.h timegm.c timegm.h base64.h \ + libevent_util.cc libevent_util.h \ app_helper.cc app_helper.h \ ssl.cc ssl.h \ shrpx_config.cc shrpx_config.h \ shrpx_error.h \ - shrpx_accept_handler.cc shrpx_accept_handler.h \ - shrpx_connection_handler.cc shrpx_connection_handler.h \ + shrpx_listen_handler.cc shrpx_listen_handler.h \ shrpx_client_handler.cc shrpx_client_handler.h \ shrpx_upstream.h \ shrpx_http2_upstream.cc shrpx_http2_upstream.h \ shrpx_https_upstream.cc shrpx_https_upstream.h \ + shrpx_downstream_queue.cc shrpx_downstream_queue.h \ shrpx_downstream.cc shrpx_downstream.h \ shrpx_downstream_connection.cc shrpx_downstream_connection.h \ shrpx_http_downstream_connection.cc shrpx_http_downstream_connection.h \ shrpx_http2_downstream_connection.cc shrpx_http2_downstream_connection.h \ shrpx_http2_session.cc shrpx_http2_session.h \ - shrpx_downstream_queue.cc shrpx_downstream_queue.h \ shrpx_log.cc shrpx_log.h \ shrpx_http.cc shrpx_http.h \ shrpx_io_control.cc shrpx_io_control.h \ shrpx_ssl.cc shrpx_ssl.h \ + shrpx_thread_event_receiver.cc shrpx_thread_event_receiver.h \ shrpx_worker.cc shrpx_worker.h \ - shrpx_log_config.cc shrpx_log_config.h \ + shrpx_worker_config.cc shrpx_worker_config.h \ shrpx_connect_blocker.cc shrpx_connect_blocker.h \ - shrpx_live_check.cc shrpx_live_check.h \ - shrpx_downstream_connection_pool.cc shrpx_downstream_connection_pool.h \ - shrpx_rate_limit.cc shrpx_rate_limit.h \ - shrpx_connection.cc shrpx_connection.h \ - shrpx_memcached_dispatcher.cc shrpx_memcached_dispatcher.h \ - shrpx_memcached_connection.cc shrpx_memcached_connection.h \ - shrpx_memcached_request.h \ - shrpx_memcached_result.h \ - shrpx_worker_process.cc shrpx_worker_process.h \ - shrpx_process.h \ - shrpx_signal.cc shrpx_signal.h \ - shrpx_router.cc shrpx_router.h \ - shrpx_api_downstream_connection.cc shrpx_api_downstream_connection.h \ - shrpx_health_monitor_downstream_connection.cc \ - shrpx_health_monitor_downstream_connection.h \ - buffer.h memchunk.h template.h allocator.h + shrpx_downstream_connection_pool.cc shrpx_downstream_connection_pool.h if HAVE_SPDYLAY NGHTTPX_SRCS += shrpx_spdy_upstream.cc shrpx_spdy_upstream.h endif # HAVE_SPDYLAY -if HAVE_MRUBY -NGHTTPX_SRCS += \ - shrpx_mruby.cc shrpx_mruby.h \ - shrpx_mruby_module.cc shrpx_mruby_module.h \ - shrpx_mruby_module_env.cc shrpx_mruby_module_env.h \ - shrpx_mruby_module_request.cc shrpx_mruby_module_request.h \ - shrpx_mruby_module_response.cc shrpx_mruby_module_response.h -endif # HAVE_MRUBY - noinst_LIBRARIES = libnghttpx.a libnghttpx_a_SOURCES = ${NGHTTPX_SRCS} -libnghttpx_a_CPPFLAGS = ${AM_CPPFLAGS} nghttpx_SOURCES = shrpx.cc shrpx.h -nghttpx_CPPFLAGS = ${libnghttpx_a_CPPFLAGS} -nghttpx_LDADD = libnghttpx.a ${LDADD} - -if HAVE_MRUBY -libnghttpx_a_CPPFLAGS += \ - -I${top_srcdir}/third-party/mruby/include @LIBMRUBY_CFLAGS@ -nghttpx_LDADD += -L${top_builddir}/third-party/mruby/build/lib @LIBMRUBY_LIBS@ -endif # HAVE_MRUBY - -if HAVE_NEVERBLEED -libnghttpx_a_CPPFLAGS += -I${top_srcdir}/third-party/neverbleed -nghttpx_LDADD += ${top_builddir}/third-party/libneverbleed.la -endif # HAVE_NEVERBLEED +nghttpx_LDFLAGS = +nghttpx_LDADD = libnghttpx.a ${LDADD} ${AM_LDFLAGS} if HAVE_CUNIT check_PROGRAMS += nghttpx-unittest @@ -178,32 +136,15 @@ shrpx_ssl_test.cc shrpx_ssl_test.h \ shrpx_downstream_test.cc shrpx_downstream_test.h \ shrpx_config_test.cc shrpx_config_test.h \ - shrpx_worker_test.cc shrpx_worker_test.h \ - shrpx_http_test.cc shrpx_http_test.h \ - shrpx_router_test.cc shrpx_router_test.h \ http2_test.cc http2_test.h \ util_test.cc util_test.h \ nghttp2_gzip_test.c nghttp2_gzip_test.h \ - nghttp2_gzip.c nghttp2_gzip.h \ - buffer_test.cc buffer_test.h \ - memchunk_test.cc memchunk_test.h \ - template_test.cc template_test.h \ - base64_test.cc base64_test.h -nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS} \ - -DNGHTTP2_SRC_DIR=\"$(top_srcdir)/src\" -nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} @CUNIT_LIBS@ @TESTLDADD@ - -if HAVE_MRUBY -nghttpx_unittest_CPPFLAGS += \ - -I${top_srcdir}/third-party/mruby/include @LIBMRUBY_CFLAGS@ -nghttpx_unittest_LDADD += \ - -L${top_builddir}/third-party/mruby/build/lib @LIBMRUBY_LIBS@ -endif # HAVE_MRUBY - -if HAVE_NEVERBLEED -nghttpx_unittest_CPPFLAGS += -I${top_srcdir}/third-party/neverbleed -nghttpx_unittest_LDADD += ${top_builddir}/third-party/libneverbleed.la -endif # HAVE_NEVERBLEED + nghttp2_gzip.c nghttp2_gzip.h +nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS}\ + -DNGHTTP2_TESTS_DIR=\"$(top_srcdir)/tests\" +nghttpx_unittest_LDFLAGS = -static +nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} ${AM_LDFLAGS} \ + @CUNIT_LIBS@ @TESTS_LIBS@ TESTS += nghttpx-unittest endif # HAVE_CUNIT @@ -231,45 +172,23 @@ lib_LTLIBRARIES = libnghttp2_asio.la libnghttp2_asio_la_SOURCES = \ - util.cc util.h http2.cc http2.h \ - ssl.cc ssl.h \ - ssl_compat.h \ - timegm.c timegm.h \ - asio_common.cc asio_common.h \ - asio_io_service_pool.cc asio_io_service_pool.h \ - asio_server_http2.cc \ - asio_server_http2_impl.cc asio_server_http2_impl.h \ + asio_connection.h \ asio_server.cc asio_server.h \ - asio_server_http2_handler.cc asio_server_http2_handler.h \ - asio_server_connection.h \ - asio_server_request.cc \ - asio_server_request_impl.cc asio_server_request_impl.h \ - asio_server_response.cc \ - asio_server_response_impl.cc asio_server_response_impl.h \ - asio_server_stream.cc asio_server_stream.h \ - asio_server_serve_mux.cc asio_server_serve_mux.h \ - asio_server_request_handler.cc asio_server_request_handler.h \ - asio_server_tls_context.cc asio_server_tls_context.h \ - asio_client_session.cc \ - asio_client_session_impl.cc asio_client_session_impl.h \ - asio_client_session_tcp_impl.cc asio_client_session_tcp_impl.h \ - asio_client_session_tls_impl.cc asio_client_session_tls_impl.h \ - asio_client_response.cc \ - asio_client_response_impl.cc asio_client_response_impl.h \ - asio_client_request.cc \ - asio_client_request_impl.cc asio_client_request_impl.h \ - asio_client_stream.cc asio_client_stream.h \ - asio_client_tls_context.cc asio_client_tls_context.h - -libnghttp2_asio_la_CPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS} -libnghttp2_asio_la_LDFLAGS = -no-undefined -version-info 1:0:0 -libnghttp2_asio_la_LIBADD = \ - $(top_builddir)/lib/libnghttp2.la \ - $(top_builddir)/third-party/libhttp-parser.la \ - @OPENSSL_LIBS@ \ + asio_io_service_pool.cc asio_io_service_pool.h \ + asio_http2_handler.cc asio_http2_handler.h \ + asio_http2_impl.cc asio_http2_impl.h \ + util.cc util.h http2.cc http2.h \ + ssl.cc ssl.h + +libnghttp2_asio_la_CPPFLAGS= ${BOOST_CPPFLAGS} ${AM_CPPFLAGS} +libnghttp2_asio_la_LDFLAGS = \ ${BOOST_LDFLAGS} \ ${BOOST_ASIO_LIB} \ ${BOOST_THREAD_LIB} \ - ${BOOST_SYSTEM_LIB} + ${BOOST_SYSTEM_LIB} \ + @OPENSSL_LIBS@ \ + -no-undefined \ + -version-info 0:0:0 +libnghttp2_asio_la_LIBADD = $(top_builddir)/lib/libnghttp2.la endif # ENABLE_ASIO_LIB diff -Nru nghttp2-1.13.0/src/Makefile.in nghttp2-0.6.7/src/Makefile.in --- nghttp2-1.13.0/src/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/src/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -33,17 +33,7 @@ VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -114,31 +104,13 @@ @ENABLE_APP_TRUE@@HAVE_LIBXML2_TRUE@am__append_2 = HtmlParser.cc @ENABLE_APP_TRUE@@HAVE_SPDYLAY_TRUE@am__append_3 = h2load_spdy_session.cc h2load_spdy_session.h @ENABLE_APP_TRUE@@HAVE_SPDYLAY_TRUE@am__append_4 = shrpx_spdy_upstream.cc shrpx_spdy_upstream.h -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@am__append_5 = \ -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@ shrpx_mruby.cc shrpx_mruby.h \ -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@ shrpx_mruby_module.cc shrpx_mruby_module.h \ -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@ shrpx_mruby_module_env.cc shrpx_mruby_module_env.h \ -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@ shrpx_mruby_module_request.cc shrpx_mruby_module_request.h \ -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@ shrpx_mruby_module_response.cc shrpx_mruby_module_response.h - -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@am__append_6 = \ -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@ -I${top_srcdir}/third-party/mruby/include @LIBMRUBY_CFLAGS@ - -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@am__append_7 = -L${top_builddir}/third-party/mruby/build/lib @LIBMRUBY_LIBS@ -@ENABLE_APP_TRUE@@HAVE_NEVERBLEED_TRUE@am__append_8 = -I${top_srcdir}/third-party/neverbleed -@ENABLE_APP_TRUE@@HAVE_NEVERBLEED_TRUE@am__append_9 = ${top_builddir}/third-party/libneverbleed.la -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@am__append_10 = nghttpx-unittest -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@@HAVE_MRUBY_TRUE@am__append_11 = \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@@HAVE_MRUBY_TRUE@ -I${top_srcdir}/third-party/mruby/include @LIBMRUBY_CFLAGS@ - -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@@HAVE_MRUBY_TRUE@am__append_12 = \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@@HAVE_MRUBY_TRUE@ -L${top_builddir}/third-party/mruby/build/lib @LIBMRUBY_LIBS@ - -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@@HAVE_NEVERBLEED_TRUE@am__append_13 = -I${top_srcdir}/third-party/neverbleed -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@@HAVE_NEVERBLEED_TRUE@am__append_14 = ${top_builddir}/third-party/libneverbleed.la -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@am__append_15 = nghttpx-unittest -@ENABLE_HPACK_TOOLS_TRUE@am__append_16 = inflatehd deflatehd +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@am__append_5 = nghttpx-unittest +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@am__append_6 = nghttpx-unittest +@ENABLE_HPACK_TOOLS_TRUE@am__append_7 = inflatehd deflatehd subdir = src +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(srcdir)/libnghttp2_asio.pc.in $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -148,13 +120,11 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = libnghttp2_asio.pc @@ -168,87 +138,54 @@ libnghttpx_a_AR = $(AR) $(ARFLAGS) libnghttpx_a_LIBADD = am__libnghttpx_a_SOURCES_DIST = util.cc util.h http2.cc http2.h \ - timegm.c timegm.h base64.h app_helper.cc app_helper.h ssl.cc \ - ssl.h shrpx_config.cc shrpx_config.h shrpx_error.h \ - shrpx_accept_handler.cc shrpx_accept_handler.h \ - shrpx_connection_handler.cc shrpx_connection_handler.h \ - shrpx_client_handler.cc shrpx_client_handler.h \ - shrpx_upstream.h shrpx_http2_upstream.cc \ - shrpx_http2_upstream.h shrpx_https_upstream.cc \ - shrpx_https_upstream.h shrpx_downstream.cc shrpx_downstream.h \ + timegm.c timegm.h base64.h libevent_util.cc libevent_util.h \ + app_helper.cc app_helper.h ssl.cc ssl.h shrpx_config.cc \ + shrpx_config.h shrpx_error.h shrpx_listen_handler.cc \ + shrpx_listen_handler.h shrpx_client_handler.cc \ + shrpx_client_handler.h shrpx_upstream.h \ + shrpx_http2_upstream.cc shrpx_http2_upstream.h \ + shrpx_https_upstream.cc shrpx_https_upstream.h \ + shrpx_downstream_queue.cc shrpx_downstream_queue.h \ + shrpx_downstream.cc shrpx_downstream.h \ shrpx_downstream_connection.cc shrpx_downstream_connection.h \ shrpx_http_downstream_connection.cc \ shrpx_http_downstream_connection.h \ shrpx_http2_downstream_connection.cc \ shrpx_http2_downstream_connection.h shrpx_http2_session.cc \ - shrpx_http2_session.h shrpx_downstream_queue.cc \ - shrpx_downstream_queue.h shrpx_log.cc shrpx_log.h \ - shrpx_http.cc shrpx_http.h shrpx_io_control.cc \ - shrpx_io_control.h shrpx_ssl.cc shrpx_ssl.h shrpx_worker.cc \ - shrpx_worker.h shrpx_log_config.cc shrpx_log_config.h \ + shrpx_http2_session.h shrpx_log.cc shrpx_log.h shrpx_http.cc \ + shrpx_http.h shrpx_io_control.cc shrpx_io_control.h \ + shrpx_ssl.cc shrpx_ssl.h shrpx_thread_event_receiver.cc \ + shrpx_thread_event_receiver.h shrpx_worker.cc shrpx_worker.h \ + shrpx_worker_config.cc shrpx_worker_config.h \ shrpx_connect_blocker.cc shrpx_connect_blocker.h \ - shrpx_live_check.cc shrpx_live_check.h \ shrpx_downstream_connection_pool.cc \ - shrpx_downstream_connection_pool.h shrpx_rate_limit.cc \ - shrpx_rate_limit.h shrpx_connection.cc shrpx_connection.h \ - shrpx_memcached_dispatcher.cc shrpx_memcached_dispatcher.h \ - shrpx_memcached_connection.cc shrpx_memcached_connection.h \ - shrpx_memcached_request.h shrpx_memcached_result.h \ - shrpx_worker_process.cc shrpx_worker_process.h shrpx_process.h \ - shrpx_signal.cc shrpx_signal.h shrpx_router.cc shrpx_router.h \ - shrpx_api_downstream_connection.cc \ - shrpx_api_downstream_connection.h \ - shrpx_health_monitor_downstream_connection.cc \ - shrpx_health_monitor_downstream_connection.h buffer.h \ - memchunk.h template.h allocator.h shrpx_spdy_upstream.cc \ - shrpx_spdy_upstream.h shrpx_mruby.cc shrpx_mruby.h \ - shrpx_mruby_module.cc shrpx_mruby_module.h \ - shrpx_mruby_module_env.cc shrpx_mruby_module_env.h \ - shrpx_mruby_module_request.cc shrpx_mruby_module_request.h \ - shrpx_mruby_module_response.cc shrpx_mruby_module_response.h -@ENABLE_APP_TRUE@@HAVE_SPDYLAY_TRUE@am__objects_1 = libnghttpx_a-shrpx_spdy_upstream.$(OBJEXT) -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@am__objects_2 = libnghttpx_a-shrpx_mruby.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@ libnghttpx_a-shrpx_mruby_module.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@ libnghttpx_a-shrpx_mruby_module_env.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@ libnghttpx_a-shrpx_mruby_module_request.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_MRUBY_TRUE@ libnghttpx_a-shrpx_mruby_module_response.$(OBJEXT) -@ENABLE_APP_TRUE@am__objects_3 = libnghttpx_a-util.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-http2.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-timegm.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-app_helper.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-ssl.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_config.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_accept_handler.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_connection_handler.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_client_handler.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_http2_upstream.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_https_upstream.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_downstream.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_downstream_connection.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_http_downstream_connection.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_http2_downstream_connection.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_http2_session.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_downstream_queue.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_log.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_http.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_io_control.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_ssl.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_worker.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_log_config.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_connect_blocker.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_live_check.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_downstream_connection_pool.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_rate_limit.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_connection.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_memcached_dispatcher.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_memcached_connection.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_worker_process.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_signal.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_router.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_api_downstream_connection.$(OBJEXT) \ -@ENABLE_APP_TRUE@ libnghttpx_a-shrpx_health_monitor_downstream_connection.$(OBJEXT) \ -@ENABLE_APP_TRUE@ $(am__objects_1) $(am__objects_2) -@ENABLE_APP_TRUE@am_libnghttpx_a_OBJECTS = $(am__objects_3) + shrpx_downstream_connection_pool.h shrpx_spdy_upstream.cc \ + shrpx_spdy_upstream.h +@ENABLE_APP_TRUE@@HAVE_SPDYLAY_TRUE@am__objects_1 = shrpx_spdy_upstream.$(OBJEXT) +@ENABLE_APP_TRUE@am__objects_2 = util.$(OBJEXT) http2.$(OBJEXT) \ +@ENABLE_APP_TRUE@ timegm.$(OBJEXT) libevent_util.$(OBJEXT) \ +@ENABLE_APP_TRUE@ app_helper.$(OBJEXT) ssl.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_config.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_listen_handler.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_client_handler.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_http2_upstream.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_https_upstream.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_downstream_queue.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_downstream.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_downstream_connection.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_http_downstream_connection.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_http2_downstream_connection.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_http2_session.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_log.$(OBJEXT) shrpx_http.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_io_control.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_ssl.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_thread_event_receiver.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_worker.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_worker_config.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_connect_blocker.$(OBJEXT) \ +@ENABLE_APP_TRUE@ shrpx_downstream_connection_pool.$(OBJEXT) \ +@ENABLE_APP_TRUE@ $(am__objects_1) +@ENABLE_APP_TRUE@am_libnghttpx_a_OBJECTS = $(am__objects_2) libnghttpx_a_OBJECTS = $(am_libnghttpx_a_OBJECTS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ @@ -280,65 +217,20 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(pkgconfigdir)" LTLIBRARIES = $(lib_LTLIBRARIES) -am__DEPENDENCIES_1 = @ENABLE_ASIO_LIB_TRUE@libnghttp2_asio_la_DEPENDENCIES = \ -@ENABLE_ASIO_LIB_TRUE@ $(top_builddir)/lib/libnghttp2.la \ -@ENABLE_ASIO_LIB_TRUE@ $(top_builddir)/third-party/libhttp-parser.la \ -@ENABLE_ASIO_LIB_TRUE@ $(am__DEPENDENCIES_1) \ -@ENABLE_ASIO_LIB_TRUE@ $(am__DEPENDENCIES_1) \ -@ENABLE_ASIO_LIB_TRUE@ $(am__DEPENDENCIES_1) \ -@ENABLE_ASIO_LIB_TRUE@ $(am__DEPENDENCIES_1) -am__libnghttp2_asio_la_SOURCES_DIST = util.cc util.h http2.cc http2.h \ - ssl.cc ssl.h ssl_compat.h timegm.c timegm.h asio_common.cc \ - asio_common.h asio_io_service_pool.cc asio_io_service_pool.h \ - asio_server_http2.cc asio_server_http2_impl.cc \ - asio_server_http2_impl.h asio_server.cc asio_server.h \ - asio_server_http2_handler.cc asio_server_http2_handler.h \ - asio_server_connection.h asio_server_request.cc \ - asio_server_request_impl.cc asio_server_request_impl.h \ - asio_server_response.cc asio_server_response_impl.cc \ - asio_server_response_impl.h asio_server_stream.cc \ - asio_server_stream.h asio_server_serve_mux.cc \ - asio_server_serve_mux.h asio_server_request_handler.cc \ - asio_server_request_handler.h asio_server_tls_context.cc \ - asio_server_tls_context.h asio_client_session.cc \ - asio_client_session_impl.cc asio_client_session_impl.h \ - asio_client_session_tcp_impl.cc asio_client_session_tcp_impl.h \ - asio_client_session_tls_impl.cc asio_client_session_tls_impl.h \ - asio_client_response.cc asio_client_response_impl.cc \ - asio_client_response_impl.h asio_client_request.cc \ - asio_client_request_impl.cc asio_client_request_impl.h \ - asio_client_stream.cc asio_client_stream.h \ - asio_client_tls_context.cc asio_client_tls_context.h +@ENABLE_ASIO_LIB_TRUE@ $(top_builddir)/lib/libnghttp2.la +am__libnghttp2_asio_la_SOURCES_DIST = asio_connection.h asio_server.cc \ + asio_server.h asio_io_service_pool.cc asio_io_service_pool.h \ + asio_http2_handler.cc asio_http2_handler.h asio_http2_impl.cc \ + asio_http2_impl.h util.cc util.h http2.cc http2.h ssl.cc ssl.h @ENABLE_ASIO_LIB_TRUE@am_libnghttp2_asio_la_OBJECTS = \ +@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server.lo \ +@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_io_service_pool.lo \ +@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_http2_handler.lo \ +@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_http2_impl.lo \ @ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-util.lo \ @ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-http2.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-ssl.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-timegm.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_common.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_io_service_pool.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_http2.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_http2_impl.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_http2_handler.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_request.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_request_impl.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_response.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_response_impl.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_stream.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_serve_mux.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_request_handler.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_server_tls_context.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_client_session.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_client_session_impl.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_client_session_tcp_impl.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_client_session_tls_impl.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_client_response.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_client_response_impl.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_client_request.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_client_request_impl.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_client_stream.lo \ -@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-asio_client_tls_context.lo +@ENABLE_ASIO_LIB_TRUE@ libnghttp2_asio_la-ssl.lo libnghttp2_asio_la_OBJECTS = $(am_libnghttp2_asio_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -357,103 +249,96 @@ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx-unittest$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) am__deflatehd_SOURCES_DIST = deflatehd.cc comp_helper.c comp_helper.h -@ENABLE_HPACK_TOOLS_TRUE@am__objects_4 = comp_helper.$(OBJEXT) +@ENABLE_HPACK_TOOLS_TRUE@am__objects_3 = comp_helper.$(OBJEXT) @ENABLE_HPACK_TOOLS_TRUE@am_deflatehd_OBJECTS = deflatehd.$(OBJEXT) \ -@ENABLE_HPACK_TOOLS_TRUE@ $(am__objects_4) +@ENABLE_HPACK_TOOLS_TRUE@ $(am__objects_3) deflatehd_OBJECTS = $(am_deflatehd_OBJECTS) deflatehd_LDADD = $(LDADD) deflatehd_DEPENDENCIES = $(top_builddir)/lib/libnghttp2.la \ $(top_builddir)/third-party/libhttp-parser.la -am__h2load_SOURCES_DIST = util.cc util.h http2.cc http2.h h2load.cc \ - h2load.h timegm.c timegm.h ssl.cc ssl.h h2load_session.h \ - h2load_http2_session.cc h2load_http2_session.h \ - h2load_http1_session.cc h2load_http1_session.h \ - h2load_spdy_session.cc h2load_spdy_session.h -@ENABLE_APP_TRUE@@HAVE_SPDYLAY_TRUE@am__objects_5 = h2load_spdy_session.$(OBJEXT) -@ENABLE_APP_TRUE@am_h2load_OBJECTS = util.$(OBJEXT) http2.$(OBJEXT) \ +am__h2load_SOURCES_DIST = util.cc util.h libevent_util.cc \ + libevent_util.h http2.cc http2.h h2load.cc h2load.h timegm.c \ + timegm.h ssl.cc ssl.h h2load_session.h h2load_http2_session.cc \ + h2load_http2_session.h h2load_spdy_session.cc \ + h2load_spdy_session.h +@ENABLE_APP_TRUE@@HAVE_SPDYLAY_TRUE@am__objects_4 = h2load_spdy_session.$(OBJEXT) +@ENABLE_APP_TRUE@am_h2load_OBJECTS = util.$(OBJEXT) \ +@ENABLE_APP_TRUE@ libevent_util.$(OBJEXT) http2.$(OBJEXT) \ @ENABLE_APP_TRUE@ h2load.$(OBJEXT) timegm.$(OBJEXT) \ @ENABLE_APP_TRUE@ ssl.$(OBJEXT) h2load_http2_session.$(OBJEXT) \ -@ENABLE_APP_TRUE@ h2load_http1_session.$(OBJEXT) \ -@ENABLE_APP_TRUE@ $(am__objects_5) +@ENABLE_APP_TRUE@ $(am__objects_4) h2load_OBJECTS = $(am_h2load_OBJECTS) h2load_LDADD = $(LDADD) h2load_DEPENDENCIES = $(top_builddir)/lib/libnghttp2.la \ $(top_builddir)/third-party/libhttp-parser.la am__inflatehd_SOURCES_DIST = inflatehd.cc comp_helper.c comp_helper.h @ENABLE_HPACK_TOOLS_TRUE@am_inflatehd_OBJECTS = inflatehd.$(OBJEXT) \ -@ENABLE_HPACK_TOOLS_TRUE@ $(am__objects_4) +@ENABLE_HPACK_TOOLS_TRUE@ $(am__objects_3) inflatehd_OBJECTS = $(am_inflatehd_OBJECTS) inflatehd_LDADD = $(LDADD) inflatehd_DEPENDENCIES = $(top_builddir)/lib/libnghttp2.la \ $(top_builddir)/third-party/libhttp-parser.la -am__nghttp_SOURCES_DIST = util.cc http2.cc timegm.c app_helper.cc \ - nghttp2_gzip.c util.h http2.h timegm.h app_helper.h \ - nghttp2_config.h nghttp2_gzip.h network.h nghttp.cc nghttp.h \ - HtmlParser.cc HtmlParser.h ssl.cc ssl.h -@ENABLE_APP_TRUE@am__objects_6 = util.$(OBJEXT) http2.$(OBJEXT) \ +am__nghttp_SOURCES_DIST = util.cc libevent_util.cc http2.cc timegm.c \ + app_helper.cc nghttp2_gzip.c util.h libevent_util.h http2.h \ + timegm.h app_helper.h nghttp2_config.h nghttp2_gzip.h \ + nghttp.cc HtmlParser.cc HtmlParser.h +@ENABLE_APP_TRUE@am__objects_5 = util.$(OBJEXT) \ +@ENABLE_APP_TRUE@ libevent_util.$(OBJEXT) http2.$(OBJEXT) \ @ENABLE_APP_TRUE@ timegm.$(OBJEXT) app_helper.$(OBJEXT) \ @ENABLE_APP_TRUE@ nghttp2_gzip.$(OBJEXT) -am__objects_7 = -@ENABLE_APP_TRUE@@HAVE_LIBXML2_TRUE@am__objects_8 = \ +am__objects_6 = +@ENABLE_APP_TRUE@@HAVE_LIBXML2_TRUE@am__objects_7 = \ @ENABLE_APP_TRUE@@HAVE_LIBXML2_TRUE@ HtmlParser.$(OBJEXT) -@ENABLE_APP_TRUE@am__objects_9 = $(am__objects_8) -@ENABLE_APP_TRUE@am_nghttp_OBJECTS = $(am__objects_6) $(am__objects_7) \ -@ENABLE_APP_TRUE@ nghttp.$(OBJEXT) $(am__objects_9) \ -@ENABLE_APP_TRUE@ $(am__objects_7) ssl.$(OBJEXT) +@ENABLE_APP_TRUE@am__objects_8 = $(am__objects_7) +@ENABLE_APP_TRUE@am_nghttp_OBJECTS = $(am__objects_5) $(am__objects_6) \ +@ENABLE_APP_TRUE@ nghttp.$(OBJEXT) $(am__objects_8) \ +@ENABLE_APP_TRUE@ $(am__objects_6) nghttp_OBJECTS = $(am_nghttp_OBJECTS) nghttp_LDADD = $(LDADD) nghttp_DEPENDENCIES = $(top_builddir)/lib/libnghttp2.la \ $(top_builddir)/third-party/libhttp-parser.la -am__nghttpd_SOURCES_DIST = util.cc http2.cc timegm.c app_helper.cc \ - nghttp2_gzip.c util.h http2.h timegm.h app_helper.h \ - nghttp2_config.h nghttp2_gzip.h network.h nghttpd.cc ssl.cc \ - ssl.h HttpServer.cc HttpServer.h -@ENABLE_APP_TRUE@am_nghttpd_OBJECTS = $(am__objects_6) \ -@ENABLE_APP_TRUE@ $(am__objects_7) nghttpd.$(OBJEXT) \ +am__nghttpd_SOURCES_DIST = util.cc libevent_util.cc http2.cc timegm.c \ + app_helper.cc nghttp2_gzip.c util.h libevent_util.h http2.h \ + timegm.h app_helper.h nghttp2_config.h nghttp2_gzip.h \ + nghttpd.cc ssl.cc ssl.h HttpServer.cc HttpServer.h +@ENABLE_APP_TRUE@am_nghttpd_OBJECTS = $(am__objects_5) \ +@ENABLE_APP_TRUE@ $(am__objects_6) nghttpd.$(OBJEXT) \ @ENABLE_APP_TRUE@ ssl.$(OBJEXT) HttpServer.$(OBJEXT) nghttpd_OBJECTS = $(am_nghttpd_OBJECTS) nghttpd_LDADD = $(LDADD) nghttpd_DEPENDENCIES = $(top_builddir)/lib/libnghttp2.la \ $(top_builddir)/third-party/libhttp-parser.la am__nghttpx_SOURCES_DIST = shrpx.cc shrpx.h -@ENABLE_APP_TRUE@am_nghttpx_OBJECTS = nghttpx-shrpx.$(OBJEXT) +@ENABLE_APP_TRUE@am_nghttpx_OBJECTS = shrpx.$(OBJEXT) nghttpx_OBJECTS = $(am_nghttpx_OBJECTS) -am__DEPENDENCIES_2 = $(top_builddir)/lib/libnghttp2.la \ - $(top_builddir)/third-party/libhttp-parser.la -@ENABLE_APP_TRUE@nghttpx_DEPENDENCIES = libnghttpx.a \ -@ENABLE_APP_TRUE@ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ -@ENABLE_APP_TRUE@ $(am__append_9) +am__DEPENDENCIES_1 = +@ENABLE_APP_TRUE@nghttpx_DEPENDENCIES = libnghttpx.a $(LDADD) \ +@ENABLE_APP_TRUE@ $(am__DEPENDENCIES_1) +nghttpx_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(nghttpx_LDFLAGS) $(LDFLAGS) -o $@ am__nghttpx_unittest_SOURCES_DIST = shrpx-unittest.cc \ shrpx_ssl_test.cc shrpx_ssl_test.h shrpx_downstream_test.cc \ shrpx_downstream_test.h shrpx_config_test.cc \ - shrpx_config_test.h shrpx_worker_test.cc shrpx_worker_test.h \ - shrpx_http_test.cc shrpx_http_test.h shrpx_router_test.cc \ - shrpx_router_test.h http2_test.cc http2_test.h util_test.cc \ + shrpx_config_test.h http2_test.cc http2_test.h util_test.cc \ util_test.h nghttp2_gzip_test.c nghttp2_gzip_test.h \ - nghttp2_gzip.c nghttp2_gzip.h buffer_test.cc buffer_test.h \ - memchunk_test.cc memchunk_test.h template_test.cc \ - template_test.h base64_test.cc base64_test.h + nghttp2_gzip.c nghttp2_gzip.h @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@am_nghttpx_unittest_OBJECTS = nghttpx_unittest-shrpx-unittest.$(OBJEXT) \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-shrpx_ssl_test.$(OBJEXT) \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-shrpx_downstream_test.$(OBJEXT) \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-shrpx_config_test.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-shrpx_worker_test.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-shrpx_http_test.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-shrpx_router_test.$(OBJEXT) \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-http2_test.$(OBJEXT) \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-util_test.$(OBJEXT) \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-nghttp2_gzip_test.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-nghttp2_gzip.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-buffer_test.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-memchunk_test.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-template_test.$(OBJEXT) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-base64_test.$(OBJEXT) +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttpx_unittest-nghttp2_gzip.$(OBJEXT) nghttpx_unittest_OBJECTS = $(am_nghttpx_unittest_OBJECTS) @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@nghttpx_unittest_DEPENDENCIES = \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ libnghttpx.a \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ $(am__DEPENDENCIES_2) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ $(am__DEPENDENCIES_1) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ $(am__append_14) +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ libnghttpx.a $(LDADD) \ +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ $(am__DEPENDENCIES_1) +nghttpx_unittest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(nghttpx_unittest_LDFLAGS) \ + $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -734,9 +619,6 @@ TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DIST_SUBDIRS = $(SUBDIRS) -am__DIST_COMMON = $(srcdir)/Makefile.in \ - $(srcdir)/libnghttp2_asio.pc.in $(top_srcdir)/depcomp \ - $(top_srcdir)/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -766,7 +648,6 @@ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -785,7 +666,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -801,7 +681,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -817,10 +696,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -832,7 +707,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -870,11 +744,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -929,7 +802,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -951,15 +823,8 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = includes -EXTRA_DIST = \ - CMakeLists.txt \ - test.example.com.pem \ - test.nghttp2.org.pem - -AM_CFLAGS = $(WARNCFLAGS) -AM_CXXFLAGS = $(WARNCXXFLAGS) $(CXX1XCXXFLAGS) AM_CPPFLAGS = \ - -DPKGDATADIR='"$(pkgdatadir)"' \ + -Wall \ -I$(top_srcdir)/lib/includes \ -I$(top_builddir)/lib/includes \ -I$(top_srcdir)/lib \ @@ -967,61 +832,61 @@ -I$(top_srcdir)/third-party \ @LIBSPDYLAY_CFLAGS@ \ @XML_CPPFLAGS@ \ - @LIBEV_CFLAGS@ \ + @LIBEVENT_OPENSSL_CFLAGS@ \ @OPENSSL_CFLAGS@ \ @JANSSON_CFLAGS@ \ @ZLIB_CFLAGS@ \ @DEFS@ -LDADD = $(top_builddir)/lib/libnghttp2.la \ - $(top_builddir)/third-party/libhttp-parser.la \ +AM_LDFLAGS = \ @JEMALLOC_LIBS@ \ @LIBSPDYLAY_LIBS@ \ @XML_LIBS@ \ - @LIBEV_LIBS@ \ + @LIBEVENT_OPENSSL_LIBS@ \ @OPENSSL_LIBS@ \ @JANSSON_LIBS@ \ @ZLIB_LIBS@ \ - @APPLDFLAGS@ + @SRC_LIBS@ -@ENABLE_APP_TRUE@HELPER_OBJECTS = util.cc \ +LDADD = \ + $(top_builddir)/lib/libnghttp2.la \ + $(top_builddir)/third-party/libhttp-parser.la + +@ENABLE_APP_TRUE@HELPER_OBJECTS = util.cc libevent_util.cc \ @ENABLE_APP_TRUE@ http2.cc timegm.c app_helper.cc nghttp2_gzip.c -@ENABLE_APP_TRUE@HELPER_HFILES = util.h \ +@ENABLE_APP_TRUE@HELPER_HFILES = util.h libevent_util.h \ @ENABLE_APP_TRUE@ http2.h timegm.h app_helper.h nghttp2_config.h \ -@ENABLE_APP_TRUE@ nghttp2_gzip.h network.h +@ENABLE_APP_TRUE@ nghttp2_gzip.h @ENABLE_APP_TRUE@HTML_PARSER_OBJECTS = $(am__append_2) @ENABLE_APP_TRUE@HTML_PARSER_HFILES = HtmlParser.h -@ENABLE_APP_TRUE@nghttp_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttp.cc nghttp.h \ -@ENABLE_APP_TRUE@ ${HTML_PARSER_OBJECTS} ${HTML_PARSER_HFILES} \ -@ENABLE_APP_TRUE@ ssl.cc ssl.h +@ENABLE_APP_TRUE@nghttp_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttp.cc \ +@ENABLE_APP_TRUE@ ${HTML_PARSER_OBJECTS} ${HTML_PARSER_HFILES} @ENABLE_APP_TRUE@nghttpd_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttpd.cc \ @ENABLE_APP_TRUE@ ssl.cc ssl.h \ @ENABLE_APP_TRUE@ HttpServer.cc HttpServer.h -@ENABLE_APP_TRUE@h2load_SOURCES = util.cc util.h http2.cc http2.h \ -@ENABLE_APP_TRUE@ h2load.cc h2load.h timegm.c timegm.h ssl.cc \ -@ENABLE_APP_TRUE@ ssl.h h2load_session.h \ -@ENABLE_APP_TRUE@ h2load_http2_session.cc \ -@ENABLE_APP_TRUE@ h2load_http2_session.h \ -@ENABLE_APP_TRUE@ h2load_http1_session.cc \ -@ENABLE_APP_TRUE@ h2load_http1_session.h $(am__append_3) +@ENABLE_APP_TRUE@h2load_SOURCES = util.cc util.h libevent_util.cc \ +@ENABLE_APP_TRUE@ libevent_util.h http2.cc http2.h h2load.cc \ +@ENABLE_APP_TRUE@ h2load.h timegm.c timegm.h ssl.cc ssl.h \ +@ENABLE_APP_TRUE@ h2load_session.h h2load_http2_session.cc \ +@ENABLE_APP_TRUE@ h2load_http2_session.h $(am__append_3) @ENABLE_APP_TRUE@NGHTTPX_SRCS = util.cc util.h http2.cc http2.h \ -@ENABLE_APP_TRUE@ timegm.c timegm.h base64.h app_helper.cc \ -@ENABLE_APP_TRUE@ app_helper.h ssl.cc ssl.h shrpx_config.cc \ -@ENABLE_APP_TRUE@ shrpx_config.h shrpx_error.h \ -@ENABLE_APP_TRUE@ shrpx_accept_handler.cc \ -@ENABLE_APP_TRUE@ shrpx_accept_handler.h \ -@ENABLE_APP_TRUE@ shrpx_connection_handler.cc \ -@ENABLE_APP_TRUE@ shrpx_connection_handler.h \ +@ENABLE_APP_TRUE@ timegm.c timegm.h base64.h libevent_util.cc \ +@ENABLE_APP_TRUE@ libevent_util.h app_helper.cc app_helper.h \ +@ENABLE_APP_TRUE@ ssl.cc ssl.h shrpx_config.cc shrpx_config.h \ +@ENABLE_APP_TRUE@ shrpx_error.h shrpx_listen_handler.cc \ +@ENABLE_APP_TRUE@ shrpx_listen_handler.h \ @ENABLE_APP_TRUE@ shrpx_client_handler.cc \ @ENABLE_APP_TRUE@ shrpx_client_handler.h shrpx_upstream.h \ @ENABLE_APP_TRUE@ shrpx_http2_upstream.cc \ @ENABLE_APP_TRUE@ shrpx_http2_upstream.h \ @ENABLE_APP_TRUE@ shrpx_https_upstream.cc \ -@ENABLE_APP_TRUE@ shrpx_https_upstream.h shrpx_downstream.cc \ +@ENABLE_APP_TRUE@ shrpx_https_upstream.h \ +@ENABLE_APP_TRUE@ shrpx_downstream_queue.cc \ +@ENABLE_APP_TRUE@ shrpx_downstream_queue.h shrpx_downstream.cc \ @ENABLE_APP_TRUE@ shrpx_downstream.h \ @ENABLE_APP_TRUE@ shrpx_downstream_connection.cc \ @ENABLE_APP_TRUE@ shrpx_downstream_connection.h \ @@ -1030,69 +895,39 @@ @ENABLE_APP_TRUE@ shrpx_http2_downstream_connection.cc \ @ENABLE_APP_TRUE@ shrpx_http2_downstream_connection.h \ @ENABLE_APP_TRUE@ shrpx_http2_session.cc shrpx_http2_session.h \ -@ENABLE_APP_TRUE@ shrpx_downstream_queue.cc \ -@ENABLE_APP_TRUE@ shrpx_downstream_queue.h shrpx_log.cc \ -@ENABLE_APP_TRUE@ shrpx_log.h shrpx_http.cc shrpx_http.h \ -@ENABLE_APP_TRUE@ shrpx_io_control.cc shrpx_io_control.h \ -@ENABLE_APP_TRUE@ shrpx_ssl.cc shrpx_ssl.h shrpx_worker.cc \ -@ENABLE_APP_TRUE@ shrpx_worker.h shrpx_log_config.cc \ -@ENABLE_APP_TRUE@ shrpx_log_config.h shrpx_connect_blocker.cc \ -@ENABLE_APP_TRUE@ shrpx_connect_blocker.h shrpx_live_check.cc \ -@ENABLE_APP_TRUE@ shrpx_live_check.h \ +@ENABLE_APP_TRUE@ shrpx_log.cc shrpx_log.h shrpx_http.cc \ +@ENABLE_APP_TRUE@ shrpx_http.h shrpx_io_control.cc \ +@ENABLE_APP_TRUE@ shrpx_io_control.h shrpx_ssl.cc shrpx_ssl.h \ +@ENABLE_APP_TRUE@ shrpx_thread_event_receiver.cc \ +@ENABLE_APP_TRUE@ shrpx_thread_event_receiver.h shrpx_worker.cc \ +@ENABLE_APP_TRUE@ shrpx_worker.h shrpx_worker_config.cc \ +@ENABLE_APP_TRUE@ shrpx_worker_config.h \ +@ENABLE_APP_TRUE@ shrpx_connect_blocker.cc \ +@ENABLE_APP_TRUE@ shrpx_connect_blocker.h \ @ENABLE_APP_TRUE@ shrpx_downstream_connection_pool.cc \ @ENABLE_APP_TRUE@ shrpx_downstream_connection_pool.h \ -@ENABLE_APP_TRUE@ shrpx_rate_limit.cc shrpx_rate_limit.h \ -@ENABLE_APP_TRUE@ shrpx_connection.cc shrpx_connection.h \ -@ENABLE_APP_TRUE@ shrpx_memcached_dispatcher.cc \ -@ENABLE_APP_TRUE@ shrpx_memcached_dispatcher.h \ -@ENABLE_APP_TRUE@ shrpx_memcached_connection.cc \ -@ENABLE_APP_TRUE@ shrpx_memcached_connection.h \ -@ENABLE_APP_TRUE@ shrpx_memcached_request.h \ -@ENABLE_APP_TRUE@ shrpx_memcached_result.h \ -@ENABLE_APP_TRUE@ shrpx_worker_process.cc \ -@ENABLE_APP_TRUE@ shrpx_worker_process.h shrpx_process.h \ -@ENABLE_APP_TRUE@ shrpx_signal.cc shrpx_signal.h \ -@ENABLE_APP_TRUE@ shrpx_router.cc shrpx_router.h \ -@ENABLE_APP_TRUE@ shrpx_api_downstream_connection.cc \ -@ENABLE_APP_TRUE@ shrpx_api_downstream_connection.h \ -@ENABLE_APP_TRUE@ shrpx_health_monitor_downstream_connection.cc \ -@ENABLE_APP_TRUE@ shrpx_health_monitor_downstream_connection.h \ -@ENABLE_APP_TRUE@ buffer.h memchunk.h template.h allocator.h \ -@ENABLE_APP_TRUE@ $(am__append_4) $(am__append_5) +@ENABLE_APP_TRUE@ $(am__append_4) @ENABLE_APP_TRUE@noinst_LIBRARIES = libnghttpx.a @ENABLE_APP_TRUE@libnghttpx_a_SOURCES = ${NGHTTPX_SRCS} -@ENABLE_APP_TRUE@libnghttpx_a_CPPFLAGS = ${AM_CPPFLAGS} \ -@ENABLE_APP_TRUE@ $(am__append_6) $(am__append_8) @ENABLE_APP_TRUE@nghttpx_SOURCES = shrpx.cc shrpx.h -@ENABLE_APP_TRUE@nghttpx_CPPFLAGS = ${libnghttpx_a_CPPFLAGS} -@ENABLE_APP_TRUE@nghttpx_LDADD = libnghttpx.a ${LDADD} $(am__append_7) \ -@ENABLE_APP_TRUE@ $(am__append_9) +@ENABLE_APP_TRUE@nghttpx_LDFLAGS = +@ENABLE_APP_TRUE@nghttpx_LDADD = libnghttpx.a ${LDADD} ${AM_LDFLAGS} @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@nghttpx_unittest_SOURCES = shrpx-unittest.cc \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ shrpx_ssl_test.cc shrpx_ssl_test.h \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ shrpx_downstream_test.cc shrpx_downstream_test.h \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ shrpx_config_test.cc shrpx_config_test.h \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ shrpx_worker_test.cc shrpx_worker_test.h \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ shrpx_http_test.cc shrpx_http_test.h \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ shrpx_router_test.cc shrpx_router_test.h \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ http2_test.cc http2_test.h \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ util_test.cc util_test.h \ @ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttp2_gzip_test.c nghttp2_gzip_test.h \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttp2_gzip.c nghttp2_gzip.h \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ buffer_test.cc buffer_test.h \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ memchunk_test.cc memchunk_test.h \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ template_test.cc template_test.h \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ base64_test.cc base64_test.h - -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@nghttpx_unittest_CPPFLAGS = \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ ${AM_CPPFLAGS} \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ -DNGHTTP2_SRC_DIR=\"$(top_srcdir)/src\" \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ $(am__append_11) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ $(am__append_13) -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@nghttpx_unittest_LDADD = \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ libnghttpx.a ${LDADD} \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ @CUNIT_LIBS@ @TESTLDADD@ \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ $(am__append_12) \ -@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ $(am__append_14) +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ nghttp2_gzip.c nghttp2_gzip.h + +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS}\ +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ -DNGHTTP2_TESTS_DIR=\"$(top_srcdir)/tests\" + +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@nghttpx_unittest_LDFLAGS = -static +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} ${AM_LDFLAGS} \ +@ENABLE_APP_TRUE@@HAVE_CUNIT_TRUE@ @CUNIT_LIBS@ @TESTS_LIBS@ + @ENABLE_HPACK_TOOLS_TRUE@HPACK_TOOLS_COMMON_SRCS = comp_helper.c comp_helper.h @ENABLE_HPACK_TOOLS_TRUE@inflatehd_SOURCES = inflatehd.cc $(HPACK_TOOLS_COMMON_SRCS) @ENABLE_HPACK_TOOLS_TRUE@deflatehd_SOURCES = deflatehd.cc $(HPACK_TOOLS_COMMON_SRCS) @@ -1101,47 +936,25 @@ @ENABLE_ASIO_LIB_TRUE@DISTCLEANFILES = $(pkgconfig_DATA) @ENABLE_ASIO_LIB_TRUE@lib_LTLIBRARIES = libnghttp2_asio.la @ENABLE_ASIO_LIB_TRUE@libnghttp2_asio_la_SOURCES = \ -@ENABLE_ASIO_LIB_TRUE@ util.cc util.h http2.cc http2.h \ -@ENABLE_ASIO_LIB_TRUE@ ssl.cc ssl.h \ -@ENABLE_ASIO_LIB_TRUE@ ssl_compat.h \ -@ENABLE_ASIO_LIB_TRUE@ timegm.c timegm.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_common.cc asio_common.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_io_service_pool.cc asio_io_service_pool.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_http2.cc \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_http2_impl.cc asio_server_http2_impl.h \ +@ENABLE_ASIO_LIB_TRUE@ asio_connection.h \ @ENABLE_ASIO_LIB_TRUE@ asio_server.cc asio_server.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_http2_handler.cc asio_server_http2_handler.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_connection.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_request.cc \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_request_impl.cc asio_server_request_impl.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_response.cc \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_response_impl.cc asio_server_response_impl.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_stream.cc asio_server_stream.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_serve_mux.cc asio_server_serve_mux.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_request_handler.cc asio_server_request_handler.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_server_tls_context.cc asio_server_tls_context.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_client_session.cc \ -@ENABLE_ASIO_LIB_TRUE@ asio_client_session_impl.cc asio_client_session_impl.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_client_session_tcp_impl.cc asio_client_session_tcp_impl.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_client_session_tls_impl.cc asio_client_session_tls_impl.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_client_response.cc \ -@ENABLE_ASIO_LIB_TRUE@ asio_client_response_impl.cc asio_client_response_impl.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_client_request.cc \ -@ENABLE_ASIO_LIB_TRUE@ asio_client_request_impl.cc asio_client_request_impl.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_client_stream.cc asio_client_stream.h \ -@ENABLE_ASIO_LIB_TRUE@ asio_client_tls_context.cc asio_client_tls_context.h - -@ENABLE_ASIO_LIB_TRUE@libnghttp2_asio_la_CPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS} -@ENABLE_ASIO_LIB_TRUE@libnghttp2_asio_la_LDFLAGS = -no-undefined -version-info 1:0:0 -@ENABLE_ASIO_LIB_TRUE@libnghttp2_asio_la_LIBADD = \ -@ENABLE_ASIO_LIB_TRUE@ $(top_builddir)/lib/libnghttp2.la \ -@ENABLE_ASIO_LIB_TRUE@ $(top_builddir)/third-party/libhttp-parser.la \ -@ENABLE_ASIO_LIB_TRUE@ @OPENSSL_LIBS@ \ +@ENABLE_ASIO_LIB_TRUE@ asio_io_service_pool.cc asio_io_service_pool.h \ +@ENABLE_ASIO_LIB_TRUE@ asio_http2_handler.cc asio_http2_handler.h \ +@ENABLE_ASIO_LIB_TRUE@ asio_http2_impl.cc asio_http2_impl.h \ +@ENABLE_ASIO_LIB_TRUE@ util.cc util.h http2.cc http2.h \ +@ENABLE_ASIO_LIB_TRUE@ ssl.cc ssl.h + +@ENABLE_ASIO_LIB_TRUE@libnghttp2_asio_la_CPPFLAGS = ${BOOST_CPPFLAGS} ${AM_CPPFLAGS} +@ENABLE_ASIO_LIB_TRUE@libnghttp2_asio_la_LDFLAGS = \ @ENABLE_ASIO_LIB_TRUE@ ${BOOST_LDFLAGS} \ @ENABLE_ASIO_LIB_TRUE@ ${BOOST_ASIO_LIB} \ @ENABLE_ASIO_LIB_TRUE@ ${BOOST_THREAD_LIB} \ -@ENABLE_ASIO_LIB_TRUE@ ${BOOST_SYSTEM_LIB} +@ENABLE_ASIO_LIB_TRUE@ ${BOOST_SYSTEM_LIB} \ +@ENABLE_ASIO_LIB_TRUE@ @OPENSSL_LIBS@ \ +@ENABLE_ASIO_LIB_TRUE@ -no-undefined \ +@ENABLE_ASIO_LIB_TRUE@ -version-info 0:0:0 +@ENABLE_ASIO_LIB_TRUE@libnghttp2_asio_la_LIBADD = $(top_builddir)/lib/libnghttp2.la all: all-recursive .SUFFIXES: @@ -1158,6 +971,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -1304,11 +1118,11 @@ nghttpx$(EXEEXT): $(nghttpx_OBJECTS) $(nghttpx_DEPENDENCIES) $(EXTRA_nghttpx_DEPENDENCIES) @rm -f nghttpx$(EXEEXT) - $(AM_V_CXXLD)$(CXXLINK) $(nghttpx_OBJECTS) $(nghttpx_LDADD) $(LIBS) + $(AM_V_CXXLD)$(nghttpx_LINK) $(nghttpx_OBJECTS) $(nghttpx_LDADD) $(LIBS) nghttpx-unittest$(EXEEXT): $(nghttpx_unittest_OBJECTS) $(nghttpx_unittest_DEPENDENCIES) $(EXTRA_nghttpx_unittest_DEPENDENCIES) @rm -f nghttpx-unittest$(EXEEXT) - $(AM_V_CXXLD)$(CXXLINK) $(nghttpx_unittest_OBJECTS) $(nghttpx_unittest_LDADD) $(LIBS) + $(AM_V_CXXLD)$(nghttpx_unittest_LINK) $(nghttpx_unittest_OBJECTS) $(nghttpx_unittest_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -1322,99 +1136,51 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comp_helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/deflatehd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h2load.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h2load_http1_session.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h2load_http2_session.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/h2load_spdy_session.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inflatehd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_client_request.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_client_request_impl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_client_response.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_client_response_impl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_client_session.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_client_session_impl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_client_session_tcp_impl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_client_session_tls_impl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_client_stream.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_client_tls_context.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_common.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libevent_util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_http2_handler.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_http2_impl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_io_service_pool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_http2.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_http2_handler.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_http2_impl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_request.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_request_handler.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_request_impl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_response.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_response_impl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_serve_mux.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_stream.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-asio_server_tls_context.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-http2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-ssl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-timegm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttp2_asio_la-util.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-app_helper.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-http2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_accept_handler.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_api_downstream_connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_client_handler.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_config.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_connect_blocker.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_connection_handler.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_downstream.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_downstream_connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_downstream_connection_pool.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_downstream_queue.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_health_monitor_downstream_connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_http.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_http2_downstream_connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_http2_session.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_http2_upstream.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_http_downstream_connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_https_upstream.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_io_control.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_live_check.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_log.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_log_config.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_memcached_connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_memcached_dispatcher.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_mruby.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_mruby_module.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_mruby_module_env.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_mruby_module_request.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_mruby_module_response.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_rate_limit.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_router.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_signal.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_spdy_upstream.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_ssl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_worker.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-shrpx_worker_process.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-ssl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-timegm.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnghttpx_a-util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttp2_gzip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx-shrpx.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-base64_test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-buffer_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-http2_test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-memchunk_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-nghttp2_gzip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-nghttp2_gzip_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-shrpx-unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-shrpx_config_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-shrpx_downstream_test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-shrpx_http_test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-shrpx_router_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-shrpx_ssl_test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-shrpx_worker_test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-template_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nghttpx_unittest-util_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_client_handler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_connect_blocker.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_downstream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_downstream_connection.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_downstream_connection_pool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_downstream_queue.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_http.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_http2_downstream_connection.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_http2_session.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_http2_upstream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_http_downstream_connection.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_https_upstream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_io_control.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_listen_handler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_log.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_spdy_upstream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_ssl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_thread_event_receiver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_worker.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shrpx_worker_config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timegm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ @@ -1443,27 +1209,6 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< -libnghttpx_a-timegm.o: timegm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnghttpx_a-timegm.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-timegm.Tpo -c -o libnghttpx_a-timegm.o `test -f 'timegm.c' || echo '$(srcdir)/'`timegm.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-timegm.Tpo $(DEPDIR)/libnghttpx_a-timegm.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timegm.c' object='libnghttpx_a-timegm.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnghttpx_a-timegm.o `test -f 'timegm.c' || echo '$(srcdir)/'`timegm.c - -libnghttpx_a-timegm.obj: timegm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnghttpx_a-timegm.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-timegm.Tpo -c -o libnghttpx_a-timegm.obj `if test -f 'timegm.c'; then $(CYGPATH_W) 'timegm.c'; else $(CYGPATH_W) '$(srcdir)/timegm.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-timegm.Tpo $(DEPDIR)/libnghttpx_a-timegm.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timegm.c' object='libnghttpx_a-timegm.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnghttpx_a-timegm.obj `if test -f 'timegm.c'; then $(CYGPATH_W) 'timegm.c'; else $(CYGPATH_W) '$(srcdir)/timegm.c'; fi` - -libnghttp2_asio_la-timegm.lo: timegm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnghttp2_asio_la-timegm.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-timegm.Tpo -c -o libnghttp2_asio_la-timegm.lo `test -f 'timegm.c' || echo '$(srcdir)/'`timegm.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-timegm.Tpo $(DEPDIR)/libnghttp2_asio_la-timegm.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timegm.c' object='libnghttp2_asio_la-timegm.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnghttp2_asio_la-timegm.lo `test -f 'timegm.c' || echo '$(srcdir)/'`timegm.c - nghttpx_unittest-nghttp2_gzip_test.o: nghttp2_gzip_test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nghttpx_unittest-nghttp2_gzip_test.o -MD -MP -MF $(DEPDIR)/nghttpx_unittest-nghttp2_gzip_test.Tpo -c -o nghttpx_unittest-nghttp2_gzip_test.o `test -f 'nghttp2_gzip_test.c' || echo '$(srcdir)/'`nghttp2_gzip_test.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-nghttp2_gzip_test.Tpo $(DEPDIR)/nghttpx_unittest-nghttp2_gzip_test.Po @@ -1516,565 +1261,33 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< -libnghttpx_a-util.o: util.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-util.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-util.Tpo -c -o libnghttpx_a-util.o `test -f 'util.cc' || echo '$(srcdir)/'`util.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-util.Tpo $(DEPDIR)/libnghttpx_a-util.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cc' object='libnghttpx_a-util.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-util.o `test -f 'util.cc' || echo '$(srcdir)/'`util.cc - -libnghttpx_a-util.obj: util.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-util.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-util.Tpo -c -o libnghttpx_a-util.obj `if test -f 'util.cc'; then $(CYGPATH_W) 'util.cc'; else $(CYGPATH_W) '$(srcdir)/util.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-util.Tpo $(DEPDIR)/libnghttpx_a-util.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='util.cc' object='libnghttpx_a-util.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-util.obj `if test -f 'util.cc'; then $(CYGPATH_W) 'util.cc'; else $(CYGPATH_W) '$(srcdir)/util.cc'; fi` - -libnghttpx_a-http2.o: http2.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-http2.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-http2.Tpo -c -o libnghttpx_a-http2.o `test -f 'http2.cc' || echo '$(srcdir)/'`http2.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-http2.Tpo $(DEPDIR)/libnghttpx_a-http2.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='http2.cc' object='libnghttpx_a-http2.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-http2.o `test -f 'http2.cc' || echo '$(srcdir)/'`http2.cc - -libnghttpx_a-http2.obj: http2.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-http2.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-http2.Tpo -c -o libnghttpx_a-http2.obj `if test -f 'http2.cc'; then $(CYGPATH_W) 'http2.cc'; else $(CYGPATH_W) '$(srcdir)/http2.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-http2.Tpo $(DEPDIR)/libnghttpx_a-http2.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='http2.cc' object='libnghttpx_a-http2.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-http2.obj `if test -f 'http2.cc'; then $(CYGPATH_W) 'http2.cc'; else $(CYGPATH_W) '$(srcdir)/http2.cc'; fi` - -libnghttpx_a-app_helper.o: app_helper.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-app_helper.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-app_helper.Tpo -c -o libnghttpx_a-app_helper.o `test -f 'app_helper.cc' || echo '$(srcdir)/'`app_helper.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-app_helper.Tpo $(DEPDIR)/libnghttpx_a-app_helper.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='app_helper.cc' object='libnghttpx_a-app_helper.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-app_helper.o `test -f 'app_helper.cc' || echo '$(srcdir)/'`app_helper.cc - -libnghttpx_a-app_helper.obj: app_helper.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-app_helper.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-app_helper.Tpo -c -o libnghttpx_a-app_helper.obj `if test -f 'app_helper.cc'; then $(CYGPATH_W) 'app_helper.cc'; else $(CYGPATH_W) '$(srcdir)/app_helper.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-app_helper.Tpo $(DEPDIR)/libnghttpx_a-app_helper.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='app_helper.cc' object='libnghttpx_a-app_helper.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-app_helper.obj `if test -f 'app_helper.cc'; then $(CYGPATH_W) 'app_helper.cc'; else $(CYGPATH_W) '$(srcdir)/app_helper.cc'; fi` - -libnghttpx_a-ssl.o: ssl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-ssl.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-ssl.Tpo -c -o libnghttpx_a-ssl.o `test -f 'ssl.cc' || echo '$(srcdir)/'`ssl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-ssl.Tpo $(DEPDIR)/libnghttpx_a-ssl.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ssl.cc' object='libnghttpx_a-ssl.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-ssl.o `test -f 'ssl.cc' || echo '$(srcdir)/'`ssl.cc - -libnghttpx_a-ssl.obj: ssl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-ssl.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-ssl.Tpo -c -o libnghttpx_a-ssl.obj `if test -f 'ssl.cc'; then $(CYGPATH_W) 'ssl.cc'; else $(CYGPATH_W) '$(srcdir)/ssl.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-ssl.Tpo $(DEPDIR)/libnghttpx_a-ssl.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ssl.cc' object='libnghttpx_a-ssl.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-ssl.obj `if test -f 'ssl.cc'; then $(CYGPATH_W) 'ssl.cc'; else $(CYGPATH_W) '$(srcdir)/ssl.cc'; fi` - -libnghttpx_a-shrpx_config.o: shrpx_config.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_config.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_config.Tpo -c -o libnghttpx_a-shrpx_config.o `test -f 'shrpx_config.cc' || echo '$(srcdir)/'`shrpx_config.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_config.Tpo $(DEPDIR)/libnghttpx_a-shrpx_config.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_config.cc' object='libnghttpx_a-shrpx_config.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_config.o `test -f 'shrpx_config.cc' || echo '$(srcdir)/'`shrpx_config.cc - -libnghttpx_a-shrpx_config.obj: shrpx_config.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_config.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_config.Tpo -c -o libnghttpx_a-shrpx_config.obj `if test -f 'shrpx_config.cc'; then $(CYGPATH_W) 'shrpx_config.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_config.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_config.Tpo $(DEPDIR)/libnghttpx_a-shrpx_config.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_config.cc' object='libnghttpx_a-shrpx_config.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_config.obj `if test -f 'shrpx_config.cc'; then $(CYGPATH_W) 'shrpx_config.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_config.cc'; fi` - -libnghttpx_a-shrpx_accept_handler.o: shrpx_accept_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_accept_handler.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_accept_handler.Tpo -c -o libnghttpx_a-shrpx_accept_handler.o `test -f 'shrpx_accept_handler.cc' || echo '$(srcdir)/'`shrpx_accept_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_accept_handler.Tpo $(DEPDIR)/libnghttpx_a-shrpx_accept_handler.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_accept_handler.cc' object='libnghttpx_a-shrpx_accept_handler.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_accept_handler.o `test -f 'shrpx_accept_handler.cc' || echo '$(srcdir)/'`shrpx_accept_handler.cc - -libnghttpx_a-shrpx_accept_handler.obj: shrpx_accept_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_accept_handler.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_accept_handler.Tpo -c -o libnghttpx_a-shrpx_accept_handler.obj `if test -f 'shrpx_accept_handler.cc'; then $(CYGPATH_W) 'shrpx_accept_handler.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_accept_handler.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_accept_handler.Tpo $(DEPDIR)/libnghttpx_a-shrpx_accept_handler.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_accept_handler.cc' object='libnghttpx_a-shrpx_accept_handler.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_accept_handler.obj `if test -f 'shrpx_accept_handler.cc'; then $(CYGPATH_W) 'shrpx_accept_handler.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_accept_handler.cc'; fi` - -libnghttpx_a-shrpx_connection_handler.o: shrpx_connection_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_connection_handler.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_connection_handler.Tpo -c -o libnghttpx_a-shrpx_connection_handler.o `test -f 'shrpx_connection_handler.cc' || echo '$(srcdir)/'`shrpx_connection_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_connection_handler.Tpo $(DEPDIR)/libnghttpx_a-shrpx_connection_handler.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_connection_handler.cc' object='libnghttpx_a-shrpx_connection_handler.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_connection_handler.o `test -f 'shrpx_connection_handler.cc' || echo '$(srcdir)/'`shrpx_connection_handler.cc - -libnghttpx_a-shrpx_connection_handler.obj: shrpx_connection_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_connection_handler.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_connection_handler.Tpo -c -o libnghttpx_a-shrpx_connection_handler.obj `if test -f 'shrpx_connection_handler.cc'; then $(CYGPATH_W) 'shrpx_connection_handler.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_connection_handler.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_connection_handler.Tpo $(DEPDIR)/libnghttpx_a-shrpx_connection_handler.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_connection_handler.cc' object='libnghttpx_a-shrpx_connection_handler.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_connection_handler.obj `if test -f 'shrpx_connection_handler.cc'; then $(CYGPATH_W) 'shrpx_connection_handler.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_connection_handler.cc'; fi` - -libnghttpx_a-shrpx_client_handler.o: shrpx_client_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_client_handler.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_client_handler.Tpo -c -o libnghttpx_a-shrpx_client_handler.o `test -f 'shrpx_client_handler.cc' || echo '$(srcdir)/'`shrpx_client_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_client_handler.Tpo $(DEPDIR)/libnghttpx_a-shrpx_client_handler.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_client_handler.cc' object='libnghttpx_a-shrpx_client_handler.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_client_handler.o `test -f 'shrpx_client_handler.cc' || echo '$(srcdir)/'`shrpx_client_handler.cc - -libnghttpx_a-shrpx_client_handler.obj: shrpx_client_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_client_handler.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_client_handler.Tpo -c -o libnghttpx_a-shrpx_client_handler.obj `if test -f 'shrpx_client_handler.cc'; then $(CYGPATH_W) 'shrpx_client_handler.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_client_handler.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_client_handler.Tpo $(DEPDIR)/libnghttpx_a-shrpx_client_handler.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_client_handler.cc' object='libnghttpx_a-shrpx_client_handler.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_client_handler.obj `if test -f 'shrpx_client_handler.cc'; then $(CYGPATH_W) 'shrpx_client_handler.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_client_handler.cc'; fi` - -libnghttpx_a-shrpx_http2_upstream.o: shrpx_http2_upstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_http2_upstream.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_http2_upstream.Tpo -c -o libnghttpx_a-shrpx_http2_upstream.o `test -f 'shrpx_http2_upstream.cc' || echo '$(srcdir)/'`shrpx_http2_upstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_http2_upstream.Tpo $(DEPDIR)/libnghttpx_a-shrpx_http2_upstream.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http2_upstream.cc' object='libnghttpx_a-shrpx_http2_upstream.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_http2_upstream.o `test -f 'shrpx_http2_upstream.cc' || echo '$(srcdir)/'`shrpx_http2_upstream.cc - -libnghttpx_a-shrpx_http2_upstream.obj: shrpx_http2_upstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_http2_upstream.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_http2_upstream.Tpo -c -o libnghttpx_a-shrpx_http2_upstream.obj `if test -f 'shrpx_http2_upstream.cc'; then $(CYGPATH_W) 'shrpx_http2_upstream.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http2_upstream.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_http2_upstream.Tpo $(DEPDIR)/libnghttpx_a-shrpx_http2_upstream.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http2_upstream.cc' object='libnghttpx_a-shrpx_http2_upstream.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_http2_upstream.obj `if test -f 'shrpx_http2_upstream.cc'; then $(CYGPATH_W) 'shrpx_http2_upstream.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http2_upstream.cc'; fi` - -libnghttpx_a-shrpx_https_upstream.o: shrpx_https_upstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_https_upstream.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_https_upstream.Tpo -c -o libnghttpx_a-shrpx_https_upstream.o `test -f 'shrpx_https_upstream.cc' || echo '$(srcdir)/'`shrpx_https_upstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_https_upstream.Tpo $(DEPDIR)/libnghttpx_a-shrpx_https_upstream.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_https_upstream.cc' object='libnghttpx_a-shrpx_https_upstream.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_https_upstream.o `test -f 'shrpx_https_upstream.cc' || echo '$(srcdir)/'`shrpx_https_upstream.cc - -libnghttpx_a-shrpx_https_upstream.obj: shrpx_https_upstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_https_upstream.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_https_upstream.Tpo -c -o libnghttpx_a-shrpx_https_upstream.obj `if test -f 'shrpx_https_upstream.cc'; then $(CYGPATH_W) 'shrpx_https_upstream.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_https_upstream.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_https_upstream.Tpo $(DEPDIR)/libnghttpx_a-shrpx_https_upstream.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_https_upstream.cc' object='libnghttpx_a-shrpx_https_upstream.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_https_upstream.obj `if test -f 'shrpx_https_upstream.cc'; then $(CYGPATH_W) 'shrpx_https_upstream.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_https_upstream.cc'; fi` - -libnghttpx_a-shrpx_downstream.o: shrpx_downstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_downstream.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_downstream.Tpo -c -o libnghttpx_a-shrpx_downstream.o `test -f 'shrpx_downstream.cc' || echo '$(srcdir)/'`shrpx_downstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_downstream.Tpo $(DEPDIR)/libnghttpx_a-shrpx_downstream.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_downstream.cc' object='libnghttpx_a-shrpx_downstream.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_downstream.o `test -f 'shrpx_downstream.cc' || echo '$(srcdir)/'`shrpx_downstream.cc - -libnghttpx_a-shrpx_downstream.obj: shrpx_downstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_downstream.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_downstream.Tpo -c -o libnghttpx_a-shrpx_downstream.obj `if test -f 'shrpx_downstream.cc'; then $(CYGPATH_W) 'shrpx_downstream.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_downstream.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_downstream.Tpo $(DEPDIR)/libnghttpx_a-shrpx_downstream.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_downstream.cc' object='libnghttpx_a-shrpx_downstream.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_downstream.obj `if test -f 'shrpx_downstream.cc'; then $(CYGPATH_W) 'shrpx_downstream.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_downstream.cc'; fi` - -libnghttpx_a-shrpx_downstream_connection.o: shrpx_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_downstream_connection.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection.Tpo -c -o libnghttpx_a-shrpx_downstream_connection.o `test -f 'shrpx_downstream_connection.cc' || echo '$(srcdir)/'`shrpx_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_downstream_connection.cc' object='libnghttpx_a-shrpx_downstream_connection.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_downstream_connection.o `test -f 'shrpx_downstream_connection.cc' || echo '$(srcdir)/'`shrpx_downstream_connection.cc - -libnghttpx_a-shrpx_downstream_connection.obj: shrpx_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_downstream_connection.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection.Tpo -c -o libnghttpx_a-shrpx_downstream_connection.obj `if test -f 'shrpx_downstream_connection.cc'; then $(CYGPATH_W) 'shrpx_downstream_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_downstream_connection.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_downstream_connection.cc' object='libnghttpx_a-shrpx_downstream_connection.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_downstream_connection.obj `if test -f 'shrpx_downstream_connection.cc'; then $(CYGPATH_W) 'shrpx_downstream_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_downstream_connection.cc'; fi` - -libnghttpx_a-shrpx_http_downstream_connection.o: shrpx_http_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_http_downstream_connection.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_http_downstream_connection.Tpo -c -o libnghttpx_a-shrpx_http_downstream_connection.o `test -f 'shrpx_http_downstream_connection.cc' || echo '$(srcdir)/'`shrpx_http_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_http_downstream_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_http_downstream_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http_downstream_connection.cc' object='libnghttpx_a-shrpx_http_downstream_connection.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_http_downstream_connection.o `test -f 'shrpx_http_downstream_connection.cc' || echo '$(srcdir)/'`shrpx_http_downstream_connection.cc - -libnghttpx_a-shrpx_http_downstream_connection.obj: shrpx_http_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_http_downstream_connection.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_http_downstream_connection.Tpo -c -o libnghttpx_a-shrpx_http_downstream_connection.obj `if test -f 'shrpx_http_downstream_connection.cc'; then $(CYGPATH_W) 'shrpx_http_downstream_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http_downstream_connection.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_http_downstream_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_http_downstream_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http_downstream_connection.cc' object='libnghttpx_a-shrpx_http_downstream_connection.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_http_downstream_connection.obj `if test -f 'shrpx_http_downstream_connection.cc'; then $(CYGPATH_W) 'shrpx_http_downstream_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http_downstream_connection.cc'; fi` - -libnghttpx_a-shrpx_http2_downstream_connection.o: shrpx_http2_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_http2_downstream_connection.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_http2_downstream_connection.Tpo -c -o libnghttpx_a-shrpx_http2_downstream_connection.o `test -f 'shrpx_http2_downstream_connection.cc' || echo '$(srcdir)/'`shrpx_http2_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_http2_downstream_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_http2_downstream_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http2_downstream_connection.cc' object='libnghttpx_a-shrpx_http2_downstream_connection.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_http2_downstream_connection.o `test -f 'shrpx_http2_downstream_connection.cc' || echo '$(srcdir)/'`shrpx_http2_downstream_connection.cc - -libnghttpx_a-shrpx_http2_downstream_connection.obj: shrpx_http2_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_http2_downstream_connection.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_http2_downstream_connection.Tpo -c -o libnghttpx_a-shrpx_http2_downstream_connection.obj `if test -f 'shrpx_http2_downstream_connection.cc'; then $(CYGPATH_W) 'shrpx_http2_downstream_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http2_downstream_connection.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_http2_downstream_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_http2_downstream_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http2_downstream_connection.cc' object='libnghttpx_a-shrpx_http2_downstream_connection.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_http2_downstream_connection.obj `if test -f 'shrpx_http2_downstream_connection.cc'; then $(CYGPATH_W) 'shrpx_http2_downstream_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http2_downstream_connection.cc'; fi` - -libnghttpx_a-shrpx_http2_session.o: shrpx_http2_session.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_http2_session.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_http2_session.Tpo -c -o libnghttpx_a-shrpx_http2_session.o `test -f 'shrpx_http2_session.cc' || echo '$(srcdir)/'`shrpx_http2_session.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_http2_session.Tpo $(DEPDIR)/libnghttpx_a-shrpx_http2_session.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http2_session.cc' object='libnghttpx_a-shrpx_http2_session.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_http2_session.o `test -f 'shrpx_http2_session.cc' || echo '$(srcdir)/'`shrpx_http2_session.cc - -libnghttpx_a-shrpx_http2_session.obj: shrpx_http2_session.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_http2_session.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_http2_session.Tpo -c -o libnghttpx_a-shrpx_http2_session.obj `if test -f 'shrpx_http2_session.cc'; then $(CYGPATH_W) 'shrpx_http2_session.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http2_session.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_http2_session.Tpo $(DEPDIR)/libnghttpx_a-shrpx_http2_session.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http2_session.cc' object='libnghttpx_a-shrpx_http2_session.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_http2_session.obj `if test -f 'shrpx_http2_session.cc'; then $(CYGPATH_W) 'shrpx_http2_session.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http2_session.cc'; fi` - -libnghttpx_a-shrpx_downstream_queue.o: shrpx_downstream_queue.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_downstream_queue.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_downstream_queue.Tpo -c -o libnghttpx_a-shrpx_downstream_queue.o `test -f 'shrpx_downstream_queue.cc' || echo '$(srcdir)/'`shrpx_downstream_queue.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_downstream_queue.Tpo $(DEPDIR)/libnghttpx_a-shrpx_downstream_queue.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_downstream_queue.cc' object='libnghttpx_a-shrpx_downstream_queue.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_downstream_queue.o `test -f 'shrpx_downstream_queue.cc' || echo '$(srcdir)/'`shrpx_downstream_queue.cc - -libnghttpx_a-shrpx_downstream_queue.obj: shrpx_downstream_queue.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_downstream_queue.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_downstream_queue.Tpo -c -o libnghttpx_a-shrpx_downstream_queue.obj `if test -f 'shrpx_downstream_queue.cc'; then $(CYGPATH_W) 'shrpx_downstream_queue.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_downstream_queue.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_downstream_queue.Tpo $(DEPDIR)/libnghttpx_a-shrpx_downstream_queue.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_downstream_queue.cc' object='libnghttpx_a-shrpx_downstream_queue.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_downstream_queue.obj `if test -f 'shrpx_downstream_queue.cc'; then $(CYGPATH_W) 'shrpx_downstream_queue.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_downstream_queue.cc'; fi` - -libnghttpx_a-shrpx_log.o: shrpx_log.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_log.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_log.Tpo -c -o libnghttpx_a-shrpx_log.o `test -f 'shrpx_log.cc' || echo '$(srcdir)/'`shrpx_log.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_log.Tpo $(DEPDIR)/libnghttpx_a-shrpx_log.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_log.cc' object='libnghttpx_a-shrpx_log.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_log.o `test -f 'shrpx_log.cc' || echo '$(srcdir)/'`shrpx_log.cc - -libnghttpx_a-shrpx_log.obj: shrpx_log.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_log.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_log.Tpo -c -o libnghttpx_a-shrpx_log.obj `if test -f 'shrpx_log.cc'; then $(CYGPATH_W) 'shrpx_log.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_log.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_log.Tpo $(DEPDIR)/libnghttpx_a-shrpx_log.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_log.cc' object='libnghttpx_a-shrpx_log.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_log.obj `if test -f 'shrpx_log.cc'; then $(CYGPATH_W) 'shrpx_log.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_log.cc'; fi` - -libnghttpx_a-shrpx_http.o: shrpx_http.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_http.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_http.Tpo -c -o libnghttpx_a-shrpx_http.o `test -f 'shrpx_http.cc' || echo '$(srcdir)/'`shrpx_http.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_http.Tpo $(DEPDIR)/libnghttpx_a-shrpx_http.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http.cc' object='libnghttpx_a-shrpx_http.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_http.o `test -f 'shrpx_http.cc' || echo '$(srcdir)/'`shrpx_http.cc - -libnghttpx_a-shrpx_http.obj: shrpx_http.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_http.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_http.Tpo -c -o libnghttpx_a-shrpx_http.obj `if test -f 'shrpx_http.cc'; then $(CYGPATH_W) 'shrpx_http.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_http.Tpo $(DEPDIR)/libnghttpx_a-shrpx_http.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http.cc' object='libnghttpx_a-shrpx_http.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_http.obj `if test -f 'shrpx_http.cc'; then $(CYGPATH_W) 'shrpx_http.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http.cc'; fi` - -libnghttpx_a-shrpx_io_control.o: shrpx_io_control.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_io_control.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_io_control.Tpo -c -o libnghttpx_a-shrpx_io_control.o `test -f 'shrpx_io_control.cc' || echo '$(srcdir)/'`shrpx_io_control.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_io_control.Tpo $(DEPDIR)/libnghttpx_a-shrpx_io_control.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_io_control.cc' object='libnghttpx_a-shrpx_io_control.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_io_control.o `test -f 'shrpx_io_control.cc' || echo '$(srcdir)/'`shrpx_io_control.cc - -libnghttpx_a-shrpx_io_control.obj: shrpx_io_control.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_io_control.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_io_control.Tpo -c -o libnghttpx_a-shrpx_io_control.obj `if test -f 'shrpx_io_control.cc'; then $(CYGPATH_W) 'shrpx_io_control.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_io_control.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_io_control.Tpo $(DEPDIR)/libnghttpx_a-shrpx_io_control.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_io_control.cc' object='libnghttpx_a-shrpx_io_control.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_io_control.obj `if test -f 'shrpx_io_control.cc'; then $(CYGPATH_W) 'shrpx_io_control.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_io_control.cc'; fi` - -libnghttpx_a-shrpx_ssl.o: shrpx_ssl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_ssl.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_ssl.Tpo -c -o libnghttpx_a-shrpx_ssl.o `test -f 'shrpx_ssl.cc' || echo '$(srcdir)/'`shrpx_ssl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_ssl.Tpo $(DEPDIR)/libnghttpx_a-shrpx_ssl.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_ssl.cc' object='libnghttpx_a-shrpx_ssl.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_ssl.o `test -f 'shrpx_ssl.cc' || echo '$(srcdir)/'`shrpx_ssl.cc - -libnghttpx_a-shrpx_ssl.obj: shrpx_ssl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_ssl.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_ssl.Tpo -c -o libnghttpx_a-shrpx_ssl.obj `if test -f 'shrpx_ssl.cc'; then $(CYGPATH_W) 'shrpx_ssl.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_ssl.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_ssl.Tpo $(DEPDIR)/libnghttpx_a-shrpx_ssl.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_ssl.cc' object='libnghttpx_a-shrpx_ssl.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_ssl.obj `if test -f 'shrpx_ssl.cc'; then $(CYGPATH_W) 'shrpx_ssl.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_ssl.cc'; fi` - -libnghttpx_a-shrpx_worker.o: shrpx_worker.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_worker.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_worker.Tpo -c -o libnghttpx_a-shrpx_worker.o `test -f 'shrpx_worker.cc' || echo '$(srcdir)/'`shrpx_worker.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_worker.Tpo $(DEPDIR)/libnghttpx_a-shrpx_worker.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_worker.cc' object='libnghttpx_a-shrpx_worker.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_worker.o `test -f 'shrpx_worker.cc' || echo '$(srcdir)/'`shrpx_worker.cc - -libnghttpx_a-shrpx_worker.obj: shrpx_worker.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_worker.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_worker.Tpo -c -o libnghttpx_a-shrpx_worker.obj `if test -f 'shrpx_worker.cc'; then $(CYGPATH_W) 'shrpx_worker.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_worker.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_worker.Tpo $(DEPDIR)/libnghttpx_a-shrpx_worker.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_worker.cc' object='libnghttpx_a-shrpx_worker.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_worker.obj `if test -f 'shrpx_worker.cc'; then $(CYGPATH_W) 'shrpx_worker.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_worker.cc'; fi` - -libnghttpx_a-shrpx_log_config.o: shrpx_log_config.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_log_config.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_log_config.Tpo -c -o libnghttpx_a-shrpx_log_config.o `test -f 'shrpx_log_config.cc' || echo '$(srcdir)/'`shrpx_log_config.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_log_config.Tpo $(DEPDIR)/libnghttpx_a-shrpx_log_config.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_log_config.cc' object='libnghttpx_a-shrpx_log_config.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_log_config.o `test -f 'shrpx_log_config.cc' || echo '$(srcdir)/'`shrpx_log_config.cc - -libnghttpx_a-shrpx_log_config.obj: shrpx_log_config.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_log_config.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_log_config.Tpo -c -o libnghttpx_a-shrpx_log_config.obj `if test -f 'shrpx_log_config.cc'; then $(CYGPATH_W) 'shrpx_log_config.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_log_config.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_log_config.Tpo $(DEPDIR)/libnghttpx_a-shrpx_log_config.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_log_config.cc' object='libnghttpx_a-shrpx_log_config.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_log_config.obj `if test -f 'shrpx_log_config.cc'; then $(CYGPATH_W) 'shrpx_log_config.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_log_config.cc'; fi` - -libnghttpx_a-shrpx_connect_blocker.o: shrpx_connect_blocker.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_connect_blocker.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_connect_blocker.Tpo -c -o libnghttpx_a-shrpx_connect_blocker.o `test -f 'shrpx_connect_blocker.cc' || echo '$(srcdir)/'`shrpx_connect_blocker.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_connect_blocker.Tpo $(DEPDIR)/libnghttpx_a-shrpx_connect_blocker.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_connect_blocker.cc' object='libnghttpx_a-shrpx_connect_blocker.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_connect_blocker.o `test -f 'shrpx_connect_blocker.cc' || echo '$(srcdir)/'`shrpx_connect_blocker.cc - -libnghttpx_a-shrpx_connect_blocker.obj: shrpx_connect_blocker.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_connect_blocker.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_connect_blocker.Tpo -c -o libnghttpx_a-shrpx_connect_blocker.obj `if test -f 'shrpx_connect_blocker.cc'; then $(CYGPATH_W) 'shrpx_connect_blocker.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_connect_blocker.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_connect_blocker.Tpo $(DEPDIR)/libnghttpx_a-shrpx_connect_blocker.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_connect_blocker.cc' object='libnghttpx_a-shrpx_connect_blocker.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_connect_blocker.obj `if test -f 'shrpx_connect_blocker.cc'; then $(CYGPATH_W) 'shrpx_connect_blocker.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_connect_blocker.cc'; fi` - -libnghttpx_a-shrpx_live_check.o: shrpx_live_check.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_live_check.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_live_check.Tpo -c -o libnghttpx_a-shrpx_live_check.o `test -f 'shrpx_live_check.cc' || echo '$(srcdir)/'`shrpx_live_check.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_live_check.Tpo $(DEPDIR)/libnghttpx_a-shrpx_live_check.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_live_check.cc' object='libnghttpx_a-shrpx_live_check.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_live_check.o `test -f 'shrpx_live_check.cc' || echo '$(srcdir)/'`shrpx_live_check.cc - -libnghttpx_a-shrpx_live_check.obj: shrpx_live_check.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_live_check.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_live_check.Tpo -c -o libnghttpx_a-shrpx_live_check.obj `if test -f 'shrpx_live_check.cc'; then $(CYGPATH_W) 'shrpx_live_check.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_live_check.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_live_check.Tpo $(DEPDIR)/libnghttpx_a-shrpx_live_check.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_live_check.cc' object='libnghttpx_a-shrpx_live_check.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_live_check.obj `if test -f 'shrpx_live_check.cc'; then $(CYGPATH_W) 'shrpx_live_check.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_live_check.cc'; fi` - -libnghttpx_a-shrpx_downstream_connection_pool.o: shrpx_downstream_connection_pool.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_downstream_connection_pool.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection_pool.Tpo -c -o libnghttpx_a-shrpx_downstream_connection_pool.o `test -f 'shrpx_downstream_connection_pool.cc' || echo '$(srcdir)/'`shrpx_downstream_connection_pool.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection_pool.Tpo $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection_pool.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_downstream_connection_pool.cc' object='libnghttpx_a-shrpx_downstream_connection_pool.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_downstream_connection_pool.o `test -f 'shrpx_downstream_connection_pool.cc' || echo '$(srcdir)/'`shrpx_downstream_connection_pool.cc - -libnghttpx_a-shrpx_downstream_connection_pool.obj: shrpx_downstream_connection_pool.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_downstream_connection_pool.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection_pool.Tpo -c -o libnghttpx_a-shrpx_downstream_connection_pool.obj `if test -f 'shrpx_downstream_connection_pool.cc'; then $(CYGPATH_W) 'shrpx_downstream_connection_pool.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_downstream_connection_pool.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection_pool.Tpo $(DEPDIR)/libnghttpx_a-shrpx_downstream_connection_pool.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_downstream_connection_pool.cc' object='libnghttpx_a-shrpx_downstream_connection_pool.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_downstream_connection_pool.obj `if test -f 'shrpx_downstream_connection_pool.cc'; then $(CYGPATH_W) 'shrpx_downstream_connection_pool.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_downstream_connection_pool.cc'; fi` - -libnghttpx_a-shrpx_rate_limit.o: shrpx_rate_limit.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_rate_limit.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_rate_limit.Tpo -c -o libnghttpx_a-shrpx_rate_limit.o `test -f 'shrpx_rate_limit.cc' || echo '$(srcdir)/'`shrpx_rate_limit.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_rate_limit.Tpo $(DEPDIR)/libnghttpx_a-shrpx_rate_limit.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_rate_limit.cc' object='libnghttpx_a-shrpx_rate_limit.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_rate_limit.o `test -f 'shrpx_rate_limit.cc' || echo '$(srcdir)/'`shrpx_rate_limit.cc - -libnghttpx_a-shrpx_rate_limit.obj: shrpx_rate_limit.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_rate_limit.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_rate_limit.Tpo -c -o libnghttpx_a-shrpx_rate_limit.obj `if test -f 'shrpx_rate_limit.cc'; then $(CYGPATH_W) 'shrpx_rate_limit.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_rate_limit.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_rate_limit.Tpo $(DEPDIR)/libnghttpx_a-shrpx_rate_limit.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_rate_limit.cc' object='libnghttpx_a-shrpx_rate_limit.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_rate_limit.obj `if test -f 'shrpx_rate_limit.cc'; then $(CYGPATH_W) 'shrpx_rate_limit.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_rate_limit.cc'; fi` - -libnghttpx_a-shrpx_connection.o: shrpx_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_connection.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_connection.Tpo -c -o libnghttpx_a-shrpx_connection.o `test -f 'shrpx_connection.cc' || echo '$(srcdir)/'`shrpx_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_connection.cc' object='libnghttpx_a-shrpx_connection.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_connection.o `test -f 'shrpx_connection.cc' || echo '$(srcdir)/'`shrpx_connection.cc - -libnghttpx_a-shrpx_connection.obj: shrpx_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_connection.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_connection.Tpo -c -o libnghttpx_a-shrpx_connection.obj `if test -f 'shrpx_connection.cc'; then $(CYGPATH_W) 'shrpx_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_connection.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_connection.cc' object='libnghttpx_a-shrpx_connection.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_connection.obj `if test -f 'shrpx_connection.cc'; then $(CYGPATH_W) 'shrpx_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_connection.cc'; fi` - -libnghttpx_a-shrpx_memcached_dispatcher.o: shrpx_memcached_dispatcher.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_memcached_dispatcher.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_memcached_dispatcher.Tpo -c -o libnghttpx_a-shrpx_memcached_dispatcher.o `test -f 'shrpx_memcached_dispatcher.cc' || echo '$(srcdir)/'`shrpx_memcached_dispatcher.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_memcached_dispatcher.Tpo $(DEPDIR)/libnghttpx_a-shrpx_memcached_dispatcher.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_memcached_dispatcher.cc' object='libnghttpx_a-shrpx_memcached_dispatcher.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_memcached_dispatcher.o `test -f 'shrpx_memcached_dispatcher.cc' || echo '$(srcdir)/'`shrpx_memcached_dispatcher.cc - -libnghttpx_a-shrpx_memcached_dispatcher.obj: shrpx_memcached_dispatcher.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_memcached_dispatcher.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_memcached_dispatcher.Tpo -c -o libnghttpx_a-shrpx_memcached_dispatcher.obj `if test -f 'shrpx_memcached_dispatcher.cc'; then $(CYGPATH_W) 'shrpx_memcached_dispatcher.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_memcached_dispatcher.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_memcached_dispatcher.Tpo $(DEPDIR)/libnghttpx_a-shrpx_memcached_dispatcher.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_memcached_dispatcher.cc' object='libnghttpx_a-shrpx_memcached_dispatcher.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_memcached_dispatcher.obj `if test -f 'shrpx_memcached_dispatcher.cc'; then $(CYGPATH_W) 'shrpx_memcached_dispatcher.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_memcached_dispatcher.cc'; fi` - -libnghttpx_a-shrpx_memcached_connection.o: shrpx_memcached_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_memcached_connection.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_memcached_connection.Tpo -c -o libnghttpx_a-shrpx_memcached_connection.o `test -f 'shrpx_memcached_connection.cc' || echo '$(srcdir)/'`shrpx_memcached_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_memcached_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_memcached_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_memcached_connection.cc' object='libnghttpx_a-shrpx_memcached_connection.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_memcached_connection.o `test -f 'shrpx_memcached_connection.cc' || echo '$(srcdir)/'`shrpx_memcached_connection.cc - -libnghttpx_a-shrpx_memcached_connection.obj: shrpx_memcached_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_memcached_connection.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_memcached_connection.Tpo -c -o libnghttpx_a-shrpx_memcached_connection.obj `if test -f 'shrpx_memcached_connection.cc'; then $(CYGPATH_W) 'shrpx_memcached_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_memcached_connection.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_memcached_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_memcached_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_memcached_connection.cc' object='libnghttpx_a-shrpx_memcached_connection.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_memcached_connection.obj `if test -f 'shrpx_memcached_connection.cc'; then $(CYGPATH_W) 'shrpx_memcached_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_memcached_connection.cc'; fi` - -libnghttpx_a-shrpx_worker_process.o: shrpx_worker_process.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_worker_process.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_worker_process.Tpo -c -o libnghttpx_a-shrpx_worker_process.o `test -f 'shrpx_worker_process.cc' || echo '$(srcdir)/'`shrpx_worker_process.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_worker_process.Tpo $(DEPDIR)/libnghttpx_a-shrpx_worker_process.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_worker_process.cc' object='libnghttpx_a-shrpx_worker_process.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_worker_process.o `test -f 'shrpx_worker_process.cc' || echo '$(srcdir)/'`shrpx_worker_process.cc - -libnghttpx_a-shrpx_worker_process.obj: shrpx_worker_process.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_worker_process.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_worker_process.Tpo -c -o libnghttpx_a-shrpx_worker_process.obj `if test -f 'shrpx_worker_process.cc'; then $(CYGPATH_W) 'shrpx_worker_process.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_worker_process.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_worker_process.Tpo $(DEPDIR)/libnghttpx_a-shrpx_worker_process.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_worker_process.cc' object='libnghttpx_a-shrpx_worker_process.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_worker_process.obj `if test -f 'shrpx_worker_process.cc'; then $(CYGPATH_W) 'shrpx_worker_process.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_worker_process.cc'; fi` - -libnghttpx_a-shrpx_signal.o: shrpx_signal.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_signal.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_signal.Tpo -c -o libnghttpx_a-shrpx_signal.o `test -f 'shrpx_signal.cc' || echo '$(srcdir)/'`shrpx_signal.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_signal.Tpo $(DEPDIR)/libnghttpx_a-shrpx_signal.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_signal.cc' object='libnghttpx_a-shrpx_signal.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_signal.o `test -f 'shrpx_signal.cc' || echo '$(srcdir)/'`shrpx_signal.cc - -libnghttpx_a-shrpx_signal.obj: shrpx_signal.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_signal.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_signal.Tpo -c -o libnghttpx_a-shrpx_signal.obj `if test -f 'shrpx_signal.cc'; then $(CYGPATH_W) 'shrpx_signal.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_signal.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_signal.Tpo $(DEPDIR)/libnghttpx_a-shrpx_signal.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_signal.cc' object='libnghttpx_a-shrpx_signal.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_signal.obj `if test -f 'shrpx_signal.cc'; then $(CYGPATH_W) 'shrpx_signal.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_signal.cc'; fi` - -libnghttpx_a-shrpx_router.o: shrpx_router.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_router.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_router.Tpo -c -o libnghttpx_a-shrpx_router.o `test -f 'shrpx_router.cc' || echo '$(srcdir)/'`shrpx_router.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_router.Tpo $(DEPDIR)/libnghttpx_a-shrpx_router.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_router.cc' object='libnghttpx_a-shrpx_router.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_router.o `test -f 'shrpx_router.cc' || echo '$(srcdir)/'`shrpx_router.cc - -libnghttpx_a-shrpx_router.obj: shrpx_router.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_router.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_router.Tpo -c -o libnghttpx_a-shrpx_router.obj `if test -f 'shrpx_router.cc'; then $(CYGPATH_W) 'shrpx_router.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_router.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_router.Tpo $(DEPDIR)/libnghttpx_a-shrpx_router.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_router.cc' object='libnghttpx_a-shrpx_router.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_router.obj `if test -f 'shrpx_router.cc'; then $(CYGPATH_W) 'shrpx_router.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_router.cc'; fi` - -libnghttpx_a-shrpx_api_downstream_connection.o: shrpx_api_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_api_downstream_connection.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_api_downstream_connection.Tpo -c -o libnghttpx_a-shrpx_api_downstream_connection.o `test -f 'shrpx_api_downstream_connection.cc' || echo '$(srcdir)/'`shrpx_api_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_api_downstream_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_api_downstream_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_api_downstream_connection.cc' object='libnghttpx_a-shrpx_api_downstream_connection.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_api_downstream_connection.o `test -f 'shrpx_api_downstream_connection.cc' || echo '$(srcdir)/'`shrpx_api_downstream_connection.cc - -libnghttpx_a-shrpx_api_downstream_connection.obj: shrpx_api_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_api_downstream_connection.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_api_downstream_connection.Tpo -c -o libnghttpx_a-shrpx_api_downstream_connection.obj `if test -f 'shrpx_api_downstream_connection.cc'; then $(CYGPATH_W) 'shrpx_api_downstream_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_api_downstream_connection.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_api_downstream_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_api_downstream_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_api_downstream_connection.cc' object='libnghttpx_a-shrpx_api_downstream_connection.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_api_downstream_connection.obj `if test -f 'shrpx_api_downstream_connection.cc'; then $(CYGPATH_W) 'shrpx_api_downstream_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_api_downstream_connection.cc'; fi` - -libnghttpx_a-shrpx_health_monitor_downstream_connection.o: shrpx_health_monitor_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_health_monitor_downstream_connection.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_health_monitor_downstream_connection.Tpo -c -o libnghttpx_a-shrpx_health_monitor_downstream_connection.o `test -f 'shrpx_health_monitor_downstream_connection.cc' || echo '$(srcdir)/'`shrpx_health_monitor_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_health_monitor_downstream_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_health_monitor_downstream_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_health_monitor_downstream_connection.cc' object='libnghttpx_a-shrpx_health_monitor_downstream_connection.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_health_monitor_downstream_connection.o `test -f 'shrpx_health_monitor_downstream_connection.cc' || echo '$(srcdir)/'`shrpx_health_monitor_downstream_connection.cc - -libnghttpx_a-shrpx_health_monitor_downstream_connection.obj: shrpx_health_monitor_downstream_connection.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_health_monitor_downstream_connection.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_health_monitor_downstream_connection.Tpo -c -o libnghttpx_a-shrpx_health_monitor_downstream_connection.obj `if test -f 'shrpx_health_monitor_downstream_connection.cc'; then $(CYGPATH_W) 'shrpx_health_monitor_downstream_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_health_monitor_downstream_connection.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_health_monitor_downstream_connection.Tpo $(DEPDIR)/libnghttpx_a-shrpx_health_monitor_downstream_connection.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_health_monitor_downstream_connection.cc' object='libnghttpx_a-shrpx_health_monitor_downstream_connection.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_health_monitor_downstream_connection.obj `if test -f 'shrpx_health_monitor_downstream_connection.cc'; then $(CYGPATH_W) 'shrpx_health_monitor_downstream_connection.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_health_monitor_downstream_connection.cc'; fi` - -libnghttpx_a-shrpx_spdy_upstream.o: shrpx_spdy_upstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_spdy_upstream.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_spdy_upstream.Tpo -c -o libnghttpx_a-shrpx_spdy_upstream.o `test -f 'shrpx_spdy_upstream.cc' || echo '$(srcdir)/'`shrpx_spdy_upstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_spdy_upstream.Tpo $(DEPDIR)/libnghttpx_a-shrpx_spdy_upstream.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_spdy_upstream.cc' object='libnghttpx_a-shrpx_spdy_upstream.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_spdy_upstream.o `test -f 'shrpx_spdy_upstream.cc' || echo '$(srcdir)/'`shrpx_spdy_upstream.cc - -libnghttpx_a-shrpx_spdy_upstream.obj: shrpx_spdy_upstream.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_spdy_upstream.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_spdy_upstream.Tpo -c -o libnghttpx_a-shrpx_spdy_upstream.obj `if test -f 'shrpx_spdy_upstream.cc'; then $(CYGPATH_W) 'shrpx_spdy_upstream.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_spdy_upstream.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_spdy_upstream.Tpo $(DEPDIR)/libnghttpx_a-shrpx_spdy_upstream.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_spdy_upstream.cc' object='libnghttpx_a-shrpx_spdy_upstream.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_spdy_upstream.obj `if test -f 'shrpx_spdy_upstream.cc'; then $(CYGPATH_W) 'shrpx_spdy_upstream.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_spdy_upstream.cc'; fi` - -libnghttpx_a-shrpx_mruby.o: shrpx_mruby.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_mruby.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_mruby.Tpo -c -o libnghttpx_a-shrpx_mruby.o `test -f 'shrpx_mruby.cc' || echo '$(srcdir)/'`shrpx_mruby.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_mruby.Tpo $(DEPDIR)/libnghttpx_a-shrpx_mruby.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_mruby.cc' object='libnghttpx_a-shrpx_mruby.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_mruby.o `test -f 'shrpx_mruby.cc' || echo '$(srcdir)/'`shrpx_mruby.cc - -libnghttpx_a-shrpx_mruby.obj: shrpx_mruby.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_mruby.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_mruby.Tpo -c -o libnghttpx_a-shrpx_mruby.obj `if test -f 'shrpx_mruby.cc'; then $(CYGPATH_W) 'shrpx_mruby.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_mruby.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_mruby.Tpo $(DEPDIR)/libnghttpx_a-shrpx_mruby.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_mruby.cc' object='libnghttpx_a-shrpx_mruby.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_mruby.obj `if test -f 'shrpx_mruby.cc'; then $(CYGPATH_W) 'shrpx_mruby.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_mruby.cc'; fi` - -libnghttpx_a-shrpx_mruby_module.o: shrpx_mruby_module.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_mruby_module.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_mruby_module.Tpo -c -o libnghttpx_a-shrpx_mruby_module.o `test -f 'shrpx_mruby_module.cc' || echo '$(srcdir)/'`shrpx_mruby_module.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_mruby_module.Tpo $(DEPDIR)/libnghttpx_a-shrpx_mruby_module.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_mruby_module.cc' object='libnghttpx_a-shrpx_mruby_module.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_mruby_module.o `test -f 'shrpx_mruby_module.cc' || echo '$(srcdir)/'`shrpx_mruby_module.cc - -libnghttpx_a-shrpx_mruby_module.obj: shrpx_mruby_module.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_mruby_module.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_mruby_module.Tpo -c -o libnghttpx_a-shrpx_mruby_module.obj `if test -f 'shrpx_mruby_module.cc'; then $(CYGPATH_W) 'shrpx_mruby_module.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_mruby_module.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_mruby_module.Tpo $(DEPDIR)/libnghttpx_a-shrpx_mruby_module.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_mruby_module.cc' object='libnghttpx_a-shrpx_mruby_module.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_mruby_module.obj `if test -f 'shrpx_mruby_module.cc'; then $(CYGPATH_W) 'shrpx_mruby_module.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_mruby_module.cc'; fi` - -libnghttpx_a-shrpx_mruby_module_env.o: shrpx_mruby_module_env.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_mruby_module_env.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_env.Tpo -c -o libnghttpx_a-shrpx_mruby_module_env.o `test -f 'shrpx_mruby_module_env.cc' || echo '$(srcdir)/'`shrpx_mruby_module_env.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_env.Tpo $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_env.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_mruby_module_env.cc' object='libnghttpx_a-shrpx_mruby_module_env.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_mruby_module_env.o `test -f 'shrpx_mruby_module_env.cc' || echo '$(srcdir)/'`shrpx_mruby_module_env.cc - -libnghttpx_a-shrpx_mruby_module_env.obj: shrpx_mruby_module_env.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_mruby_module_env.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_env.Tpo -c -o libnghttpx_a-shrpx_mruby_module_env.obj `if test -f 'shrpx_mruby_module_env.cc'; then $(CYGPATH_W) 'shrpx_mruby_module_env.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_mruby_module_env.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_env.Tpo $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_env.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_mruby_module_env.cc' object='libnghttpx_a-shrpx_mruby_module_env.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_mruby_module_env.obj `if test -f 'shrpx_mruby_module_env.cc'; then $(CYGPATH_W) 'shrpx_mruby_module_env.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_mruby_module_env.cc'; fi` - -libnghttpx_a-shrpx_mruby_module_request.o: shrpx_mruby_module_request.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_mruby_module_request.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_request.Tpo -c -o libnghttpx_a-shrpx_mruby_module_request.o `test -f 'shrpx_mruby_module_request.cc' || echo '$(srcdir)/'`shrpx_mruby_module_request.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_request.Tpo $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_request.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_mruby_module_request.cc' object='libnghttpx_a-shrpx_mruby_module_request.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_mruby_module_request.o `test -f 'shrpx_mruby_module_request.cc' || echo '$(srcdir)/'`shrpx_mruby_module_request.cc - -libnghttpx_a-shrpx_mruby_module_request.obj: shrpx_mruby_module_request.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_mruby_module_request.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_request.Tpo -c -o libnghttpx_a-shrpx_mruby_module_request.obj `if test -f 'shrpx_mruby_module_request.cc'; then $(CYGPATH_W) 'shrpx_mruby_module_request.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_mruby_module_request.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_request.Tpo $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_request.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_mruby_module_request.cc' object='libnghttpx_a-shrpx_mruby_module_request.obj' libtool=no @AMDEPBACKSLASH@ +libnghttp2_asio_la-asio_server.lo: asio_server.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server.Tpo -c -o libnghttp2_asio_la-asio_server.lo `test -f 'asio_server.cc' || echo '$(srcdir)/'`asio_server.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server.cc' object='libnghttp2_asio_la-asio_server.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_mruby_module_request.obj `if test -f 'shrpx_mruby_module_request.cc'; then $(CYGPATH_W) 'shrpx_mruby_module_request.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_mruby_module_request.cc'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server.lo `test -f 'asio_server.cc' || echo '$(srcdir)/'`asio_server.cc -libnghttpx_a-shrpx_mruby_module_response.o: shrpx_mruby_module_response.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_mruby_module_response.o -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_response.Tpo -c -o libnghttpx_a-shrpx_mruby_module_response.o `test -f 'shrpx_mruby_module_response.cc' || echo '$(srcdir)/'`shrpx_mruby_module_response.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_response.Tpo $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_response.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_mruby_module_response.cc' object='libnghttpx_a-shrpx_mruby_module_response.o' libtool=no @AMDEPBACKSLASH@ +libnghttp2_asio_la-asio_io_service_pool.lo: asio_io_service_pool.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_io_service_pool.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_io_service_pool.Tpo -c -o libnghttp2_asio_la-asio_io_service_pool.lo `test -f 'asio_io_service_pool.cc' || echo '$(srcdir)/'`asio_io_service_pool.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_io_service_pool.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_io_service_pool.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_io_service_pool.cc' object='libnghttp2_asio_la-asio_io_service_pool.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_mruby_module_response.o `test -f 'shrpx_mruby_module_response.cc' || echo '$(srcdir)/'`shrpx_mruby_module_response.cc +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_io_service_pool.lo `test -f 'asio_io_service_pool.cc' || echo '$(srcdir)/'`asio_io_service_pool.cc -libnghttpx_a-shrpx_mruby_module_response.obj: shrpx_mruby_module_response.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttpx_a-shrpx_mruby_module_response.obj -MD -MP -MF $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_response.Tpo -c -o libnghttpx_a-shrpx_mruby_module_response.obj `if test -f 'shrpx_mruby_module_response.cc'; then $(CYGPATH_W) 'shrpx_mruby_module_response.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_mruby_module_response.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_response.Tpo $(DEPDIR)/libnghttpx_a-shrpx_mruby_module_response.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_mruby_module_response.cc' object='libnghttpx_a-shrpx_mruby_module_response.obj' libtool=no @AMDEPBACKSLASH@ +libnghttp2_asio_la-asio_http2_handler.lo: asio_http2_handler.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_http2_handler.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_http2_handler.Tpo -c -o libnghttp2_asio_la-asio_http2_handler.lo `test -f 'asio_http2_handler.cc' || echo '$(srcdir)/'`asio_http2_handler.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_http2_handler.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_http2_handler.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_http2_handler.cc' object='libnghttp2_asio_la-asio_http2_handler.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_http2_handler.lo `test -f 'asio_http2_handler.cc' || echo '$(srcdir)/'`asio_http2_handler.cc + +libnghttp2_asio_la-asio_http2_impl.lo: asio_http2_impl.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_http2_impl.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_http2_impl.Tpo -c -o libnghttp2_asio_la-asio_http2_impl.lo `test -f 'asio_http2_impl.cc' || echo '$(srcdir)/'`asio_http2_impl.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_http2_impl.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_http2_impl.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_http2_impl.cc' object='libnghttp2_asio_la-asio_http2_impl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttpx_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttpx_a-shrpx_mruby_module_response.obj `if test -f 'shrpx_mruby_module_response.cc'; then $(CYGPATH_W) 'shrpx_mruby_module_response.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_mruby_module_response.cc'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_http2_impl.lo `test -f 'asio_http2_impl.cc' || echo '$(srcdir)/'`asio_http2_impl.cc libnghttp2_asio_la-util.lo: util.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-util.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-util.Tpo -c -o libnghttp2_asio_la-util.lo `test -f 'util.cc' || echo '$(srcdir)/'`util.cc @@ -2097,188 +1310,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-ssl.lo `test -f 'ssl.cc' || echo '$(srcdir)/'`ssl.cc -libnghttp2_asio_la-asio_common.lo: asio_common.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_common.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_common.Tpo -c -o libnghttp2_asio_la-asio_common.lo `test -f 'asio_common.cc' || echo '$(srcdir)/'`asio_common.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_common.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_common.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_common.cc' object='libnghttp2_asio_la-asio_common.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_common.lo `test -f 'asio_common.cc' || echo '$(srcdir)/'`asio_common.cc - -libnghttp2_asio_la-asio_io_service_pool.lo: asio_io_service_pool.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_io_service_pool.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_io_service_pool.Tpo -c -o libnghttp2_asio_la-asio_io_service_pool.lo `test -f 'asio_io_service_pool.cc' || echo '$(srcdir)/'`asio_io_service_pool.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_io_service_pool.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_io_service_pool.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_io_service_pool.cc' object='libnghttp2_asio_la-asio_io_service_pool.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_io_service_pool.lo `test -f 'asio_io_service_pool.cc' || echo '$(srcdir)/'`asio_io_service_pool.cc - -libnghttp2_asio_la-asio_server_http2.lo: asio_server_http2.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_http2.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_http2.Tpo -c -o libnghttp2_asio_la-asio_server_http2.lo `test -f 'asio_server_http2.cc' || echo '$(srcdir)/'`asio_server_http2.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_http2.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_http2.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_http2.cc' object='libnghttp2_asio_la-asio_server_http2.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_http2.lo `test -f 'asio_server_http2.cc' || echo '$(srcdir)/'`asio_server_http2.cc - -libnghttp2_asio_la-asio_server_http2_impl.lo: asio_server_http2_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_http2_impl.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_http2_impl.Tpo -c -o libnghttp2_asio_la-asio_server_http2_impl.lo `test -f 'asio_server_http2_impl.cc' || echo '$(srcdir)/'`asio_server_http2_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_http2_impl.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_http2_impl.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_http2_impl.cc' object='libnghttp2_asio_la-asio_server_http2_impl.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_http2_impl.lo `test -f 'asio_server_http2_impl.cc' || echo '$(srcdir)/'`asio_server_http2_impl.cc - -libnghttp2_asio_la-asio_server.lo: asio_server.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server.Tpo -c -o libnghttp2_asio_la-asio_server.lo `test -f 'asio_server.cc' || echo '$(srcdir)/'`asio_server.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server.cc' object='libnghttp2_asio_la-asio_server.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server.lo `test -f 'asio_server.cc' || echo '$(srcdir)/'`asio_server.cc - -libnghttp2_asio_la-asio_server_http2_handler.lo: asio_server_http2_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_http2_handler.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_http2_handler.Tpo -c -o libnghttp2_asio_la-asio_server_http2_handler.lo `test -f 'asio_server_http2_handler.cc' || echo '$(srcdir)/'`asio_server_http2_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_http2_handler.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_http2_handler.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_http2_handler.cc' object='libnghttp2_asio_la-asio_server_http2_handler.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_http2_handler.lo `test -f 'asio_server_http2_handler.cc' || echo '$(srcdir)/'`asio_server_http2_handler.cc - -libnghttp2_asio_la-asio_server_request.lo: asio_server_request.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_request.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_request.Tpo -c -o libnghttp2_asio_la-asio_server_request.lo `test -f 'asio_server_request.cc' || echo '$(srcdir)/'`asio_server_request.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_request.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_request.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_request.cc' object='libnghttp2_asio_la-asio_server_request.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_request.lo `test -f 'asio_server_request.cc' || echo '$(srcdir)/'`asio_server_request.cc - -libnghttp2_asio_la-asio_server_request_impl.lo: asio_server_request_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_request_impl.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_request_impl.Tpo -c -o libnghttp2_asio_la-asio_server_request_impl.lo `test -f 'asio_server_request_impl.cc' || echo '$(srcdir)/'`asio_server_request_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_request_impl.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_request_impl.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_request_impl.cc' object='libnghttp2_asio_la-asio_server_request_impl.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_request_impl.lo `test -f 'asio_server_request_impl.cc' || echo '$(srcdir)/'`asio_server_request_impl.cc - -libnghttp2_asio_la-asio_server_response.lo: asio_server_response.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_response.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_response.Tpo -c -o libnghttp2_asio_la-asio_server_response.lo `test -f 'asio_server_response.cc' || echo '$(srcdir)/'`asio_server_response.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_response.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_response.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_response.cc' object='libnghttp2_asio_la-asio_server_response.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_response.lo `test -f 'asio_server_response.cc' || echo '$(srcdir)/'`asio_server_response.cc - -libnghttp2_asio_la-asio_server_response_impl.lo: asio_server_response_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_response_impl.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_response_impl.Tpo -c -o libnghttp2_asio_la-asio_server_response_impl.lo `test -f 'asio_server_response_impl.cc' || echo '$(srcdir)/'`asio_server_response_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_response_impl.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_response_impl.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_response_impl.cc' object='libnghttp2_asio_la-asio_server_response_impl.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_response_impl.lo `test -f 'asio_server_response_impl.cc' || echo '$(srcdir)/'`asio_server_response_impl.cc - -libnghttp2_asio_la-asio_server_stream.lo: asio_server_stream.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_stream.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_stream.Tpo -c -o libnghttp2_asio_la-asio_server_stream.lo `test -f 'asio_server_stream.cc' || echo '$(srcdir)/'`asio_server_stream.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_stream.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_stream.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_stream.cc' object='libnghttp2_asio_la-asio_server_stream.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_stream.lo `test -f 'asio_server_stream.cc' || echo '$(srcdir)/'`asio_server_stream.cc - -libnghttp2_asio_la-asio_server_serve_mux.lo: asio_server_serve_mux.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_serve_mux.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_serve_mux.Tpo -c -o libnghttp2_asio_la-asio_server_serve_mux.lo `test -f 'asio_server_serve_mux.cc' || echo '$(srcdir)/'`asio_server_serve_mux.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_serve_mux.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_serve_mux.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_serve_mux.cc' object='libnghttp2_asio_la-asio_server_serve_mux.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_serve_mux.lo `test -f 'asio_server_serve_mux.cc' || echo '$(srcdir)/'`asio_server_serve_mux.cc - -libnghttp2_asio_la-asio_server_request_handler.lo: asio_server_request_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_request_handler.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_request_handler.Tpo -c -o libnghttp2_asio_la-asio_server_request_handler.lo `test -f 'asio_server_request_handler.cc' || echo '$(srcdir)/'`asio_server_request_handler.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_request_handler.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_request_handler.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_request_handler.cc' object='libnghttp2_asio_la-asio_server_request_handler.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_request_handler.lo `test -f 'asio_server_request_handler.cc' || echo '$(srcdir)/'`asio_server_request_handler.cc - -libnghttp2_asio_la-asio_server_tls_context.lo: asio_server_tls_context.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_server_tls_context.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_server_tls_context.Tpo -c -o libnghttp2_asio_la-asio_server_tls_context.lo `test -f 'asio_server_tls_context.cc' || echo '$(srcdir)/'`asio_server_tls_context.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_server_tls_context.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_server_tls_context.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_server_tls_context.cc' object='libnghttp2_asio_la-asio_server_tls_context.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_server_tls_context.lo `test -f 'asio_server_tls_context.cc' || echo '$(srcdir)/'`asio_server_tls_context.cc - -libnghttp2_asio_la-asio_client_session.lo: asio_client_session.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_client_session.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_client_session.Tpo -c -o libnghttp2_asio_la-asio_client_session.lo `test -f 'asio_client_session.cc' || echo '$(srcdir)/'`asio_client_session.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_client_session.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_client_session.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_client_session.cc' object='libnghttp2_asio_la-asio_client_session.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_client_session.lo `test -f 'asio_client_session.cc' || echo '$(srcdir)/'`asio_client_session.cc - -libnghttp2_asio_la-asio_client_session_impl.lo: asio_client_session_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_client_session_impl.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_client_session_impl.Tpo -c -o libnghttp2_asio_la-asio_client_session_impl.lo `test -f 'asio_client_session_impl.cc' || echo '$(srcdir)/'`asio_client_session_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_client_session_impl.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_client_session_impl.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_client_session_impl.cc' object='libnghttp2_asio_la-asio_client_session_impl.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_client_session_impl.lo `test -f 'asio_client_session_impl.cc' || echo '$(srcdir)/'`asio_client_session_impl.cc - -libnghttp2_asio_la-asio_client_session_tcp_impl.lo: asio_client_session_tcp_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_client_session_tcp_impl.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_client_session_tcp_impl.Tpo -c -o libnghttp2_asio_la-asio_client_session_tcp_impl.lo `test -f 'asio_client_session_tcp_impl.cc' || echo '$(srcdir)/'`asio_client_session_tcp_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_client_session_tcp_impl.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_client_session_tcp_impl.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_client_session_tcp_impl.cc' object='libnghttp2_asio_la-asio_client_session_tcp_impl.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_client_session_tcp_impl.lo `test -f 'asio_client_session_tcp_impl.cc' || echo '$(srcdir)/'`asio_client_session_tcp_impl.cc - -libnghttp2_asio_la-asio_client_session_tls_impl.lo: asio_client_session_tls_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_client_session_tls_impl.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_client_session_tls_impl.Tpo -c -o libnghttp2_asio_la-asio_client_session_tls_impl.lo `test -f 'asio_client_session_tls_impl.cc' || echo '$(srcdir)/'`asio_client_session_tls_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_client_session_tls_impl.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_client_session_tls_impl.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_client_session_tls_impl.cc' object='libnghttp2_asio_la-asio_client_session_tls_impl.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_client_session_tls_impl.lo `test -f 'asio_client_session_tls_impl.cc' || echo '$(srcdir)/'`asio_client_session_tls_impl.cc - -libnghttp2_asio_la-asio_client_response.lo: asio_client_response.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_client_response.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_client_response.Tpo -c -o libnghttp2_asio_la-asio_client_response.lo `test -f 'asio_client_response.cc' || echo '$(srcdir)/'`asio_client_response.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_client_response.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_client_response.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_client_response.cc' object='libnghttp2_asio_la-asio_client_response.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_client_response.lo `test -f 'asio_client_response.cc' || echo '$(srcdir)/'`asio_client_response.cc - -libnghttp2_asio_la-asio_client_response_impl.lo: asio_client_response_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_client_response_impl.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_client_response_impl.Tpo -c -o libnghttp2_asio_la-asio_client_response_impl.lo `test -f 'asio_client_response_impl.cc' || echo '$(srcdir)/'`asio_client_response_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_client_response_impl.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_client_response_impl.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_client_response_impl.cc' object='libnghttp2_asio_la-asio_client_response_impl.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_client_response_impl.lo `test -f 'asio_client_response_impl.cc' || echo '$(srcdir)/'`asio_client_response_impl.cc - -libnghttp2_asio_la-asio_client_request.lo: asio_client_request.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_client_request.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_client_request.Tpo -c -o libnghttp2_asio_la-asio_client_request.lo `test -f 'asio_client_request.cc' || echo '$(srcdir)/'`asio_client_request.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_client_request.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_client_request.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_client_request.cc' object='libnghttp2_asio_la-asio_client_request.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_client_request.lo `test -f 'asio_client_request.cc' || echo '$(srcdir)/'`asio_client_request.cc - -libnghttp2_asio_la-asio_client_request_impl.lo: asio_client_request_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_client_request_impl.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_client_request_impl.Tpo -c -o libnghttp2_asio_la-asio_client_request_impl.lo `test -f 'asio_client_request_impl.cc' || echo '$(srcdir)/'`asio_client_request_impl.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_client_request_impl.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_client_request_impl.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_client_request_impl.cc' object='libnghttp2_asio_la-asio_client_request_impl.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_client_request_impl.lo `test -f 'asio_client_request_impl.cc' || echo '$(srcdir)/'`asio_client_request_impl.cc - -libnghttp2_asio_la-asio_client_stream.lo: asio_client_stream.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_client_stream.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_client_stream.Tpo -c -o libnghttp2_asio_la-asio_client_stream.lo `test -f 'asio_client_stream.cc' || echo '$(srcdir)/'`asio_client_stream.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_client_stream.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_client_stream.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_client_stream.cc' object='libnghttp2_asio_la-asio_client_stream.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_client_stream.lo `test -f 'asio_client_stream.cc' || echo '$(srcdir)/'`asio_client_stream.cc - -libnghttp2_asio_la-asio_client_tls_context.lo: asio_client_tls_context.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libnghttp2_asio_la-asio_client_tls_context.lo -MD -MP -MF $(DEPDIR)/libnghttp2_asio_la-asio_client_tls_context.Tpo -c -o libnghttp2_asio_la-asio_client_tls_context.lo `test -f 'asio_client_tls_context.cc' || echo '$(srcdir)/'`asio_client_tls_context.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnghttp2_asio_la-asio_client_tls_context.Tpo $(DEPDIR)/libnghttp2_asio_la-asio_client_tls_context.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='asio_client_tls_context.cc' object='libnghttp2_asio_la-asio_client_tls_context.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnghttp2_asio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libnghttp2_asio_la-asio_client_tls_context.lo `test -f 'asio_client_tls_context.cc' || echo '$(srcdir)/'`asio_client_tls_context.cc - -nghttpx-shrpx.o: shrpx.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx-shrpx.o -MD -MP -MF $(DEPDIR)/nghttpx-shrpx.Tpo -c -o nghttpx-shrpx.o `test -f 'shrpx.cc' || echo '$(srcdir)/'`shrpx.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx-shrpx.Tpo $(DEPDIR)/nghttpx-shrpx.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx.cc' object='nghttpx-shrpx.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx-shrpx.o `test -f 'shrpx.cc' || echo '$(srcdir)/'`shrpx.cc - -nghttpx-shrpx.obj: shrpx.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx-shrpx.obj -MD -MP -MF $(DEPDIR)/nghttpx-shrpx.Tpo -c -o nghttpx-shrpx.obj `if test -f 'shrpx.cc'; then $(CYGPATH_W) 'shrpx.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx-shrpx.Tpo $(DEPDIR)/nghttpx-shrpx.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx.cc' object='nghttpx-shrpx.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx-shrpx.obj `if test -f 'shrpx.cc'; then $(CYGPATH_W) 'shrpx.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx.cc'; fi` - nghttpx_unittest-shrpx-unittest.o: shrpx-unittest.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-shrpx-unittest.o -MD -MP -MF $(DEPDIR)/nghttpx_unittest-shrpx-unittest.Tpo -c -o nghttpx_unittest-shrpx-unittest.o `test -f 'shrpx-unittest.cc' || echo '$(srcdir)/'`shrpx-unittest.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-shrpx-unittest.Tpo $(DEPDIR)/nghttpx_unittest-shrpx-unittest.Po @@ -2335,48 +1366,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-shrpx_config_test.obj `if test -f 'shrpx_config_test.cc'; then $(CYGPATH_W) 'shrpx_config_test.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_config_test.cc'; fi` -nghttpx_unittest-shrpx_worker_test.o: shrpx_worker_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-shrpx_worker_test.o -MD -MP -MF $(DEPDIR)/nghttpx_unittest-shrpx_worker_test.Tpo -c -o nghttpx_unittest-shrpx_worker_test.o `test -f 'shrpx_worker_test.cc' || echo '$(srcdir)/'`shrpx_worker_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-shrpx_worker_test.Tpo $(DEPDIR)/nghttpx_unittest-shrpx_worker_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_worker_test.cc' object='nghttpx_unittest-shrpx_worker_test.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-shrpx_worker_test.o `test -f 'shrpx_worker_test.cc' || echo '$(srcdir)/'`shrpx_worker_test.cc - -nghttpx_unittest-shrpx_worker_test.obj: shrpx_worker_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-shrpx_worker_test.obj -MD -MP -MF $(DEPDIR)/nghttpx_unittest-shrpx_worker_test.Tpo -c -o nghttpx_unittest-shrpx_worker_test.obj `if test -f 'shrpx_worker_test.cc'; then $(CYGPATH_W) 'shrpx_worker_test.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_worker_test.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-shrpx_worker_test.Tpo $(DEPDIR)/nghttpx_unittest-shrpx_worker_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_worker_test.cc' object='nghttpx_unittest-shrpx_worker_test.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-shrpx_worker_test.obj `if test -f 'shrpx_worker_test.cc'; then $(CYGPATH_W) 'shrpx_worker_test.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_worker_test.cc'; fi` - -nghttpx_unittest-shrpx_http_test.o: shrpx_http_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-shrpx_http_test.o -MD -MP -MF $(DEPDIR)/nghttpx_unittest-shrpx_http_test.Tpo -c -o nghttpx_unittest-shrpx_http_test.o `test -f 'shrpx_http_test.cc' || echo '$(srcdir)/'`shrpx_http_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-shrpx_http_test.Tpo $(DEPDIR)/nghttpx_unittest-shrpx_http_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http_test.cc' object='nghttpx_unittest-shrpx_http_test.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-shrpx_http_test.o `test -f 'shrpx_http_test.cc' || echo '$(srcdir)/'`shrpx_http_test.cc - -nghttpx_unittest-shrpx_http_test.obj: shrpx_http_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-shrpx_http_test.obj -MD -MP -MF $(DEPDIR)/nghttpx_unittest-shrpx_http_test.Tpo -c -o nghttpx_unittest-shrpx_http_test.obj `if test -f 'shrpx_http_test.cc'; then $(CYGPATH_W) 'shrpx_http_test.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http_test.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-shrpx_http_test.Tpo $(DEPDIR)/nghttpx_unittest-shrpx_http_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_http_test.cc' object='nghttpx_unittest-shrpx_http_test.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-shrpx_http_test.obj `if test -f 'shrpx_http_test.cc'; then $(CYGPATH_W) 'shrpx_http_test.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_http_test.cc'; fi` - -nghttpx_unittest-shrpx_router_test.o: shrpx_router_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-shrpx_router_test.o -MD -MP -MF $(DEPDIR)/nghttpx_unittest-shrpx_router_test.Tpo -c -o nghttpx_unittest-shrpx_router_test.o `test -f 'shrpx_router_test.cc' || echo '$(srcdir)/'`shrpx_router_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-shrpx_router_test.Tpo $(DEPDIR)/nghttpx_unittest-shrpx_router_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_router_test.cc' object='nghttpx_unittest-shrpx_router_test.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-shrpx_router_test.o `test -f 'shrpx_router_test.cc' || echo '$(srcdir)/'`shrpx_router_test.cc - -nghttpx_unittest-shrpx_router_test.obj: shrpx_router_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-shrpx_router_test.obj -MD -MP -MF $(DEPDIR)/nghttpx_unittest-shrpx_router_test.Tpo -c -o nghttpx_unittest-shrpx_router_test.obj `if test -f 'shrpx_router_test.cc'; then $(CYGPATH_W) 'shrpx_router_test.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_router_test.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-shrpx_router_test.Tpo $(DEPDIR)/nghttpx_unittest-shrpx_router_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shrpx_router_test.cc' object='nghttpx_unittest-shrpx_router_test.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-shrpx_router_test.obj `if test -f 'shrpx_router_test.cc'; then $(CYGPATH_W) 'shrpx_router_test.cc'; else $(CYGPATH_W) '$(srcdir)/shrpx_router_test.cc'; fi` - nghttpx_unittest-http2_test.o: http2_test.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-http2_test.o -MD -MP -MF $(DEPDIR)/nghttpx_unittest-http2_test.Tpo -c -o nghttpx_unittest-http2_test.o `test -f 'http2_test.cc' || echo '$(srcdir)/'`http2_test.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-http2_test.Tpo $(DEPDIR)/nghttpx_unittest-http2_test.Po @@ -2405,62 +1394,6 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-util_test.obj `if test -f 'util_test.cc'; then $(CYGPATH_W) 'util_test.cc'; else $(CYGPATH_W) '$(srcdir)/util_test.cc'; fi` -nghttpx_unittest-buffer_test.o: buffer_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-buffer_test.o -MD -MP -MF $(DEPDIR)/nghttpx_unittest-buffer_test.Tpo -c -o nghttpx_unittest-buffer_test.o `test -f 'buffer_test.cc' || echo '$(srcdir)/'`buffer_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-buffer_test.Tpo $(DEPDIR)/nghttpx_unittest-buffer_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='buffer_test.cc' object='nghttpx_unittest-buffer_test.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-buffer_test.o `test -f 'buffer_test.cc' || echo '$(srcdir)/'`buffer_test.cc - -nghttpx_unittest-buffer_test.obj: buffer_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-buffer_test.obj -MD -MP -MF $(DEPDIR)/nghttpx_unittest-buffer_test.Tpo -c -o nghttpx_unittest-buffer_test.obj `if test -f 'buffer_test.cc'; then $(CYGPATH_W) 'buffer_test.cc'; else $(CYGPATH_W) '$(srcdir)/buffer_test.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-buffer_test.Tpo $(DEPDIR)/nghttpx_unittest-buffer_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='buffer_test.cc' object='nghttpx_unittest-buffer_test.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-buffer_test.obj `if test -f 'buffer_test.cc'; then $(CYGPATH_W) 'buffer_test.cc'; else $(CYGPATH_W) '$(srcdir)/buffer_test.cc'; fi` - -nghttpx_unittest-memchunk_test.o: memchunk_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-memchunk_test.o -MD -MP -MF $(DEPDIR)/nghttpx_unittest-memchunk_test.Tpo -c -o nghttpx_unittest-memchunk_test.o `test -f 'memchunk_test.cc' || echo '$(srcdir)/'`memchunk_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-memchunk_test.Tpo $(DEPDIR)/nghttpx_unittest-memchunk_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='memchunk_test.cc' object='nghttpx_unittest-memchunk_test.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-memchunk_test.o `test -f 'memchunk_test.cc' || echo '$(srcdir)/'`memchunk_test.cc - -nghttpx_unittest-memchunk_test.obj: memchunk_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-memchunk_test.obj -MD -MP -MF $(DEPDIR)/nghttpx_unittest-memchunk_test.Tpo -c -o nghttpx_unittest-memchunk_test.obj `if test -f 'memchunk_test.cc'; then $(CYGPATH_W) 'memchunk_test.cc'; else $(CYGPATH_W) '$(srcdir)/memchunk_test.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-memchunk_test.Tpo $(DEPDIR)/nghttpx_unittest-memchunk_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='memchunk_test.cc' object='nghttpx_unittest-memchunk_test.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-memchunk_test.obj `if test -f 'memchunk_test.cc'; then $(CYGPATH_W) 'memchunk_test.cc'; else $(CYGPATH_W) '$(srcdir)/memchunk_test.cc'; fi` - -nghttpx_unittest-template_test.o: template_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-template_test.o -MD -MP -MF $(DEPDIR)/nghttpx_unittest-template_test.Tpo -c -o nghttpx_unittest-template_test.o `test -f 'template_test.cc' || echo '$(srcdir)/'`template_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-template_test.Tpo $(DEPDIR)/nghttpx_unittest-template_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='template_test.cc' object='nghttpx_unittest-template_test.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-template_test.o `test -f 'template_test.cc' || echo '$(srcdir)/'`template_test.cc - -nghttpx_unittest-template_test.obj: template_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-template_test.obj -MD -MP -MF $(DEPDIR)/nghttpx_unittest-template_test.Tpo -c -o nghttpx_unittest-template_test.obj `if test -f 'template_test.cc'; then $(CYGPATH_W) 'template_test.cc'; else $(CYGPATH_W) '$(srcdir)/template_test.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-template_test.Tpo $(DEPDIR)/nghttpx_unittest-template_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='template_test.cc' object='nghttpx_unittest-template_test.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-template_test.obj `if test -f 'template_test.cc'; then $(CYGPATH_W) 'template_test.cc'; else $(CYGPATH_W) '$(srcdir)/template_test.cc'; fi` - -nghttpx_unittest-base64_test.o: base64_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-base64_test.o -MD -MP -MF $(DEPDIR)/nghttpx_unittest-base64_test.Tpo -c -o nghttpx_unittest-base64_test.o `test -f 'base64_test.cc' || echo '$(srcdir)/'`base64_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-base64_test.Tpo $(DEPDIR)/nghttpx_unittest-base64_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='base64_test.cc' object='nghttpx_unittest-base64_test.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-base64_test.o `test -f 'base64_test.cc' || echo '$(srcdir)/'`base64_test.cc - -nghttpx_unittest-base64_test.obj: base64_test.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT nghttpx_unittest-base64_test.obj -MD -MP -MF $(DEPDIR)/nghttpx_unittest-base64_test.Tpo -c -o nghttpx_unittest-base64_test.obj `if test -f 'base64_test.cc'; then $(CYGPATH_W) 'base64_test.cc'; else $(CYGPATH_W) '$(srcdir)/base64_test.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nghttpx_unittest-base64_test.Tpo $(DEPDIR)/nghttpx_unittest-base64_test.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='base64_test.cc' object='nghttpx_unittest-base64_test.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nghttpx_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o nghttpx_unittest-base64_test.obj `if test -f 'base64_test.cc'; then $(CYGPATH_W) 'base64_test.cc'; else $(CYGPATH_W) '$(srcdir)/base64_test.cc'; fi` - mostlyclean-libtool: -rm -f *.lo @@ -2617,7 +1550,7 @@ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ - elif test -n "$$redo_logs"; then \ + else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ @@ -2945,8 +1878,6 @@ uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-pkgconfigDATA -.PRECIOUS: Makefile - # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru nghttp2-1.13.0/src/memchunk.h nghttp2-0.6.7/src/memchunk.h --- nghttp2-1.13.0/src/memchunk.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/memchunk.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,438 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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 MEMCHUNK_H -#define MEMCHUNK_H - -#include "nghttp2_config.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "template.h" - -namespace nghttp2 { - -#define DEFAULT_WR_IOVCNT 16 - -#if defined(IOV_MAX) && IOV_MAX < DEFAULT_WR_IOVCNT -#define MAX_WR_IOVCNT IOV_MAX -#else // !defined(IOV_MAX) || IOV_MAX >= DEFAULT_WR_IOVCNT -#define MAX_WR_IOVCNT DEFAULT_WR_IOVCNT -#endif // !defined(IOV_MAX) || IOV_MAX >= DEFAULT_WR_IOVCNT - -template struct Memchunk { - Memchunk(std::unique_ptr next_chunk) - : pos(std::begin(buf)), - last(pos), - knext(std::move(next_chunk)), - next(nullptr) {} - size_t len() const { return last - pos; } - size_t left() const { return std::end(buf) - last; } - void reset() { pos = last = std::begin(buf); } - std::array buf; - uint8_t *pos, *last; - std::unique_ptr knext; - Memchunk *next; - static const size_t size = N; -}; - -template struct Pool { - Pool() : pool(nullptr), freelist(nullptr), poolsize(0) {} - T *get() { - if (freelist) { - auto m = freelist; - freelist = freelist->next; - m->next = nullptr; - m->reset(); - return m; - } - - pool = make_unique(std::move(pool)); - poolsize += T::size; - return pool.get(); - } - void recycle(T *m) { - m->next = freelist; - freelist = m; - } - void clear() { - freelist = nullptr; - pool = nullptr; - poolsize = 0; - } - using value_type = T; - std::unique_ptr pool; - T *freelist; - size_t poolsize; -}; - -template struct Memchunks { - Memchunks(Pool *pool) - : pool(pool), head(nullptr), tail(nullptr), len(0) {} - Memchunks(const Memchunks &) = delete; - Memchunks(Memchunks &&other) noexcept : pool(other.pool), - head(other.head), - tail(other.tail), - len(other.len) { - // keep other.pool - other.head = other.tail = nullptr; - other.len = 0; - } - Memchunks &operator=(const Memchunks &) = delete; - Memchunks &operator=(Memchunks &&other) noexcept { - if (this == &other) { - return *this; - } - - reset(); - - pool = other.pool; - head = other.head; - tail = other.tail; - len = other.len; - - other.head = other.tail = nullptr; - other.len = 0; - - return *this; - } - ~Memchunks() { - if (!pool) { - return; - } - for (auto m = head; m;) { - auto next = m->next; - pool->recycle(m); - m = next; - } - } - size_t append(char c) { - if (!tail) { - head = tail = pool->get(); - } else if (tail->left() == 0) { - tail->next = pool->get(); - tail = tail->next; - } - *tail->last++ = c; - ++len; - return 1; - } - size_t append(const void *src, size_t count) { - if (count == 0) { - return 0; - } - - auto first = static_cast(src); - auto last = first + count; - - if (!tail) { - head = tail = pool->get(); - } - - for (;;) { - auto n = std::min(static_cast(last - first), tail->left()); - tail->last = std::copy_n(first, n, tail->last); - first += n; - len += n; - if (first == last) { - break; - } - - tail->next = pool->get(); - tail = tail->next; - } - - return count; - } - template size_t append(const char(&s)[N]) { - return append(s, N - 1); - } - size_t append(const std::string &s) { return append(s.c_str(), s.size()); } - size_t append(const StringRef &s) { return append(s.c_str(), s.size()); } - size_t remove(void *dest, size_t count) { - if (!tail || count == 0) { - return 0; - } - - auto first = static_cast(dest); - auto last = first + count; - - auto m = head; - - while (m) { - auto next = m->next; - auto n = std::min(static_cast(last - first), m->len()); - - assert(m->len()); - first = std::copy_n(m->pos, n, first); - m->pos += n; - len -= n; - if (m->len() > 0) { - break; - } - pool->recycle(m); - m = next; - } - head = m; - if (head == nullptr) { - tail = nullptr; - } - - return first - static_cast(dest); - } - size_t remove(Memchunks &dest, size_t count) { - if (!tail || count == 0) { - return 0; - } - - auto left = count; - auto m = head; - - while (m) { - auto next = m->next; - auto n = std::min(left, m->len()); - - assert(m->len()); - dest.append(m->pos, n); - m->pos += n; - len -= n; - left -= n; - if (m->len() > 0) { - break; - } - pool->recycle(m); - m = next; - } - head = m; - if (head == nullptr) { - tail = nullptr; - } - - return count - left; - } - size_t drain(size_t count) { - auto ndata = count; - auto m = head; - while (m) { - auto next = m->next; - auto n = std::min(count, m->len()); - m->pos += n; - count -= n; - len -= n; - if (m->len() > 0) { - break; - } - - pool->recycle(m); - m = next; - } - head = m; - if (head == nullptr) { - tail = nullptr; - } - return ndata - count; - } - int riovec(struct iovec *iov, int iovcnt) const { - if (!head) { - return 0; - } - auto m = head; - int i; - for (i = 0; i < iovcnt && m; ++i, m = m->next) { - iov[i].iov_base = m->pos; - iov[i].iov_len = m->len(); - } - return i; - } - size_t rleft() const { return len; } - void reset() { - for (auto m = head; m;) { - auto next = m->next; - pool->recycle(m); - m = next; - } - len = 0; - head = tail = nullptr; - } - - Pool *pool; - Memchunk *head, *tail; - size_t len; -}; - -// Wrapper around Memchunks to offer "peeking" functionality. -template struct PeekMemchunks { - PeekMemchunks(Pool *pool) - : memchunks(pool), - cur(nullptr), - cur_pos(nullptr), - cur_last(nullptr), - len(0), - peeking(true) {} - PeekMemchunks(const PeekMemchunks &) = delete; - PeekMemchunks(PeekMemchunks &&other) noexcept - : memchunks(std::move(other.memchunks)), - cur(other.cur), - cur_pos(other.cur_pos), - cur_last(other.cur_last), - len(other.len), - peeking(other.peeking) { - other.reset(); - } - PeekMemchunks &operator=(const PeekMemchunks &) = delete; - PeekMemchunks &operator=(PeekMemchunks &&other) noexcept { - if (this == &other) { - return *this; - } - - memchunks = std::move(other.memchunks); - cur = other.cur; - cur_pos = other.cur_pos; - cur_last = other.cur_last; - len = other.len; - peeking = other.peeking; - - other.reset(); - - return *this; - } - size_t append(const void *src, size_t count) { - count = memchunks.append(src, count); - len += count; - return count; - } - size_t remove(void *dest, size_t count) { - if (!peeking) { - count = memchunks.remove(dest, count); - len -= count; - return count; - } - - if (count == 0 || len == 0) { - return 0; - } - - if (!cur) { - cur = memchunks.head; - cur_pos = cur->pos; - } - - // cur_last could be updated in append - cur_last = cur->last; - - if (cur_pos == cur_last) { - assert(cur->next); - cur = cur->next; - } - - auto first = static_cast(dest); - auto last = first + count; - - for (;;) { - auto n = std::min(last - first, cur_last - cur_pos); - - first = std::copy_n(cur_pos, n, first); - cur_pos += n; - len -= n; - - if (first == last) { - break; - } - assert(cur_pos == cur_last); - if (!cur->next) { - break; - } - cur = cur->next; - cur_pos = cur->pos; - cur_last = cur->last; - } - return first - static_cast(dest); - } - size_t rleft() const { return len; } - size_t rleft_buffered() const { return memchunks.rleft(); } - void disable_peek(bool drain) { - if (!peeking) { - return; - } - if (drain) { - auto n = rleft_buffered() - rleft(); - memchunks.drain(n); - assert(len == memchunks.rleft()); - } else { - len = memchunks.rleft(); - } - cur = nullptr; - cur_pos = cur_last = nullptr; - peeking = false; - } - void reset() { - memchunks.reset(); - cur = nullptr; - cur_pos = cur_last = nullptr; - len = 0; - peeking = true; - } - Memchunks memchunks; - // Pointer to the Memchunk currently we are reading/writing. - Memchunk *cur; - // Region inside cur, we have processed to cur_pos. - uint8_t *cur_pos, *cur_last; - // This is the length we have left unprocessed. len <= - // memchunk.rleft() must hold. - size_t len; - // true if peeking is enabled. Initially it is true. - bool peeking; -}; - -using Memchunk16K = Memchunk<16_k>; -using MemchunkPool = Pool; -using DefaultMemchunks = Memchunks; -using DefaultPeekMemchunks = PeekMemchunks; - -inline int limit_iovec(struct iovec *iov, int iovcnt, size_t max) { - if (max == 0) { - return 0; - } - for (int i = 0; i < iovcnt; ++i) { - auto d = std::min(max, iov[i].iov_len); - iov[i].iov_len = d; - max -= d; - if (max == 0) { - return i + 1; - } - } - return iovcnt; -} - -} // namespace nghttp2 - -#endif // MEMCHUNK_H diff -Nru nghttp2-1.13.0/src/memchunk_test.cc nghttp2-0.6.7/src/memchunk_test.cc --- nghttp2-1.13.0/src/memchunk_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/memchunk_test.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,336 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "memchunk_test.h" - -#include - -#include - -#include "memchunk.h" -#include "util.h" - -namespace nghttp2 { - -void test_pool_recycle(void) { - MemchunkPool pool; - - CU_ASSERT(!pool.pool); - CU_ASSERT(0 == pool.poolsize); - CU_ASSERT(nullptr == pool.freelist); - - auto m1 = pool.get(); - - CU_ASSERT(m1 == pool.pool.get()); - CU_ASSERT(MemchunkPool::value_type::size == pool.poolsize); - CU_ASSERT(nullptr == pool.freelist); - - auto m2 = pool.get(); - - CU_ASSERT(m2 == pool.pool.get()); - CU_ASSERT(2 * MemchunkPool::value_type::size == pool.poolsize); - CU_ASSERT(nullptr == pool.freelist); - CU_ASSERT(m1 == m2->knext.get()); - CU_ASSERT(nullptr == m1->knext.get()); - - auto m3 = pool.get(); - - CU_ASSERT(m3 == pool.pool.get()); - CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize); - CU_ASSERT(nullptr == pool.freelist); - - pool.recycle(m3); - - CU_ASSERT(m3 == pool.pool.get()); - CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize); - CU_ASSERT(m3 == pool.freelist); - - auto m4 = pool.get(); - - CU_ASSERT(m3 == m4); - CU_ASSERT(m4 == pool.pool.get()); - CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize); - CU_ASSERT(nullptr == pool.freelist); - - pool.recycle(m2); - pool.recycle(m1); - - CU_ASSERT(m1 == pool.freelist); - CU_ASSERT(m2 == m1->next); - CU_ASSERT(nullptr == m2->next); -} - -using Memchunk16 = Memchunk<16>; -using MemchunkPool16 = Pool; -using Memchunks16 = Memchunks; -using PeekMemchunks16 = PeekMemchunks; - -void test_memchunks_append(void) { - MemchunkPool16 pool; - Memchunks16 chunks(&pool); - - chunks.append("012"); - - auto m = chunks.tail; - - CU_ASSERT(3 == m->len()); - CU_ASSERT(13 == m->left()); - - chunks.append("3456789abcdef@"); - - CU_ASSERT(16 == m->len()); - CU_ASSERT(0 == m->left()); - - m = chunks.tail; - - CU_ASSERT(1 == m->len()); - CU_ASSERT(15 == m->left()); - CU_ASSERT(17 == chunks.rleft()); - - char buf[16]; - size_t nread; - - nread = chunks.remove(buf, 8); - - CU_ASSERT(8 == nread); - CU_ASSERT(0 == memcmp("01234567", buf, nread)); - CU_ASSERT(9 == chunks.rleft()); - - nread = chunks.remove(buf, sizeof(buf)); - - CU_ASSERT(9 == nread); - CU_ASSERT(0 == memcmp("89abcdef@", buf, nread)); - CU_ASSERT(0 == chunks.rleft()); - CU_ASSERT(nullptr == chunks.head); - CU_ASSERT(nullptr == chunks.tail); - CU_ASSERT(32 == pool.poolsize); -} - -void test_memchunks_drain(void) { - MemchunkPool16 pool; - Memchunks16 chunks(&pool); - - chunks.append("0123456789"); - - size_t nread; - - nread = chunks.drain(3); - - CU_ASSERT(3 == nread); - - char buf[16]; - - nread = chunks.remove(buf, sizeof(buf)); - - CU_ASSERT(7 == nread); - CU_ASSERT(0 == memcmp("3456789", buf, nread)); -} - -void test_memchunks_riovec(void) { - MemchunkPool16 pool; - Memchunks16 chunks(&pool); - - char buf[3 * 16]; - - chunks.append(buf, sizeof(buf)); - - std::array iov; - auto iovcnt = chunks.riovec(iov.data(), iov.size()); - - auto m = chunks.head; - - CU_ASSERT(2 == iovcnt); - CU_ASSERT(m->buf.data() == iov[0].iov_base); - CU_ASSERT(m->len() == iov[0].iov_len); - - m = m->next; - - CU_ASSERT(m->buf.data() == iov[1].iov_base); - CU_ASSERT(m->len() == iov[1].iov_len); - - chunks.drain(2 * 16); - - iovcnt = chunks.riovec(iov.data(), iov.size()); - - CU_ASSERT(1 == iovcnt); - - m = chunks.head; - CU_ASSERT(m->buf.data() == iov[0].iov_base); - CU_ASSERT(m->len() == iov[0].iov_len); -} - -void test_memchunks_recycle(void) { - MemchunkPool16 pool; - { - Memchunks16 chunks(&pool); - char buf[32]; - chunks.append(buf, sizeof(buf)); - } - CU_ASSERT(32 == pool.poolsize); - CU_ASSERT(nullptr != pool.freelist); - - auto m = pool.freelist; - m = m->next; - - CU_ASSERT(nullptr != m); - CU_ASSERT(nullptr == m->next); -} - -void test_memchunks_reset(void) { - MemchunkPool16 pool; - Memchunks16 chunks(&pool); - - std::array b{}; - - chunks.append(b.data(), b.size()); - - CU_ASSERT(32 == chunks.rleft()); - - chunks.reset(); - - CU_ASSERT(0 == chunks.rleft()); - CU_ASSERT(nullptr == chunks.head); - CU_ASSERT(nullptr == chunks.tail); - - auto m = pool.freelist; - - CU_ASSERT(nullptr != m); - CU_ASSERT(nullptr != m->next); - CU_ASSERT(nullptr == m->next->next); -} - -void test_peek_memchunks_append(void) { - MemchunkPool16 pool; - PeekMemchunks16 pchunks(&pool); - - std::array b{{ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', - '5', '6', '7', '8', '9', '0', '1', }}, - d; - - pchunks.append(b.data(), b.size()); - - CU_ASSERT(32 == pchunks.rleft()); - CU_ASSERT(32 == pchunks.rleft_buffered()); - - CU_ASSERT(0 == pchunks.remove(nullptr, 0)); - - CU_ASSERT(32 == pchunks.rleft()); - CU_ASSERT(32 == pchunks.rleft_buffered()); - - CU_ASSERT(12 == pchunks.remove(d.data(), 12)); - - CU_ASSERT(std::equal(std::begin(b), std::begin(b) + 12, std::begin(d))); - - CU_ASSERT(20 == pchunks.rleft()); - CU_ASSERT(32 == pchunks.rleft_buffered()); - - CU_ASSERT(20 == pchunks.remove(d.data(), d.size())); - - CU_ASSERT(std::equal(std::begin(b) + 12, std::end(b), std::begin(d))); - - CU_ASSERT(0 == pchunks.rleft()); - CU_ASSERT(32 == pchunks.rleft_buffered()); -} - -void test_peek_memchunks_disable_peek_drain(void) { - MemchunkPool16 pool; - PeekMemchunks16 pchunks(&pool); - - std::array b{{ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', - '5', '6', '7', '8', '9', '0', '1', }}, - d; - - pchunks.append(b.data(), b.size()); - - CU_ASSERT(12 == pchunks.remove(d.data(), 12)); - - pchunks.disable_peek(true); - - CU_ASSERT(!pchunks.peeking); - CU_ASSERT(20 == pchunks.rleft()); - CU_ASSERT(20 == pchunks.rleft_buffered()); - - CU_ASSERT(20 == pchunks.remove(d.data(), d.size())); - - CU_ASSERT(std::equal(std::begin(b) + 12, std::end(b), std::begin(d))); - - CU_ASSERT(0 == pchunks.rleft()); - CU_ASSERT(0 == pchunks.rleft_buffered()); -} - -void test_peek_memchunks_disable_peek_no_drain(void) { - MemchunkPool16 pool; - PeekMemchunks16 pchunks(&pool); - - std::array b{{ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', - '5', '6', '7', '8', '9', '0', '1', }}, - d; - - pchunks.append(b.data(), b.size()); - - CU_ASSERT(12 == pchunks.remove(d.data(), 12)); - - pchunks.disable_peek(false); - - CU_ASSERT(!pchunks.peeking); - CU_ASSERT(32 == pchunks.rleft()); - CU_ASSERT(32 == pchunks.rleft_buffered()); - - CU_ASSERT(32 == pchunks.remove(d.data(), d.size())); - - CU_ASSERT(std::equal(std::begin(b), std::end(b), std::begin(d))); - - CU_ASSERT(0 == pchunks.rleft()); - CU_ASSERT(0 == pchunks.rleft_buffered()); -} - -void test_peek_memchunks_reset(void) { - MemchunkPool16 pool; - PeekMemchunks16 pchunks(&pool); - - std::array b{{ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', - '5', '6', '7', '8', '9', '0', '1', }}, - d; - - pchunks.append(b.data(), b.size()); - - CU_ASSERT(12 == pchunks.remove(d.data(), 12)); - - pchunks.disable_peek(true); - pchunks.reset(); - - CU_ASSERT(0 == pchunks.rleft()); - CU_ASSERT(0 == pchunks.rleft_buffered()); - - CU_ASSERT(nullptr == pchunks.cur); - CU_ASSERT(nullptr == pchunks.cur_pos); - CU_ASSERT(nullptr == pchunks.cur_last); - CU_ASSERT(pchunks.peeking); -} - -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/memchunk_test.h nghttp2-0.6.7/src/memchunk_test.h --- nghttp2-1.13.0/src/memchunk_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/memchunk_test.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 MEMCHUNK_TEST_H -#define MEMCHUNK_TEST_H - -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - -namespace nghttp2 { - -void test_pool_recycle(void); -void test_memchunks_append(void); -void test_memchunks_drain(void); -void test_memchunks_riovec(void); -void test_memchunks_recycle(void); -void test_memchunks_reset(void); -void test_peek_memchunks_append(void); -void test_peek_memchunks_disable_peek_drain(void); -void test_peek_memchunks_disable_peek_no_drain(void); -void test_peek_memchunks_reset(void); - -} // namespace nghttp2 - -#endif // MEMCHUNK_TEST_H diff -Nru nghttp2-1.13.0/src/network.h nghttp2-0.6.7/src/network.h --- nghttp2-1.13.0/src/network.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/network.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 NETWORK_H -#define NETWORK_H - -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif // HAVE_SYS_SOCKET_H -#include -#ifdef HAVE_NETINET_IN_H -#include -#endif // HAVE_NETINET_IN_H -#ifdef HAVE_ARPA_INET_H -#include -#endif // HAVE_ARPA_INET_H - -namespace nghttp2 { - -union sockaddr_union { - sockaddr_storage storage; - sockaddr sa; - sockaddr_in6 in6; - sockaddr_in in; - sockaddr_un un; -}; - -struct Address { - size_t len; - union sockaddr_union su; -}; - -} // namespace nghttp2 - -#endif // NETWORK_H diff -Nru nghttp2-1.13.0/src/nghttp2_config.h nghttp2-0.6.7/src/nghttp2_config.h --- nghttp2-1.13.0/src/nghttp2_config.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/nghttp2_config.h 2014-11-30 14:15:07.000000000 +0000 @@ -29,4 +29,10 @@ #include #endif // HAVE_CONFIG_H +// gcc 4.6 has std::chrono::monotonic_clock, which was renamed as +// std::chrono::steady_clock in C++11 standard. +#ifndef HAVE_STEADY_CLOCK +#define steady_clock monotonic_clock +#endif // !HAVE_STEADY_CLOCK + #endif // NGHTTP2_CONFIG_H diff -Nru nghttp2-1.13.0/src/nghttp2_gzip_test.c nghttp2-0.6.7/src/nghttp2_gzip_test.c --- nghttp2-1.13.0/src/nghttp2_gzip_test.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/nghttp2_gzip_test.c 2014-11-30 14:15:07.000000000 +0000 @@ -33,8 +33,8 @@ #include "nghttp2_gzip.h" -static size_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in, - size_t inlen) { +static ssize_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in, + size_t inlen) { int rv; z_stream zst; zst.next_in = Z_NULL; diff -Nru nghttp2-1.13.0/src/nghttp2_gzip_test.h nghttp2-0.6.7/src/nghttp2_gzip_test.h --- nghttp2-1.13.0/src/nghttp2_gzip_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/nghttp2_gzip_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,10 +25,6 @@ #ifndef NGHTTP2_GZIP_TEST_H #define NGHTTP2_GZIP_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - #ifdef __cplusplus extern "C" { #endif diff -Nru nghttp2-1.13.0/src/nghttp.cc nghttp2-0.6.7/src/nghttp.cc --- nghttp2-1.13.0/src/nghttp.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/nghttp.cc 2014-11-30 14:15:07.000000000 +0000 @@ -22,19 +22,17 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "nghttp.h" +#include "nghttp2_config.h" +#include #include -#ifdef HAVE_UNISTD_H +#include +#include #include -#endif // HAVE_UNISTD_H -#ifdef HAVE_FCNTL_H #include -#endif // HAVE_FCNTL_H -#ifdef HAVE_NETINET_IN_H #include -#endif // HAVE_NETINET_IN_H #include +#include #include #include @@ -42,23 +40,41 @@ #include #include #include +#include #include +#include +#include #include +#include +#include +#include #include #include +#include +#include #include +#include + +#include +#include +#include + +#include #ifdef HAVE_JANSSON #include #endif // HAVE_JANSSON +#include "http-parser/http_parser.h" + #include "app_helper.h" #include "HtmlParser.h" #include "util.h" +#include "libevent_util.h" #include "base64.h" -#include "ssl.h" -#include "template.h" +#include "http2.h" +#include "nghttp2_gzip.h" #ifndef O_BINARY #define O_BINARY (0) @@ -66,73 +82,70 @@ namespace nghttp2 { -// The anchor stream nodes when --no-dep is not used. The stream ID = -// 1 is excluded since it is used as first stream in upgrade case. We -// follows the same dependency anchor nodes as Firefox does. -struct Anchor { - int32_t stream_id; - // stream ID this anchor depends on - int32_t dep_stream_id; - // .. with this weight. +namespace { +struct Config { + Headers headers; + std::string certfile; + std::string keyfile; + std::string datafile; + std::string harfile; + nghttp2_option *http2_option; + size_t output_upper_thres; + size_t padding; + ssize_t peer_max_concurrent_streams; + ssize_t header_table_size; int32_t weight; -}; + int multiply; + // milliseconds + int timeout; + int window_bits; + int connection_window_bits; + int verbose; + bool null_out; + bool remote_name; + bool get_assets; + bool stat; + bool upgrade; + bool continuation; + bool no_content_length; + bool no_dep; + + Config() + : output_upper_thres(1024 * 1024), padding(0), + peer_max_concurrent_streams(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS), + header_table_size(-1), weight(NGHTTP2_DEFAULT_WEIGHT), multiply(1), + timeout(-1), window_bits(-1), connection_window_bits(-1), verbose(0), + null_out(false), remote_name(false), get_assets(false), stat(false), + upgrade(false), continuation(false), no_content_length(false), + no_dep(false) { + nghttp2_option_new(&http2_option); + nghttp2_option_set_peer_max_concurrent_streams(http2_option, + peer_max_concurrent_streams); + } -// This is index into anchors. Firefox uses ANCHOR_FOLLOWERS for html -// file. -enum { - ANCHOR_LEADERS, - ANCHOR_UNBLOCKED, - ANCHOR_BACKGROUND, - ANCHOR_SPECULATIVE, - ANCHOR_FOLLOWERS, + ~Config() { nghttp2_option_del(http2_option); } }; - -namespace { -constexpr auto anchors = std::array{{ - {3, 0, 201}, {5, 0, 101}, {7, 0, 1}, {9, 7, 1}, {11, 3, 1}, }}; } // namespace -Config::Config() - : header_table_size(-1), - min_header_table_size(std::numeric_limits::max()), - padding(0), - max_concurrent_streams(100), - peer_max_concurrent_streams(100), - weight(NGHTTP2_DEFAULT_WEIGHT), - multiply(1), - timeout(0.), - window_bits(-1), - connection_window_bits(-1), - verbose(0), - null_out(false), - remote_name(false), - get_assets(false), - stat(false), - upgrade(false), - continuation(false), - no_content_length(false), - no_dep(false), - hexdump(false), - no_push(false), - expect_continue(false) { - nghttp2_option_new(&http2_option); - nghttp2_option_set_peer_max_concurrent_streams(http2_option, - peer_max_concurrent_streams); - nghttp2_option_set_builtin_recv_extension_type(http2_option, NGHTTP2_ALTSVC); -} - -Config::~Config() { nghttp2_option_del(http2_option); } - namespace { Config config; } // namespace +enum StatStage { + STAT_INITIAL, + STAT_ON_REQUEST, + STAT_ON_RESPONSE, + STAT_ON_COMPLETE +}; + namespace { -void print_protocol_nego_error() { - std::cerr << "[ERROR] HTTP/2 protocol was not selected." - << " (nghttp2 expects " << NGHTTP2_PROTO_VERSION_ID << ")" - << std::endl; -} +struct RequestStat { + std::chrono::steady_clock::time_point on_request_time; + std::chrono::steady_clock::time_point on_response_time; + std::chrono::steady_clock::time_point on_complete_time; + StatStage stage; + RequestStat() : stage(STAT_INITIAL) {} +}; } // namespace namespace { @@ -145,471 +158,322 @@ } } // namespace -Request::Request(const std::string &uri, const http_parser_url &u, - const nghttp2_data_provider *data_prd, int64_t data_length, - const nghttp2_priority_spec &pri_spec, int level) - : uri(uri), - u(u), - pri_spec(pri_spec), - data_length(data_length), - data_offset(0), - response_len(0), - inflater(nullptr), - html_parser(nullptr), - data_prd(data_prd), - header_buffer_size(0), - stream_id(-1), - status(0), - level(level), - expect_final_response(false) { - http2::init_hdidx(res_hdidx); - http2::init_hdidx(req_hdidx); -} - -Request::~Request() { - nghttp2_gzip_inflate_del(inflater); - delete html_parser; -} - -void Request::init_inflater() { - int rv; - rv = nghttp2_gzip_inflate_new(&inflater); - assert(rv == 0); -} - -void Request::init_html_parser() { html_parser = new HtmlParser(uri); } - -int Request::update_html_parser(const uint8_t *data, size_t len, int fin) { - if (!html_parser) { - return 0; - } - return html_parser->parse_chunk(reinterpret_cast(data), len, - fin); -} - -std::string Request::make_reqpath() const { - std::string path = util::has_uri_field(u, UF_PATH) - ? util::get_uri_field(uri.c_str(), u, UF_PATH).str() - : "/"; - if (util::has_uri_field(u, UF_QUERY)) { - path += '?'; - path.append(uri.c_str() + u.field_data[UF_QUERY].off, - u.field_data[UF_QUERY].len); - } - return path; -} +namespace { +struct Request; +} // namespace namespace { -// Perform special handling |host| if it is IPv6 literal and includes -// zone ID per RFC 6874. -std::string decode_host(const StringRef &host) { - auto zone_start = std::find(std::begin(host), std::end(host), '%'); - if (zone_start == std::end(host) || - !util::ipv6_numeric_addr( - std::string(std::begin(host), zone_start).c_str())) { - return host.str(); - } - // case: ::1% - if (zone_start + 1 == std::end(host)) { - return StringRef{host.c_str(), host.size() - 1}.str(); - } - // case: ::1%12 or ::1%1 - if (zone_start + 3 >= std::end(host)) { - return host.str(); - } - // If we see "%25", followed by more characters, then decode %25 as - // '%'. - auto zone_id_src = (*(zone_start + 1) == '2' && *(zone_start + 2) == '5') - ? zone_start + 3 - : zone_start + 1; - auto zone_id = util::percent_decode(zone_id_src, std::end(host)); - auto res = std::string(std::begin(host), zone_start + 1); - res += zone_id; - return res; -} +struct Dependency { + std::vector> deps; +}; } // namespace namespace { -nghttp2_priority_spec resolve_dep(int res_type) { +struct Request { + Headers res_nva; + Headers req_nva; + // URI without fragment + std::string uri; + http_parser_url u; + std::shared_ptr dep; nghttp2_priority_spec pri_spec; - - if (config.no_dep) { - nghttp2_priority_spec_default_init(&pri_spec); - - return pri_spec; - } - - int32_t anchor_id; - int32_t weight; - switch (res_type) { - case REQ_CSS: - case REQ_JS: - anchor_id = anchors[ANCHOR_LEADERS].stream_id; - weight = 2; - break; - case REQ_UNBLOCK_JS: - anchor_id = anchors[ANCHOR_UNBLOCKED].stream_id; - weight = 2; - break; - case REQ_IMG: - anchor_id = anchors[ANCHOR_FOLLOWERS].stream_id; - weight = 12; - break; - default: - anchor_id = anchors[ANCHOR_FOLLOWERS].stream_id; - weight = 2; + RequestStat stat; + int64_t data_length; + int64_t data_offset; + // Number of bytes received from server + int64_t response_len; + nghttp2_gzip *inflater; + HtmlParser *html_parser; + const nghttp2_data_provider *data_prd; + int32_t stream_id; + int status; + // Recursion level: 0: first entity, 1: entity linked from first entity + int level; + // RequestPriority value defined in HtmlParser.h + int pri; + bool expect_final_response; + + // For pushed request, |uri| is empty and |u| is zero-cleared. + Request(const std::string &uri, const http_parser_url &u, + const nghttp2_data_provider *data_prd, int64_t data_length, + const nghttp2_priority_spec &pri_spec, + std::shared_ptr dep, int pri = 0, int level = 0) + : uri(uri), u(u), dep(std::move(dep)), pri_spec(pri_spec), + data_length(data_length), data_offset(0), response_len(0), + inflater(nullptr), html_parser(nullptr), data_prd(data_prd), + stream_id(-1), status(0), level(level), pri(pri), + expect_final_response(false) {} + + ~Request() { + nghttp2_gzip_inflate_del(inflater); + delete html_parser; + } + + void init_inflater() { + int rv; + rv = nghttp2_gzip_inflate_new(&inflater); + assert(rv == 0); } - nghttp2_priority_spec_init(&pri_spec, anchor_id, weight, 0); - return pri_spec; -} -} // namespace - -bool Request::is_ipv6_literal_addr() const { - if (util::has_uri_field(u, UF_HOST)) { - return memchr(uri.c_str() + u.field_data[UF_HOST].off, ':', - u.field_data[UF_HOST].len); - } else { - return false; - } -} + void init_html_parser() { html_parser = new HtmlParser(uri); } -Headers::value_type *Request::get_res_header(int32_t token) { - auto idx = res_hdidx[token]; - if (idx == -1) { - return nullptr; + int update_html_parser(const uint8_t *data, size_t len, int fin) { + if (!html_parser) { + return 0; + } + int rv; + rv = html_parser->parse_chunk(reinterpret_cast(data), len, + fin); + return rv; } - return &res_nva[idx]; -} -Headers::value_type *Request::get_req_header(int32_t token) { - auto idx = req_hdidx[token]; - if (idx == -1) { - return nullptr; + std::string make_reqpath() const { + std::string path = util::has_uri_field(u, UF_PATH) + ? util::get_uri_field(uri.c_str(), u, UF_PATH) + : "/"; + if (util::has_uri_field(u, UF_QUERY)) { + path += "?"; + path.append(uri.c_str() + u.field_data[UF_QUERY].off, + u.field_data[UF_QUERY].len); + } + return path; + } + + int32_t find_dep_stream_id(int start) { + for (auto i = start; i >= 0; --i) { + for (auto req : dep->deps[i]) { + return req->stream_id; + } + } + return -1; } - return &req_nva[idx]; -} - -void Request::record_request_start_time() { - timing.state = RequestState::ON_REQUEST; - timing.request_start_time = get_time(); -} -void Request::record_response_start_time() { - timing.state = RequestState::ON_RESPONSE; - timing.response_start_time = get_time(); -} + nghttp2_priority_spec resolve_dep(int32_t pri) { + nghttp2_priority_spec pri_spec; + int exclusive = 0; + int32_t stream_id = -1; -void Request::record_response_end_time() { - timing.state = RequestState::ON_COMPLETE; - timing.response_end_time = get_time(); -} + nghttp2_priority_spec_default_init(&pri_spec); -namespace { -void continue_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto client = static_cast(ev_userdata(loop)); - auto req = static_cast(w->data); - int error; + if (config.no_dep || pri == 0) { + return pri_spec; + } - error = nghttp2_submit_data(client->session, NGHTTP2_FLAG_END_STREAM, - req->stream_id, req->data_prd); + nghttp2_priority_spec_default_init(&pri_spec); - if (error) { - std::cerr << "[ERROR] nghttp2_submit_data() returned error: " - << nghttp2_strerror(error) << std::endl; - nghttp2_submit_rst_stream(client->session, NGHTTP2_FLAG_NONE, - req->stream_id, NGHTTP2_INTERNAL_ERROR); - } + auto start = std::min(pri, (int)dep->deps.size() - 1); - client->signal_write(); -} -} // namespace + for (auto i = start; i >= 0; --i) { + if (dep->deps[i][0]->pri < pri) { + stream_id = find_dep_stream_id(i); -ContinueTimer::ContinueTimer(struct ev_loop *loop, Request *req) : loop(loop) { - ev_timer_init(&timer, continue_timeout_cb, 1., 0.); - timer.data = req; -} + if (i != (int)dep->deps.size() - 1) { + exclusive = 1; + } -ContinueTimer::~ContinueTimer() { stop(); } + break; + } else if (dep->deps[i][0]->pri == pri) { + stream_id = find_dep_stream_id(i - 1); -void ContinueTimer::start() { ev_timer_start(loop, &timer); } + break; + } + } -void ContinueTimer::stop() { ev_timer_stop(loop, &timer); } + if (stream_id == -1) { + return pri_spec; + } -void ContinueTimer::dispatch_continue() { - // Only dispatch the timeout callback if it hasn't already been called. - if (ev_is_active(&timer)) { - ev_feed_event(loop, &timer, 0); - } -} + nghttp2_priority_spec_init(&pri_spec, stream_id, NGHTTP2_DEFAULT_WEIGHT, + exclusive); -namespace { -int htp_msg_begincb(http_parser *htp) { - if (config.verbose) { - print_timer(); - std::cout << " HTTP Upgrade response" << std::endl; + return pri_spec; } - return 0; -} -} // namespace - -namespace { -int htp_statuscb(http_parser *htp, const char *at, size_t length) { - auto client = static_cast(htp->data); - client->upgrade_response_status_code = htp->status_code; - return 0; -} -} // namespace - -namespace { -int htp_msg_completecb(http_parser *htp) { - auto client = static_cast(htp->data); - client->upgrade_response_complete = true; - return 0; -} -} // namespace -namespace { -http_parser_settings htp_hooks = { - htp_msg_begincb, // http_cb on_message_begin; - nullptr, // http_data_cb on_url; - htp_statuscb, // http_data_cb on_status; - nullptr, // http_data_cb on_header_field; - nullptr, // http_data_cb on_header_value; - nullptr, // http_cb on_headers_complete; - nullptr, // http_data_cb on_body; - htp_msg_completecb // http_cb on_message_complete; -}; -} // namespace - -namespace { -int submit_request(HttpClient *client, const Headers &headers, Request *req) { - auto path = req->make_reqpath(); - auto scheme = util::get_uri_field(req->uri.c_str(), req->u, UF_SCHEMA); - auto build_headers = Headers{{":method", req->data_prd ? "POST" : "GET"}, - {":path", path}, - {":scheme", scheme.str()}, - {":authority", client->hostport}, - {"accept", "*/*"}, - {"accept-encoding", "gzip, deflate"}, - {"user-agent", "nghttp2/" NGHTTP2_VERSION}}; - bool expect_continue = false; - - if (config.continuation) { - for (size_t i = 0; i < 6; ++i) { - build_headers.emplace_back("continuation-test-" + util::utos(i + 1), - std::string(4_k, '-')); + bool is_ipv6_literal_addr() const { + if (util::has_uri_field(u, UF_HOST)) { + return memchr(uri.c_str() + u.field_data[UF_HOST].off, ':', + u.field_data[UF_HOST].len); + } else { + return false; } } - auto num_initial_headers = build_headers.size(); - - if (req->data_prd) { - if (!config.no_content_length) { - build_headers.emplace_back("content-length", - util::utos(req->data_length)); - } - if (config.expect_continue) { - expect_continue = true; - build_headers.emplace_back("expect", "100-continue"); - } + bool response_pseudo_header_allowed() const { + return res_nva.empty() || res_nva.back().name.c_str()[0] == ':'; } - for (auto &kv : headers) { - size_t i; - for (i = 0; i < num_initial_headers; ++i) { - if (kv.name == build_headers[i].name) { - build_headers[i].value = kv.value; - break; - } - } - if (i < num_initial_headers) { - continue; - } - - build_headers.emplace_back(kv.name, kv.value, kv.no_index); + bool push_request_pseudo_header_allowed() const { + return res_nva.empty() || req_nva.back().name.c_str()[0] == ':'; } - auto nva = std::vector(); - nva.reserve(build_headers.size()); - - for (auto &kv : build_headers) { - nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); + void record_request_time() { + stat.stage = STAT_ON_REQUEST; + stat.on_request_time = get_time(); } - auto method = http2::get_header(build_headers, ":method"); - assert(method); - - req->method = method->value; - - std::string trailer_names; - if (!config.trailer.empty()) { - trailer_names = config.trailer[0].name; - for (size_t i = 1; i < config.trailer.size(); ++i) { - trailer_names += ", "; - trailer_names += config.trailer[i].name; - } - nva.push_back(http2::make_nv_ls("trailer", trailer_names)); + void record_response_time() { + stat.stage = STAT_ON_RESPONSE; + stat.on_response_time = get_time(); } - int32_t stream_id; - - if (expect_continue) { - stream_id = nghttp2_submit_headers(client->session, 0, -1, &req->pri_spec, - nva.data(), nva.size(), req); - } else { - stream_id = - nghttp2_submit_request(client->session, &req->pri_spec, nva.data(), - nva.size(), req->data_prd, req); + void record_complete_time() { + stat.stage = STAT_ON_COMPLETE; + stat.on_complete_time = get_time(); } +}; +} // namespace - if (stream_id < 0) { - std::cerr << "[ERROR] nghttp2_submit_" - << (expect_continue ? "headers" : "request") - << "() returned error: " << nghttp2_strerror(stream_id) - << std::endl; - return -1; - } +namespace { +struct SessionStat { + // The point in time when download was started. + std::chrono::system_clock::time_point started_system_time; + // The point of time when download was started. + std::chrono::steady_clock::time_point on_started_time; + // The point of time when DNS resolution was completed. + std::chrono::steady_clock::time_point on_dns_complete_time; + // The point of time when connection was established or SSL/TLS + // handshake was completed. + std::chrono::steady_clock::time_point on_connect_time; + // The point of time when HTTP/2 commnucation was started. + std::chrono::steady_clock::time_point on_handshake_time; +}; +} // namespace - req->stream_id = stream_id; - client->request_done(req); +namespace { +size_t populate_settings(nghttp2_settings_entry *iv) { + size_t niv = 2; - req->req_nva = std::move(build_headers); + iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; + iv[0].value = 100; - if (expect_continue) { - auto timer = make_unique(client->loop, req); - req->continue_timer = std::move(timer); + iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; + if (config.window_bits != -1) { + iv[1].value = (1 << config.window_bits) - 1; + } else { + iv[1].value = NGHTTP2_INITIAL_WINDOW_SIZE; } - return 0; + if (config.header_table_size >= 0) { + iv[niv].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; + iv[niv].value = config.header_table_size; + ++niv; + } + return niv; } } // namespace namespace { -void readcb(struct ev_loop *loop, ev_io *w, int revents) { - auto client = static_cast(w->data); - if (client->do_read() != 0) { - client->disconnect(); - } -} +void eventcb(bufferevent *bev, short events, void *ptr); } // namespace namespace { -void writecb(struct ev_loop *loop, ev_io *w, int revents) { - auto client = static_cast(w->data); - auto rv = client->do_write(); - if (rv == HttpClient::ERR_CONNECT_FAIL) { - client->connect_fail(); - return; - } - if (rv != 0) { - client->disconnect(); - } -} +extern http_parser_settings htp_hooks; } // namespace namespace { -void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - auto client = static_cast(w->data); - std::cerr << "[ERROR] Timeout" << std::endl; - client->disconnect(); -} +void upgrade_readcb(bufferevent *bev, void *ptr); } // namespace namespace { -void settings_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto client = static_cast(w->data); - ev_timer_stop(loop, w); - - nghttp2_session_terminate_session(client->session, NGHTTP2_SETTINGS_TIMEOUT); - - client->signal_write(); -} +void readcb(bufferevent *bev, void *ptr); } // namespace -HttpClient::HttpClient(const nghttp2_session_callbacks *callbacks, - struct ev_loop *loop, SSL_CTX *ssl_ctx) - : wb(&mcpool), - session(nullptr), - callbacks(callbacks), - loop(loop), - ssl_ctx(ssl_ctx), - ssl(nullptr), - addrs(nullptr), - next_addr(nullptr), - cur_addr(nullptr), - complete(0), - success(0), - settings_payloadlen(0), - state(ClientState::IDLE), - upgrade_response_status_code(0), - fd(-1), - upgrade_response_complete(false) { - ev_io_init(&wev, writecb, 0, EV_WRITE); - ev_io_init(&rev, readcb, 0, EV_READ); - - wev.data = this; - rev.data = this; - - ev_timer_init(&wt, timeoutcb, 0., config.timeout); - ev_timer_init(&rt, timeoutcb, 0., config.timeout); +namespace { +void writecb(bufferevent *bev, void *ptr); +} // namespace - wt.data = this; - rt.data = this; +namespace { +struct HttpClient; +} // namespace - ev_timer_init(&settings_timer, settings_timeout_cb, 0., 10.); +namespace { +int submit_request(HttpClient *client, const Headers &headers, Request *req); +} // namespace - settings_timer.data = this; -} +namespace { +void settings_timeout_cb(evutil_socket_t fd, short what, void *arg); +} // namespace -HttpClient::~HttpClient() { - disconnect(); +enum client_state { STATE_IDLE, STATE_CONNECTED }; - if (addrs) { - freeaddrinfo(addrs); - addrs = nullptr; - next_addr = nullptr; - } -} +namespace { +struct HttpClient { + std::vector> reqvec; + // Insert path already added in reqvec to prevent multiple request + // for 1 resource. + std::set path_cache; + std::string scheme; + std::string host; + std::string hostport; + // Used for parse the HTTP upgrade response from server + std::unique_ptr htp; + SessionStat stat; + nghttp2_session *session; + const nghttp2_session_callbacks *callbacks; + event_base *evbase; + SSL_CTX *ssl_ctx; + SSL *ssl; + bufferevent *bev; + event *settings_timerev; + addrinfo *addrs; + addrinfo *next_addr; + // The number of completed requests, including failed ones. + size_t complete; + // The length of settings_payload + size_t settings_payloadlen; + client_state state; + // The HTTP status code of the response message of HTTP Upgrade. + unsigned int upgrade_response_status_code; + // true if the response message of HTTP Upgrade request is fully + // received. It is not relevant the upgrade succeeds, or not. + bool upgrade_response_complete; + // SETTINGS payload sent as token68 in HTTP Upgrade + uint8_t settings_payload[128]; -bool HttpClient::need_upgrade() const { - return config.upgrade && scheme == "http"; -} + HttpClient(const nghttp2_session_callbacks *callbacks, event_base *evbase, + SSL_CTX *ssl_ctx) + : session(nullptr), callbacks(callbacks), evbase(evbase), + ssl_ctx(ssl_ctx), ssl(nullptr), bev(nullptr), settings_timerev(nullptr), + addrs(nullptr), next_addr(nullptr), complete(0), settings_payloadlen(0), + state(STATE_IDLE), upgrade_response_status_code(0), + upgrade_response_complete(false) {} -int HttpClient::resolve_host(const std::string &host, uint16_t port) { - int rv; - this->host = host; - addrinfo hints{}; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - hints.ai_flags = AI_ADDRCONFIG; - rv = getaddrinfo(host.c_str(), util::utos(port).c_str(), &hints, &addrs); - if (rv != 0) { - std::cerr << "[ERROR] getaddrinfo() failed: " << gai_strerror(rv) - << std::endl; - return -1; - } - if (addrs == nullptr) { - std::cerr << "[ERROR] No address returned" << std::endl; - return -1; + ~HttpClient() { + disconnect(); + if (addrs) { + freeaddrinfo(addrs); + addrs = nullptr; + next_addr = nullptr; + } } - next_addr = addrs; - return 0; -} -int HttpClient::initiate_connection() { - int rv; + bool need_upgrade() const { return config.upgrade && scheme == "http"; } - cur_addr = nullptr; - while (next_addr) { - cur_addr = next_addr; - next_addr = next_addr->ai_next; - fd = util::create_nonblock_socket(cur_addr->ai_family); - if (fd == -1) { - continue; + int resolve_host(const std::string &host, uint16_t port) { + int rv; + addrinfo hints; + this->host = host; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + hints.ai_flags = AI_ADDRCONFIG; + rv = getaddrinfo(host.c_str(), util::utos(port).c_str(), &hints, &addrs); + if (rv != 0) { + std::cerr << "[ERROR] getaddrinfo() failed: " << gai_strerror(rv) + << std::endl; + return -1; + } + if (addrs == nullptr) { + std::cerr << "[ERROR] No address returned" << std::endl; + return -1; } + next_addr = addrs; + return 0; + } + int initiate_connection() { + int rv = 0; if (ssl_ctx) { // We are establishing TLS connection. ssl = SSL_new(ssl_ctx); @@ -619,17 +483,12 @@ return -1; } - SSL_set_fd(ssl, fd); - SSL_set_connect_state(ssl); - - // If the user overrode the :authority or host header, use that - // value for the SNI extension + // If the user overrode the host header, use that value for the + // SNI extension const char *host_string = nullptr; auto i = std::find_if(std::begin(config.headers), std::end(config.headers), - [](const Header &nv) { - return ":authority" == nv.name || "host" == nv.name; - }); + [](const Header &nv) { return "host" == nv.name; }); if (i != std::end(config.headers)) { host_string = (*i).value.c_str(); } else { @@ -639,942 +498,691 @@ if (!util::numeric_host(host_string)) { SSL_set_tlsext_host_name(ssl, host_string); } - } - - rv = connect(fd, cur_addr->ai_addr, cur_addr->ai_addrlen); - - if (rv != 0 && errno != EINPROGRESS) { - if (ssl) { - SSL_free(ssl); - ssl = nullptr; - } - close(fd); - fd = -1; - continue; - } - break; - } - - if (fd == -1) { - return -1; - } - - writefn = &HttpClient::connected; - - if (need_upgrade()) { - on_readfn = &HttpClient::on_upgrade_read; - on_writefn = &HttpClient::on_upgrade_connect; - } else { - on_readfn = &HttpClient::on_read; - on_writefn = &HttpClient::on_write; - } - - ev_io_set(&rev, fd, EV_READ); - ev_io_set(&wev, fd, EV_WRITE); - - ev_io_start(loop, &wev); - ev_timer_again(loop, &wt); - - return 0; -} - -void HttpClient::disconnect() { - state = ClientState::IDLE; - - for (auto req = std::begin(reqvec); req != std::end(reqvec); ++req) { - if ((*req)->continue_timer) { - (*req)->continue_timer->stop(); + bev = bufferevent_openssl_socket_new( + evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS); + } else { + bev = bufferevent_socket_new(evbase, -1, BEV_OPT_DEFER_CALLBACKS); } - } - - ev_timer_stop(loop, &settings_timer); - - ev_timer_stop(loop, &rt); - ev_timer_stop(loop, &wt); - - ev_io_stop(loop, &rev); - ev_io_stop(loop, &wev); - - nghttp2_session_del(session); - session = nullptr; - - if (ssl) { - SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); - ERR_clear_error(); - SSL_shutdown(ssl); - SSL_free(ssl); - ssl = nullptr; - } - - if (fd != -1) { - shutdown(fd, SHUT_WR); - close(fd); - fd = -1; - } -} - -int HttpClient::read_clear() { - ev_timer_again(loop, &rt); - - std::array buf; - - for (;;) { - ssize_t nread; - while ((nread = read(fd, buf.data(), buf.size())) == -1 && errno == EINTR) - ; - if (nread == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - return 0; + rv = -1; + while (next_addr) { + rv = bufferevent_socket_connect(bev, next_addr->ai_addr, + next_addr->ai_addrlen); + next_addr = next_addr->ai_next; + if (rv == 0) { + break; } - return -1; } - - if (nread == 0) { - return -1; - } - - if (on_readfn(*this, buf.data(), nread) != 0) { - return -1; - } - } - - return 0; -} - -int HttpClient::write_clear() { - ev_timer_again(loop, &rt); - - std::array iov; - - for (;;) { - if (on_writefn(*this) != 0) { + if (rv != 0) { return -1; } - - auto iovcnt = wb.riovec(iov.data(), iov.size()); - - if (iovcnt == 0) { - break; + bufferevent_enable(bev, EV_READ); + if (need_upgrade()) { + htp = util::make_unique(); + http_parser_init(htp.get(), HTTP_RESPONSE); + htp->data = this; + bufferevent_setcb(bev, upgrade_readcb, nullptr, eventcb, this); + } else { + bufferevent_setcb(bev, readcb, writecb, eventcb, this); } - - ssize_t nwrite; - while ((nwrite = writev(fd, iov.data(), iovcnt)) == -1 && errno == EINTR) - ; - if (nwrite == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - ev_io_start(loop, &wev); - ev_timer_again(loop, &wt); - return 0; - } - return -1; + if (config.timeout != -1) { + timeval tv = {config.timeout, 0}; + bufferevent_set_timeouts(bev, &tv, &tv); } - - wb.drain(nwrite); + return 0; } - ev_io_stop(loop, &wev); - ev_timer_stop(loop, &wt); - - return 0; -} - -int HttpClient::noop() { return 0; } - -void HttpClient::connect_fail() { - if (state == ClientState::IDLE) { - std::cerr << "[ERROR] Could not connect to the address " - << util::numeric_name(cur_addr->ai_addr, cur_addr->ai_addrlen) - << std::endl; - } - auto cur_state = state; - disconnect(); - if (cur_state == ClientState::IDLE) { - if (initiate_connection() == 0) { - std::cerr << "Trying next address " - << util::numeric_name(cur_addr->ai_addr, cur_addr->ai_addrlen) - << std::endl; + void disconnect() { + int fd = -1; + state = STATE_IDLE; + nghttp2_session_del(session); + session = nullptr; + if (ssl) { + fd = SSL_get_fd(ssl); + SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); + SSL_shutdown(ssl); + } + if (bev) { + bufferevent_disable(bev, EV_READ | EV_WRITE); + bufferevent_free(bev); + bev = nullptr; + } + if (settings_timerev) { + event_free(settings_timerev); + settings_timerev = nullptr; + } + if (ssl) { + SSL_free(ssl); + ssl = nullptr; } - } -} - -int HttpClient::connected() { - if (!util::check_socket_connected(fd)) { - return ERR_CONNECT_FAIL; - } - - if (config.verbose) { - print_timer(); - std::cout << " Connected" << std::endl; - } - - state = ClientState::CONNECTED; - - ev_io_start(loop, &rev); - ev_io_stop(loop, &wev); - - ev_timer_again(loop, &rt); - ev_timer_stop(loop, &wt); - - if (ssl) { - readfn = &HttpClient::tls_handshake; - writefn = &HttpClient::tls_handshake; - - return do_write(); - } - - readfn = &HttpClient::read_clear; - writefn = &HttpClient::write_clear; - - if (need_upgrade()) { - htp = make_unique(); - http_parser_init(htp.get(), HTTP_RESPONSE); - htp->data = this; - - return do_write(); - } - - if (connection_made() != 0) { - return -1; - } - - return 0; -} - -namespace { -size_t populate_settings(nghttp2_settings_entry *iv) { - size_t niv = 2; - - iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; - iv[0].value = config.max_concurrent_streams; - - iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; - if (config.window_bits != -1) { - iv[1].value = (1 << config.window_bits) - 1; - } else { - iv[1].value = NGHTTP2_INITIAL_WINDOW_SIZE; - } - - if (config.header_table_size >= 0) { - if (config.min_header_table_size < config.header_table_size) { - iv[niv].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; - iv[niv].value = config.min_header_table_size; - ++niv; + if (fd != -1) { + shutdown(fd, SHUT_WR); + close(fd); } - - iv[niv].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; - iv[niv].value = config.header_table_size; - ++niv; } - if (config.no_push) { - iv[niv].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; - iv[niv].value = 0; - ++niv; - } - - return niv; -} -} // namespace - -int HttpClient::on_upgrade_connect() { - ssize_t rv; - record_connect_end_time(); - assert(!reqvec.empty()); - std::array iv; - size_t niv = populate_settings(iv.data()); - assert(settings_payload.size() >= 8 * niv); - rv = nghttp2_pack_settings_payload(settings_payload.data(), - settings_payload.size(), iv.data(), niv); - if (rv < 0) { - return -1; - } - settings_payloadlen = rv; - auto token68 = - base64::encode(std::begin(settings_payload), - std::begin(settings_payload) + settings_payloadlen); - util::to_token68(token68); - - std::string req; - if (reqvec[0]->data_prd) { - // If the request contains upload data, use OPTIONS * to upgrade - req = "OPTIONS *"; - } else { - auto meth = std::find_if( - std::begin(config.headers), std::end(config.headers), - [](const Header &kv) { return util::streq_l(":method", kv.name); }); - - if (meth == std::end(config.headers)) { - req = "GET "; - reqvec[0]->method = "GET"; - } else { - req = (*meth).value; - req += ' '; - reqvec[0]->method = (*meth).value; - } - req += reqvec[0]->make_reqpath(); - } - - auto headers = Headers{{"host", hostport}, - {"connection", "Upgrade, HTTP2-Settings"}, - {"upgrade", NGHTTP2_CLEARTEXT_PROTO_VERSION_ID}, - {"http2-settings", token68}, - {"accept", "*/*"}, - {"user-agent", "nghttp2/" NGHTTP2_VERSION}}; - auto initial_headerslen = headers.size(); - - for (auto &kv : config.headers) { - size_t i; - if (kv.name.empty() || kv.name[0] == ':') { - continue; + int on_upgrade_connect() { + ssize_t rv; + record_handshake_time(); + assert(!reqvec.empty()); + nghttp2_settings_entry iv[32]; + size_t niv = populate_settings(iv); + assert(sizeof(settings_payload) >= 8 * niv); + rv = nghttp2_pack_settings_payload(settings_payload, + sizeof(settings_payload), iv, niv); + if (rv < 0) { + return -1; } - for (i = 0; i < initial_headerslen; ++i) { - if (kv.name == headers[i].name) { - headers[i].value = kv.value; - break; - } + settings_payloadlen = rv; + auto token68 = base64::encode(&settings_payload[0], + &settings_payload[settings_payloadlen]); + util::to_token68(token68); + std::string req; + if (reqvec[0]->data_prd) { + // If the request contains upload data, use OPTIONS * to upgrade + req = "OPTIONS *"; + } else { + req = "GET "; + req += reqvec[0]->make_reqpath(); } - if (i < initial_headerslen) { - continue; + req += " HTTP/1.1\r\n" + "Host: "; + req += hostport; + req += "\r\n" + "Connection: Upgrade, HTTP2-Settings\r\n" + "Upgrade: " NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "\r\n" + "HTTP2-Settings: "; + req += token68; + req += "\r\n" + "Accept: */*\r\n" + "User-Agent: nghttp2/" NGHTTP2_VERSION "\r\n" + "\r\n"; + bufferevent_write(bev, req.c_str(), req.size()); + if (config.verbose) { + print_timer(); + std::cout << " HTTP Upgrade request\n" << req << std::endl; } - headers.emplace_back(kv.name, kv.value, kv.no_index); - } - - req += " HTTP/1.1\r\n"; - - for (auto &kv : headers) { - req += kv.name; - req += ": "; - req += kv.value; - req += "\r\n"; - } - req += "\r\n"; - - wb.append(req); - - if (config.verbose) { - print_timer(); - std::cout << " HTTP Upgrade request\n" << req << std::endl; + return 0; } - if (!reqvec[0]->data_prd) { - // record request time if this is a part of real request. - reqvec[0]->record_request_start_time(); - reqvec[0]->req_nva = std::move(headers); - } + int on_upgrade_read() { + int rv; + auto input = bufferevent_get_input(bev); - on_writefn = &HttpClient::noop; + for (;;) { + auto inputlen = evbuffer_get_contiguous_space(input); - signal_write(); + if (inputlen == 0) { + assert(evbuffer_get_length(input) == 0); - return 0; -} - -int HttpClient::on_upgrade_read(const uint8_t *data, size_t len) { - int rv; + return 0; + } - auto nread = http_parser_execute(htp.get(), &htp_hooks, - reinterpret_cast(data), len); + auto mem = evbuffer_pullup(input, inputlen); - if (config.verbose) { - std::cout.write(reinterpret_cast(data), nread); - } + auto nread = http_parser_execute( + htp.get(), &htp_hooks, reinterpret_cast(mem), inputlen); - auto htperr = HTTP_PARSER_ERRNO(htp.get()); + if (config.verbose) { + std::cout.write(reinterpret_cast(mem), nread); + } - if (htperr != HPE_OK) { - std::cerr << "[ERROR] Failed to parse HTTP Upgrade response header: " - << "(" << http_errno_name(htperr) << ") " - << http_errno_description(htperr) << std::endl; - return -1; - } + if (evbuffer_drain(input, nread) != 0) { + return -1; + } - if (!upgrade_response_complete) { - return 0; - } + auto htperr = HTTP_PARSER_ERRNO(htp.get()); - if (config.verbose) { - std::cout << std::endl; - } + if (htperr != HPE_OK) { + std::cerr << "[ERROR] Failed to parse HTTP Upgrade response header: " + << "(" << http_errno_name(htperr) << ") " + << http_errno_description(htperr) << std::endl; + return -1; + } - if (upgrade_response_status_code != 101) { - std::cerr << "[ERROR] HTTP Upgrade failed" << std::endl; + if (upgrade_response_complete) { - return -1; - } + if (config.verbose) { + std::cout << std::endl; + } - if (config.verbose) { - print_timer(); - std::cout << " HTTP Upgrade success" << std::endl; - } + if (upgrade_response_status_code == 101) { + if (config.verbose) { + print_timer(); + std::cout << " HTTP Upgrade success" << std::endl; + } - on_readfn = &HttpClient::on_read; - on_writefn = &HttpClient::on_write; + bufferevent_setcb(bev, readcb, writecb, eventcb, this); - rv = connection_made(); - if (rv != 0) { - return rv; - } + rv = on_connect(); - // Read remaining data in the buffer because it is not notified - // callback anymore. - rv = on_readfn(*this, data + nread, len - nread); - if (rv != 0) { - return rv; - } + if (rv != 0) { + return rv; + } - return 0; -} + // Read remaining data in the buffer because it is not + // notified callback anymore. + rv = on_read(); -int HttpClient::do_read() { return readfn(*this); } -int HttpClient::do_write() { return writefn(*this); } + if (rv != 0) { + return rv; + } -int HttpClient::connection_made() { - int rv; + return 0; + } - if (!need_upgrade()) { - record_connect_end_time(); - } + std::cerr << "[ERROR] HTTP Upgrade failed" << std::endl; - if (ssl) { - // Check NPN or ALPN result - const unsigned char *next_proto = nullptr; - unsigned int next_proto_len; - SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len); - for (int i = 0; i < 2; ++i) { - if (next_proto) { - auto proto = StringRef{next_proto, next_proto_len}; - if (config.verbose) { - std::cout << "The negotiated protocol: " << proto << std::endl; - } - if (!util::check_h2_is_selected(proto)) { - next_proto = nullptr; - } - break; + return -1; } -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len); -#else // OPENSSL_VERSION_NUMBER < 0x10002000L - break; -#endif // OPENSSL_VERSION_NUMBER < 0x10002000L - } - if (!next_proto) { - print_protocol_nego_error(); - return -1; } } - rv = nghttp2_session_client_new2(&session, callbacks, this, - config.http2_option); - - if (rv != 0) { - return -1; - } - if (need_upgrade()) { - // Adjust stream user-data depending on the existence of upload - // data - Request *stream_user_data = nullptr; - if (!reqvec[0]->data_prd) { - stream_user_data = reqvec[0].get(); - } - // If HEAD is used, that is only when user specified it with -H - // option. - auto head_request = stream_user_data && stream_user_data->method == "HEAD"; - rv = nghttp2_session_upgrade2(session, settings_payload.data(), - settings_payloadlen, head_request, - stream_user_data); - if (rv != 0) { - std::cerr << "[ERROR] nghttp2_session_upgrade() returned error: " - << nghttp2_strerror(rv) << std::endl; - return -1; - } - if (stream_user_data) { - stream_user_data->stream_id = 1; - request_done(stream_user_data); - } - } - // If upgrade succeeds, the SETTINGS value sent with - // HTTP2-Settings header field has already been submitted to - // session object. - if (!need_upgrade()) { - std::array iv; - auto niv = populate_settings(iv.data()); - rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv.data(), niv); - if (rv != 0) { - return -1; + int on_connect() { + int rv; + if (!need_upgrade()) { + record_handshake_time(); } - } - if (!config.no_dep) { - // Create anchor stream nodes - nghttp2_priority_spec pri_spec; - for (auto &anchor : anchors) { - nghttp2_priority_spec_init(&pri_spec, anchor.dep_stream_id, anchor.weight, - 0); - rv = nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, anchor.stream_id, - &pri_spec); - if (rv != 0) { - return -1; - } - } + rv = nghttp2_session_client_new2(&session, callbacks, this, + config.http2_option); - rv = nghttp2_session_set_next_stream_id( - session, anchors[ANCHOR_FOLLOWERS].stream_id + 2); if (rv != 0) { return -1; } - if (need_upgrade()) { - // Amend the priority because we cannot send priority in - // HTTP/1.1 Upgrade. - auto &anchor = anchors[ANCHOR_FOLLOWERS]; - nghttp2_priority_spec_init(&pri_spec, anchor.stream_id, config.weight, 0); - - rv = nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec); + // Adjust stream user-data depending on the existence of upload + // data + Request *stream_user_data = nullptr; + if (!reqvec[0]->data_prd) { + stream_user_data = reqvec[0].get(); + } + rv = nghttp2_session_upgrade(session, settings_payload, + settings_payloadlen, stream_user_data); if (rv != 0) { + std::cerr << "[ERROR] nghttp2_session_upgrade() returned error: " + << nghttp2_strerror(rv) << std::endl; return -1; } + if (stream_user_data) { + stream_user_data->stream_id = 1; + on_request(stream_user_data); + } } - } else if (need_upgrade() && config.weight != NGHTTP2_DEFAULT_WEIGHT) { - // Amend the priority because we cannot send priority in - // HTTP/1.1 Upgrade. - nghttp2_priority_spec pri_spec; - - nghttp2_priority_spec_init(&pri_spec, 0, config.weight, 0); - - rv = nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec); - if (rv != 0) { - return -1; + // Send connection header here + bufferevent_write(bev, NGHTTP2_CLIENT_CONNECTION_PREFACE, + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); + // If upgrade succeeds, the SETTINGS value sent with + // HTTP2-Settings header field has already been submitted to + // session object. + if (!need_upgrade()) { + nghttp2_settings_entry iv[16]; + auto niv = populate_settings(iv); + rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, niv); + if (rv != 0) { + return -1; + } } - } - - ev_timer_again(loop, &settings_timer); - - if (config.connection_window_bits != -1) { - int32_t window_size = (1 << config.connection_window_bits) - 1; - rv = nghttp2_session_set_local_window_size(session, NGHTTP2_FLAG_NONE, 0, - window_size); - if (rv != 0) { - return -1; + assert(settings_timerev == nullptr); + settings_timerev = evtimer_new(evbase, settings_timeout_cb, this); + // SETTINGS ACK timeout is 10 seconds for now + timeval settings_timeout = {10, 0}; + evtimer_add(settings_timerev, &settings_timeout); + + if (config.connection_window_bits != -1) { + int32_t wininc = (1 << config.connection_window_bits) - 1 - + NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; + rv = nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, wininc); + if (rv != 0) { + return -1; + } } - } - // Adjust first request depending on the existence of the upload - // data - for (auto i = std::begin(reqvec) + (need_upgrade() && !reqvec[0]->data_prd); - i != std::end(reqvec); ++i) { - if (submit_request(this, config.headers, (*i).get()) != 0) { - return -1; + // Adjust first request depending on the existence of the upload + // data + for (auto i = std::begin(reqvec) + (need_upgrade() && !reqvec[0]->data_prd); + i != std::end(reqvec); ++i) { + if (submit_request(this, config.headers, (*i).get()) != 0) { + return -1; + } } + return on_write(); } - signal_write(); + int on_read() { + int rv; + auto input = bufferevent_get_input(bev); - return 0; -} + for (;;) { + auto inputlen = evbuffer_get_contiguous_space(input); -int HttpClient::on_read(const uint8_t *data, size_t len) { - if (config.hexdump) { - util::hexdump(stdout, data, len); - } + if (inputlen == 0) { + assert(evbuffer_get_length(input) == 0); - auto rv = nghttp2_session_mem_recv(session, data, len); - if (rv < 0) { - std::cerr << "[ERROR] nghttp2_session_mem_recv() returned error: " - << nghttp2_strerror(rv) << std::endl; - return -1; - } + return on_write(); + } - assert(static_cast(rv) == len); + auto mem = evbuffer_pullup(input, inputlen); - if (nghttp2_session_want_read(session) == 0 && - nghttp2_session_want_write(session) == 0 && wb.rleft() == 0) { - return -1; + rv = nghttp2_session_mem_recv(session, mem, inputlen); + + if (rv < 0) { + std::cerr << "[ERROR] nghttp2_session_mem_recv() returned error: " + << nghttp2_strerror(rv) << std::endl; + return -1; + } + + if (evbuffer_drain(input, rv) != 0) { + return -1; + } + } } - signal_write(); + int on_write() { + int rv; + uint8_t buf[4096]; + auto output = bufferevent_get_output(bev); + util::EvbufferBuffer evbbuf(output, buf, sizeof(buf)); + for (;;) { + if (evbuffer_get_length(output) + evbbuf.get_buflen() > + config.output_upper_thres) { + break; + } - return 0; -} + const uint8_t *data; + auto datalen = nghttp2_session_mem_send(session, &data); -int HttpClient::on_write() { - for (;;) { - if (wb.rleft() >= 16384) { - return 0; + if (datalen < 0) { + std::cerr << "[ERROR] nghttp2_session_mem_send() returned error: " + << nghttp2_strerror(datalen) << std::endl; + return -1; + } + if (datalen == 0) { + break; + } + rv = evbbuf.add(data, datalen); + if (rv != 0) { + std::cerr << "[ERROR] evbuffer_add() failed" << std::endl; + return -1; + } } - - const uint8_t *data; - auto len = nghttp2_session_mem_send(session, &data); - if (len < 0) { - std::cerr << "[ERROR] nghttp2_session_send() returned error: " - << nghttp2_strerror(len) << std::endl; + rv = evbbuf.flush(); + if (rv != 0) { + std::cerr << "[ERROR] evbuffer_add() failed" << std::endl; + return -1; + } + if (nghttp2_session_want_read(session) == 0 && + nghttp2_session_want_write(session) == 0 && + evbuffer_get_length(output) == 0) { return -1; } + return 0; + } - if (len == 0) { - break; + bool all_requests_processed() const { return complete == reqvec.size(); } + void update_hostport() { + if (reqvec.empty()) { + return; + } + scheme = + util::get_uri_field(reqvec[0]->uri.c_str(), reqvec[0]->u, UF_SCHEMA); + std::stringstream ss; + if (reqvec[0]->is_ipv6_literal_addr()) { + ss << "["; + util::write_uri_field(ss, reqvec[0]->uri.c_str(), reqvec[0]->u, UF_HOST); + ss << "]"; + } else { + util::write_uri_field(ss, reqvec[0]->uri.c_str(), reqvec[0]->u, UF_HOST); + } + if (util::has_uri_field(reqvec[0]->u, UF_PORT) && + reqvec[0]->u.port != + util::get_default_port(reqvec[0]->uri.c_str(), reqvec[0]->u)) { + ss << ":" << reqvec[0]->u.port; + } + hostport = ss.str(); + } + bool add_request(const std::string &uri, + const nghttp2_data_provider *data_prd, int64_t data_length, + const nghttp2_priority_spec &pri_spec, + std::shared_ptr dep, int pri = 0, + int level = 0) { + http_parser_url u; + memset(&u, 0, sizeof(u)); + if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) { + return false; + } + if (path_cache.count(uri)) { + return false; } - wb.append(data, len); - } + if (config.multiply == 1) { + path_cache.insert(uri); + } - if (nghttp2_session_want_read(session) == 0 && - nghttp2_session_want_write(session) == 0 && wb.rleft() == 0) { - return -1; + reqvec.push_back(util::make_unique( + uri, u, data_prd, data_length, pri_spec, std::move(dep), pri, level)); + return true; } - return 0; -} + void record_handshake_time() { stat.on_handshake_time = get_time(); } -int HttpClient::tls_handshake() { - ev_timer_again(loop, &rt); + void record_started_time() { + stat.started_system_time = std::chrono::system_clock::now(); + stat.on_started_time = get_time(); + } - ERR_clear_error(); + void record_dns_complete_time() { stat.on_dns_complete_time = get_time(); } - auto rv = SSL_do_handshake(ssl); + void record_connect_time() { stat.on_connect_time = get_time(); } - if (rv <= 0) { - auto err = SSL_get_error(ssl, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - ev_io_stop(loop, &wev); - ev_timer_stop(loop, &wt); - return 0; - case SSL_ERROR_WANT_WRITE: - ev_io_start(loop, &wev); - ev_timer_again(loop, &wt); - return 0; - default: - return -1; - } - } + void on_request(Request *req) { + req->record_request_time(); - ev_io_stop(loop, &wev); - ev_timer_stop(loop, &wt); + if (req->pri == 0 && req->dep) { + assert(req->dep->deps.empty()); - readfn = &HttpClient::read_tls; - writefn = &HttpClient::write_tls; + req->dep->deps.push_back(std::vector{req}); - if (connection_made() != 0) { - return -1; - } + return; + } - return 0; -} + if (req->stream_id % 2 == 0) { + return; + } -int HttpClient::read_tls() { - ev_timer_again(loop, &rt); + auto itr = std::begin(req->dep->deps); + for (; itr != std::end(req->dep->deps); ++itr) { + if ((*itr)[0]->pri == req->pri) { + (*itr).push_back(req); + + break; + } - ERR_clear_error(); + if ((*itr)[0]->pri > req->pri) { + auto v = std::vector{req}; + req->dep->deps.insert(itr, std::move(v)); - std::array buf; - for (;;) { - auto rv = SSL_read(ssl, buf.data(), buf.size()); - - if (rv <= 0) { - auto err = SSL_get_error(ssl, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - return 0; - case SSL_ERROR_WANT_WRITE: - // renegotiation started - return -1; - default: - return -1; + break; } } - if (on_readfn(*this, buf.data(), rv) != 0) { - return -1; + if (itr == std::end(req->dep->deps)) { + req->dep->deps.push_back(std::vector{req}); } } -} -int HttpClient::write_tls() { - ev_timer_again(loop, &rt); +#ifdef HAVE_JANSSON + void output_har(FILE *outfile) { + static auto PAGE_ID = "page_0"; - ERR_clear_error(); + auto root = json_object(); + auto log = json_object(); + json_object_set_new(root, "log", log); + json_object_set_new(log, "version", json_string("1.2")); - struct iovec iov; + auto creator = json_object(); + json_object_set_new(log, "creator", creator); - for (;;) { - if (on_writefn(*this) != 0) { - return -1; - } + json_object_set_new(creator, "name", json_string("nghttp")); + json_object_set_new(creator, "version", json_string(NGHTTP2_VERSION)); - auto iovcnt = wb.riovec(&iov, 1); + auto pages = json_array(); + json_object_set_new(log, "pages", pages); - if (iovcnt == 0) { - break; - } + auto page = json_object(); + json_array_append_new(pages, page); - auto rv = SSL_write(ssl, iov.iov_base, iov.iov_len); + json_object_set_new( + page, "startedDateTime", + json_string(util::format_iso8601(stat.started_system_time).c_str())); + json_object_set_new(page, "id", json_string(PAGE_ID)); + json_object_set_new(page, "title", json_string("")); - if (rv <= 0) { - auto err = SSL_get_error(ssl, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - // renegotiation started - return -1; - case SSL_ERROR_WANT_WRITE: - ev_io_start(loop, &wev); - ev_timer_again(loop, &wt); - return 0; - default: - return -1; - } - } + json_object_set_new(page, "pageTimings", json_object()); - wb.drain(rv); - } + auto entries = json_array(); + json_object_set_new(log, "entries", entries); - ev_io_stop(loop, &wev); - ev_timer_stop(loop, &wt); + auto dns_delta = + std::chrono::duration_cast( + stat.on_dns_complete_time - stat.on_started_time).count() / + 1000.0; + auto connect_delta = + std::chrono::duration_cast( + stat.on_connect_time - stat.on_dns_complete_time).count() / + 1000.0; - return 0; -} + for (size_t i = 0; i < reqvec.size(); ++i) { + auto &req = reqvec[i]; -void HttpClient::signal_write() { ev_io_start(loop, &wev); } + if (req->stat.stage != STAT_ON_COMPLETE) { + continue; + } -bool HttpClient::all_requests_processed() const { - return complete == reqvec.size(); -} + auto entry = json_object(); + json_array_append_new(entries, entry); -void HttpClient::update_hostport() { - if (reqvec.empty()) { - return; - } - scheme = util::get_uri_field(reqvec[0]->uri.c_str(), reqvec[0]->u, UF_SCHEMA) - .str(); - std::stringstream ss; - if (reqvec[0]->is_ipv6_literal_addr()) { - // we may have zone ID, which must start with "%25", or "%". RFC - // 6874 defines "%25" only, and just "%" is allowed for just - // convenience to end-user input. - auto host = - util::get_uri_field(reqvec[0]->uri.c_str(), reqvec[0]->u, UF_HOST); - auto end = std::find(std::begin(host), std::end(host), '%'); - ss << "["; - ss.write(host.c_str(), end - std::begin(host)); - ss << "]"; - } else { - util::write_uri_field(ss, reqvec[0]->uri.c_str(), reqvec[0]->u, UF_HOST); - } - if (util::has_uri_field(reqvec[0]->u, UF_PORT) && - reqvec[0]->u.port != - util::get_default_port(reqvec[0]->uri.c_str(), reqvec[0]->u)) { - ss << ":" << reqvec[0]->u.port; - } - hostport = ss.str(); -} + auto &req_stat = req->stat; + auto request_time = + (i == 0) ? stat.started_system_time + : stat.started_system_time + + std::chrono::duration_cast< + std::chrono::system_clock::duration>( + req_stat.on_request_time - stat.on_started_time); -bool HttpClient::add_request(const std::string &uri, - const nghttp2_data_provider *data_prd, - int64_t data_length, - const nghttp2_priority_spec &pri_spec, int level) { - http_parser_url u{}; - if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) { - return false; - } - if (path_cache.count(uri)) { - return false; - } + auto wait_delta = + std::chrono::duration_cast( + req_stat.on_response_time - req_stat.on_request_time).count() / + 1000.0; + auto receive_delta = + std::chrono::duration_cast( + req_stat.on_complete_time - req_stat.on_response_time).count() / + 1000.0; - if (config.multiply == 1) { - path_cache.insert(uri); - } + auto time_sum = + std::chrono::duration_cast( + (i == 0) ? (req_stat.on_complete_time - stat.on_started_time) + : (req_stat.on_complete_time - req_stat.on_request_time)) + .count() / + 1000.0; - reqvec.push_back( - make_unique(uri, u, data_prd, data_length, pri_spec, level)); - return true; -} + json_object_set_new( + entry, "startedDateTime", + json_string(util::format_iso8601(request_time).c_str())); + json_object_set_new(entry, "time", json_real(time_sum)); -void HttpClient::record_start_time() { - timing.system_start_time = std::chrono::system_clock::now(); - timing.start_time = get_time(); -} + auto request = json_object(); + json_object_set_new(entry, "request", request); -void HttpClient::record_domain_lookup_end_time() { - timing.domain_lookup_end_time = get_time(); -} + auto method_ptr = http2::get_header(req->req_nva, ":method"); -void HttpClient::record_connect_end_time() { - timing.connect_end_time = get_time(); -} + const char *method = "GET"; + if (method_ptr) { + method = (*method_ptr).value.c_str(); + } -void HttpClient::request_done(Request *req) { - if (req->stream_id % 2 == 0) { - return; - } -} + auto req_headers = json_array(); + json_object_set_new(request, "headers", req_headers); -#ifdef HAVE_JANSSON -void HttpClient::output_har(FILE *outfile) { - static auto PAGE_ID = "page_0"; + for (auto &nv : req->req_nva) { + auto hd = json_object(); + json_array_append_new(req_headers, hd); - auto root = json_object(); - auto log = json_object(); - json_object_set_new(root, "log", log); - json_object_set_new(log, "version", json_string("1.2")); - - auto creator = json_object(); - json_object_set_new(log, "creator", creator); - - json_object_set_new(creator, "name", json_string("nghttp")); - json_object_set_new(creator, "version", json_string(NGHTTP2_VERSION)); - - auto pages = json_array(); - json_object_set_new(log, "pages", pages); - - auto page = json_object(); - json_array_append_new(pages, page); - - json_object_set_new( - page, "startedDateTime", - json_string(util::format_iso8601(timing.system_start_time).c_str())); - json_object_set_new(page, "id", json_string(PAGE_ID)); - json_object_set_new(page, "title", json_string("")); - - json_object_set_new(page, "pageTimings", json_object()); - - auto entries = json_array(); - json_object_set_new(log, "entries", entries); - - auto dns_delta = - std::chrono::duration_cast( - timing.domain_lookup_end_time - timing.start_time).count() / - 1000.0; - auto connect_delta = - std::chrono::duration_cast( - timing.connect_end_time - timing.domain_lookup_end_time).count() / - 1000.0; + json_object_set_new(hd, "name", json_string(nv.name.c_str())); + json_object_set_new(hd, "value", json_string(nv.value.c_str())); + } - for (size_t i = 0; i < reqvec.size(); ++i) { - auto &req = reqvec[i]; + json_object_set_new(request, "method", json_string(method)); + json_object_set_new(request, "url", json_string(req->uri.c_str())); + json_object_set_new(request, "httpVersion", json_string("HTTP/2.0")); + json_object_set_new(request, "cookies", json_array()); + json_object_set_new(request, "queryString", json_array()); + json_object_set_new(request, "headersSize", json_integer(-1)); + json_object_set_new(request, "bodySize", json_integer(-1)); - if (req->timing.state != RequestState::ON_COMPLETE) { - continue; - } + auto response = json_object(); + json_object_set_new(entry, "response", response); - auto entry = json_object(); - json_array_append_new(entries, entry); + auto res_headers = json_array(); + json_object_set_new(response, "headers", res_headers); - auto &req_timing = req->timing; - auto request_time = - (i == 0) ? timing.system_start_time - : timing.system_start_time + - std::chrono::duration_cast< - std::chrono::system_clock::duration>( - req_timing.request_start_time - timing.start_time); - - auto wait_delta = std::chrono::duration_cast( - req_timing.response_start_time - - req_timing.request_start_time).count() / - 1000.0; - auto receive_delta = std::chrono::duration_cast( - req_timing.response_end_time - - req_timing.response_start_time).count() / - 1000.0; + for (auto &nv : req->res_nva) { + auto hd = json_object(); + json_array_append_new(res_headers, hd); - auto time_sum = - std::chrono::duration_cast( - (i == 0) ? (req_timing.response_end_time - timing.start_time) - : (req_timing.response_end_time - - req_timing.request_start_time)).count() / - 1000.0; + json_object_set_new(hd, "name", json_string(nv.name.c_str())); + json_object_set_new(hd, "value", json_string(nv.value.c_str())); + } - json_object_set_new( - entry, "startedDateTime", - json_string(util::format_iso8601(request_time).c_str())); - json_object_set_new(entry, "time", json_real(time_sum)); + json_object_set_new(response, "status", json_integer(req->status)); + json_object_set_new(response, "statusText", json_string("")); + json_object_set_new(response, "httpVersion", json_string("HTTP/2.0")); + json_object_set_new(response, "cookies", json_array()); - auto pushed = req->stream_id % 2 == 0; + auto content = json_object(); + json_object_set_new(response, "content", content); - json_object_set_new(entry, "comment", - json_string(pushed ? "Pushed Object" : "")); + json_object_set_new(content, "size", json_integer(req->response_len)); - auto request = json_object(); - json_object_set_new(entry, "request", request); + auto content_type_ptr = http2::get_header(req->res_nva, "content-type"); - auto req_headers = json_array(); - json_object_set_new(request, "headers", req_headers); + const char *content_type = ""; + if (content_type_ptr) { + content_type = content_type_ptr->value.c_str(); + } - for (auto &nv : req->req_nva) { - auto hd = json_object(); - json_array_append_new(req_headers, hd); + json_object_set_new(content, "mimeType", json_string(content_type)); - json_object_set_new(hd, "name", json_string(nv.name.c_str())); - json_object_set_new(hd, "value", json_string(nv.value.c_str())); - } + json_object_set_new(response, "redirectURL", json_string("")); + json_object_set_new(response, "headersSize", json_integer(-1)); + json_object_set_new(response, "bodySize", json_integer(-1)); + + json_object_set_new(entry, "cache", json_object()); - json_object_set_new(request, "method", json_string(req->method.c_str())); - json_object_set_new(request, "url", json_string(req->uri.c_str())); - json_object_set_new(request, "httpVersion", json_string("HTTP/2.0")); - json_object_set_new(request, "cookies", json_array()); - json_object_set_new(request, "queryString", json_array()); - json_object_set_new(request, "headersSize", json_integer(-1)); - json_object_set_new(request, "bodySize", json_integer(-1)); + auto timings = json_object(); + json_object_set_new(entry, "timings", timings); - auto response = json_object(); - json_object_set_new(entry, "response", response); + auto dns_timing = (i == 0) ? dns_delta : 0; + auto connect_timing = (i == 0) ? connect_delta : 0; - auto res_headers = json_array(); - json_object_set_new(response, "headers", res_headers); + json_object_set_new(timings, "dns", json_real(dns_timing)); + json_object_set_new(timings, "connect", json_real(connect_timing)); - for (auto &nv : req->res_nva) { - auto hd = json_object(); - json_array_append_new(res_headers, hd); + json_object_set_new(timings, "blocked", json_real(0.0)); + json_object_set_new(timings, "send", json_real(0.0)); + json_object_set_new(timings, "wait", json_real(wait_delta)); + json_object_set_new(timings, "receive", json_real(receive_delta)); - json_object_set_new(hd, "name", json_string(nv.name.c_str())); - json_object_set_new(hd, "value", json_string(nv.value.c_str())); + json_object_set_new(entry, "pageref", json_string(PAGE_ID)); } - json_object_set_new(response, "status", json_integer(req->status)); - json_object_set_new(response, "statusText", json_string("")); - json_object_set_new(response, "httpVersion", json_string("HTTP/2.0")); - json_object_set_new(response, "cookies", json_array()); + json_dumpf(root, outfile, JSON_PRESERVE_ORDER | JSON_INDENT(2)); + json_decref(root); + } +#endif // HAVE_JANSSON +}; +} // namespace + +namespace { +int htp_msg_begincb(http_parser *htp) { + if (config.verbose) { + print_timer(); + std::cout << " HTTP Upgrade response" << std::endl; + } + return 0; +} +} // namespace - auto content = json_object(); - json_object_set_new(response, "content", content); +namespace { +int htp_statuscb(http_parser *htp, const char *at, size_t length) { + auto client = static_cast(htp->data); + client->upgrade_response_status_code = htp->status_code; + return 0; +} +} // namespace - json_object_set_new(content, "size", json_integer(req->response_len)); +namespace { +int htp_msg_completecb(http_parser *htp) { + auto client = static_cast(htp->data); + client->upgrade_response_complete = true; + return 0; +} +} // namespace - auto content_type_ptr = http2::get_header(req->res_nva, "content-type"); +namespace { +http_parser_settings htp_hooks = { + htp_msg_begincb, // http_cb on_message_begin; + nullptr, // http_data_cb on_url; + htp_statuscb, // http_data_cb on_status; + nullptr, // http_data_cb on_header_field; + nullptr, // http_data_cb on_header_value; + nullptr, // http_cb on_headers_complete; + nullptr, // http_data_cb on_body; + htp_msg_completecb // http_cb on_message_complete; +}; +} // namespace - const char *content_type = ""; - if (content_type_ptr) { - content_type = content_type_ptr->value.c_str(); +namespace { +int submit_request(HttpClient *client, const Headers &headers, Request *req) { + auto path = req->make_reqpath(); + auto scheme = util::get_uri_field(req->uri.c_str(), req->u, UF_SCHEMA); + auto build_headers = Headers{{":method", req->data_prd ? "POST" : "GET"}, + {":path", path}, + {":scheme", scheme}, + {":authority", client->hostport}, + {"accept", "*/*"}, + {"accept-encoding", "gzip, deflate"}, + {"user-agent", "nghttp2/" NGHTTP2_VERSION}}; + if (config.continuation) { + for (size_t i = 0; i < 6; ++i) { + build_headers.emplace_back("continuation-test-" + util::utos(i + 1), + std::string(4096, '-')); + } + } + auto num_initial_headers = build_headers.size(); + if (!config.no_content_length && req->data_prd) { + build_headers.emplace_back("content-length", util::utos(req->data_length)); + } + for (auto &kv : headers) { + size_t i; + for (i = 0; i < num_initial_headers; ++i) { + if (kv.name == build_headers[i].name) { + build_headers[i].value = kv.value; + break; + } + } + if (i < num_initial_headers) { + continue; } - json_object_set_new(content, "mimeType", json_string(content_type)); - - json_object_set_new(response, "redirectURL", json_string("")); - json_object_set_new(response, "headersSize", json_integer(-1)); - json_object_set_new(response, "bodySize", json_integer(-1)); - json_object_set_new(entry, "cache", json_object()); + build_headers.emplace_back(kv.name, kv.value, kv.no_index); + } + std::stable_sort(std::begin(build_headers), std::end(build_headers), + http2::name_less); - auto timings = json_object(); - json_object_set_new(entry, "timings", timings); + auto nva = std::vector(); + nva.reserve(build_headers.size()); - auto dns_timing = (i == 0) ? dns_delta : 0; - auto connect_timing = (i == 0) ? connect_delta : 0; + for (auto &kv : build_headers) { + nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); + } - json_object_set_new(timings, "dns", json_real(dns_timing)); - json_object_set_new(timings, "connect", json_real(connect_timing)); + auto stream_id = + nghttp2_submit_request(client->session, &req->pri_spec, nva.data(), + nva.size(), req->data_prd, req); + if (stream_id < 0) { + std::cerr << "[ERROR] nghttp2_submit_request() returned error: " + << nghttp2_strerror(stream_id) << std::endl; + return -1; + } - json_object_set_new(timings, "blocked", json_real(0.0)); - json_object_set_new(timings, "send", json_real(0.0)); - json_object_set_new(timings, "wait", json_real(wait_delta)); - json_object_set_new(timings, "receive", json_real(receive_delta)); + req->stream_id = stream_id; + client->on_request(req); - json_object_set_new(entry, "pageref", json_string(PAGE_ID)); - json_object_set_new(entry, "connection", - json_string(util::utos(req->stream_id).c_str())); - } + req->req_nva = std::move(build_headers); - json_dumpf(root, outfile, JSON_PRESERVE_ORDER | JSON_INDENT(2)); - json_decref(root); + return 0; } -#endif // HAVE_JANSSON +} // namespace namespace { void update_html_parser(HttpClient *client, Request *req, const uint8_t *data, @@ -1586,17 +1194,19 @@ for (auto &p : req->html_parser->get_links()) { auto uri = strip_fragment(p.first.c_str()); - auto res_type = p.second; + auto pri = p.second; - http_parser_url u{}; + http_parser_url u; + memset(&u, 0, sizeof(u)); if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) == 0 && util::fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_SCHEMA) && util::fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_HOST) && util::porteq(uri.c_str(), u, req->uri.c_str(), req->u)) { // No POST data for assets - auto pri_spec = resolve_dep(res_type); + auto pri_spec = req->resolve_dep(pri); - if (client->add_request(uri, nullptr, 0, pri_spec, req->level + 1)) { + if (client->add_request(uri, nullptr, 0, pri_spec, req->dep, pri, + req->level + 1)) { submit_request(client, config.headers, client->reqvec.back().get()); } @@ -1607,7 +1217,7 @@ } // namespace namespace { -HttpClient *get_client(void *user_data) { +HttpClient *get_session(void *user_data) { return static_cast(user_data); } } // namespace @@ -1616,7 +1226,7 @@ int 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) { - auto client = get_client(user_data); + auto client = get_session(user_data); auto req = static_cast( nghttp2_session_get_stream_user_data(session, stream_id)); @@ -1629,27 +1239,32 @@ user_data); } - req->response_len += len; + if (req->status == 0) { + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id, + NGHTTP2_PROTOCOL_ERROR); + return 0; + } if (req->inflater) { while (len > 0) { - const size_t MAX_OUTLEN = 4_k; - std::array out; + const size_t MAX_OUTLEN = 4096; + uint8_t out[MAX_OUTLEN]; size_t outlen = MAX_OUTLEN; size_t tlen = len; - int rv = - nghttp2_gzip_inflate(req->inflater, out.data(), &outlen, data, &tlen); + int rv = nghttp2_gzip_inflate(req->inflater, out, &outlen, data, &tlen); if (rv != 0) { nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id, NGHTTP2_INTERNAL_ERROR); break; } + req->response_len += outlen; + if (!config.null_out) { - std::cout.write(reinterpret_cast(out.data()), outlen); + std::cout.write(reinterpret_cast(out), outlen); } - update_html_parser(client, req, out.data(), outlen, 0); + update_html_parser(client, req, out, outlen, 0); data += tlen; len -= tlen; } @@ -1657,6 +1272,8 @@ return 0; } + req->response_len += len; + if (!config.null_out) { std::cout.write(reinterpret_cast(data), len); } @@ -1668,6 +1285,18 @@ } // namespace namespace { +void settings_timeout_cb(evutil_socket_t fd, short what, void *arg) { + int rv; + auto client = get_session(arg); + nghttp2_session_terminate_session(client->session, NGHTTP2_SETTINGS_TIMEOUT); + rv = client->on_write(); + if (rv != 0) { + client->disconnect(); + } +} +} // namespace + +namespace { ssize_t select_padding_callback(nghttp2_session *session, const nghttp2_frame *frame, size_t max_payload, void *user_data) { @@ -1681,45 +1310,37 @@ req->expect_final_response = false; - auto status_hd = req->get_res_header(http2::HD__STATUS); + for (auto &nv : req->res_nva) { + if ("content-encoding" == nv.name) { + gzip = + util::strieq("gzip", nv.value) || util::strieq("deflate", nv.value); + continue; + } + if (":status" == nv.name) { + int status; + if (req->status != 0 || + (status = http2::parse_http_status_code(nv.value)) == -1) { - if (!status_hd) { - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, req->stream_id, - NGHTTP2_PROTOCOL_ERROR); - return; + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, req->stream_id, + NGHTTP2_PROTOCOL_ERROR); + return; + } + + req->status = status; + } } - auto status = http2::parse_http_status_code(StringRef{status_hd->value}); - if (status == -1) { + if (req->status == 0) { nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, req->stream_id, NGHTTP2_PROTOCOL_ERROR); return; } - req->status = status; - - for (auto &nv : req->res_nva) { - if ("content-encoding" == nv.name) { - gzip = util::strieq_l("gzip", nv.value) || - util::strieq_l("deflate", nv.value); - continue; - } - } - if (req->status / 100 == 1) { - if (req->continue_timer && (req->status == 100)) { - // If the request is waiting for a 100 Continue, complete the handshake. - req->continue_timer->dispatch_continue(); - } - req->expect_final_response = true; req->status = 0; req->res_nva.clear(); - http2::init_hdidx(req->res_hdidx); return; - } else if (req->continue_timer) { - // A final response stops any pending Expect/Continue handshake. - req->continue_timer->stop(); } if (gzip) { @@ -1732,47 +1353,29 @@ req->init_html_parser(); } } -} -} // namespace - -namespace { -int on_begin_headers_callback(nghttp2_session *session, - const nghttp2_frame *frame, void *user_data) { - auto client = get_client(user_data); - switch (frame->hd.type) { - case NGHTTP2_HEADERS: { - auto req = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); - if (!req) { - break; - } - - switch (frame->headers.cat) { - case NGHTTP2_HCAT_RESPONSE: - case NGHTTP2_HCAT_PUSH_RESPONSE: - req->record_response_start_time(); - break; - default: - break; - } - - break; - } +} +} // namespace + +namespace { +int on_begin_headers_callback(nghttp2_session *session, + const nghttp2_frame *frame, void *user_data) { + auto client = get_session(user_data); + switch (frame->hd.type) { case NGHTTP2_PUSH_PROMISE: { auto stream_id = frame->push_promise.promised_stream_id; - http_parser_url u{}; + http_parser_url u; + memset(&u, 0, sizeof(u)); // TODO Set pri and level nghttp2_priority_spec pri_spec; nghttp2_priority_spec_default_init(&pri_spec); - auto req = make_unique("", u, nullptr, 0, pri_spec); + auto req = util::make_unique("", u, nullptr, 0, pri_spec, nullptr); req->stream_id = stream_id; nghttp2_session_set_stream_user_data(session, stream_id, req.get()); - client->request_done(req.get()); - req->record_request_start_time(); + client->on_request(req.get()); client->reqvec.push_back(std::move(req)); break; @@ -1792,6 +1395,12 @@ flags, user_data); } + if (!http2::check_nv(name, namelen, value, valuelen)) { + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + switch (frame->hd.type) { case NGHTTP2_HEADERS: { auto req = static_cast( @@ -1801,25 +1410,24 @@ break; } - /* ignore trailer header */ - if (frame->headers.cat == NGHTTP2_HCAT_HEADERS && - !req->expect_final_response) { + if (frame->headers.cat != NGHTTP2_HCAT_RESPONSE && + frame->headers.cat != NGHTTP2_HCAT_PUSH_RESPONSE && + (frame->headers.cat != NGHTTP2_HCAT_HEADERS || + !req->expect_final_response)) { break; } - if (req->header_buffer_size + namelen + valuelen > 64_k) { - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id, - NGHTTP2_INTERNAL_ERROR); - return 0; + if (namelen > 0 && name[0] == ':') { + if (!req->response_pseudo_header_allowed() || + !http2::check_http2_response_pseudo_header(name, namelen)) { + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->hd.stream_id, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } } - req->header_buffer_size += namelen + valuelen; - - auto token = http2::lookup_token(name, namelen); - - http2::index_header(req->res_hdidx, token, req->res_nva.size()); http2::add_header(req->res_nva, name, namelen, value, valuelen, - flags & NGHTTP2_NV_FLAG_NO_INDEX, token); + flags & NGHTTP2_NV_FLAG_NO_INDEX); break; } case NGHTTP2_PUSH_PROMISE: { @@ -1830,20 +1438,18 @@ break; } - if (req->header_buffer_size + namelen + valuelen > 64_k) { - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, - frame->push_promise.promised_stream_id, - NGHTTP2_INTERNAL_ERROR); - return 0; + if (namelen > 0 && name[0] == ':') { + if (!req->push_request_pseudo_header_allowed() || + !http2::check_http2_request_pseudo_header(name, namelen)) { + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->push_promise.promised_stream_id, + NGHTTP2_PROTOCOL_ERROR); + break; + } } - req->header_buffer_size += namelen + valuelen; - - auto token = http2::lookup_token(name, namelen); - - http2::index_header(req->req_hdidx, token, req->req_nva.size()); http2::add_header(req->req_nva, name, namelen, value, valuelen, - flags & NGHTTP2_NV_FLAG_NO_INDEX, token); + flags & NGHTTP2_NV_FLAG_NO_INDEX); break; } } @@ -1860,56 +1466,39 @@ verbose_on_frame_recv_callback(session, frame, user_data); } - auto client = get_client(user_data); + auto client = get_session(user_data); switch (frame->hd.type) { - case NGHTTP2_DATA: { - auto req = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); - if (!req) { - return 0; - ; - } - - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - req->record_response_end_time(); - ++client->success; - } - - break; - } case NGHTTP2_HEADERS: { auto req = static_cast( nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); // If this is the HTTP Upgrade with OPTIONS method to avoid POST, // req is nullptr. if (!req) { - return 0; - ; + break; } - switch (frame->headers.cat) { - case NGHTTP2_HCAT_RESPONSE: - case NGHTTP2_HCAT_PUSH_RESPONSE: + if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE || + frame->headers.cat == NGHTTP2_HCAT_PUSH_RESPONSE) { + req->record_response_time(); check_response_header(session, req); + break; - case NGHTTP2_HCAT_HEADERS: + } + + if (frame->headers.cat == NGHTTP2_HCAT_HEADERS) { if (req->expect_final_response) { check_response_header(session, req); - break; - } - if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { + } else { nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id, NGHTTP2_PROTOCOL_ERROR); - return 0; + break; } - break; - default: - assert(0); } - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - req->record_response_end_time(); - ++client->success; + if (req->status == 0 && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + break; } break; @@ -1918,7 +1507,11 @@ if ((frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) { break; } - ev_timer_stop(client->loop, &client->settings_timer); + if (client->settings_timerev) { + evtimer_del(client->settings_timerev); + event_free(client->settings_timerev); + client->settings_timerev = nullptr; + } break; case NGHTTP2_PUSH_PROMISE: { auto req = static_cast(nghttp2_session_get_stream_user_data( @@ -1926,31 +1519,38 @@ if (!req) { break; } - - // Reset for response header field reception - req->header_buffer_size = 0; - - auto scheme = req->get_req_header(http2::HD__SCHEME); - auto authority = req->get_req_header(http2::HD__AUTHORITY); - auto path = req->get_req_header(http2::HD__PATH); - - if (!authority) { - authority = req->get_req_header(http2::HD_HOST); + std::string scheme, authority, method, path; + for (auto &nv : req->req_nva) { + if (nv.name == ":scheme") { + scheme = nv.value; + continue; + } + if (nv.name == ":authority" || nv.name == "host") { + authority = nv.value; + continue; + } + if (nv.name == ":method") { + method = nv.value; + continue; + } + if (nv.name == ":path") { + path = nv.value; + continue; + } } - - // libnghttp2 guarantees :scheme, :method, :path and (:authority | - // host) exist and non-empty. - if (path->value[0] != '/') { + if (scheme.empty() || authority.empty() || method.empty() || path.empty() || + path[0] != '/') { nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->push_promise.promised_stream_id, NGHTTP2_PROTOCOL_ERROR); break; } - std::string uri = scheme->value; + std::string uri = scheme; uri += "://"; - uri += authority->value; - uri += path->value; - http_parser_url u{}; + uri += authority; + uri += path; + http_parser_url u; + memset(&u, 0, sizeof(u)); if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) { nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->push_promise.promised_stream_id, @@ -1959,18 +1559,6 @@ } req->uri = uri; req->u = u; - - if (client->path_cache.count(uri)) { - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, - frame->push_promise.promised_stream_id, - NGHTTP2_CANCEL); - break; - } - - if (config.multiply == 1) { - client->path_cache.insert(uri); - } - break; } } @@ -1979,74 +1567,9 @@ } // namespace namespace { -int before_frame_send_callback(nghttp2_session *session, - const nghttp2_frame *frame, void *user_data) { - if (frame->hd.type != NGHTTP2_HEADERS || - frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - return 0; - } - auto req = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); - assert(req); - req->record_request_start_time(); - return 0; -} - -} // namespace - -namespace { -int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame, - void *user_data) { - if (config.verbose) { - verbose_on_frame_send_callback(session, frame, user_data); - } - - if (frame->hd.type != NGHTTP2_HEADERS || - frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - return 0; - } - - auto req = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); - if (!req) { - return 0; - } - - // If this request is using Expect/Continue, start its ContinueTimer. - if (req->continue_timer) { - req->continue_timer->start(); - } - - return 0; -} -} // namespace - -namespace { -int on_frame_not_send_callback(nghttp2_session *session, - const nghttp2_frame *frame, int lib_error_code, - void *user_data) { - if (frame->hd.type != NGHTTP2_HEADERS || - frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - return 0; - } - - auto req = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); - if (!req) { - return 0; - } - - std::cerr << "[ERROR] request " << req->uri - << " failed: " << nghttp2_strerror(lib_error_code) << std::endl; - - return 0; -} -} // namespace - -namespace { int on_stream_close_callback(nghttp2_session *session, int32_t stream_id, uint32_t error_code, void *user_data) { - auto client = get_client(user_data); + auto client = get_session(user_data); auto req = static_cast( nghttp2_session_get_stream_user_data(session, stream_id)); @@ -2054,12 +1577,8 @@ return 0; } - // If this request is using Expect/Continue, stop its ContinueTimer. - if (req->continue_timer) { - req->continue_timer->stop(); - } - update_html_parser(client, req, nullptr, 0, 1); + req->record_complete_time(); ++client->complete; if (client->all_requests_processed()) { @@ -2070,69 +1589,40 @@ } } // namespace -struct RequestResult { - std::chrono::microseconds time; -}; - namespace { void print_stats(const HttpClient &client) { std::cout << "***** Statistics *****" << std::endl; - - std::vector reqs; - reqs.reserve(client.reqvec.size()); - for (const auto &req : client.reqvec) { - if (req->timing.state == RequestState::ON_COMPLETE) { - reqs.push_back(req.get()); + int i = 0; + for (auto &req : client.reqvec) { + std::cout << "#" << ++i << ": " << req->uri << std::endl; + std::cout << " Status: " << req->status << std::endl; + std::cout << " Delta (ms) from handshake(HEADERS):" << std::endl; + if (req->stat.stage >= STAT_ON_RESPONSE) { + std::cout << " response HEADERS: " + << time_delta(req->stat.on_response_time, + client.stat.on_handshake_time).count() << "(" + << time_delta(req->stat.on_response_time, + req->stat.on_request_time).count() << ")" + << std::endl; + } + if (req->stat.stage >= STAT_ON_COMPLETE) { + std::cout << " Completed: " + << time_delta(req->stat.on_complete_time, + client.stat.on_handshake_time).count() << "(" + << time_delta(req->stat.on_complete_time, + req->stat.on_request_time).count() << ")" + << std::endl; } + std::cout << std::endl; } +} +} // namespace - std::sort(std::begin(reqs), std::end(reqs), - [](const Request *lhs, const Request *rhs) { - const auto <iming = lhs->timing; - const auto &rtiming = rhs->timing; - return ltiming.response_end_time < rtiming.response_end_time || - (ltiming.response_end_time == rtiming.response_end_time && - ltiming.request_start_time < rtiming.request_start_time); - }); - - std::cout << R"( -Request timing: - 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' - -id responseEnd requestStart process code size request path)" << std::endl; - - const auto &base = client.timing.connect_end_time; - for (const auto &req : reqs) { - auto response_end = std::chrono::duration_cast( - req->timing.response_end_time - base); - auto request_start = std::chrono::duration_cast( - req->timing.request_start_time - base); - auto total = std::chrono::duration_cast( - req->timing.response_end_time - req->timing.request_start_time); - auto pushed = req->stream_id % 2 == 0; - - std::cout << std::setw(3) << req->stream_id << " " << std::setw(11) - << ("+" + util::format_duration(response_end)) << " " - << (pushed ? "*" : " ") << std::setw(11) - << ("+" + util::format_duration(request_start)) << " " - << std::setw(8) << util::format_duration(total) << " " - << std::setw(4) << req->status << " " << std::setw(4) - << util::utos_unit(req->response_len) << " " - << req->make_reqpath() << std::endl; - } +namespace { +void print_protocol_nego_error() { + std::cerr << "[ERROR] HTTP/2 protocol was not selected." + << " (nghttp2 expects " << NGHTTP2_PROTO_VERSION_ID << ")" + << std::endl; } } // namespace @@ -2151,8 +1641,7 @@ std::cout << std::endl; } } - if (!util::select_h2(const_cast(out), outlen, in, - inlen)) { + if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) { print_protocol_nego_error(); return SSL_TLSEXT_ERR_NOACK; } @@ -2161,31 +1650,137 @@ } // namespace namespace { -// Recommended general purpose "Intermediate compatibility" cipher by -// mozilla. -// -// https://wiki.mozilla.org/Security/Server_Side_TLS -const char *const CIPHER_LIST = - "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-" - "AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:" - "DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-" - "AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-" - "AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-" - "AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:" - "DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-" - "SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-" - "SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!" - "aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"; +void upgrade_readcb(bufferevent *bev, void *ptr) { + int rv; + auto client = static_cast(ptr); + rv = client->on_upgrade_read(); + if (rv != 0) { + client->disconnect(); + } +} +} // namespace + +namespace { +void readcb(bufferevent *bev, void *ptr) { + int rv; + auto client = static_cast(ptr); + rv = client->on_read(); + if (rv != 0) { + client->disconnect(); + } +} +} // namespace + +namespace { +void writecb(bufferevent *bev, void *ptr) { + if (evbuffer_get_length(bufferevent_get_output(bev)) > 0) { + return; + } + int rv; + auto client = static_cast(ptr); + rv = client->on_write(); + if (rv != 0) { + client->disconnect(); + } +} +} // namespace + +namespace { +void eventcb(bufferevent *bev, short events, void *ptr) { + int rv; + auto client = static_cast(ptr); + if (events & BEV_EVENT_CONNECTED) { + client->record_connect_time(); + client->state = STATE_CONNECTED; + int fd = bufferevent_getfd(bev); + int val = 1; + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&val), + sizeof(val)) == -1) { + std::cerr << "[ERROR] Setting option TCP_NODELAY failed: errno=" << errno + << std::endl; + } + if (client->need_upgrade()) { + rv = client->on_upgrade_connect(); + } else { + if (client->ssl) { + // Check NPN or ALPN result + const unsigned char *next_proto = nullptr; + unsigned int next_proto_len; + SSL_get0_next_proto_negotiated(client->ssl, &next_proto, + &next_proto_len); + for (int i = 0; i < 2; ++i) { + if (next_proto) { + if (config.verbose) { + std::cout << "The negotiated protocol: "; + std::cout.write(reinterpret_cast(next_proto), + next_proto_len); + std::cout << std::endl; + } + if (!util::check_h2_is_selected(next_proto, next_proto_len)) { + next_proto = nullptr; + } + break; + } +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + SSL_get0_alpn_selected(client->ssl, &next_proto, &next_proto_len); +#else // OPENSSL_VERSION_NUMBER < 0x10002000L + break; +#endif // OPENSSL_VERSION_NUMBER < 0x10002000L + } + if (!next_proto) { + print_protocol_nego_error(); + client->disconnect(); + return; + } + } + rv = client->on_connect(); + } + if (rv != 0) { + client->disconnect(); + return; + } + return; + } + if (events & BEV_EVENT_EOF) { + std::cerr << "EOF" << std::endl; + auto state = client->state; + client->disconnect(); + if (state == STATE_IDLE) { + if (client->initiate_connection() == 0) { + std::cerr << "Trying next address" << std::endl; + } + } + return; + } + if (events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { + if (events & BEV_EVENT_ERROR) { + if (client->state == STATE_IDLE) { + std::cerr << "[ERROR] Could not connect to the host" << std::endl; + } else { + std::cerr << "[ERROR] Network error" << std::endl; + } + } else { + std::cerr << "[ERROR] Timeout" << std::endl; + } + auto state = client->state; + client->disconnect(); + if (state == STATE_IDLE) { + if (client->initiate_connection() == 0) { + std::cerr << "Trying next address" << std::endl; + } + } + return; + } +} } // namespace namespace { int communicate( const std::string &scheme, const std::string &host, uint16_t port, std::vector> - requests, - const nghttp2_session_callbacks *callbacks) { + requests, const nghttp2_session_callbacks *callbacks) { int result = 0; - auto loop = EV_DEFAULT; + auto evbase = event_base_new(); SSL_CTX *ssl_ctx = nullptr; if (scheme == "https") { ssl_ctx = SSL_CTX_new(SSLv23_client_method()); @@ -2195,20 +1790,12 @@ result = -1; goto fin; } - - auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | - SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; - - SSL_CTX_set_options(ssl_ctx, ssl_opts); + SSL_CTX_set_options(ssl_ctx, + SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | + SSL_OP_NO_COMPRESSION | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS); - if (SSL_CTX_set_cipher_list(ssl_ctx, CIPHER_LIST) == 0) { - std::cerr << "[ERROR] " << ERR_error_string(ERR_get_error(), nullptr) - << std::endl; - result = -1; - goto fin; - } if (!config.keyfile.empty()) { if (SSL_CTX_use_PrivateKey_file(ssl_ctx, config.keyfile.c_str(), SSL_FILETYPE_PEM) != 1) { @@ -2237,42 +1824,37 @@ #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L } { - HttpClient client{callbacks, loop, ssl_ctx}; + HttpClient client{callbacks, evbase, ssl_ctx}; nghttp2_priority_spec pri_spec; - int32_t dep_stream_id = 0; - if (!config.no_dep) { - dep_stream_id = anchors[ANCHOR_FOLLOWERS].stream_id; + if (config.weight != NGHTTP2_DEFAULT_WEIGHT) { + nghttp2_priority_spec_init(&pri_spec, 0, config.weight, 0); + } else { + nghttp2_priority_spec_default_init(&pri_spec); } - nghttp2_priority_spec_init(&pri_spec, dep_stream_id, config.weight, 0); - for (auto req : requests) { for (int i = 0; i < config.multiply; ++i) { + auto dep = std::make_shared(); client.add_request(std::get<0>(req), std::get<1>(req), std::get<2>(req), - pri_spec); + pri_spec, std::move(dep)); } } client.update_hostport(); - client.record_start_time(); + client.record_started_time(); if (client.resolve_host(host, port) != 0) { goto fin; } - client.record_domain_lookup_end_time(); + client.record_dns_complete_time(); if (client.initiate_connection() != 0) { - std::cerr << "[ERROR] Could not connect to " << host << ", port " << port - << std::endl; goto fin; } - - ev_set_userdata(loop, &client); - ev_run(loop, 0); - ev_set_userdata(loop, nullptr); + event_base_loop(evbase, 0); #ifdef HAVE_JANSSON if (!config.harfile.empty()) { @@ -2296,9 +1878,9 @@ } #endif // HAVE_JANSSON - if (client.success != client.reqvec.size()) { + if (!client.all_requests_processed()) { std::cerr << "Some requests were not processed. total=" - << client.reqvec.size() << ", processed=" << client.success + << client.reqvec.size() << ", processed=" << client.complete << std::endl; } if (config.stat) { @@ -2309,6 +1891,9 @@ if (ssl_ctx) { SSL_CTX_free(ssl_ctx); } + if (evbase) { + event_base_free(evbase); + } return result; } } // namespace @@ -2317,7 +1902,6 @@ ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { - int rv; auto req = static_cast( nghttp2_session_get_stream_user_data(session, stream_id)); assert(req); @@ -2332,31 +1916,10 @@ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } - req->data_offset += nread; - - if (req->data_offset == req->data_length) { + if (nread == 0) { *data_flags |= NGHTTP2_DATA_FLAG_EOF; - if (!config.trailer.empty()) { - std::vector nva; - nva.reserve(config.trailer.size()); - for (auto &kv : config.trailer) { - nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); - } - rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size()); - if (rv != 0) { - if (nghttp2_is_fatal(rv)) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - } else { - *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM; - } - } - - return nread; - } - - if (req->data_offset > req->data_length || nread == 0) { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } else { + req->data_offset += nread; } return nread; @@ -2368,7 +1931,7 @@ nghttp2_session_callbacks *callbacks; nghttp2_session_callbacks_new(&callbacks); - auto cbsdel = defer(nghttp2_session_callbacks_del, callbacks); + auto cbsdel = util::defer(callbacks, nghttp2_session_callbacks_del); nghttp2_session_callbacks_set_on_stream_close_callback( callbacks, on_stream_close_callback); @@ -2377,11 +1940,11 @@ on_frame_recv_callback2); if (config.verbose) { + nghttp2_session_callbacks_set_on_frame_send_callback( + callbacks, verbose_on_frame_send_callback); + nghttp2_session_callbacks_set_on_invalid_frame_recv_callback( callbacks, verbose_on_invalid_frame_recv_callback); - - nghttp2_session_callbacks_set_error_callback(callbacks, - verbose_error_callback); } nghttp2_session_callbacks_set_on_data_chunk_recv_callback( @@ -2393,15 +1956,6 @@ nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header_callback); - nghttp2_session_callbacks_set_before_frame_send_callback( - callbacks, before_frame_send_callback); - - nghttp2_session_callbacks_set_on_frame_send_callback(callbacks, - on_frame_send_callback); - - nghttp2_session_callbacks_set_on_frame_not_send_callback( - callbacks, on_frame_not_send_callback); - if (config.padding) { nghttp2_session_callbacks_set_select_padding_callback( callbacks, select_padding_callback); @@ -2416,65 +1970,17 @@ struct stat data_stat; if (!config.datafile.empty()) { - if (config.datafile == "-") { - if (fstat(0, &data_stat) == 0 && - (data_stat.st_mode & S_IFMT) == S_IFREG) { - // use STDIN if it is a regular file - data_fd = 0; - } else { - // copy the contents of STDIN to a temporary file - char tempfn[] = "/tmp/nghttp.temp.XXXXXX"; - data_fd = mkstemp(tempfn); - if (data_fd == -1) { - std::cerr << "[ERROR] Could not create a temporary file in /tmp" - << std::endl; - return 1; - } - if (unlink(tempfn) != 0) { - std::cerr << "[WARNING] failed to unlink temporary file:" << tempfn - << std::endl; - } - while (1) { - std::array buf; - ssize_t rret, wret; - while ((rret = read(0, buf.data(), buf.size())) == -1 && - errno == EINTR) - ; - if (rret == 0) - break; - if (rret == -1) { - std::cerr << "[ERROR] I/O error while reading from STDIN" - << std::endl; - return 1; - } - while ((wret = write(data_fd, buf.data(), rret)) == -1 && - errno == EINTR) - ; - if (wret != rret) { - std::cerr << "[ERROR] I/O error while writing to temporary file" - << std::endl; - return 1; - } - } - if (fstat(data_fd, &data_stat) == -1) { - close(data_fd); - std::cerr << "[ERROR] Could not stat temporary file" << std::endl; - return 1; - } - } - } else { - data_fd = open(config.datafile.c_str(), O_RDONLY | O_BINARY); - if (data_fd == -1) { - std::cerr << "[ERROR] Could not open file " << config.datafile - << std::endl; - return 1; - } - if (fstat(data_fd, &data_stat) == -1) { - close(data_fd); - std::cerr << "[ERROR] Could not stat file " << config.datafile - << std::endl; - return 1; - } + data_fd = open(config.datafile.c_str(), O_RDONLY | O_BINARY); + if (data_fd == -1) { + std::cerr << "[ERROR] Could not open file " << config.datafile + << std::endl; + return 1; + } + if (fstat(data_fd, &data_stat) == -1) { + close(data_fd); + std::cerr << "[ERROR] Could not stat file " << config.datafile + << std::endl; + return 1; } data_prd.source.fd = data_fd; data_prd.read_callback = file_read_callback; @@ -2482,36 +1988,31 @@ std::vector> requests; for (int i = 0; i < n; ++i) { - http_parser_url u{}; + http_parser_url u; + memset(&u, 0, sizeof(u)); auto uri = strip_fragment(uris[i]); - if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) { - std::cerr << "[ERROR] Could not parse URI " << uri << std::endl; - continue; - } - if (!util::has_uri_field(u, UF_SCHEMA)) { - std::cerr << "[ERROR] URI " << uri << " does not have scheme part" - << std::endl; - continue; - } - auto port = util::has_uri_field(u, UF_PORT) - ? u.port - : util::get_default_port(uri.c_str(), u); - auto host = decode_host(util::get_uri_field(uri.c_str(), u, UF_HOST)); - if (!util::fieldeq(uri.c_str(), u, UF_SCHEMA, prev_scheme.c_str()) || - host != prev_host || port != prev_port) { - if (!requests.empty()) { - if (communicate(prev_scheme, prev_host, prev_port, std::move(requests), - callbacks) != 0) { - ++failures; + if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) == 0 && + util::has_uri_field(u, UF_SCHEMA)) { + uint16_t port = util::has_uri_field(u, UF_PORT) + ? u.port + : util::get_default_port(uri.c_str(), u); + if (!util::fieldeq(uri.c_str(), u, UF_SCHEMA, prev_scheme.c_str()) || + !util::fieldeq(uri.c_str(), u, UF_HOST, prev_host.c_str()) || + port != prev_port) { + if (!requests.empty()) { + if (communicate(prev_scheme, prev_host, prev_port, + std::move(requests), callbacks) != 0) { + ++failures; + } + requests.clear(); } - requests.clear(); + prev_scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA); + prev_host = util::get_uri_field(uri.c_str(), u, UF_HOST); + prev_port = port; } - prev_scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA).str(); - prev_host = std::move(host); - prev_port = port; + requests.emplace_back(uri, data_fd == -1 ? nullptr : &data_prd, + data_stat.st_size); } - requests.emplace_back(uri, data_fd == -1 ? nullptr : &data_prd, - data_stat.st_size); } if (!requests.empty()) { if (communicate(prev_scheme, prev_host, prev_port, std::move(requests), @@ -2532,7 +2033,7 @@ namespace { void print_usage(std::ostream &out) { out << R"(Usage: nghttp [OPTIONS]... ... -HTTP/2 client)" << std::endl; +HTTP/2 experimental client)" << std::endl; } } // namespace @@ -2540,116 +2041,77 @@ void print_help(std::ostream &out) { print_usage(out); out << R"( - Specify URI to access. + Specify URI to access. Options: - -v, --verbose - Print debug information such as reception and - transmission of frames and name/value pairs. Specifying - this option multiple times increases verbosity. - -n, --null-out - Discard downloaded data. - -O, --remote-name - Save download data in the current directory. The - filename is derived from URI. If URI ends with '/', - 'index.html' is used as a filename. Not implemented - yet. - -t, --timeout= - Timeout each request after . Set 0 to disable - timeout. + -v, --verbose Print debug information such as reception and + transmission of frames and name/value pairs. + Specifying this option multiple times increases + verbosity. + -n, --null-out Discard downloaded data. + -O, --remote-name Save download data in the current directory. The + filename is dereived from URI. If URI ends with + '/', 'index.html' is used as a filename. Not + implemented yet. + -t, --timeout= Timeout each request after seconds. -w, --window-bits= - Sets the stream level initial window size to 2**-1. + Sets the stream level initial window size to + 2**-1. -W, --connection-window-bits= - Sets the connection level initial window size to - 2**-1. - -a, --get-assets - Download assets such as stylesheets, images and script - files linked from the downloaded resource. Only links - whose origins are the same with the linking resource - will be downloaded. nghttp prioritizes resources using - HTTP/2 dependency based priority. The priority order, - from highest to lowest, is html itself, css, javascript - and images. - -s, --stat Print statistics. + Sets the connection level initial window size to + 2**-1. + -a, --get-assets Download assets such as stylesheets, images and + script files linked from the downloaded resource. + Only links whose origins are the same with the + linking resource will be downloaded. nghttp + prioritizes resources using HTTP/2 dependency + based priority. The priority order, from highest + to lowest, is html itself, css, javascript and + images. + -s, --stat Print statistics. -H, --header=
- Add a header to the requests. Example: -H':method: PUT' - --trailer=
- Add a trailer header to the requests.
must not - include pseudo header field (header field name starting - with ':'). To send trailer, one must use -d option to - send request body. Example: --trailer 'foo: bar'. - --cert= - Use the specified client certificate file. The file - must be in PEM format. - --key= Use the client private key file. The file must be in - PEM format. - -d, --data= - Post FILE to server. If '-' is given, data will be read - from stdin. - -m, --multiply= - Request each URI times. By default, same URI is not - requested twice. This option disables it too. - -u, --upgrade - Perform HTTP Upgrade for HTTP/2. This option is ignored - if the request URI has https scheme. If -d is used, the - HTTP upgrade request is performed with OPTIONS method. + Add a header to the requests. Example: + -H':method: PUT' + --cert= Use the specified client certificate file. The + file must be in PEM format. + --key= Use the client private key file. The file must + be in PEM format. + -d, --data= Post FILE to server. If '-' is given, data will + be read from stdin. + -m, --multiply= Request each URI times. By default, same URI + is not requested twice. This option disables it + too. + -u, --upgrade Perform HTTP Upgrade for HTTP/2. This option is + ignored if the request URI has https scheme. If + -d is used, the HTTP upgrade request is performed + with OPTIONS method. -p, --weight= - Sets priority group weight. The valid value range is - [)" << NGHTTP2_MIN_WEIGHT << ", " << NGHTTP2_MAX_WEIGHT - << R"(], inclusive. - Default: )" << NGHTTP2_DEFAULT_WEIGHT << R"( + Sets priority group weight. The valid value + range is [)" << NGHTTP2_MIN_WEIGHT << ", " + << NGHTTP2_MAX_WEIGHT << R"(], inclusive. + Default: )" << NGHTTP2_DEFAULT_WEIGHT << R"( -M, --peer-max-concurrent-streams= - Use as SETTINGS_MAX_CONCURRENT_STREAMS value of - remote endpoint as if it is received in SETTINGS frame. - Default: 100 - -c, --header-table-size= - Specify decoder header table size. If this option is - used multiple times, and the minimum value among the - given values except for last one is strictly less than - the last value, that minimum value is set in SETTINGS - frame payload before the last value, to simulate - multiple header table size change. - -b, --padding= - Add at most bytes to a frame payload as padding. - Specify 0 to disable padding. - -r, --har= - Output HTTP transactions in HAR format. If '-' - is given, data is written to stdout. - --color Force colored log output. - --continuation - Send large header to test CONTINUATION. + Use as SETTINGS_MAX_CONCURRENT_STREAMS value + of remote endpoint as if it is received in + SETTINGS frame. The default is large enough as + it is seen as unlimited. + -c, --header-table-size= + Specify decoder header table size. + -b, --padding= Add at most bytes to a frame payload as + padding. Specify 0 to disable padding. + -r, --har= Output HTTP transactions in HAR format. + If '-' is given, data is written to stdout. + --color Force colored log output. + --continuation Send large header to test CONTINUATION. --no-content-length - Don't send content-length header field. - --no-dep Don't send dependency based priority hint to server. - --hexdump Display the incoming traffic in hexadecimal (Canonical - hex+ASCII display). If SSL/TLS is used, decrypted data - are used. - --no-push Disable server push. - --max-concurrent-streams= - The number of concurrent pushed streams this client - accepts. - --expect-continue - Perform an Expect/Continue handshake: wait to send DATA - (up to a short timeout) until the server sends a 100 - Continue interim response. This option is ignored unless - combined with the -d option. - --version Display version information and exit. - -h, --help Display this help and exit. - --- - - The argument is an integer and an optional unit (e.g., 10K is - 10 * 1024). Units are K, M and G (powers of 1024). - - The 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.)" << std::endl; + Don't send content-length header field. + --no-dep Don't send dependency based priority hint to + server. + --version Display version information and exit. + -h, --help Display this help and exit.)" << std::endl; } } // namespace int main(int argc, char **argv) { - ssl::libssl_init(); - bool color = false; while (1) { static int flag = 0; @@ -2679,15 +2141,11 @@ {"version", no_argument, &flag, 5}, {"no-content-length", no_argument, &flag, 6}, {"no-dep", no_argument, &flag, 7}, - {"trailer", required_argument, &flag, 9}, - {"hexdump", no_argument, &flag, 10}, - {"no-push", no_argument, &flag, 11}, - {"max-concurrent-streams", required_argument, &flag, 12}, - {"expect-continue", no_argument, &flag, 13}, {nullptr, 0, nullptr, 0}}; int option_index = 0; int c = getopt_long(argc, argv, "M:Oab:c:d:gm:np:r:hH:vst:uw:W:", long_options, &option_index); + char *end; if (c == -1) { break; } @@ -2733,11 +2191,7 @@ ++config.verbose; break; case 't': - config.timeout = util::parse_duration_with_unit(optarg); - if (config.timeout == std::numeric_limits::infinity()) { - std::cerr << "-t: bad timeout value: " << optarg << std::endl; - exit(EXIT_FAILURE); - } + config.timeout = atoi(optarg) * 1000; break; case 'u': config.upgrade = true; @@ -2781,7 +2235,10 @@ << std::endl; exit(EXIT_FAILURE); } - config.headers.emplace_back(header, value, false); + // To test "never index" repr, don't index authorization header + // field unconditionally. + auto no_index = util::strieq("authorization", header); + config.headers.emplace_back(header, value, no_index); util::inp_strlower(config.headers.back().name); break; } @@ -2797,20 +2254,18 @@ config.stat = true; break; case 'd': - config.datafile = optarg; + config.datafile = strcmp("-", optarg) == 0 ? "/dev/stdin" : optarg; break; case 'm': config.multiply = strtoul(optarg, nullptr, 10); break; case 'c': errno = 0; - config.header_table_size = util::parse_uint_with_unit(optarg); - if (config.header_table_size == -1) { + config.header_table_size = strtol(optarg, &end, 10); + if (errno == ERANGE || *end != '\0') { std::cerr << "-c: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } - config.min_header_table_size = - std::min(config.min_header_table_size, config.header_table_size); break; case '?': util::show_candidates(argv[optind - 1], long_options); @@ -2845,46 +2300,6 @@ // no-dep option config.no_dep = true; break; - case 9: { - // trailer option - auto header = optarg; - auto value = strchr(optarg, ':'); - if (!value) { - std::cerr << "--trailer: invalid header: " << optarg << std::endl; - exit(EXIT_FAILURE); - } - *value = 0; - value++; - while (isspace(*value)) { - value++; - } - if (*value == 0) { - // This could also be a valid case for suppressing a header - // similar to curl - std::cerr << "--trailer: invalid header - value missing: " << optarg - << std::endl; - exit(EXIT_FAILURE); - } - config.trailer.emplace_back(header, value, false); - util::inp_strlower(config.trailer.back().name); - break; - } - case 10: - // hexdump option - config.hexdump = true; - break; - case 11: - // no-push option - config.no_push = true; - break; - case 12: - // max-concurrent-streams option - config.max_concurrent_streams = strtoul(optarg, nullptr, 10); - break; - case 13: - // expect-continue option - config.expect_continue = true; - break; } break; default: @@ -2897,15 +2312,18 @@ nghttp2_option_set_peer_max_concurrent_streams( config.http2_option, config.peer_max_concurrent_streams); - struct sigaction act {}; + struct sigaction act; + memset(&act, 0, sizeof(struct sigaction)); act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, nullptr); + OPENSSL_config(nullptr); + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); + SSL_library_init(); reset_timer(); return run(argv + optind, argc - optind); } } // namespace nghttp2 -int main(int argc, char **argv) { - return nghttp2::run_app(nghttp2::main, argc, argv); -} +int main(int argc, char **argv) { return nghttp2::main(argc, argv); } diff -Nru nghttp2-1.13.0/src/nghttpd.cc nghttp2-0.6.7/src/nghttpd.cc --- nghttp2-1.13.0/src/nghttpd.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/nghttpd.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,13 +24,7 @@ */ #include "nghttp2_config.h" -#ifdef __sgi -#define daemon _daemonize -#endif - -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H #include #include @@ -43,6 +37,7 @@ #include #include +#include #include #include "app_helper.h" @@ -58,9 +53,9 @@ if (eq == NULL) { return -1; } - auto &paths = config.push[std::string(optarg, eq)]; + auto paths = std::vector(); auto optarg_end = optarg + strlen(optarg); - auto i = eq + 1; + const char *i = eq + 1; for (;;) { const char *j = strchr(i, ','); if (j == NULL) { @@ -73,7 +68,7 @@ i = j; ++i; } - + config.push[std::string(optarg, eq)] = std::move(paths); return 0; } } // namespace @@ -86,116 +81,73 @@ namespace { void print_usage(std::ostream &out) { - out << "Usage: nghttpd [OPTION]... [ ]\n" - << "HTTP/2 server" << std::endl; + out << "Usage: nghttpd [OPTION]... \n" + << " or: nghttpd --no-tls [OPTION]... \n" + << "HTTP/2 experimental server" << std::endl; } } // namespace namespace { void print_help(std::ostream &out) { - Config config; print_usage(out); out << R"( - Specify listening port number. - - Set path to server's private key. Required unless - --no-tls is specified. - Set path to server's certificate. Required unless - --no-tls is specified. + Specify listening port number. + Set path to server's private key. Required + unless --no-tls is specified. + Set path to server's certificate. Required + unless --no-tls is specified. Options: - -a, --address= - The address to bind to. If not specified the default IP - address determined by getaddrinfo is used. - -D, --daemon - Run in a background. If -D is used, the current working - directory is changed to '/'. Therefore if this option - is used, -d option must be specified. + -D, --daemon Run in a background. If -D is used, the current + working directory is changed to '/'. Therefore + if this option is used, -d option must be + specified. -V, --verify-client - The server sends a client certificate request. If the - client did not return a certificate, the handshake is - terminated. Currently, this option just requests a - client certificate and does not verify it. + The server sends a client certificate request. + If the client did not return a certificate, the + handshake is terminated. Currently, this option + just requests a client certificate and does not + verify it. -d, --htdocs= - Specify document root. If this option is not specified, - the document root is the current working directory. - -v, --verbose - Print debug information such as reception/ transmission - of frames and name/value pairs. - --no-tls Disable SSL/TLS. - -c, --header-table-size= - Specify decoder header table size. - --color Force colored log output. + Specify document root. If this option is not + specified, the document root is the current + working directory. + -v, --verbose Print debug information such as reception/ + transmission of frames and name/value pairs. + --no-tls Disable SSL/TLS. + -c, --header-table-size= + Specify decoder header table size. + --color Force colored log output. -p, --push== - Push resources s when is requested. - This option can be used repeatedly to specify multiple - push configurations. and s are - relative to document root. See --htdocs option. - Example: -p/=/foo.png -p/doc=/bar.css - -b, --padding= - Add at most bytes to a frame payload as padding. - Specify 0 to disable padding. - -m, --max-concurrent-streams= - Set the maximum number of the concurrent streams in one - HTTP/2 session. - Default: )" << config.max_concurrent_streams << R"( - -n, --workers= - Set the number of worker threads. - Default: 1 - -e, --error-gzip - Make error response gzipped. - -w, --window-bits= - Sets the stream level initial window size to 2**-1. - -W, --connection-window-bits= - Sets the connection level initial window size to - 2**-1. + Push resources s when is + requested. This option can be used repeatedly to + specify multiple push configurations. and + s are relative to document root. See + --htdocs option. Example: -p/=/foo.png + -p/doc=/bar.css + -b, --padding= Add at most bytes to a frame payload as + padding. Specify 0 to disable padding. + -n, --workers= + Set the number of worker threads. + Default: 1 + -e, --error-gzip Make error response gzipped. --dh-param-file= - Path to file that contains DH parameters in PEM format. - Without this option, DHE cipher suites are not - available. - --early-response - Start sending response when request HEADERS is received, - rather than complete request is received. - --trailer=
- Add a trailer header to a response.
must not - include pseudo header field (header field name starting - with ':'). The trailer is sent only if a response has - body part. Example: --trailer 'foo: bar'. - --hexdump Display the incoming traffic in hexadecimal (Canonical - hex+ASCII display). If SSL/TLS is used, decrypted data - are used. - --echo-upload - Send back uploaded content if method is POST or PUT. - --mime-types-file= - Path to file that contains MIME media types and the - extensions that represent them. - Default: )" << config.mime_types_file << R"( - --no-content-length - Don't send content-length header field. - --version Display version information and exit. - -h, --help Display this help and exit. - --- - - The argument is an integer and an optional unit (e.g., 10K is - 10 * 1024). Units are K, M and G (powers of 1024).)" << std::endl; + Path to file that contains DH parameters in PEM + format. Without this option, DHE cipher suites + are not available. + --early-response Start sending response when request HEADERS is + received, rather than complete request is + received. + --version Display version information and exit. + -h, --help Display this help and exit.)" << std::endl; } } // namespace int main(int argc, char **argv) { - ssl::libssl_init(); - -#ifndef NOTHREADS - ssl::LibsslGlobalLock lock; -#endif // NOTHREADS - Config config; bool color = false; - auto mime_types_file_set_manually = false; - while (1) { static int flag = 0; static option long_options[] = { - {"address", required_argument, nullptr, 'a'}, {"daemon", no_argument, nullptr, 'D'}, {"htdocs", required_argument, nullptr, 'd'}, {"help", no_argument, nullptr, 'h'}, @@ -204,32 +156,22 @@ {"header-table-size", required_argument, nullptr, 'c'}, {"push", required_argument, nullptr, 'p'}, {"padding", required_argument, nullptr, 'b'}, - {"max-concurrent-streams", required_argument, nullptr, 'm'}, {"workers", required_argument, nullptr, 'n'}, {"error-gzip", no_argument, nullptr, 'e'}, - {"window-bits", required_argument, nullptr, 'w'}, - {"connection-window-bits", required_argument, nullptr, 'W'}, {"no-tls", no_argument, &flag, 1}, {"color", no_argument, &flag, 2}, {"version", no_argument, &flag, 3}, {"dh-param-file", required_argument, &flag, 4}, {"early-response", no_argument, &flag, 5}, - {"trailer", required_argument, &flag, 6}, - {"hexdump", no_argument, &flag, 7}, - {"echo-upload", no_argument, &flag, 8}, - {"mime-types-file", required_argument, &flag, 9}, - {"no-content-length", no_argument, &flag, 10}, {nullptr, 0, nullptr, 0}}; int option_index = 0; - int c = getopt_long(argc, argv, "DVb:c:d:ehm:n:p:va:w:W:", long_options, - &option_index); + int c = + getopt_long(argc, argv, "DVb:c:d:ehn:p:v", long_options, &option_index); + char *end; if (c == -1) { break; } switch (c) { - case 'a': - config.address = optarg; - break; case 'D': config.daemon = true; break; @@ -245,22 +187,11 @@ case 'e': config.error_gzip = true; break; - case 'm': { - // max-concurrent-streams option - auto n = util::parse_uint(optarg); - if (n == -1) { - std::cerr << "-m: invalid argument: " << optarg << std::endl; - exit(EXIT_FAILURE); - } - config.max_concurrent_streams = n; - break; - } - case 'n': { + case 'n': #ifdef NOTHREADS std::cerr << "-n: WARNING: Threading disabled at build time, " << "no threads created." << std::endl; #else - char *end; errno = 0; config.num_worker = strtoul(optarg, &end, 10); if (errno == ERANGE || *end != '\0' || config.num_worker == 0) { @@ -269,7 +200,6 @@ } #endif // NOTHREADS break; - } case 'h': print_help(std::cout); exit(EXIT_SUCCESS); @@ -278,8 +208,8 @@ break; case 'c': errno = 0; - config.header_table_size = util::parse_uint_with_unit(optarg); - if (config.header_table_size == -1) { + config.header_table_size = strtol(optarg, &end, 10); + if (errno == ERANGE || *end != '\0') { std::cerr << "-c: Bad option value: " << optarg << std::endl; exit(EXIT_FAILURE); } @@ -289,26 +219,6 @@ std::cerr << "-p: Bad option value: " << optarg << std::endl; } break; - case 'w': - case 'W': { - char *endptr; - errno = 0; - auto n = strtoul(optarg, &endptr, 10); - if (errno != 0 || *endptr != '\0' || n >= 31) { - std::cerr << "-" << static_cast(c) - << ": specify the integer in the range [0, 30], inclusive" - << std::endl; - exit(EXIT_FAILURE); - } - - if (c == 'w') { - config.window_bits = n; - } else { - config.connection_window_bits = n; - } - - break; - } case '?': util::show_candidates(argv[optind - 1], long_options); exit(EXIT_FAILURE); @@ -334,47 +244,6 @@ // early-response config.early_response = true; break; - case 6: { - // trailer option - auto header = optarg; - auto value = strchr(optarg, ':'); - if (!value) { - std::cerr << "--trailer: invalid header: " << optarg << std::endl; - exit(EXIT_FAILURE); - } - *value = 0; - value++; - while (isspace(*value)) { - value++; - } - if (*value == 0) { - // This could also be a valid case for suppressing a header - // similar to curl - std::cerr << "--trailer: invalid header - value missing: " << optarg - << std::endl; - exit(EXIT_FAILURE); - } - config.trailer.emplace_back(header, value, false); - util::inp_strlower(config.trailer.back().name); - break; - } - case 7: - // hexdump option - config.hexdump = true; - break; - case 8: - // echo-upload option - config.echo_upload = true; - break; - case 9: - // mime-types-file option - mime_types_file_set_manually = true; - config.mime_types_file = optarg; - break; - case 10: - // no-content-length option - config.no_content_length = true; - break; } break; default: @@ -400,11 +269,7 @@ std::cerr << "-d option must be specified when -D is used." << std::endl; exit(EXIT_FAILURE); } -#ifdef __sgi - if (daemon(0, 0, 0, 0) == -1) { -#else if (daemon(0, 0) == -1) { -#endif perror("daemon"); exit(EXIT_FAILURE); } @@ -413,40 +278,27 @@ config.htdocs = "./"; } - if (util::read_mime_types(config.mime_types, - config.mime_types_file.c_str()) != 0) { - if (mime_types_file_set_manually) { - std::cerr << "--mime-types-file: Could not open mime types file: " - << config.mime_types_file << std::endl; - } - } - - auto &trailer_names = config.trailer_names; - for (auto &h : config.trailer) { - trailer_names += h.name; - trailer_names += ", "; - } - if (trailer_names.size() >= 2) { - trailer_names.resize(trailer_names.size() - 2); - } - set_color_output(color || isatty(fileno(stdout))); - struct sigaction act {}; + struct sigaction act; + memset(&act, 0, sizeof(struct sigaction)); act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, nullptr); + OPENSSL_config(nullptr); + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); + SSL_library_init(); +#ifndef NOTHREADS + ssl::LibsslGlobalLock lock; +#endif // NOTHREADS reset_timer(); HttpServer server(&config); - if (server.run() != 0) { - exit(EXIT_FAILURE); - } + server.run(); return 0; } } // namespace nghttp2 -int main(int argc, char **argv) { - return nghttp2::run_app(nghttp2::main, argc, argv); -} +int main(int argc, char **argv) { return nghttp2::main(argc, argv); } diff -Nru nghttp2-1.13.0/src/nghttp.h nghttp2-0.6.7/src/nghttp.h --- nghttp2-1.13.0/src/nghttp.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/nghttp.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,294 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 NGHTTP_H -#define NGHTTP_H - -#include "nghttp2_config.h" - -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif // HAVE_SYS_SOCKET_H -#ifdef HAVE_NETDB_H -#include -#endif // HAVE_NETDB_H - -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#include "http-parser/http_parser.h" - -#include "memchunk.h" -#include "http2.h" -#include "nghttp2_gzip.h" -#include "template.h" - -namespace nghttp2 { - -class HtmlParser; - -struct Config { - Config(); - ~Config(); - - Headers headers; - Headers trailer; - std::string certfile; - std::string keyfile; - std::string datafile; - std::string harfile; - nghttp2_option *http2_option; - int64_t header_table_size; - int64_t min_header_table_size; - size_t padding; - size_t max_concurrent_streams; - ssize_t peer_max_concurrent_streams; - int32_t weight; - int multiply; - // milliseconds - ev_tstamp timeout; - int window_bits; - int connection_window_bits; - int verbose; - bool null_out; - bool remote_name; - bool get_assets; - bool stat; - bool upgrade; - bool continuation; - bool no_content_length; - bool no_dep; - bool hexdump; - bool no_push; - bool expect_continue; -}; - -enum class RequestState { INITIAL, ON_REQUEST, ON_RESPONSE, ON_COMPLETE }; - -struct RequestTiming { - // The point in time when request is started to be sent. - // Corresponds to requestStart in Resource Timing TR. - std::chrono::steady_clock::time_point request_start_time; - // The point in time when first byte of response is received. - // Corresponds to responseStart in Resource Timing TR. - std::chrono::steady_clock::time_point response_start_time; - // The point in time when last byte of response is received. - // Corresponds to responseEnd in Resource Timing TR. - std::chrono::steady_clock::time_point response_end_time; - RequestState state; - RequestTiming() : state(RequestState::INITIAL) {} -}; - -struct Request; // forward declaration for ContinueTimer - -struct ContinueTimer { - ContinueTimer(struct ev_loop *loop, Request *req); - ~ContinueTimer(); - - void start(); - void stop(); - - // Schedules an immediate run of the continue callback on the loop, if the - // callback has not already been run - void dispatch_continue(); - - struct ev_loop *loop; - ev_timer timer; -}; - -struct Request { - // For pushed request, |uri| is empty and |u| is zero-cleared. - Request(const std::string &uri, const http_parser_url &u, - const nghttp2_data_provider *data_prd, int64_t data_length, - const nghttp2_priority_spec &pri_spec, int level = 0); - ~Request(); - - void init_inflater(); - - void init_html_parser(); - int update_html_parser(const uint8_t *data, size_t len, int fin); - - std::string make_reqpath() const; - - bool is_ipv6_literal_addr() const; - - Headers::value_type *get_res_header(int32_t token); - Headers::value_type *get_req_header(int32_t token); - - void record_request_start_time(); - void record_response_start_time(); - void record_response_end_time(); - - Headers res_nva; - Headers req_nva; - std::string method; - // URI without fragment - std::string uri; - http_parser_url u; - nghttp2_priority_spec pri_spec; - RequestTiming timing; - int64_t data_length; - int64_t data_offset; - // Number of bytes received from server - int64_t response_len; - nghttp2_gzip *inflater; - HtmlParser *html_parser; - const nghttp2_data_provider *data_prd; - size_t header_buffer_size; - int32_t stream_id; - int status; - // Recursion level: 0: first entity, 1: entity linked from first entity - int level; - http2::HeaderIndex res_hdidx; - // used for incoming PUSH_PROMISE - http2::HeaderIndex req_hdidx; - bool expect_final_response; - // only assigned if this request is using Expect/Continue - std::unique_ptr continue_timer; -}; - -struct SessionTiming { - // The point in time when operation was started. Corresponds to - // startTime in Resource Timing TR, but recorded in system clock time. - std::chrono::system_clock::time_point system_start_time; - // Same as above, but recorded in steady clock time. - std::chrono::steady_clock::time_point start_time; - // The point in time when DNS resolution was completed. Corresponds - // to domainLookupEnd in Resource Timing TR. - std::chrono::steady_clock::time_point domain_lookup_end_time; - // The point in time when connection was established or SSL/TLS - // handshake was completed. Corresponds to connectEnd in Resource - // Timing TR. - std::chrono::steady_clock::time_point connect_end_time; -}; - -enum class ClientState { IDLE, CONNECTED }; - -struct HttpClient { - HttpClient(const nghttp2_session_callbacks *callbacks, struct ev_loop *loop, - SSL_CTX *ssl_ctx); - ~HttpClient(); - - bool need_upgrade() const; - int resolve_host(const std::string &host, uint16_t port); - int initiate_connection(); - void disconnect(); - - int noop(); - int read_clear(); - int write_clear(); - int connected(); - int tls_handshake(); - int read_tls(); - int write_tls(); - - int do_read(); - int do_write(); - - int on_upgrade_connect(); - int on_upgrade_read(const uint8_t *data, size_t len); - int on_read(const uint8_t *data, size_t len); - int on_write(); - - int connection_made(); - void connect_fail(); - void request_done(Request *req); - - void signal_write(); - - bool all_requests_processed() const; - void update_hostport(); - bool add_request(const std::string &uri, - const nghttp2_data_provider *data_prd, int64_t data_length, - const nghttp2_priority_spec &pri_spec, int level = 0); - - void record_start_time(); - void record_domain_lookup_end_time(); - void record_connect_end_time(); - -#ifdef HAVE_JANSSON - void output_har(FILE *outfile); -#endif // HAVE_JANSSON - - MemchunkPool mcpool; - DefaultMemchunks wb; - std::vector> reqvec; - // Insert path already added in reqvec to prevent multiple request - // for 1 resource. - std::set path_cache; - std::string scheme; - std::string host; - std::string hostport; - // Used for parse the HTTP upgrade response from server - std::unique_ptr htp; - SessionTiming timing; - ev_io wev; - ev_io rev; - ev_timer wt; - ev_timer rt; - ev_timer settings_timer; - std::function readfn, writefn; - std::function on_readfn; - std::function on_writefn; - nghttp2_session *session; - const nghttp2_session_callbacks *callbacks; - struct ev_loop *loop; - SSL_CTX *ssl_ctx; - SSL *ssl; - addrinfo *addrs; - addrinfo *next_addr; - addrinfo *cur_addr; - // The number of completed requests, including failed ones. - size_t complete; - // The number of requests that local endpoint received END_STREAM - // from peer. - size_t success; - // The length of settings_payload - size_t settings_payloadlen; - ClientState state; - // The HTTP status code of the response message of HTTP Upgrade. - unsigned int upgrade_response_status_code; - int fd; - // true if the response message of HTTP Upgrade request is fully - // received. It is not relevant the upgrade succeeds, or not. - bool upgrade_response_complete; - // SETTINGS payload sent as token68 in HTTP Upgrade - std::array settings_payload; - - enum { ERR_CONNECT_FAIL = -100 }; -}; - -} // namespace nghttp2 - -#endif // NGHTTP_H diff -Nru nghttp2-1.13.0/src/shrpx_accept_handler.cc nghttp2-0.6.7/src/shrpx_accept_handler.cc --- nghttp2-1.13.0/src/shrpx_accept_handler.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_accept_handler.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,112 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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. - */ -#include "shrpx_accept_handler.h" - -#ifdef HAVE_UNISTD_H -#include -#endif // HAVE_UNISTD_H - -#include - -#include "shrpx_connection_handler.h" -#include "shrpx_config.h" -#include "util.h" - -using namespace nghttp2; - -namespace shrpx { - -namespace { -void acceptcb(struct ev_loop *loop, ev_io *w, int revent) { - auto h = static_cast(w->data); - h->accept_connection(); -} -} // namespace - -AcceptHandler::AcceptHandler(const UpstreamAddr *faddr, ConnectionHandler *h) - : conn_hnr_(h), faddr_(faddr) { - ev_io_init(&wev_, acceptcb, faddr_->fd, EV_READ); - wev_.data = this; - ev_io_start(conn_hnr_->get_loop(), &wev_); -} - -AcceptHandler::~AcceptHandler() { - ev_io_stop(conn_hnr_->get_loop(), &wev_); - close(faddr_->fd); -} - -void AcceptHandler::accept_connection() { - sockaddr_union sockaddr; - socklen_t addrlen = sizeof(sockaddr); - -#ifdef HAVE_ACCEPT4 - auto cfd = - accept4(faddr_->fd, &sockaddr.sa, &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC); -#else // !HAVE_ACCEPT4 - auto cfd = accept(faddr_->fd, &sockaddr.sa, &addrlen); -#endif // !HAVE_ACCEPT4 - - if (cfd == -1) { - switch (errno) { - case EINTR: - case ENETDOWN: - case EPROTO: - case ENOPROTOOPT: - case EHOSTDOWN: -#ifdef ENONET - case ENONET: -#endif // ENONET - case EHOSTUNREACH: - case EOPNOTSUPP: - case ENETUNREACH: - return; - case EMFILE: - case ENFILE: - LOG(WARN) << "acceptor: running out file descriptor; disable acceptor " - "temporarily"; - conn_hnr_->sleep_acceptor(get_config()->conn.listener.timeout.sleep); - return; - default: - return; - } - } - -#ifndef HAVE_ACCEPT4 - util::make_socket_nonblocking(cfd); - util::make_socket_closeonexec(cfd); -#endif // !HAVE_ACCEPT4 - - util::make_socket_nodelay(cfd); - - conn_hnr_->handle_connection(cfd, &sockaddr.sa, addrlen, faddr_); -} - -void AcceptHandler::enable() { ev_io_start(conn_hnr_->get_loop(), &wev_); } - -void AcceptHandler::disable() { ev_io_stop(conn_hnr_->get_loop(), &wev_); } - -int AcceptHandler::get_fd() const { return faddr_->fd; } - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_accept_handler.h nghttp2-0.6.7/src/shrpx_accept_handler.h --- nghttp2-1.13.0/src/shrpx_accept_handler.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_accept_handler.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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 SHRPX_ACCEPT_HANDLER_H -#define SHRPX_ACCEPT_HANDLER_H - -#include "shrpx.h" - -#include - -namespace shrpx { - -class ConnectionHandler; -struct UpstreamAddr; - -class AcceptHandler { -public: - AcceptHandler(const UpstreamAddr *faddr, ConnectionHandler *h); - ~AcceptHandler(); - void accept_connection(); - void enable(); - void disable(); - int get_fd() const; - -private: - ev_io wev_; - ConnectionHandler *conn_hnr_; - const UpstreamAddr *faddr_; -}; - -} // namespace shrpx - -#endif // SHRPX_ACCEPT_HANDLER_H diff -Nru nghttp2-1.13.0/src/shrpx_api_downstream_connection.cc nghttp2-0.6.7/src/shrpx_api_downstream_connection.cc --- nghttp2-1.13.0/src/shrpx_api_downstream_connection.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_api_downstream_connection.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,311 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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. - */ -#include "shrpx_api_downstream_connection.h" - -#include "shrpx_client_handler.h" -#include "shrpx_upstream.h" -#include "shrpx_downstream.h" -#include "shrpx_worker.h" -#include "shrpx_connection_handler.h" - -namespace shrpx { - -APIDownstreamConnection::APIDownstreamConnection(Worker *worker) - : worker_(worker), abandoned_(false) {} - -APIDownstreamConnection::~APIDownstreamConnection() {} - -int APIDownstreamConnection::attach_downstream(Downstream *downstream) { - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream; - } - - downstream_ = downstream; - - return 0; -} - -void APIDownstreamConnection::detach_downstream(Downstream *downstream) { - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "Detaching from DOWNSTREAM:" << downstream; - } - downstream_ = nullptr; -} - -// API status, which is independent from HTTP status code. But -// generally, 2xx code for API_SUCCESS, and otherwise API_FAILURE. -enum { - API_SUCCESS, - API_FAILURE, -}; - -int APIDownstreamConnection::send_reply(unsigned int http_status, - int api_status) { - abandoned_ = true; - - auto upstream = downstream_->get_upstream(); - - auto &resp = downstream_->response(); - - resp.http_status = http_status; - - auto &balloc = downstream_->get_block_allocator(); - - StringRef api_status_str; - - switch (api_status) { - case API_SUCCESS: - api_status_str = StringRef::from_lit("Success"); - break; - case API_FAILURE: - api_status_str = StringRef::from_lit("Failure"); - break; - default: - assert(0); - } - - constexpr auto M1 = StringRef::from_lit("{\"status\":\""); - constexpr auto M2 = StringRef::from_lit("\",\"code\":"); - constexpr auto M3 = StringRef::from_lit("}"); - - // 3 is the number of digits in http_status, assuming it is 3 digits - // number. - auto buflen = M1.size() + M2.size() + M3.size() + api_status_str.size() + 3; - - auto buf = make_byte_ref(balloc, buflen); - auto p = buf.base; - - p = std::copy(std::begin(M1), std::end(M1), p); - p = std::copy(std::begin(api_status_str), std::end(api_status_str), p); - p = std::copy(std::begin(M2), std::end(M2), p); - p = util::utos(p, http_status); - p = std::copy(std::begin(M3), std::end(M3), p); - - buf.len = p - buf.base; - - auto content_length = util::make_string_ref_uint(balloc, buf.len); - - resp.fs.add_header_token(StringRef::from_lit("content-length"), - content_length, false, http2::HD_CONTENT_LENGTH); - - switch (http_status) { - case 400: - case 405: - case 413: - resp.fs.add_header_token(StringRef::from_lit("connection"), - StringRef::from_lit("close"), false, - http2::HD_CONNECTION); - break; - } - - if (upstream->send_reply(downstream_, buf.base, buf.len) != 0) { - return -1; - } - - return 0; -} - -int APIDownstreamConnection::push_request_headers() { - auto &req = downstream_->request(); - auto &resp = downstream_->response(); - - auto path = - StringRef{std::begin(req.path), - std::find(std::begin(req.path), std::end(req.path), '?')}; - - if (path != StringRef::from_lit("/api/v1beta1/backendconfig")) { - send_reply(404, API_FAILURE); - - return 0; - } - - if (req.method != HTTP_POST && req.method != HTTP_PUT) { - resp.fs.add_header_token(StringRef::from_lit("allow"), - StringRef::from_lit("POST, PUT"), false, -1); - send_reply(405, API_FAILURE); - - return 0; - } - - // This works with req.fs.content_length == -1 - if (req.fs.content_length > - static_cast(get_config()->api.max_request_body)) { - send_reply(413, API_FAILURE); - - return 0; - } - - return 0; -} - -int APIDownstreamConnection::push_upload_data_chunk(const uint8_t *data, - size_t datalen) { - if (abandoned_) { - return 0; - } - - auto output = downstream_->get_request_buf(); - - auto &apiconf = get_config()->api; - - if (output->rleft() + datalen > apiconf.max_request_body) { - send_reply(413, API_FAILURE); - - return 0; - } - - output->append(data, datalen); - - // We don't have to call Upstream::resume_read() here, because - // request buffer is effectively unlimited. Actually, we cannot - // call it here since it could recursively call this function again. - - return 0; -} - -int APIDownstreamConnection::end_upload_data() { - if (abandoned_) { - return 0; - } - - auto output = downstream_->get_request_buf(); - - std::array iov; - auto iovcnt = output->riovec(iov.data(), 2); - - if (iovcnt == 0) { - send_reply(200, API_SUCCESS); - - return 0; - } - - std::unique_ptr large_buf; - - // If data spans in multiple chunks, pull them up into one - // contiguous buffer. - if (iovcnt > 1) { - large_buf = make_unique(output->rleft()); - auto len = output->rleft(); - output->remove(large_buf.get(), len); - - iov[0].iov_base = large_buf.get(); - iov[0].iov_len = len; - } - - Config config{}; - config.conn.downstream = std::make_shared(); - const auto &downstreamconf = config.conn.downstream; - - auto &src = get_config()->conn.downstream; - - downstreamconf->timeout = src->timeout; - downstreamconf->connections_per_host = src->connections_per_host; - downstreamconf->connections_per_frontend = src->connections_per_frontend; - downstreamconf->request_buffer_size = src->request_buffer_size; - downstreamconf->response_buffer_size = src->response_buffer_size; - downstreamconf->family = src->family; - - std::set include_set; - - for (auto first = reinterpret_cast(iov[0].iov_base), - last = first + iov[0].iov_len; - first != last;) { - auto eol = std::find(first, last, '\n'); - if (eol == last) { - break; - } - - if (first == eol || *first == '#') { - first = ++eol; - continue; - } - - auto eq = std::find(first, eol, '='); - if (eq == eol) { - send_reply(400, API_FAILURE); - return 0; - } - - auto opt = StringRef{first, eq}; - auto optval = StringRef{eq + 1, eol}; - - auto optid = option_lookup_token(opt.c_str(), opt.size()); - - switch (optid) { - case SHRPX_OPTID_BACKEND: - break; - default: - first = ++eol; - continue; - } - - if (parse_config(&config, optid, opt, optval, include_set) != 0) { - send_reply(400, API_FAILURE); - return 0; - } - - first = ++eol; - } - - auto &tlsconf = get_config()->tls; - if (configure_downstream_group(&config, get_config()->http2_proxy, true, - tlsconf) != 0) { - send_reply(400, API_FAILURE); - return 0; - } - - auto conn_handler = worker_->get_connection_handler(); - - conn_handler->send_replace_downstream(downstreamconf); - - send_reply(200, API_SUCCESS); - - return 0; -} - -void APIDownstreamConnection::pause_read(IOCtrlReason reason) {} - -int APIDownstreamConnection::resume_read(IOCtrlReason reason, size_t consumed) { - return 0; -} - -void APIDownstreamConnection::force_resume_read() {} - -int APIDownstreamConnection::on_read() { return 0; } - -int APIDownstreamConnection::on_write() { return 0; } - -void APIDownstreamConnection::on_upstream_change(Upstream *uptream) {} - -bool APIDownstreamConnection::poolable() const { return false; } - -DownstreamAddrGroup * -APIDownstreamConnection::get_downstream_addr_group() const { - return nullptr; -} - -DownstreamAddr *APIDownstreamConnection::get_addr() const { return nullptr; } - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_api_downstream_connection.h nghttp2-0.6.7/src/shrpx_api_downstream_connection.h --- nghttp2-1.13.0/src/shrpx_api_downstream_connection.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_api_downstream_connection.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 SHRPX_API_DOWNSTREAM_CONNECTION_H -#define SHRPX_API_DOWNSTREAM_CONNECTION_H - -#include "shrpx_downstream_connection.h" - -namespace shrpx { - -class Worker; - -class APIDownstreamConnection : public DownstreamConnection { -public: - APIDownstreamConnection(Worker *worker); - virtual ~APIDownstreamConnection(); - virtual int attach_downstream(Downstream *downstream); - virtual void detach_downstream(Downstream *downstream); - - virtual int push_request_headers(); - virtual int push_upload_data_chunk(const uint8_t *data, size_t datalen); - virtual int end_upload_data(); - - virtual void pause_read(IOCtrlReason reason); - virtual int resume_read(IOCtrlReason reason, size_t consumed); - virtual void force_resume_read(); - - virtual int on_read(); - virtual int on_write(); - - virtual void on_upstream_change(Upstream *uptream); - - // true if this object is poolable. - virtual bool poolable() const; - - virtual DownstreamAddrGroup *get_downstream_addr_group() const; - virtual DownstreamAddr *get_addr() const; - - int send_reply(unsigned int http_status, int api_status); - -private: - Worker *worker_; - bool abandoned_; -}; - -} // namespace shrpx - -#endif // SHRPX_API_DOWNSTREAM_CONNECTION_H diff -Nru nghttp2-1.13.0/src/shrpx.cc nghttp2-0.6.7/src/shrpx.cc --- nghttp2-1.13.0/src/shrpx.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,68 +24,42 @@ */ #include "shrpx.h" +#include #include -#include #include -#ifdef HAVE_SYS_SOCKET_H #include -#endif // HAVE_SYS_SOCKET_H -#include -#ifdef HAVE_NETDB_H #include -#endif // HAVE_NETDB_H #include -#ifdef HAVE_NETINET_IN_H #include -#endif // HAVE_NETINET_IN_H -#include -#ifdef HAVE_ARPA_INET_H #include -#endif // HAVE_ARPA_INET_H -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H #include -#ifdef HAVE_SYSLOG_H #include -#endif // HAVE_SYSLOG_H -#ifdef HAVE_LIMITS_H +#include #include -#endif // HAVE_LIMITS_H -#ifdef HAVE_SYS_TIME_H -#include -#endif // HAVE_SYS_TIME_H -#include -#include #include #include #include #include #include -#include -#include #include #include -#include +#include + +#include #include #include "shrpx_config.h" +#include "shrpx_listen_handler.h" #include "shrpx_ssl.h" -#include "shrpx_log_config.h" +#include "shrpx_worker_config.h" #include "shrpx_worker.h" -#include "shrpx_http2_upstream.h" -#include "shrpx_http2_session.h" -#include "shrpx_worker_process.h" -#include "shrpx_process.h" -#include "shrpx_signal.h" -#include "shrpx_connection.h" #include "util.h" #include "app_helper.h" #include "ssl.h" -#include "template.h" extern char **environ; @@ -93,171 +67,287 @@ namespace shrpx { -// Deprecated: Environment variables to tell new binary the listening -// socket's file descriptors. They are not close-on-exec. -constexpr auto ENV_LISTENER4_FD = StringRef::from_lit("NGHTTPX_LISTENER4_FD"); -constexpr auto ENV_LISTENER6_FD = StringRef::from_lit("NGHTTPX_LISTENER6_FD"); - -// Deprecated: Environment variable to tell new binary the port number -// the current binary is listening to. -constexpr auto ENV_PORT = StringRef::from_lit("NGHTTPX_PORT"); - -// Deprecated: Environment variable to tell new binary the listening -// socket's file descriptor if frontend listens UNIX domain socket. -constexpr auto ENV_UNIX_FD = StringRef::from_lit("NGHTTP2_UNIX_FD"); -// Deprecated: Environment variable to tell new binary the UNIX domain -// socket path. -constexpr auto ENV_UNIX_PATH = StringRef::from_lit("NGHTTP2_UNIX_PATH"); - -// Prefix of environment variables to tell new binary the listening -// socket's file descriptor. They are not close-on-exec. For TCP -// socket, the value must be comma separated 2 parameters: tcp,. -// is file descriptor. For UNIX domain socket, the value must be -// comma separated 3 parameters: unix,,. is file -// descriptor. is a path to UNIX domain socket. -constexpr auto ENV_ACCEPT_PREFIX = StringRef::from_lit("NGHTTPX_ACCEPT_"); - -#ifndef _KERNEL_FASTOPEN -#define _KERNEL_FASTOPEN -// conditional define for TCP_FASTOPEN mostly on ubuntu -#ifndef TCP_FASTOPEN -#define TCP_FASTOPEN 23 -#endif - -// conditional define for SOL_TCP mostly on ubuntu -#ifndef SOL_TCP -#define SOL_TCP 6 -#endif -#endif - -struct SignalServer { - SignalServer() : ipc_fd{{-1, -1}}, worker_process_pid(-1) {} - ~SignalServer() { - if (ipc_fd[0] != -1) { - close(ipc_fd[0]); - } - if (ipc_fd[1] != -1) { - shutdown(ipc_fd[1], SHUT_WR); - close(ipc_fd[1]); - } - } +namespace { +const int REOPEN_LOG_SIGNAL = SIGUSR1; +const int EXEC_BINARY_SIGNAL = SIGUSR2; +const int GRACEFUL_SHUTDOWN_SIGNAL = SIGQUIT; +} // namespace - std::array ipc_fd; - pid_t worker_process_pid; -}; +// Environment variables to tell new binary the listening socket's +// file descriptors. They are not close-on-exec. +#define ENV_LISTENER4_FD "NGHTTPX_LISTENER4_FD" +#define ENV_LISTENER6_FD "NGHTTPX_LISTENER6_FD" + +// Environment variable to tell new binary the port number the current +// binary is listening to. +#define ENV_PORT "NGHTTPX_PORT" namespace { -int chown_to_running_user(const char *path) { - return chown(path, get_config()->uid, get_config()->gid); +void ssl_acceptcb(evconnlistener *listener, int fd, sockaddr *addr, int addrlen, + void *arg) { + auto handler = static_cast(arg); + handler->accept_connection(fd, addr, addrlen); } } // namespace namespace { -void save_pid() { - constexpr auto SUFFIX = StringRef::from_lit(".XXXXXX"); - auto &pid_file = get_config()->pid_file; +bool is_ipv6_numeric_addr(const char *host) { + uint8_t dst[16]; + return inet_pton(AF_INET6, host, dst) == 1; +} +} // namespace - auto len = get_config()->pid_file.size() + SUFFIX.size(); - auto buf = make_unique(len + 1); - auto p = buf.get(); +namespace { +int resolve_hostname(sockaddr_union *addr, size_t *addrlen, + const char *hostname, uint16_t port, int family) { + addrinfo hints; + int rv; - p = std::copy(std::begin(pid_file), std::end(pid_file), p); - p = std::copy(std::begin(SUFFIX), std::end(SUFFIX), p); - *p = '\0'; + auto service = util::utos(port); + memset(&hints, 0, sizeof(addrinfo)); - auto temp_path = buf.get(); + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; +#ifdef AI_ADDRCONFIG + hints.ai_flags |= AI_ADDRCONFIG; +#endif // AI_ADDRCONFIG + addrinfo *res; - auto fd = mkstemp(temp_path); - if (fd == -1) { - auto error = errno; - LOG(ERROR) << "Could not save PID to file " << pid_file << ": " - << strerror(error); - exit(EXIT_FAILURE); + rv = getaddrinfo(hostname, service.c_str(), &hints, &res); + if (rv != 0) { + LOG(FATAL) << "Unable to resolve address for " << hostname << ": " + << gai_strerror(rv); + return -1; } - auto content = util::utos(get_config()->pid) + '\n'; + char host[NI_MAXHOST]; + rv = getnameinfo(res->ai_addr, res->ai_addrlen, host, sizeof(host), 0, 0, + NI_NUMERICHOST); + if (rv != 0) { + LOG(FATAL) << "Address resolution for " << hostname + << " failed: " << gai_strerror(rv); - if (write(fd, content.c_str(), content.size()) == -1) { - auto error = errno; - LOG(ERROR) << "Could not save PID to file " << pid_file << ": " - << strerror(error); - exit(EXIT_FAILURE); + freeaddrinfo(res); + + return -1; } - if (fsync(fd) == -1) { - auto error = errno; - LOG(ERROR) << "Could not save PID to file " << pid_file << ": " - << strerror(error); - exit(EXIT_FAILURE); + if (LOG_ENABLED(INFO)) { + LOG(INFO) << "Address resolution for " << hostname + << " succeeded: " << host; } - close(fd); + memcpy(addr, res->ai_addr, res->ai_addrlen); + *addrlen = res->ai_addrlen; + freeaddrinfo(res); + return 0; +} +} // namespace - if (rename(temp_path, pid_file.c_str()) == -1) { - auto error = errno; - LOG(ERROR) << "Could not save PID to file " << pid_file << ": " - << strerror(error); +namespace { +void evlistener_errorcb(evconnlistener *listener, void *ptr) { + LOG(ERROR) << "Accepting incoming connection failed"; - unlink(temp_path); + auto listener_handler = static_cast(ptr); - exit(EXIT_FAILURE); - } + listener_handler->disable_evlistener_temporary( + &get_config()->listener_disable_timeout); +} +} // namespace - if (get_config()->uid != 0) { - if (chown_to_running_user(pid_file.c_str()) == -1) { - auto error = errno; - LOG(WARN) << "Changing owner of pid file " << pid_file - << " failed: " << strerror(error); - } - } +namespace { +evconnlistener *new_evlistener(ListenHandler *handler, int fd) { + auto evlistener = evconnlistener_new( + handler->get_evbase(), ssl_acceptcb, handler, + LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, get_config()->backlog, fd); + evconnlistener_set_error_cb(evlistener, evlistener_errorcb); + return evlistener; } } // namespace namespace { -void exec_binary(SignalServer *ssv) { +evconnlistener *create_evlistener(ListenHandler *handler, int family) { + { + auto envfd = + getenv(family == AF_INET ? ENV_LISTENER4_FD : ENV_LISTENER6_FD); + auto envport = getenv(ENV_PORT); + + if (envfd && envport) { + auto fd = strtoul(envfd, nullptr, 10); + auto port = strtoul(envport, nullptr, 10); + + // Only do this iff NGHTTPX_PORT == get_config()->port. + // Otherwise, close fd, and create server socket as usual. + + if (port == get_config()->port) { + LOG(NOTICE) << "Listening on port " << get_config()->port; + + return new_evlistener(handler, fd); + } + + LOG(WARN) << "Port was changed between old binary (" << port + << ") and new binary (" << get_config()->port << ")"; + close(fd); + } + } + + addrinfo hints; + int fd = -1; int rv; - sigset_t oldset; - LOG(NOTICE) << "Executing new binary"; + auto service = util::utos(get_config()->port); + memset(&hints, 0, sizeof(addrinfo)); + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; +#ifdef AI_ADDRCONFIG + hints.ai_flags |= AI_ADDRCONFIG; +#endif // AI_ADDRCONFIG + + auto node = strcmp("*", get_config()->host.get()) == 0 + ? nullptr + : get_config()->host.get(); + + addrinfo *res, *rp; + rv = getaddrinfo(node, service.c_str(), &hints, &res); + if (rv != 0) { + if (LOG_ENABLED(INFO)) { + LOG(INFO) << "Unable to get IPv" << (family == AF_INET ? "4" : "6") + << " address for " << get_config()->host.get() << ": " + << gai_strerror(rv); + } + return nullptr; + } + for (rp = res; rp; rp = rp->ai_next) { + fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (fd == -1) { + continue; + } + int val = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, + static_cast(sizeof(val))) == -1) { + close(fd); + continue; + } + evutil_make_socket_nonblocking(fd); +#ifdef IPV6_V6ONLY + if (family == AF_INET6) { + if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, + static_cast(sizeof(val))) == -1) { + close(fd); + continue; + } + } +#endif // IPV6_V6ONLY + if (bind(fd, rp->ai_addr, rp->ai_addrlen) == 0) { + break; + } + close(fd); + } + + if (!rp) { + LOG(WARN) << "Listening " << (family == AF_INET ? "IPv4" : "IPv6") + << " socket failed"; + + freeaddrinfo(res); + + return nullptr; + } + + char host[NI_MAXHOST]; + rv = getnameinfo(rp->ai_addr, rp->ai_addrlen, host, sizeof(host), nullptr, 0, + NI_NUMERICHOST); + + freeaddrinfo(res); - rv = shrpx_signal_block_all(&oldset); if (rv != 0) { - auto error = errno; - LOG(ERROR) << "Blocking all signals failed: " << strerror(error); + LOG(WARN) << gai_strerror(rv); - return; + close(fd); + + return nullptr; } - auto pid = fork(); + LOG(NOTICE) << "Listening on " << host << ", port " << get_config()->port; - if (pid != 0) { - if (pid == -1) { + return new_evlistener(handler, fd); +} +} // namespace + +namespace { +void drop_privileges() { + if (getuid() == 0 && get_config()->uid != 0) { + if (setgid(get_config()->gid) != 0) { + auto error = errno; + LOG(FATAL) << "Could not change gid: " << strerror(error); + exit(EXIT_FAILURE); + } + if (setuid(get_config()->uid) != 0) { auto error = errno; - LOG(ERROR) << "fork() failed errno=" << error; + LOG(FATAL) << "Could not change uid: " << strerror(error); + exit(EXIT_FAILURE); + } + if (setuid(0) != -1) { + LOG(FATAL) << "Still have root privileges?"; + exit(EXIT_FAILURE); } + } +} +} // namespace - rv = shrpx_signal_set(&oldset); +namespace { +void save_pid() { + std::ofstream out(get_config()->pid_file.get(), std::ios::binary); + out << get_config()->pid << "\n"; + out.close(); + if (!out) { + LOG(ERROR) << "Could not save PID to file " << get_config()->pid_file.get(); + exit(EXIT_FAILURE); + } - if (rv != 0) { + if (get_config()->uid != 0) { + if (chown(get_config()->pid_file.get(), get_config()->uid, + get_config()->gid) == -1) { auto error = errno; - LOG(FATAL) << "Restoring signal mask failed: " << strerror(error); - - exit(EXIT_FAILURE); + LOG(WARN) << "Changing owner of pid file " << get_config()->pid_file.get() + << " failed: " << strerror(error); } + } +} +} // namespace - return; +namespace { +void reopen_log_signal_cb(evutil_socket_t sig, short events, void *arg) { + auto listener_handler = static_cast(arg); + + if (LOG_ENABLED(INFO)) { + LOG(INFO) << "Reopening log files: worker_info(" << worker_config << ")"; + } + + (void)reopen_log_files(); + + if (get_config()->num_worker > 1) { + listener_handler->worker_reopen_log_files(); } +} +} // namespace - // child process +namespace { +void exec_binary_signal_cb(evutil_socket_t sig, short events, void *arg) { + auto listener_handler = static_cast(arg); - shrpx_signal_unset_master_proc_ign_handler(); + LOG(NOTICE) << "Executing new binary"; - rv = shrpx_signal_unblock_all(); - if (rv != 0) { + auto pid = fork(); + + if (pid == -1) { auto error = errno; - LOG(ERROR) << "Unblocking all signals failed: " << strerror(error); + LOG(ERROR) << "fork() failed errno=" << error; + return; + } - _Exit(EXIT_FAILURE); + if (pid != 0) { + return; } auto exec_path = util::get_exec_path(get_config()->argc, get_config()->argv, @@ -265,54 +355,46 @@ if (!exec_path) { LOG(ERROR) << "Could not resolve the executable path"; - _Exit(EXIT_FAILURE); + return; } - auto argv = make_unique(get_config()->argc + 1); + auto argv = util::make_unique(get_config()->argc + 1); argv[0] = exec_path; for (int i = 1; i < get_config()->argc; ++i) { - argv[i] = get_config()->argv[i]; + argv[i] = strdup(get_config()->argv[i]); } argv[get_config()->argc] = nullptr; size_t envlen = 0; for (char **p = environ; *p; ++p, ++envlen) ; - - auto &listenerconf = get_config()->conn.listener; - - auto envp = make_unique(envlen + listenerconf.addrs.size() + 1); + // 3 for missing fd4, fd6 and port. + auto envp = util::make_unique(envlen + 3 + 1); size_t envidx = 0; - std::vector fd_envs; - for (size_t i = 0; i < listenerconf.addrs.size(); ++i) { - auto &addr = listenerconf.addrs[i]; - auto s = ENV_ACCEPT_PREFIX.str(); - s += util::utos(i + 1); - s += '='; - if (addr.host_unix) { - s += "unix,"; - s += util::utos(addr.fd); - s += ','; - s += addr.host; - } else { - s += "tcp,"; - s += util::utos(addr.fd); - } - - fd_envs.emplace_back(s); - envp[envidx++] = const_cast(fd_envs.back().c_str()); - } + auto evlistener4 = listener_handler->get_evlistener4(); + if (evlistener4) { + std::string fd4 = ENV_LISTENER4_FD "="; + fd4 += util::utos(evconnlistener_get_fd(evlistener4)); + envp[envidx++] = strdup(fd4.c_str()); + } + + auto evlistener6 = listener_handler->get_evlistener6(); + if (evlistener6) { + std::string fd6 = ENV_LISTENER6_FD "="; + fd6 += util::utos(evconnlistener_get_fd(evlistener6)); + envp[envidx++] = strdup(fd6.c_str()); + } + + std::string port = ENV_PORT "="; + port += util::utos(get_config()->port); + envp[envidx++] = strdup(port.c_str()); for (size_t i = 0; i < envlen; ++i) { - auto env = StringRef{environ[i]}; - if (util::starts_with(env, ENV_ACCEPT_PREFIX) || - util::starts_with(env, ENV_LISTENER4_FD) || - util::starts_with(env, ENV_LISTENER6_FD) || - util::starts_with(env, ENV_PORT) || - util::starts_with(env, ENV_UNIX_FD) || - util::starts_with(env, ENV_UNIX_PATH)) { + if (strcmp(ENV_LISTENER4_FD, environ[i]) == 0 || + strcmp(ENV_LISTENER6_FD, environ[i]) == 0 || + strcmp(ENV_PORT, environ[i]) == 0) { continue; } @@ -332,9 +414,6 @@ } } - // restores original stderr - util::restore_original_fds(); - if (execve(argv[0], argv.get(), envp.get()) == -1) { auto error = errno; LOG(ERROR) << "execve failed: errno=" << error; @@ -344,659 +423,205 @@ } // namespace namespace { -void ipc_send(SignalServer *ssv, uint8_t ipc_event) { - ssize_t nwrite; - while ((nwrite = write(ssv->ipc_fd[1], &ipc_event, 1)) == -1 && - errno == EINTR) - ; +void graceful_shutdown_signal_cb(evutil_socket_t sig, short events, void *arg) { + auto listener_handler = static_cast(arg); - if (nwrite < 0) { - auto error = errno; - LOG(ERROR) << "Could not send IPC event to worker process: " - << strerror(error); - return; - } + LOG(NOTICE) << "Graceful shutdown signal received"; - if (nwrite == 0) { - LOG(ERROR) << "Could not send IPC event due to pipe overflow"; - return; - } + worker_config->graceful_shutdown = true; + + listener_handler->disable_evlistener(); + + // After disabling accepting new connection, disptach incoming + // connection in backlog. + + listener_handler->accept_pending_connection(); + + listener_handler->graceful_shutdown_worker(); } } // namespace namespace { -void reopen_log(SignalServer *ssv) { - LOG(NOTICE) << "Reopening log files: master process"; - - (void)reopen_log_files(); - redirect_stderr_to_errorlog(); - ipc_send(ssv, SHRPX_IPC_REOPEN_LOG); +std::unique_ptr generate_time() { + return util::make_unique( + util::format_common_log(std::chrono::system_clock::now())); } } // namespace namespace { -void signal_cb(struct ev_loop *loop, ev_signal *w, int revents) { - auto ssv = static_cast(w->data); - if (ssv->worker_process_pid == -1) { - ev_break(loop); - return; - } - - switch (w->signum) { - case REOPEN_LOG_SIGNAL: - reopen_log(ssv); - return; - case EXEC_BINARY_SIGNAL: - exec_binary(ssv); - return; - case GRACEFUL_SHUTDOWN_SIGNAL: - ipc_send(ssv, SHRPX_IPC_GRACEFUL_SHUTDOWN); - return; - default: - kill(ssv->worker_process_pid, w->signum); - ev_break(loop); - return; +void refresh_cb(evutil_socket_t sig, short events, void *arg) { + auto listener_handler = static_cast(arg); + auto worker_stat = listener_handler->get_worker_stat(); + + mod_config()->cached_time = generate_time(); + // In multi threaded mode (get_config()->num_worker > 1), we have to + // wait for event notification to workers to finish. + if (get_config()->num_worker == 1 && worker_config->graceful_shutdown && + (!worker_stat || worker_stat->num_connections == 0)) { + event_base_loopbreak(listener_handler->get_evbase()); } } } // namespace namespace { -void worker_process_child_cb(struct ev_loop *loop, ev_child *w, int revents) { - log_chld(w->rpid, w->rstatus, "Worker process"); - - ev_child_stop(loop, w); +int event_loop() { + int rv; - ev_break(loop); -} -} // namespace + auto evbase = event_base_new(); + if (!evbase) { + LOG(FATAL) << "event_base_new() failed"; + exit(EXIT_FAILURE); + } + SSL_CTX *sv_ssl_ctx, *cl_ssl_ctx; -struct InheritedAddr { - // IP address if TCP socket. Otherwise, UNIX domain socket path. - ImmutableString host; - uint16_t port; - // true if UNIX domain socket path - bool host_unix; - int fd; - bool used; -}; + if (get_config()->client_mode) { + sv_ssl_ctx = nullptr; + cl_ssl_ctx = get_config()->downstream_no_tls + ? nullptr + : ssl::create_ssl_client_context(); + } else { + sv_ssl_ctx = + get_config()->upstream_no_tls ? nullptr : get_config()->default_ssl_ctx; + cl_ssl_ctx = get_config()->http2_bridge && !get_config()->downstream_no_tls + ? ssl::create_ssl_client_context() + : nullptr; + } -namespace { -int create_unix_domain_server_socket(UpstreamAddr &faddr, - std::vector &iaddrs) { - auto found = std::find_if( - std::begin(iaddrs), std::end(iaddrs), [&faddr](const InheritedAddr &ia) { - return !ia.used && ia.host_unix && ia.host == faddr.host; - }); + auto listener_handler = new ListenHandler(evbase, sv_ssl_ctx, cl_ssl_ctx); + if (get_config()->daemon) { + if (daemon(0, 0) == -1) { + auto error = errno; + LOG(FATAL) << "Failed to daemonize: " << strerror(error); + exit(EXIT_FAILURE); + } - if (found != std::end(iaddrs)) { - LOG(NOTICE) << "Listening on UNIX domain socket " << faddr.host - << (faddr.tls ? ", tls" : ""); - (*found).used = true; - faddr.fd = (*found).fd; - faddr.hostport = "localhost"; + // We get new PID after successful daemon(). + mod_config()->pid = getpid(); + } - return 0; + if (get_config()->pid_file) { + save_pid(); } -#ifdef SOCK_NONBLOCK - auto fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); - if (fd == -1) { - auto error = errno; - LOG(WARN) << "socket() syscall failed: " << strerror(error); - return -1; + auto evlistener6 = create_evlistener(listener_handler, AF_INET6); + auto evlistener4 = create_evlistener(listener_handler, AF_INET); + if (!evlistener6 && !evlistener4) { + LOG(FATAL) << "Failed to listen on address " << get_config()->host.get() + << ", port " << get_config()->port; + exit(EXIT_FAILURE); } -#else // !SOCK_NONBLOCK - auto fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) { - auto error = errno; - LOG(WARN) << "socket() syscall failed: " << strerror(error); - return -1; + + listener_handler->set_evlistener4(evlistener4); + listener_handler->set_evlistener6(evlistener6); + + // ListenHandler loads private key, and we listen on a priveleged port. + // After that, we drop the root privileges if needed. + drop_privileges(); + +#ifndef NOTHREADS + sigset_t signals; + sigemptyset(&signals); + sigaddset(&signals, REOPEN_LOG_SIGNAL); + sigaddset(&signals, EXEC_BINARY_SIGNAL); + sigaddset(&signals, GRACEFUL_SHUTDOWN_SIGNAL); + rv = pthread_sigmask(SIG_BLOCK, &signals, nullptr); + if (rv != 0) { + LOG(ERROR) << "Blocking signals failed: " << strerror(rv); } - util::make_socket_nonblocking(fd); -#endif // !SOCK_NONBLOCK - int val = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, - static_cast(sizeof(val))) == -1) { - auto error = errno; - LOG(WARN) << "Failed to set SO_REUSEADDR option to listener socket: " - << strerror(error); - close(fd); - return -1; +#endif // !NOTHREADS + + if (get_config()->num_worker > 1) { + listener_handler->create_worker_thread(get_config()->num_worker); + } else if (get_config()->downstream_proto == PROTO_HTTP2) { + listener_handler->create_http2_session(); + } else { + listener_handler->create_http1_connect_blocker(); } - sockaddr_union addr; - addr.un.sun_family = AF_UNIX; - if (faddr.host.size() + 1 > sizeof(addr.un.sun_path)) { - LOG(FATAL) << "UNIX domain socket path " << faddr.host << " is too long > " - << sizeof(addr.un.sun_path); - close(fd); - return -1; +#ifndef NOTHREADS + rv = pthread_sigmask(SIG_UNBLOCK, &signals, nullptr); + if (rv != 0) { + LOG(ERROR) << "Unblocking signals failed: " << strerror(rv); } - // copy path including terminal NULL - std::copy_n(faddr.host.c_str(), faddr.host.size() + 1, addr.un.sun_path); +#endif // !NOTHREADS - // unlink (remove) already existing UNIX domain socket path - unlink(faddr.host.c_str()); + auto reopen_log_signal_event = evsignal_new( + evbase, REOPEN_LOG_SIGNAL, reopen_log_signal_cb, listener_handler); - if (bind(fd, &addr.sa, sizeof(addr.un)) != 0) { - auto error = errno; - LOG(FATAL) << "Failed to bind UNIX domain socket: " << strerror(error); - close(fd); - return -1; + if (!reopen_log_signal_event) { + LOG(ERROR) << "evsignal_new failed"; + } else { + rv = event_add(reopen_log_signal_event, nullptr); + if (rv < 0) { + LOG(ERROR) << "event_add for reopen_log_signal_event failed"; + } } - auto &listenerconf = get_config()->conn.listener; + auto exec_binary_signal_event = evsignal_new( + evbase, EXEC_BINARY_SIGNAL, exec_binary_signal_cb, listener_handler); + rv = event_add(exec_binary_signal_event, nullptr); - if (listen(fd, listenerconf.backlog) != 0) { - auto error = errno; - LOG(FATAL) << "Failed to listen to UNIX domain socket: " << strerror(error); - close(fd); - return -1; - } + if (rv == -1) { + LOG(FATAL) << "event_add for exec_binary_signal_event failed"; - LOG(NOTICE) << "Listening on UNIX domain socket " << faddr.host - << (faddr.tls ? ", tls" : ""); + exit(EXIT_FAILURE); + } - faddr.fd = fd; - faddr.hostport = "localhost"; + auto graceful_shutdown_signal_event = + evsignal_new(evbase, GRACEFUL_SHUTDOWN_SIGNAL, + graceful_shutdown_signal_cb, listener_handler); - return 0; -} -} // namespace + rv = event_add(graceful_shutdown_signal_event, nullptr); -namespace { -int create_tcp_server_socket(UpstreamAddr &faddr, - std::vector &iaddrs) { - int fd = -1; - int rv; + if (rv == -1) { + LOG(FATAL) << "event_add for graceful_shutdown_signal_event failed"; - auto &listenerconf = get_config()->conn.listener; + exit(EXIT_FAILURE); + } - auto service = util::utos(faddr.port); - addrinfo hints{}; - hints.ai_family = faddr.family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; -#ifdef AI_ADDRCONFIG - hints.ai_flags |= AI_ADDRCONFIG; -#endif // AI_ADDRCONFIG + auto refresh_event = + event_new(evbase, -1, EV_PERSIST, refresh_cb, listener_handler); - auto node = - faddr.host == StringRef::from_lit("*") ? nullptr : faddr.host.c_str(); + if (!refresh_event) { + LOG(ERROR) << "event_new failed"; - addrinfo *res, *rp; - rv = getaddrinfo(node, service.c_str(), &hints, &res); - if (rv != 0) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Unable to get IPv" << (faddr.family == AF_INET ? "4" : "6") - << " address for " << faddr.host << ", port " << faddr.port - << ": " << gai_strerror(rv); - } - return -1; + exit(EXIT_FAILURE); } - auto res_d = defer(freeaddrinfo, res); + timeval refresh_timeout = {1, 0}; + rv = event_add(refresh_event, &refresh_timeout); - std::array host; + if (rv == -1) { + LOG(ERROR) << "Adding refresh_event failed"; - for (rp = res; rp; rp = rp->ai_next) { + exit(EXIT_FAILURE); + } - rv = getnameinfo(rp->ai_addr, rp->ai_addrlen, host.data(), host.size(), - nullptr, 0, NI_NUMERICHOST); + if (LOG_ENABLED(INFO)) { + LOG(INFO) << "Entering event loop"; + } + event_base_loop(evbase, 0); - if (rv != 0) { - LOG(WARN) << "getnameinfo() failed: " << gai_strerror(rv); - continue; - } + listener_handler->join_worker(); - auto found = std::find_if(std::begin(iaddrs), std::end(iaddrs), - [&host, &faddr](const InheritedAddr &ia) { - return !ia.used && !ia.host_unix && - ia.host == host.data() && - ia.port == faddr.port; - }); - - if (found != std::end(iaddrs)) { - (*found).used = true; - fd = (*found).fd; - break; - } - -#ifdef SOCK_NONBLOCK - fd = - socket(rp->ai_family, rp->ai_socktype | SOCK_NONBLOCK, rp->ai_protocol); - if (fd == -1) { - auto error = errno; - LOG(WARN) << "socket() syscall failed: " << strerror(error); - continue; - } -#else // !SOCK_NONBLOCK - fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (fd == -1) { - auto error = errno; - LOG(WARN) << "socket() syscall failed: " << strerror(error); - continue; - } - util::make_socket_nonblocking(fd); -#endif // !SOCK_NONBLOCK - int val = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, - static_cast(sizeof(val))) == -1) { - auto error = errno; - LOG(WARN) << "Failed to set SO_REUSEADDR option to listener socket: " - << strerror(error); - close(fd); - continue; - } - -#ifdef IPV6_V6ONLY - if (faddr.family == AF_INET6) { - if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, - static_cast(sizeof(val))) == -1) { - auto error = errno; - LOG(WARN) << "Failed to set IPV6_V6ONLY option to listener socket: " - << strerror(error); - close(fd); - continue; - } - } -#endif // IPV6_V6ONLY - -#ifdef TCP_DEFER_ACCEPT - val = 3; - if (setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val, - static_cast(sizeof(val))) == -1) { - auto error = errno; - LOG(WARN) << "Failed to set TCP_DEFER_ACCEPT option to listener socket: " - << strerror(error); - } -#endif // TCP_DEFER_ACCEPT - - // When we are executing new binary, and the old binary did not - // bind privileged port (< 1024) for some reason, binding to those - // ports will fail with permission denied error. - if (bind(fd, rp->ai_addr, rp->ai_addrlen) == -1) { - auto error = errno; - LOG(WARN) << "bind() syscall failed: " << strerror(error); - close(fd); - continue; - } - - if (listenerconf.fastopen > 0) { - val = listenerconf.fastopen; - if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &val, - static_cast(sizeof(val))) == -1) { - auto error = errno; - LOG(WARN) << "Failed to set TCP_FASTOPEN option to listener socket: " - << strerror(error); - } - } - - if (listen(fd, listenerconf.backlog) == -1) { - auto error = errno; - LOG(WARN) << "listen() syscall failed: " << strerror(error); - close(fd); - continue; - } - - break; - } - - if (!rp) { - LOG(WARN) << "Listening " << (faddr.family == AF_INET ? "IPv4" : "IPv6") - << " socket failed"; - - return -1; - } - - faddr.fd = fd; - faddr.hostport = util::make_http_hostport(StringRef{host.data()}, faddr.port); - - LOG(NOTICE) << "Listening on " << faddr.hostport - << (faddr.tls ? ", tls" : ""); - - return 0; -} -} // namespace - -namespace { -int create_acceptor_socket() { - int rv; - - auto &listenerconf = mod_config()->conn.listener; - - std::vector iaddrs; - - { - // Upgrade from 1.7.0 or earlier - auto portenv = getenv(ENV_PORT.c_str()); - if (portenv) { - size_t i = 1; - for (auto env_name : {ENV_LISTENER4_FD, ENV_LISTENER6_FD}) { - auto fdenv = getenv(env_name.c_str()); - if (fdenv) { - auto name = ENV_ACCEPT_PREFIX.str(); - name += util::utos(i); - std::string value = "tcp,"; - value += fdenv; - setenv(name.c_str(), value.c_str(), 0); - ++i; - } - } - } else { - auto pathenv = getenv(ENV_UNIX_PATH.c_str()); - auto fdenv = getenv(ENV_UNIX_FD.c_str()); - if (pathenv && fdenv) { - auto name = ENV_ACCEPT_PREFIX.str(); - name += '1'; - std::string value = "unix,"; - value += fdenv; - value += ','; - value += pathenv; - setenv(name.c_str(), value.c_str(), 0); - } - } - } - - for (size_t i = 1;; ++i) { - auto name = ENV_ACCEPT_PREFIX.str(); - name += util::utos(i); - auto env = getenv(name.c_str()); - if (!env) { - break; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Read env " << name << "=" << env; - } - - auto end_type = strchr(env, ','); - if (!end_type) { - continue; - } - - auto type = StringRef(env, end_type); - auto value = end_type + 1; - - if (type == StringRef::from_lit("unix")) { - auto endfd = strchr(value, ','); - if (!endfd) { - continue; - } - auto fd = util::parse_uint(reinterpret_cast(value), - endfd - value); - if (fd == -1) { - LOG(WARN) << "Could not parse file descriptor from " - << std::string(value, endfd - value); - continue; - } - - auto path = endfd + 1; - if (strlen(path) == 0) { - LOG(WARN) << "Empty UNIX domain socket path (fd=" << fd << ")"; - close(fd); - continue; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Inherit UNIX domain socket fd=" << fd - << ", path=" << path; - } - - InheritedAddr addr{}; - addr.host = path; - addr.host_unix = true; - addr.fd = static_cast(fd); - iaddrs.push_back(std::move(addr)); - } - - if (type == StringRef::from_lit("tcp")) { - auto fd = util::parse_uint(value); - if (fd == -1) { - LOG(WARN) << "Could not parse file descriptor from " << value; - continue; - } - - sockaddr_union su; - socklen_t salen = sizeof(su); - - if (getsockname(fd, &su.sa, &salen) != 0) { - auto error = errno; - LOG(WARN) << "getsockname() syscall failed (fd=" << fd - << "): " << strerror(error); - close(fd); - continue; - } - - uint16_t port; - - switch (su.storage.ss_family) { - case AF_INET: - port = ntohs(su.in.sin_port); - break; - case AF_INET6: - port = ntohs(su.in6.sin6_port); - break; - default: - close(fd); - continue; - } - - std::array host; - rv = getnameinfo(&su.sa, salen, host.data(), host.size(), nullptr, 0, - NI_NUMERICHOST); - if (rv != 0) { - LOG(WARN) << "getnameinfo() failed (fd=" << fd - << "): " << gai_strerror(rv); - close(fd); - continue; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Inherit TCP socket fd=" << fd - << ", address=" << host.data() << ", port=" << port; - } - - InheritedAddr addr{}; - addr.host = host.data(); - addr.port = static_cast(port); - addr.fd = static_cast(fd); - iaddrs.push_back(std::move(addr)); - continue; - } - } - - for (auto &addr : listenerconf.addrs) { - if (addr.host_unix) { - if (create_unix_domain_server_socket(addr, iaddrs) != 0) { - return -1; - } - - if (get_config()->uid != 0) { - // fd is not associated to inode, so we cannot use fchown(2) - // here. https://lkml.org/lkml/2004/11/1/84 - if (chown_to_running_user(addr.host.c_str()) == -1) { - auto error = errno; - LOG(WARN) << "Changing owner of UNIX domain socket " << addr.host - << " failed: " << strerror(error); - } - } - continue; - } - - if (create_tcp_server_socket(addr, iaddrs) != 0) { - return -1; - } - } - - for (auto &ia : iaddrs) { - if (ia.used) { - continue; - } - - close(ia.fd); - } - - return 0; -} -} // namespace - -namespace { -int call_daemon() { -#ifdef __sgi - return _daemonize(0, 0, 0, 0); -#else // !__sgi - return daemon(0, 0); -#endif // !__sgi -} -} // namespace - -namespace { -pid_t fork_worker_process(SignalServer *ssv) { - int rv; - sigset_t oldset; - - rv = shrpx_signal_block_all(&oldset); - if (rv != 0) { - auto error = errno; - LOG(ERROR) << "Blocking all signals failed: " << strerror(error); - - return -1; - } - - auto pid = fork(); - - if (pid == 0) { - ev_loop_fork(EV_DEFAULT); - - shrpx_signal_set_worker_proc_ign_handler(); - - rv = shrpx_signal_unblock_all(); - if (rv != 0) { - auto error = errno; - LOG(FATAL) << "Unblocking all signals failed: " << strerror(error); - - _Exit(EXIT_FAILURE); - } - - close(ssv->ipc_fd[1]); - WorkerProcessConfig wpconf{ssv->ipc_fd[0]}; - rv = worker_process_event_loop(&wpconf); - if (rv != 0) { - LOG(FATAL) << "Worker process returned error"; - - _Exit(EXIT_FAILURE); - } - - LOG(NOTICE) << "Worker process shutting down momentarily"; - - // call exit(...) instead of _Exit to get leak sanitizer report - _Exit(EXIT_SUCCESS); - } - - // parent process - if (pid == -1) { - auto error = errno; - LOG(ERROR) << "Could not spawn worker process: " << strerror(error); - } - - rv = shrpx_signal_set(&oldset); - if (rv != 0) { - auto error = errno; - LOG(FATAL) << "Restoring signal mask failed: " << strerror(error); - - exit(EXIT_FAILURE); - } - - if (pid == -1) { - return -1; - } - - close(ssv->ipc_fd[0]); - - LOG(NOTICE) << "Worker process [" << pid << "] spawned"; - - return pid; -} -} // namespace - -namespace { -int event_loop() { - int rv; - - shrpx_signal_set_master_proc_ign_handler(); - - if (get_config()->daemon) { - if (call_daemon() == -1) { - auto error = errno; - LOG(FATAL) << "Failed to daemonize: " << strerror(error); - return -1; - } - - // We get new PID after successful daemon(). - mod_config()->pid = getpid(); - - // daemon redirects stderr file descriptor to /dev/null, so we - // need this. - redirect_stderr_to_errorlog(); + if (refresh_event) { + event_free(refresh_event); } - - SignalServer ssv; - - rv = pipe(ssv.ipc_fd.data()); - if (rv == -1) { - auto error = errno; - LOG(WARN) << "Failed to create pipe to communicate worker process: " - << strerror(error); - return -1; + if (graceful_shutdown_signal_event) { + event_free(graceful_shutdown_signal_event); } - - for (int i = 0; i < 2; ++i) { - auto fd = ssv.ipc_fd[i]; - util::make_socket_nonblocking(fd); - util::make_socket_closeonexec(fd); + if (exec_binary_signal_event) { + event_free(exec_binary_signal_event); } - - if (create_acceptor_socket() != 0) { - return -1; + if (reopen_log_signal_event) { + event_free(reopen_log_signal_event); } - - auto loop = ev_default_loop(get_config()->ev_loop_flags); - - auto pid = fork_worker_process(&ssv); - - if (pid == -1) { - return -1; + if (evlistener4) { + evconnlistener_free(evlistener4); } - - ssv.worker_process_pid = pid; - - constexpr auto signals = std::array{ - {REOPEN_LOG_SIGNAL, EXEC_BINARY_SIGNAL, GRACEFUL_SHUTDOWN_SIGNAL}}; - auto sigevs = std::array(); - - for (size_t i = 0; i < signals.size(); ++i) { - auto sigev = &sigevs[i]; - ev_signal_init(sigev, signal_cb, signals[i]); - sigev->data = &ssv; - ev_signal_start(loop, sigev); - } - - ev_child worker_process_childev; - ev_child_init(&worker_process_childev, worker_process_child_cb, pid, 0); - worker_process_childev.data = nullptr; - ev_child_start(loop, &worker_process_childev); - - // Write PID file when we are ready to accept connection from peer. - // This makes easier to write restart script for nghttpx. Because - // when we know that PID file is recreated, it means we can send - // QUIT signal to the old process to make it shutdown gracefully. - if (!get_config()->pid_file.empty()) { - save_pid(); + if (evlistener6) { + evconnlistener_free(evlistener6); } - - ev_run(loop, 0); - return 0; } } // namespace @@ -1011,1306 +636,563 @@ } // namespace namespace { -constexpr auto DEFAULT_NPN_LIST = StringRef::from_lit("h2,h2-16,h2-14," +const char *DEFAULT_NPN_LIST = NGHTTP2_PROTO_VERSION_ID "," #ifdef HAVE_SPDYLAY - "spdy/3.1," + "spdy/3.1," #endif // HAVE_SPDYLAY - "http/1.1"); -} // namespace - -namespace { -constexpr auto DEFAULT_TLS_PROTO_LIST = StringRef::from_lit("TLSv1.2,TLSv1.1"); -} // namespace - -namespace { -constexpr auto DEFAULT_ACCESSLOG_FORMAT = StringRef::from_lit( - R"($remote_addr - - [$time_local] )" - R"("$request" $status $body_bytes_sent )" - R"("$http_referer" "$http_user_agent")"); -} // namespace - -namespace { -void fill_default_config() { - *mod_config() = {}; - - mod_config()->num_worker = 1; - mod_config()->conf_path = "/etc/nghttpx/nghttpx.conf"; - mod_config()->pid = getpid(); - - if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) { - mod_config()->ev_loop_flags = ev_recommended_backends() | EVBACKEND_KQUEUE; - } - - auto &tlsconf = mod_config()->tls; - { - auto &ticketconf = tlsconf.ticket; - { - auto &memcachedconf = ticketconf.memcached; - memcachedconf.max_retry = 3; - memcachedconf.max_fail = 2; - memcachedconf.interval = 10_min; - memcachedconf.family = AF_UNSPEC; - } - - auto &session_cacheconf = tlsconf.session_cache; - { - auto &memcachedconf = session_cacheconf.memcached; - memcachedconf.family = AF_UNSPEC; - } - - ticketconf.cipher = EVP_aes_128_cbc(); - } - - { - auto &ocspconf = tlsconf.ocsp; - // ocsp update interval = 14400 secs = 4 hours, borrowed from h2o - ocspconf.update_interval = 4_h; - ocspconf.fetch_ocsp_response_file = PKGDATADIR "/fetch-ocsp-response"; - } - - { - auto &dyn_recconf = tlsconf.dyn_rec; - dyn_recconf.warmup_threshold = 1_m; - dyn_recconf.idle_timeout = 1_s; - } - - tlsconf.session_timeout = std::chrono::hours(12); - - auto &httpconf = mod_config()->http; - httpconf.server_name = - StringRef::from_lit("nghttpx nghttp2/" NGHTTP2_VERSION); - httpconf.no_host_rewrite = true; - httpconf.request_header_field_buffer = 64_k; - httpconf.max_request_header_fields = 100; - httpconf.response_header_field_buffer = 64_k; - httpconf.max_response_header_fields = 500; - - auto &http2conf = mod_config()->http2; - { - auto &upstreamconf = http2conf.upstream; - - { - auto &timeoutconf = upstreamconf.timeout; - timeoutconf.settings = 10_s; - } - - // window bits for HTTP/2 and SPDY upstream connection per - // stream. 2**16-1 = 64KiB-1, which is HTTP/2 default. Please note - // that SPDY/3 default is 64KiB. - upstreamconf.window_bits = 16; - // HTTP/2 SPDY/3.1 has connection-level flow control. The default - // window size for HTTP/2 is 64KiB - 1. SPDY/3's default is 64KiB - upstreamconf.connection_window_bits = 16; - upstreamconf.max_concurrent_streams = 100; - - nghttp2_option_new(&upstreamconf.option); - nghttp2_option_set_no_auto_window_update(upstreamconf.option, 1); - nghttp2_option_set_no_recv_client_magic(upstreamconf.option, 1); - - // For API endpoint, we enable automatic window update. This is - // because we are a sink. - nghttp2_option_new(&upstreamconf.alt_mode_option); - nghttp2_option_set_no_recv_client_magic(upstreamconf.alt_mode_option, 1); - } - - { - auto &downstreamconf = http2conf.downstream; - - { - auto &timeoutconf = downstreamconf.timeout; - timeoutconf.settings = 10_s; - } - - downstreamconf.window_bits = 16; - downstreamconf.connection_window_bits = 30; - downstreamconf.max_concurrent_streams = 100; - - nghttp2_option_new(&downstreamconf.option); - nghttp2_option_set_no_auto_window_update(downstreamconf.option, 1); - nghttp2_option_set_peer_max_concurrent_streams(downstreamconf.option, 100); - } - - auto &loggingconf = mod_config()->logging; - { - auto &accessconf = loggingconf.access; - accessconf.format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT); - - auto &errorconf = loggingconf.error; - errorconf.file = "/dev/stderr"; - } - - loggingconf.syslog_facility = LOG_DAEMON; - - auto &connconf = mod_config()->conn; - { - auto &listenerconf = connconf.listener; - { - // Default accept() backlog - listenerconf.backlog = 512; - listenerconf.timeout.sleep = 30_s; - } - } - - { - auto &upstreamconf = connconf.upstream; - { - auto &timeoutconf = upstreamconf.timeout; - // Read timeout for HTTP2 upstream connection - timeoutconf.http2_read = 3_min; - - // Read timeout for non-HTTP2 upstream connection - timeoutconf.read = 1_min; - - // Write timeout for HTTP2/non-HTTP2 upstream connection - timeoutconf.write = 30_s; - } - } - - { - connconf.downstream = std::make_shared(); - auto &downstreamconf = *connconf.downstream; - { - auto &timeoutconf = downstreamconf.timeout; - // Read/Write timeouts for downstream connection - timeoutconf.read = 1_min; - timeoutconf.write = 30_s; - // Timeout for pooled (idle) connections - timeoutconf.idle_read = 2_s; - timeoutconf.max_backoff = 120_s; - } - - downstreamconf.connections_per_host = 8; - downstreamconf.request_buffer_size = 16_k; - downstreamconf.response_buffer_size = 128_k; - downstreamconf.family = AF_UNSPEC; - } - - auto &apiconf = mod_config()->api; - apiconf.max_request_body = 16_k; -} - -} // namespace - -namespace { -void print_version(std::ostream &out) { - out << get_config()->http.server_name.c_str() << std::endl; -} -} // namespace - -namespace { -void print_usage(std::ostream &out) { - out << R"(Usage: nghttpx [OPTIONS]... [ ] -A reverse proxy for HTTP/2, HTTP/1 and SPDY.)" << std::endl; -} -} // namespace - -namespace { -void print_help(std::ostream &out) { - print_usage(out); - out << R"( - - Set path to server's private key. Required unless - "no-tls" parameter is used in --frontend option. - Set path to server's certificate. Required unless - "no-tls" parameter is used in --frontend option. To - make OCSP stapling work, this must be an absolute path. - -Options: - The options are categorized into several groups. - -Connections: - -b, --backend=(,|unix:)[;[[:...]][[;PARAM]...] - - Set backend host and port. The multiple backend - addresses are accepted by repeating this option. UNIX - domain socket can be specified by prefixing path name - with "unix:" (e.g., unix:/var/run/backend.sock). - - Optionally, if s are given, the backend address - is only used if request matches the pattern. If - --http2-proxy is used, s are ignored. The - pattern matching is closely designed to ServeMux in - net/http package of Go programming language. - consists of path, host + path or just host. The path - must start with "/". If it ends with "/", it matches - all request path in its subtree. To deal with the - request to the directory without trailing slash, the - path which ends with "/" also matches the request path - which only lacks trailing '/' (e.g., path "/foo/" - matches request path "/foo"). If it does not end with - "/", it performs exact match against the request path. - If host is given, it performs exact match against the - request host. If host alone is given, "/" is appended - to it, so that it matches all request paths under the - host (e.g., specifying "nghttp2.org" equals to - "nghttp2.org/"). - - Patterns with host take precedence over patterns with - just path. Then, longer patterns take precedence over - shorter ones. - - Host can include "*" in the left most position to - indicate wildcard match (only suffix match is done). - The "*" must match at least one character. For example, - host pattern "*.nghttp2.org" matches against - "www.nghttp2.org" and "git.ngttp2.org", but does not - match against "nghttp2.org". The exact hosts match - takes precedence over the wildcard hosts match. - - If is omitted or empty string, "/" is used as - pattern, which matches all request paths (catch-all - pattern). The catch-all backend must be given. - - When doing a match, nghttpx made some normalization to - pattern, request host and path. For host part, they are - converted to lower case. For path part, percent-encoded - unreserved characters defined in RFC 3986 are decoded, - and any dot-segments (".." and ".") are resolved and - removed. - - For example, -b'127.0.0.1,8080;nghttp2.org/httpbin/' - matches the request host "nghttp2.org" and the request - path "/httpbin/get", but does not match the request host - "nghttp2.org" and the request path "/index.html". - - The multiple s can be specified, delimiting - them by ":". Specifying - -b'127.0.0.1,8080;nghttp2.org:www.nghttp2.org' has the - same effect to specify -b'127.0.0.1,8080;nghttp2.org' - and -b'127.0.0.1,8080;www.nghttp2.org'. - - The backend addresses sharing same are grouped - together forming load balancing group. - - Several parameters are accepted after . - The parameters are delimited by ";". The available - parameters are: "proto=", "tls", - "sni=", "fall=", "rise=", and - "affinity=". The parameter consists of keyword, - and optionally followed by "=" and value. For example, - the parameter "proto=h2" consists of the keyword "proto" - and value "h2". The parameter "tls" consists of the - keyword "tls" without value. Each parameter is - described as follows. - - The backend application protocol can be specified using - optional "proto" parameter, and in the form of - "proto=". should be one of the following - list without quotes: "h2", "http/1.1". The default - value of is "http/1.1". Note that usually "h2" - refers to HTTP/2 over TLS. But in this option, it may - mean HTTP/2 over cleartext TCP unless "tls" keyword is - used (see below). - - TLS can be enabled by specifying optional "tls" - parameter. TLS is not enabled by default. - - With "sni=" parameter, it can override the TLS - SNI field value with given . This will - default to the backend name - - The feature to detect whether backend is online or - offline can be enabled using optional "fall" and "rise" - parameters. Using "fall=" parameter, if nghttpx - cannot connect to a this backend times in a row, - this backend is assumed to be offline, and it is - excluded from load balancing. If is 0, this backend - never be excluded from load balancing whatever times - nghttpx cannot connect to it, and this is the default. - There is also "rise=" parameter. After backend was - excluded from load balancing group, nghttpx periodically - attempts to make a connection to the failed backend, and - if the connection is made successfully times in a - row, the backend is assumed to be online, and it is now - eligible for load balancing target. If is 0, a - backend is permanently offline, once it goes in that - state, and this is the default behaviour. - - The session affinity is enabled using - "affinity=" parameter. If "ip" is given in - , client IP based session affinity is enabled. - If "none" is given in , session affinity is - disabled, and this is the default. The session affinity - is enabled per . If at least one backend has - "affinity" parameter, and its is not "none", - session affinity is enabled for all backend servers - sharing the same . It is advised to set - "affinity" parameter to all backend explicitly if - session affinity is desired. The session affinity may - break if one of the backend gets unreachable, or backend - settings are reloaded or replaced by API. - - Since ";" and ":" are used as delimiter, must - not contain these characters. Since ";" has special - meaning in shell, the option value must be quoted. - - Default: )" << DEFAULT_DOWNSTREAM_HOST << "," - << DEFAULT_DOWNSTREAM_PORT << R"( - -f, --frontend=(,|unix:)[[;PARAM]...] - Set frontend host and port. If is '*', it - assumes all addresses including both IPv4 and IPv6. - UNIX domain socket can be specified by prefixing path - name with "unix:" (e.g., unix:/var/run/nghttpx.sock). - This option can be used multiple times to listen to - multiple addresses. - - This option can take 0 or more parameters, which are - described below. Note that "api" and "healthmon" - parameters are mutually exclusive. - - Optionally, TLS can be disabled by specifying "no-tls" - parameter. TLS is enabled by default. - - To make this frontend as API endpoint, specify "api" - parameter. This is disabled by default. It is - important to limit the access to the API frontend. - Otherwise, someone may change the backend server, and - break your services, or expose confidential information - to the outside the world. - - To make this frontend as health monitor endpoint, - specify "healthmon" parameter. This is disabled by - default. Any requests which come through this address - are replied with 200 HTTP status, without no body. - - Default: *,3000 - --backlog= - Set listen backlog size. - Default: )" << get_config()->conn.listener.backlog << R"( - --backend-address-family=(auto|IPv4|IPv6) - Specify address family of backend connections. If - "auto" is given, both IPv4 and IPv6 are considered. If - "IPv4" is given, only IPv4 address is considered. If - "IPv6" is given, only IPv6 address is considered. - Default: auto - --backend-http-proxy-uri= - Specify proxy URI in the form - http://[:@]:. If a proxy - requires authentication, specify and . - Note that they must be properly percent-encoded. This - proxy is used when the backend connection is HTTP/2. - First, make a CONNECT request to the proxy and it - connects to the backend on behalf of nghttpx. This - forms tunnel. After that, nghttpx performs SSL/TLS - handshake with the downstream through the tunnel. The - timeouts when connecting and making CONNECT request can - be specified by --backend-read-timeout and - --backend-write-timeout options. - --accept-proxy-protocol - Accept PROXY protocol version 1 on frontend connection. - -Performance: - -n, --workers= - Set the number of worker threads. - Default: )" << get_config()->num_worker << R"( - --read-rate= - Set maximum average read rate on frontend connection. - Setting 0 to this option means read rate is unlimited. - Default: )" << get_config()->conn.upstream.ratelimit.read.rate - << R"( - --read-burst= - Set maximum read burst size on frontend connection. - Setting 0 to this option means read burst size is - unlimited. - Default: )" << get_config()->conn.upstream.ratelimit.read.burst - << R"( - --write-rate= - Set maximum average write rate on frontend connection. - Setting 0 to this option means write rate is unlimited. - Default: )" << get_config()->conn.upstream.ratelimit.write.rate - << R"( - --write-burst= - Set maximum write burst size on frontend connection. - Setting 0 to this option means write burst size is - unlimited. - Default: )" << get_config()->conn.upstream.ratelimit.write.burst - << R"( - --worker-read-rate= - Set maximum average read rate on frontend connection per - worker. Setting 0 to this option means read rate is - unlimited. Not implemented yet. - Default: 0 - --worker-read-burst= - Set maximum read burst size on frontend connection per - worker. Setting 0 to this option means read burst size - is unlimited. Not implemented yet. - Default: 0 - --worker-write-rate= - Set maximum average write rate on frontend connection - per worker. Setting 0 to this option means write rate - is unlimited. Not implemented yet. - Default: 0 - --worker-write-burst= - Set maximum write burst size on frontend connection per - worker. Setting 0 to this option means write burst size - is unlimited. Not implemented yet. - Default: 0 - --worker-frontend-connections= - Set maximum number of simultaneous connections frontend - accepts. Setting 0 means unlimited. - Default: )" << get_config()->conn.upstream.worker_connections - << R"( - --backend-connections-per-host= - Set maximum number of backend concurrent connections - (and/or streams in case of HTTP/2) per origin host. - This option is meaningful when --http2-proxy option is - used. The origin host is determined by authority - portion of request URI (or :authority header field for - HTTP/2). To limit the number of connections per - frontend for default mode, use - --backend-connections-per-frontend. - Default: )" << get_config()->conn.downstream->connections_per_host - << R"( - --backend-connections-per-frontend= - Set maximum number of backend concurrent connections - (and/or streams in case of HTTP/2) per frontend. This - option is only used for default mode. 0 means - unlimited. To limit the number of connections per host - with --http2-proxy option, use - --backend-connections-per-host. - Default: )" - << get_config()->conn.downstream->connections_per_frontend << R"( - --rlimit-nofile= - Set maximum number of open files (RLIMIT_NOFILE) to . - If 0 is given, nghttpx does not set the limit. - Default: )" << get_config()->rlimit_nofile << R"( - --backend-request-buffer= - Set buffer size used to store backend request. - Default: )" - << util::utos_unit(get_config()->conn.downstream->request_buffer_size) - << R"( - --backend-response-buffer= - Set buffer size used to store backend response. - Default: )" - << util::utos_unit(get_config()->conn.downstream->response_buffer_size) - << R"( - --fastopen= - Enables "TCP Fast Open" for the listening socket and - limits the maximum length for the queue of connections - that have not yet completed the three-way handshake. If - value is 0 then fast open is disabled. - Default: )" << get_config()->conn.listener.fastopen << R"( - --no-kqueue Don't use kqueue. This option is only applicable for - the platforms which have kqueue. For other platforms, - this option will be simply ignored. - -Timeout: - --frontend-http2-read-timeout= - Specify read timeout for HTTP/2 and SPDY frontend - connection. - Default: )" - << util::duration_str(get_config()->conn.upstream.timeout.http2_read) - << R"( - --frontend-read-timeout= - Specify read timeout for HTTP/1.1 frontend connection. - Default: )" - << util::duration_str(get_config()->conn.upstream.timeout.read) << R"( - --frontend-write-timeout= - Specify write timeout for all frontend connections. - Default: )" - << util::duration_str(get_config()->conn.upstream.timeout.write) << R"( - --stream-read-timeout= - Specify read timeout for HTTP/2 and SPDY streams. 0 - means no timeout. - Default: )" - << util::duration_str(get_config()->http2.timeout.stream_read) << R"( - --stream-write-timeout= - Specify write timeout for HTTP/2 and SPDY streams. 0 - means no timeout. - Default: )" - << util::duration_str(get_config()->http2.timeout.stream_write) << R"( - --backend-read-timeout= - Specify read timeout for backend connection. - Default: )" - << util::duration_str(get_config()->conn.downstream->timeout.read) << R"( - --backend-write-timeout= - Specify write timeout for backend connection. - Default: )" - << util::duration_str(get_config()->conn.downstream->timeout.write) << R"( - --backend-keep-alive-timeout= - Specify keep-alive timeout for backend connection. - Default: )" - << util::duration_str(get_config()->conn.downstream->timeout.idle_read) - << R"( - --listener-disable-timeout= - After accepting connection failed, connection listener - is disabled for a given amount of time. Specifying 0 - disables this feature. - Default: )" - << util::duration_str(get_config()->conn.listener.timeout.sleep) << R"( - --frontend-http2-setting-timeout= - Specify timeout before SETTINGS ACK is received from - client. - Default: )" - << util::duration_str(get_config()->http2.upstream.timeout.settings) - << R"( - --backend-http2-settings-timeout= - Specify timeout before SETTINGS ACK is received from - backend server. - Default: )" - << util::duration_str(get_config()->http2.downstream.timeout.settings) - << R"( - --backend-max-backoff= - Specify maximum backoff interval. This is used when - doing health check against offline backend (see "fail" - parameter in --backend option). It is also used to - limit the maximum interval to temporarily disable - backend when nghttpx failed to connect to it. These - intervals are calculated using exponential backoff, and - consecutive failed attempts increase the interval. This - option caps its maximum value. - Default: )" - << util::duration_str(get_config()->conn.downstream->timeout.max_backoff) - << R"( - -SSL/TLS: - --ciphers= - Set allowed cipher list. The format of the string is - described in OpenSSL ciphers(1). - -k, --insecure - Don't verify backend server's certificate if TLS is - enabled for backend connections. - --cacert= - Set path to trusted CA certificate file used in backend - TLS connections. The file must be in PEM format. It - can contain multiple certificates. If the linked - OpenSSL is configured to load system wide certificates, - they are loaded at startup regardless of this option. - --private-key-passwd-file= - Path to file that contains password for the server's - private key. If none is given and the private key is - password protected it'll be requested interactively. - --subcert=: - 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. To make OCSP - stapling work, must be absolute path. - --dh-param-file= - Path to file that contains DH parameters in PEM format. - Without this option, DHE cipher suites are not - available. - --npn-list= - Comma delimited list of ALPN protocol identifier sorted - in the order of preference. That means most desirable - protocol comes first. This is used in both ALPN and - NPN. The parameter must be delimited by a single comma - only and any white spaces are treated as a part of - protocol string. - Default: )" << DEFAULT_NPN_LIST << R"( - --verify-client - Require and verify client certificate. - --verify-client-cacert= - Path to file that contains CA certificates to verify - client certificate. The file must be in PEM format. It - can contain multiple certificates. - --client-private-key-file= - Path to file that contains client private key used in - backend client authentication. - --client-cert-file= - Path to file that contains client certificate used in - backend client authentication. - --tls-proto-list= - Comma delimited list of SSL/TLS protocol to be enabled. - The following protocols are available: TLSv1.2, TLSv1.1 - and TLSv1.0. The name matching is done in - case-insensitive manner. The parameter must be - delimited by a single comma only and any white spaces - are treated as a part of protocol string. If the - protocol list advertised by client does not overlap this - list, you will receive the error message "unknown - protocol". - Default: )" << DEFAULT_TLS_PROTO_LIST << R"( - --tls-ticket-key-file= - Path to file that contains random data to construct TLS - session ticket parameters. If aes-128-cbc is given in - --tls-ticket-key-cipher, the file must contain exactly - 48 bytes. If aes-256-cbc is given in - --tls-ticket-key-cipher, the file must contain exactly - 80 bytes. This options can be used repeatedly to - specify multiple ticket parameters. If several files - are given, only the first key is used to encrypt TLS - session tickets. Other keys are accepted but server - will issue new session ticket with first key. This - allows session key rotation. Please note that key - rotation does not occur automatically. User should - rearrange files or change options values and restart - nghttpx gracefully. If opening or reading given file - fails, all loaded keys are discarded and it is treated - as if none of this option is given. If this option is - not given or an error occurred while opening or reading - a file, key is generated every 1 hour internally and - they are valid for 12 hours. This is recommended if - ticket key sharing between nghttpx instances is not - required. - --tls-ticket-key-memcached=,[;tls] - Specify address of memcached server to get TLS ticket - keys for session resumption. This enables shared TLS - ticket key between multiple nghttpx instances. nghttpx - does not set TLS ticket key to memcached. The external - ticket key generator is required. nghttpx just gets TLS - ticket keys from memcached, and use them, possibly - replacing current set of keys. It is up to extern TLS - ticket key generator to rotate keys frequently. See - "TLS SESSION TICKET RESUMPTION" section in manual page - to know the data format in memcached entry. Optionally, - memcached connection can be encrypted with TLS by - specifying "tls" parameter. - --tls-ticket-key-memcached-address-family=(auto|IPv4|IPv6) - Specify address family of memcached connections to get - TLS ticket keys. If "auto" is given, both IPv4 and IPv6 - are considered. If "IPv4" is given, only IPv4 address - is considered. If "IPv6" is given, only IPv6 address is - considered. - Default: auto - --tls-ticket-key-memcached-interval= - Set interval to get TLS ticket keys from memcached. - Default: )" - << util::duration_str(get_config()->tls.ticket.memcached.interval) << R"( - --tls-ticket-key-memcached-max-retry= - Set maximum number of consecutive retries before - abandoning TLS ticket key retrieval. If this number is - reached, the attempt is considered as failure, and - "failure" count is incremented by 1, which contributed - to the value controlled - --tls-ticket-key-memcached-max-fail option. - Default: )" << get_config()->tls.ticket.memcached.max_retry << R"( - --tls-ticket-key-memcached-max-fail= - Set maximum number of consecutive failure before - disabling TLS ticket until next scheduled key retrieval. - Default: )" << get_config()->tls.ticket.memcached.max_fail << R"( - --tls-ticket-key-cipher= - Specify cipher to encrypt TLS session ticket. Specify - either aes-128-cbc or aes-256-cbc. By default, - aes-128-cbc is used. - --tls-ticket-key-memcached-cert-file= - Path to client certificate for memcached connections to - get TLS ticket keys. - --tls-ticket-key-memcached-private-key-file= - Path to client private key for memcached connections to - get TLS ticket keys. - --fetch-ocsp-response-file= - Path to fetch-ocsp-response script file. It should be - absolute path. - Default: )" << get_config()->tls.ocsp.fetch_ocsp_response_file - << R"( - --ocsp-update-interval= - Set interval to update OCSP response cache. - Default: )" - << util::duration_str(get_config()->tls.ocsp.update_interval) << R"( - --no-ocsp Disable OCSP stapling. - --tls-session-cache-memcached=,[;tls] - Specify address of memcached server to store session - cache. This enables shared session cache between - multiple nghttpx instances. Optionally, memcached - connection can be encrypted with TLS by specifying "tls" - parameter. - --tls-session-cache-memcached-address-family=(auto|IPv4|IPv6) - Specify address family of memcached connections to store - session cache. If "auto" is given, both IPv4 and IPv6 - are considered. If "IPv4" is given, only IPv4 address - is considered. If "IPv6" is given, only IPv6 address is - considered. - Default: auto - --tls-session-cache-memcached-cert-file= - Path to client certificate for memcached connections to - store session cache. - --tls-session-cache-memcached-private-key-file= - Path to client private key for memcached connections to - store session cache. - --tls-dyn-rec-warmup-threshold= - Specify the threshold size for TLS dynamic record size - behaviour. During a TLS session, after the threshold - number of bytes have been written, the TLS record size - will be increased to the maximum allowed (16K). The max - record size will continue to be used on the active TLS - session. After --tls-dyn-rec-idle-timeout has elapsed, - the record size is reduced to 1300 bytes. Specify 0 to - always use the maximum record size, regardless of idle - period. This behaviour applies to all TLS based - frontends, and TLS HTTP/2 backends. - Default: )" - << util::utos_unit(get_config()->tls.dyn_rec.warmup_threshold) << R"( - --tls-dyn-rec-idle-timeout= - Specify TLS dynamic record size behaviour timeout. See - --tls-dyn-rec-warmup-threshold for more information. - This behaviour applies to all TLS based frontends, and - TLS HTTP/2 backends. - Default: )" - << util::duration_str(get_config()->tls.dyn_rec.idle_timeout) << R"( - --no-http2-cipher-black-list - Allow black listed cipher suite on HTTP/2 connection. - See https://tools.ietf.org/html/rfc7540#appendix-A for - the complete HTTP/2 cipher suites black list. - -HTTP/2 and SPDY: - -c, --frontend-http2-max-concurrent-streams= - Set the maximum number of the concurrent streams in one - frontend HTTP/2 and SPDY session. - Default: )" - << get_config()->http2.upstream.max_concurrent_streams << R"( - --backend-http2-max-concurrent-streams= - Set the maximum number of the concurrent streams in one - backend HTTP/2 session. This sets maximum number of - concurrent opened pushed streams. The maximum number of - concurrent requests are set by a remote server. - Default: )" - << get_config()->http2.downstream.max_concurrent_streams << R"( - --frontend-http2-window-bits= - Sets the per-stream initial window size of HTTP/2 SPDY - frontend connection. For HTTP/2, the size is 2**-1. - For SPDY, the size is 2**. - Default: )" << get_config()->http2.upstream.window_bits << R"( - --frontend-http2-connection-window-bits= - Sets the per-connection window size of HTTP/2 and SPDY - frontend connection. For HTTP/2, the size is - 2**-1. For SPDY, the size is 2**. - Default: )" << get_config()->http2.upstream.connection_window_bits - << R"( - --backend-http2-window-bits= - Sets the initial window size of HTTP/2 backend - connection to 2**-1. - Default: )" << get_config()->http2.downstream.window_bits << R"( - --backend-http2-connection-window-bits= - Sets the per-connection window size of HTTP/2 backend - connection to 2**-1. - Default: )" - << get_config()->http2.downstream.connection_window_bits << R"( - --http2-no-cookie-crumbling - Don't crumble cookie header field. - --padding= - Add at most bytes to a HTTP/2 frame payload as - padding. Specify 0 to disable padding. This option is - meant for debugging purpose and not intended to enhance - protocol security. - --no-server-push - Disable HTTP/2 server push. Server push is supported by - default mode and HTTP/2 frontend via Link header field. - It is also supported if both frontend and backend are - HTTP/2 in default mode. In this case, server push from - backend session is relayed to frontend, and server push - via Link header field is also supported. SPDY frontend - does not support server push. - -Mode: - (default mode) - Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS. "no-tls" - parameter is used in --frontend option, accept HTTP/2 - and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1 - connection can be upgraded to HTTP/2 through HTTP - Upgrade. - -s, --http2-proxy - Like default mode, but enable forward proxy. This is so - called HTTP/2 proxy mode. - -Logging: - -L, --log-level= - Set the severity level of log output. must be - one of INFO, NOTICE, WARN, ERROR and FATAL. - Default: NOTICE - --accesslog-file= - Set path to write access log. To reopen file, send USR1 - signal to nghttpx. - --accesslog-syslog - Send access log to syslog. If this option is used, - --accesslog-file option is ignored. - --accesslog-format= - Specify format string for access log. The default - format is combined format. The following variables are - available: - - * $remote_addr: client IP address. - * $time_local: local time in Common Log format. - * $time_iso8601: local time in ISO 8601 format. - * $request: HTTP request line. - * $status: HTTP response status code. - * $body_bytes_sent: the number of bytes sent to client - as response body. - * $http_: value of HTTP request header where - '_' in is replaced with '-'. - * $remote_port: client port. - * $server_port: server port. - * $request_time: request processing time in seconds with - milliseconds resolution. - * $pid: PID of the running process. - * $alpn: ALPN identifier of the protocol which generates - the response. For HTTP/1, ALPN is always http/1.1, - regardless of minor version. - * $ssl_cipher: cipher used for SSL/TLS connection. - * $ssl_protocol: protocol for SSL/TLS connection. - * $ssl_session_id: session ID for SSL/TLS connection. - * $ssl_session_reused: "r" if SSL/TLS session was - reused. Otherwise, "." - - The variable can be enclosed by "{" and "}" for - disambiguation (e.g., ${remote_addr}). - - Default: )" << DEFAULT_ACCESSLOG_FORMAT << R"( - --errorlog-file= - Set path to write error log. To reopen file, send USR1 - signal to nghttpx. stderr will be redirected to the - error log file unless --errorlog-syslog is used. - Default: )" << get_config()->logging.error.file << R"( - --errorlog-syslog - Send error log to syslog. If this option is used, - --errorlog-file option is ignored. - --syslog-facility= - Set syslog facility to . - Default: )" - << str_syslog_facility(get_config()->logging.syslog_facility) << R"( - -HTTP: - --add-x-forwarded-for - Append X-Forwarded-For header field to the downstream - request. - --strip-incoming-x-forwarded-for - Strip X-Forwarded-For header field from inbound client - requests. - --add-forwarded= - Append RFC 7239 Forwarded header field with parameters - specified in comma delimited list . The supported - parameters are "by", "for", "host", and "proto". By - default, the value of "by" and "for" parameters are - obfuscated string. See --forwarded-by and - --forwarded-for options respectively. Note that nghttpx - does not translate non-standard X-Forwarded-* header - fields into Forwarded header field, and vice versa. - --strip-incoming-forwarded - Strip Forwarded header field from inbound client - requests. - --forwarded-by=(obfuscated|ip|) - Specify the parameter value sent out with "by" parameter - of Forwarded header field. If "obfuscated" is given, - the string is randomly generated at startup. If "ip" is - given, the interface address of the connection, - including port number, is sent with "by" parameter. In - case of UNIX domain socket, "localhost" is used instead - of address and port. User can also specify the static - obfuscated string. The limitation is that it must start - with "_", and only consists of character set - [A-Za-z0-9._-], as described in RFC 7239. - Default: obfuscated - --forwarded-for=(obfuscated|ip) - Specify the parameter value sent out with "for" - parameter of Forwarded header field. If "obfuscated" is - given, the string is randomly generated for each client - connection. If "ip" is given, the remote client address - of the connection, without port number, is sent with - "for" parameter. In case of UNIX domain socket, - "localhost" is used instead of address. - Default: obfuscated - --no-via Don't append to Via header field. If Via header field - is received, it is left unaltered. - --no-location-rewrite - Don't rewrite location header field in default mode. - When --http2-proxy is used, location header field will - not be altered regardless of this option. - --host-rewrite - Rewrite host and :authority header fields in default - mode. When --http2-proxy is used, these headers will - not be altered regardless of this option. - --altsvc= - Specify protocol ID, port, host and origin of - alternative service. and are optional. - 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: --altsvc=h2,443 - --add-request-header=
- Specify additional header field to add to request header - set. This option just appends header field and won't - replace anything already set. This option can be used - several times to specify multiple header fields. - Example: --add-request-header="foo: bar" - --add-response-header=
- Specify additional header field to add to response - header set. This option just appends header field and - won't replace anything already set. This option can be - used several times to specify multiple header fields. - Example: --add-response-header="foo: bar" - --request-header-field-buffer= - Set maximum buffer size for incoming HTTP request header - field list. This is the sum of header name and value in - bytes. If trailer fields exist, they are counted - towards this number. - Default: )" - << util::utos_unit(get_config()->http.request_header_field_buffer) << R"( - --max-request-header-fields= - Set maximum number of incoming HTTP request header - fields. If trailer fields exist, they are counted - towards this number. - Default: )" << get_config()->http.max_request_header_fields << R"( - --response-header-field-buffer= - Set maximum buffer size for incoming HTTP response - header field list. This is the sum of header name and - value in bytes. If trailer fields exist, they are - counted towards this number. - Default: )" - << util::utos_unit(get_config()->http.response_header_field_buffer) << R"( - --max-response-header-fields= - Set maximum number of incoming HTTP response header - fields. If trailer fields exist, they are counted - towards this number. - Default: )" << get_config()->http.max_response_header_fields - << R"( - --error-page=(|*)= - Set file path to custom error page served when nghttpx - originally generates HTTP error status code . - must be greater than or equal to 400, and at most - 599. If "*" is used instead of , it matches all - HTTP status code. If error status code comes from - backend server, the custom error pages are not used. - -API: - --api-max-request-body= - Set the maximum size of request body for API request. - Default: )" << util::utos_unit(get_config()->api.max_request_body) - << R"( - -Debug: - --frontend-http2-dump-request-header= - Dumps request headers received by HTTP/2 frontend to the - file denoted in . The output is done in HTTP/1 - header field format and each header block is followed by - an empty line. This option is not thread safe and MUST - NOT be used with option -n, where >= 2. - --frontend-http2-dump-response-header= - Dumps response headers sent from HTTP/2 frontend to the - file denoted in . The output is done in HTTP/1 - header field format and each header block is followed by - an empty line. This option is not thread safe and MUST - NOT be used with option -n, where >= 2. - -o, --frontend-frame-debug - Print HTTP/2 frames in frontend to stderr. This option - is not thread safe and MUST NOT be used with option - -n=N, where N >= 2. - -Process: - -D, --daemon - Run in a background. If -D is used, the current working - directory is changed to '/'. - --pid-file= - Set path to save PID of this program. - --user= - Run this program as . This option is intended to - be used to drop root privileges. - -Scripting: - --mruby-file= - Set mruby script file - -Misc: - --conf= - Load configuration from . - Default: )" << get_config()->conf_path << R"( - --include= - Load additional configurations from . File - is read when configuration parser encountered this - option. This option can be used multiple times, or even - recursively. - -v, --version - Print version and exit. - -h, --help Print this help and exit. - --- - - The argument is an integer and an optional unit (e.g., 10K is - 10 * 1024). Units are K, M and G (powers of 1024). - - The 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.)" << std::endl; -} + "http/1.1"; } // namespace -namespace { -void process_options(int argc, char **argv, - std::vector> &cmdcfgs) { - if (conf_exists(get_config()->conf_path.c_str())) { - std::set include_set; - if (load_config(get_config()->conf_path.c_str(), include_set) == -1) { - LOG(FATAL) << "Failed to load configuration from " - << get_config()->conf_path; - exit(EXIT_FAILURE); - } - assert(include_set.empty()); - } - - if (argc - optind >= 2) { - cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_FILE, StringRef{argv[optind++]}); - cmdcfgs.emplace_back(SHRPX_OPT_CERTIFICATE_FILE, StringRef{argv[optind++]}); - } - - // Reopen log files using configurations in file - reopen_log_files(); - - { - std::set include_set; - - for (auto &p : cmdcfgs) { - if (parse_config(mod_config(), p.first, p.second, include_set) == -1) { - LOG(FATAL) << "Failed to parse command-line argument."; - exit(EXIT_FAILURE); - } - } - - assert(include_set.empty()); - } - - auto &loggingconf = get_config()->logging; - - if (loggingconf.access.syslog || loggingconf.error.syslog) { - openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID, - loggingconf.syslog_facility); - } - - if (reopen_log_files() != 0) { - LOG(FATAL) << "Failed to open log file"; - exit(EXIT_FAILURE); - } - - redirect_stderr_to_errorlog(); - - if (get_config()->uid != 0) { - if (log_config()->accesslog_fd != -1 && - fchown(log_config()->accesslog_fd, get_config()->uid, - get_config()->gid) == -1) { - auto error = errno; - LOG(WARN) << "Changing owner of access log file failed: " - << strerror(error); - } - if (log_config()->errorlog_fd != -1 && - fchown(log_config()->errorlog_fd, get_config()->uid, - get_config()->gid) == -1) { - auto error = errno; - LOG(WARN) << "Changing owner of error log file failed: " - << strerror(error); - } - } - - auto &http2conf = mod_config()->http2; - { - auto &dumpconf = http2conf.upstream.debug.dump; - - if (!dumpconf.request_header_file.empty()) { - auto path = dumpconf.request_header_file.c_str(); - auto f = open_file_for_write(path); - - if (f == nullptr) { - LOG(FATAL) << "Failed to open http2 upstream request header file: " - << path; - exit(EXIT_FAILURE); - } - - dumpconf.request_header = f; - - if (get_config()->uid != 0) { - if (chown_to_running_user(path) == -1) { - auto error = errno; - LOG(WARN) << "Changing owner of http2 upstream request header file " - << path << " failed: " << strerror(error); - } - } - } - - if (!dumpconf.response_header_file.empty()) { - auto path = dumpconf.response_header_file.c_str(); - auto f = open_file_for_write(path); - - if (f == nullptr) { - LOG(FATAL) << "Failed to open http2 upstream response header file: " - << path; - exit(EXIT_FAILURE); - } - - dumpconf.response_header = f; - - if (get_config()->uid != 0) { - if (chown_to_running_user(path) == -1) { - auto error = errno; - LOG(WARN) << "Changing owner of http2 upstream response header file" - << " " << path << " failed: " << strerror(error); - } - } - } - } - - auto &tlsconf = mod_config()->tls; - - if (tlsconf.npn_list.empty()) { - tlsconf.npn_list = util::parse_config_str_list(DEFAULT_NPN_LIST); - } - if (tlsconf.tls_proto_list.empty()) { - tlsconf.tls_proto_list = - util::parse_config_str_list(DEFAULT_TLS_PROTO_LIST); - } +namespace { +const char *DEFAULT_TLS_PROTO_LIST = "TLSv1.2,TLSv1.1"; +} // namespace - tlsconf.tls_proto_mask = ssl::create_tls_proto_mask(tlsconf.tls_proto_list); +namespace { +const char *DEFAULT_ACCESSLOG_FORMAT = "$remote_addr - - [$time_local] " + "\"$request\" $status $body_bytes_sent " + "\"$http_referer\" \"$http_user_agent\""; +} // namespace - tlsconf.alpn_prefs = ssl::set_alpn_prefs(tlsconf.npn_list); +namespace { +void fill_default_config() { + memset(mod_config(), 0, sizeof(*mod_config())); - tlsconf.bio_method = create_bio_method(); + mod_config()->verbose = false; + mod_config()->daemon = false; - auto &listenerconf = mod_config()->conn.listener; - auto &upstreamconf = mod_config()->conn.upstream; + mod_config()->server_name = "nghttpx nghttp2/" NGHTTP2_VERSION; + mod_config()->host = strcopy("*"); + mod_config()->port = 3000; + mod_config()->private_key_file = nullptr; + mod_config()->private_key_passwd = nullptr; + mod_config()->cert_file = nullptr; + + // Read timeout for HTTP2 upstream connection + mod_config()->http2_upstream_read_timeout = {180, 0}; + + // Read timeout for non-HTTP2 upstream connection + mod_config()->upstream_read_timeout = {30, 0}; + + // Write timeout for HTTP2/non-HTTP2 upstream connection + mod_config()->upstream_write_timeout = {30, 0}; + + // Read/Write timeouts for downstream connection + mod_config()->downstream_read_timeout = {30, 0}; + mod_config()->downstream_write_timeout = {30, 0}; + + // Read timeout for HTTP/2 stream + mod_config()->stream_read_timeout = {0, 0}; + + // Write timeout for HTTP/2 stream + mod_config()->stream_write_timeout = {0, 0}; + + // Timeout for pooled (idle) connections + mod_config()->downstream_idle_read_timeout = {60, 0}; + + // window bits for HTTP/2 and SPDY upstream/downstream connection + // per stream. 2**16-1 = 64KiB-1, which is HTTP/2 default. Please + // note that SPDY/3 default is 64KiB. + mod_config()->http2_upstream_window_bits = 16; + mod_config()->http2_downstream_window_bits = 16; + + // HTTP/2 SPDY/3.1 has connection-level flow control. The default + // window size for HTTP/2 is 64KiB - 1. SPDY/3's default is 64KiB + mod_config()->http2_upstream_connection_window_bits = 16; + mod_config()->http2_downstream_connection_window_bits = 16; + + mod_config()->upstream_no_tls = false; + mod_config()->downstream_no_tls = false; + + mod_config()->downstream_host = strcopy("127.0.0.1"); + mod_config()->downstream_port = 80; + mod_config()->downstream_hostport = nullptr; + mod_config()->downstream_addrlen = 0; - if (listenerconf.addrs.empty()) { - UpstreamAddr addr{}; - addr.host = "*"; - addr.port = 3000; - addr.tls = true; - addr.family = AF_INET; - listenerconf.addrs.push_back(addr); - addr.family = AF_INET6; - listenerconf.addrs.push_back(std::move(addr)); - } + mod_config()->num_worker = 1; + mod_config()->http2_max_concurrent_streams = 100; + mod_config()->add_x_forwarded_for = false; + mod_config()->strip_incoming_x_forwarded_for = false; + mod_config()->no_via = false; + mod_config()->accesslog_file = nullptr; + mod_config()->accesslog_syslog = false; + mod_config()->accesslog_format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT); +#if defined(__ANDROID__) || defined(ANDROID) + // Android does not have /dev/stderr. Use /proc/self/fd/2 instead. + mod_config()->errorlog_file = strcopy("/proc/self/fd/2"); +#else // !__ANDROID__ && ANDROID + mod_config()->errorlog_file = strcopy("/dev/stderr"); +#endif // !__ANDROID__ && ANDROID + mod_config()->errorlog_syslog = false; + mod_config()->conf_path = strcopy("/etc/nghttpx/nghttpx.conf"); + mod_config()->syslog_facility = LOG_DAEMON; + // Default accept() backlog + mod_config()->backlog = -1; + mod_config()->ciphers = nullptr; + mod_config()->http2_proxy = false; + mod_config()->http2_bridge = false; + mod_config()->client_proxy = false; + mod_config()->client = false; + mod_config()->client_mode = false; + mod_config()->insecure = false; + mod_config()->cacert = nullptr; + mod_config()->pid_file = nullptr; + mod_config()->uid = 0; + mod_config()->gid = 0; + mod_config()->pid = getpid(); + mod_config()->backend_ipv4 = false; + mod_config()->backend_ipv6 = false; + mod_config()->cert_tree = nullptr; + mod_config()->downstream_http_proxy_userinfo = nullptr; + mod_config()->downstream_http_proxy_host = nullptr; + mod_config()->downstream_http_proxy_port = 0; + mod_config()->downstream_http_proxy_addrlen = 0; + mod_config()->rate_limit_cfg = nullptr; + mod_config()->read_rate = 0; + mod_config()->read_burst = 1 << 30; + mod_config()->write_rate = 0; + mod_config()->write_burst = 0; + mod_config()->worker_read_rate = 0; + mod_config()->worker_read_burst = 0; + mod_config()->worker_write_rate = 0; + mod_config()->worker_write_burst = 0; + mod_config()->worker_rate_limit_cfg = nullptr; + mod_config()->verify_client = false; + mod_config()->verify_client_cacert = nullptr; + mod_config()->client_private_key_file = nullptr; + mod_config()->client_cert_file = nullptr; + mod_config()->http2_upstream_dump_request_header = nullptr; + mod_config()->http2_upstream_dump_response_header = nullptr; + mod_config()->http2_no_cookie_crumbling = false; + mod_config()->upstream_frame_debug = false; + mod_config()->padding = 0; + mod_config()->worker_frontend_connections = 0; + + nghttp2_option_new(&mod_config()->http2_option); + + nghttp2_option_set_no_auto_window_update(mod_config()->http2_option, 1); + + mod_config()->tls_proto_mask = 0; + mod_config()->cached_time = generate_time(); + mod_config()->no_location_rewrite = false; + mod_config()->argc = 0; + mod_config()->argv = nullptr; + mod_config()->max_downstream_connections = 100; + mod_config()->listener_disable_timeout = {0, 0}; +} +} // namespace - if (upstreamconf.worker_connections == 0) { - upstreamconf.worker_connections = std::numeric_limits::max(); +namespace { +size_t get_rate_limit(size_t rate_limit) { + if (rate_limit == 0) { + return EV_RATE_LIMIT_MAX; + } else { + return rate_limit; } +} +} // namespace - if (ssl::upstream_tls_enabled() && - (tlsconf.private_key_file.empty() || tlsconf.cert_file.empty())) { - print_usage(std::cerr); - LOG(FATAL) << "Too few arguments"; - exit(EXIT_FAILURE); - } +namespace { +void print_version(std::ostream &out) { + out << get_config()->server_name << std::endl; +} +} // namespace - if (ssl::upstream_tls_enabled() && !tlsconf.ocsp.disabled) { - struct stat buf; - if (stat(tlsconf.ocsp.fetch_ocsp_response_file.c_str(), &buf) != 0) { - tlsconf.ocsp.disabled = true; - LOG(WARN) << "--fetch-ocsp-response-file: " - << tlsconf.ocsp.fetch_ocsp_response_file - << " not found. OCSP stapling has been disabled."; - } - } +namespace { +void print_usage(std::ostream &out) { + out << R"(Usage: nghttpx [OPTIONS]... [ ] +A reverse proxy for HTTP/2, HTTP/1 and SPDY.)" << std::endl; +} +} // namespace - if (configure_downstream_group(mod_config(), get_config()->http2_proxy, false, - tlsconf) != 0) { - exit(EXIT_FAILURE); - } +namespace { +void print_help(std::ostream &out) { + print_usage(out); + out << R"( + Set path to server's private key. Required + unless -p, --client or --frontend-no-tls are + given. + Set path to server's certificate. Required + unless -p, --client or --frontend-no-tls are + given. +Options: + The options are categorized into several groups. - auto &proxy = mod_config()->downstream_http_proxy; - if (!proxy.host.empty()) { - auto hostport = util::make_hostport(StringRef{proxy.host}, proxy.port); - if (resolve_hostname(&proxy.addr, proxy.host.c_str(), proxy.port, - AF_UNSPEC) == -1) { - LOG(FATAL) << "Resolving backend HTTP proxy address failed: " << hostport; - exit(EXIT_FAILURE); - } - LOG(NOTICE) << "Backend HTTP proxy address: " << hostport << " -> " - << util::to_numeric_addr(&proxy.addr); - } +Connections: + -b, --backend= + Set backend host and port. + Default: ')" << get_config()->downstream_host.get() << "," + << get_config()->downstream_port << R"(' + -f, --frontend= + Set frontend host and port. If is '*', it + assumes all addresses including both IPv4 and + IPv6. + Default: ')" << get_config()->host.get() << "," + << get_config()->port << R"(' + --backlog= Set listen backlog size. If -1 is given, + libevent will choose suitable value. + Default: )" << get_config()->backlog << R"( + --backend-ipv4 Resolve backend hostname to IPv4 address only. + --backend-ipv6 Resolve backend hostname to IPv6 address only. + --backend-http-proxy-uri= + Specify proxy URI in the form + http://[:@]:. If a + proxy requires authentication, specify and + . Note that they must be properly + percent-encoded. This proxy is used when the + backend connection is HTTP/2. First, make a + CONNECT request to the proxy and it connects to + the backend on behalf of nghttpx. This forms + tunnel. After that, nghttpx performs SSL/TLS + handshake with the downstream through the tunnel. + The timeouts when connecting and making CONNECT + request can be specified by + --backend-read-timeout and + --backend-write-timeout options. - { - auto &memcachedconf = tlsconf.session_cache.memcached; - if (!memcachedconf.host.empty()) { - auto hostport = util::make_hostport(StringRef{memcachedconf.host}, - memcachedconf.port); - if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.c_str(), - memcachedconf.port, memcachedconf.family) == -1) { - LOG(FATAL) - << "Resolving memcached address for TLS session cache failed: " - << hostport; - exit(EXIT_FAILURE); - } - LOG(NOTICE) << "Memcached address for TLS session cache: " << hostport - << " -> " << util::to_numeric_addr(&memcachedconf.addr); - if (memcachedconf.tls) { - LOG(NOTICE) << "Connection to memcached for TLS session cache will be " - "encrypted by TLS"; - } - } - } +Performance: + -n, --workers= + Set the number of worker threads. + Default: )" << get_config()->num_worker << R"( + --read-rate= + Set maximum average read rate on frontend + connection. Setting 0 to this option means read + rate is unlimited. + Default: )" << get_config()->read_rate << R"( + --read-burst= + Set maximum read burst size on frontend + connection. Setting 0 does not work, but it is + not a problem because --read-rate=0 will give + unlimited read rate regardless of this option + value. + Default: )" << get_config()->read_burst << R"( + --write-rate= + Set maximum average write rate on frontend + connection. Setting 0 to this option means write + rate is unlimited. + Default: )" << get_config()->write_rate << R"( + --write-burst= + Set maximum write burst size on frontend + connection. Setting 0 to this option means write + burst size is unlimited. + Default: )" << get_config()->write_burst << R"( + --worker-read-rate= + Set maximum average read rate on frontend + connection per worker. Setting 0 to this option + means read rate is unlimited. + Default: )" << get_config()->worker_read_rate << R"( + --worker-read-burst= + Set maximum read burst size on frontend + connection per worker. Setting 0 to this option + means read burst size is unlimited. + Default: )" << get_config()->worker_read_burst << R"( + --worker-write-rate= + Set maximum average write rate on frontend + connection per worker. Setting 0 to this option + means write rate is unlimited. + Default: )" << get_config()->worker_write_rate << R"( + --worker-write-burst= + Set maximum write burst size on frontend + connection per worker. Setting 0 to this option + means write burst size is unlimited. + Default: )" << get_config()->worker_write_burst << R"( + --worker-frontend-connections= + Set maximum number of simultaneous connections + frontend accepts. Setting 0 means unlimited. + Default: 0 + --backend-connections-per-frontend= + Set maximum number of backend simultaneous + connections per frontend. This option is + meaningful when the combination of HTTP/2 or SPDY + frontend and HTTP/1 backend is used. + Default: )" << get_config()->max_downstream_connections + << R"( - { - auto &memcachedconf = tlsconf.ticket.memcached; - if (!memcachedconf.host.empty()) { - auto hostport = util::make_hostport(StringRef{memcachedconf.host}, - memcachedconf.port); - if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.c_str(), - memcachedconf.port, memcachedconf.family) == -1) { - LOG(FATAL) << "Resolving memcached address for TLS ticket key failed: " - << hostport; - exit(EXIT_FAILURE); - } - LOG(NOTICE) << "Memcached address for TLS ticket key: " << hostport - << " -> " << util::to_numeric_addr(&memcachedconf.addr); - if (memcachedconf.tls) { - LOG(NOTICE) << "Connection to memcached for TLS ticket key will be " - "encrypted by TLS"; - } - } - } +Timeout: + --frontend-http2-read-timeout= + Specify read timeout for HTTP/2 and SPDY frontend + connection. + Default: )" + << get_config()->http2_upstream_read_timeout.tv_sec << R"( + --frontend-read-timeout= + Specify read timeout for HTTP/1.1 frontend + connection. + Default: )" << get_config()->upstream_read_timeout.tv_sec + << R"( + --frontend-write-timeout= + Specify write timeout for all frontend + connections. + Default: )" << get_config()->upstream_write_timeout.tv_sec + << R"( + --stream-read-timeout= + Specify read timeout for HTTP/2 and SPDY streams. + 0 means no timeout. + Default: )" << get_config()->stream_read_timeout.tv_sec + << R"( + --stream-write-timeout= + Specify write timeout for HTTP/2 and SPDY + streams. 0 means no timeout. + Default: )" << get_config()->stream_write_timeout.tv_sec + << R"( + --backend-read-timeout= + Specify read timeout for backend connection. + Default: )" << get_config()->downstream_read_timeout.tv_sec + << R"( + --backend-write-timeout= + Specify write timeout for backend connection. + Default: )" + << get_config()->downstream_write_timeout.tv_sec << R"( + --backend-keep-alive-timeout= + Specify keep-alive timeout for backend + connection. + Default: )" + << get_config()->downstream_idle_read_timeout.tv_sec << R"( + --listener-disable-timeout= + After accepting connection failed, connection + listener is disabled for a given time in seconds. + Specifying 0 disables this feature. + Default: )" + << get_config()->listener_disable_timeout.tv_sec << R"( - if (get_config()->rlimit_nofile) { - struct rlimit lim = {static_cast(get_config()->rlimit_nofile), - static_cast(get_config()->rlimit_nofile)}; - if (setrlimit(RLIMIT_NOFILE, &lim) != 0) { - auto error = errno; - LOG(WARN) << "Setting rlimit-nofile failed: " << strerror(error); - } - } +SSL/TLS: + --ciphers= Set allowed cipher list. The format of the + string is described in OpenSSL ciphers(1). + -k, --insecure + Don't verify backend server's certificate if -p, + --client or --http2-bridge are given and + --backend-no-tls is not given. + --cacert= Set path to trusted CA certificate file if -p, + --client or --http2-bridge are given and + --backend-no-tls is not given. The file must be + in PEM format. It can contain multiple + certificates. If the linked OpenSSL is + configured to load system wide certificates, they + are loaded at startup regardless of this option. + --private-key-passwd-file= + Path to file that contains password for the + server's private key. If none is given and the + private key is password protected it'll be + requested interactively. + --subcert=: + 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. + --backend-tls-sni-field= + Explicitly set the content of the TLS SNI + extension. This will default to the backend HOST + name. + --dh-param-file= + Path to file that contains DH parameters in PEM + format. Without this option, DHE cipher suites + are not available. + --npn-list= Comma delimited list of ALPN protocol identifier + sorted in the order of preference. That means + most desirable protocol comes first. This is + used in both ALPN and NPN. The parameter must be + delimited by a single comma only and any white + spaces are treated as a part of protocol string. + Default: )" << DEFAULT_NPN_LIST << R"( + --verify-client Require and verify client certificate. + --verify-client-cacert= + Path to file that contains CA certificates to + verify client certificate. The file must be in + PEM format. It can contain multiple + certificates. + --client-private-key-file= + Path to file that contains client private key + used in backend client authentication. + --client-cert-file= + Path to file that contains client certificate + used in backend client authentication. + --tls-proto-list= + Comma delimited list of SSL/TLS protocol to be + enabled. The following protocols are available: + TLSv1.2, TLSv1.1 and TLSv1.0. The name matching + is done in case-insensitive manner. The + parameter must be delimited by a single comma + only and any white spaces are treated as a part + of protocol string. + Default: )" << DEFAULT_TLS_PROTO_LIST << R"( - auto &fwdconf = mod_config()->http.forwarded; +HTTP/2 and SPDY: + -c, --http2-max-concurrent-streams= + Set the maximum number of the concurrent streams + in one HTTP/2 and SPDY session. + Default: )" << get_config()->http2_max_concurrent_streams + << R"( + --frontend-http2-window-bits= + Sets the per-stream initial window size of HTTP/2 + SPDY frontend connection. For HTTP/2, the size + is 2**-1. For SPDY, the size is 2**. + Default: )" << get_config()->http2_upstream_window_bits + << R"( + --frontend-http2-connection-window-bits= + Sets the per-connection window size of HTTP/2 and + SPDY frontend connection. For HTTP/2, the size + is 2**-1. For SPDY, the size is 2**. + Default: )" + << get_config()->http2_upstream_connection_window_bits << R"( + --frontend-no-tls Disable SSL/TLS on frontend connections. + --backend-http2-window-bits= + Sets the initial window size of HTTP/2 backend + connection to 2**-1. + Default: )" << get_config()->http2_downstream_window_bits + << R"( + --backend-http2-connection-window-bits= + Sets the per-connection window size of HTTP/2 + backend connection to 2**-1. + Default: )" + << get_config()->http2_downstream_connection_window_bits << R"( + --backend-no-tls Disable SSL/TLS on backend connections. + --http2-no-cookie-crumbling + Don't crumble cookie header field. + --padding= Add at most bytes to a HTTP/2 frame payload + as padding. Specify 0 to disable padding. This + option is meant for debugging purpose and not + intended to enhance protocol security. - if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED && - fwdconf.by_obfuscated.empty()) { - std::random_device rd; - std::mt19937 gen(rd()); - auto &dst = fwdconf.by_obfuscated; - dst = "_"; - dst += util::random_alpha_digit(gen, SHRPX_OBFUSCATED_NODE_LENGTH); - } +Mode: + (default mode) Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS. + If --frontend-no-tls is used, accept HTTP/2 and + HTTP/1.1. The incoming HTTP/1.1 connection can + be upgraded to HTTP/2 through HTTP Upgrade. The + protocol to the backend is HTTP/1.1. + -s, --http2-proxy Like default mode, but enable secure proxy mode. + --http2-bridge Like default mode, but communicate with the + backend in HTTP/2 over SSL/TLS. Thus the + incoming all connections are converted to HTTP/2 + connection and relayed to the backend. See + --backend-http-proxy-uri option if you are behind + the proxy and want to connect to the outside + HTTP/2 proxy. + --client Accept HTTP/2 and HTTP/1.1 without SSL/TLS. The + incoming HTTP/1.1 connection can be upgraded to + HTTP/2 connection through HTTP Upgrade. The + protocol to the backend is HTTP/2. To use + nghttpx as a forward proxy, use -p option + instead. + -p, --client-proxy + Like --client option, but it also requires the + request path from frontend must be an absolute + URI, suitable for use as a forward proxy. - if (get_config()->http2.upstream.debug.frame_debug) { - // To make it sync to logging - set_output(stderr); - if (isatty(fileno(stdout))) { - set_color_output(true); - } - reset_timer(); - } +Logging: + -L, --log-level= + Set the severity level of log output. + must be one of INFO, NOTICE, WARN, ERROR and + FATAL. + Default: NOTICE + --accesslog-file= + Set path to write access log. To reopen file, + send USR1 signal to nghttpx. + --accesslog-syslog + Send access log to syslog. If this option is + used, --access-file option is ignored. + --accesslog-format= + Specify format string for access log. The + default format is combined format. The following + variables are available: + $remote_addr: client IP address. + $time_local: local time in Common Log format. + $time_iso8601: local time in ISO 8601 format. + $request: HTTP request line. + $status: HTTP response status code. + $body_bytes_sent: the number of bytes sent to + client as response body. + $http_: value of HTTP request header + where '_' in is replaced with '-'. + $remote_port: client port. + $server_port: server port. + $request_time: request processing time in + seconds with milliseconds resolution. + $pid: PID of the running process. + $alpn: ALPN identifier of the protocol which + generates the response. For HTTP/1, ALPN is + always http/1.1, regardless of minor version. + Default: )" << DEFAULT_ACCESSLOG_FORMAT << R"( + --errorlog-file= + Set path to write error log. To reopen file, + send USR1 signal to nghttpx. + Default: )" << get_config()->errorlog_file.get() << R"( + --errorlog-syslog Send error log to syslog. If this option is + used, --errorlog-file option is ignored. + --syslog-facility= + Set syslog facility to . + Default: )" + << str_syslog_facility(get_config()->syslog_facility) << R"( - mod_config()->http2.upstream.callbacks = create_http2_upstream_callbacks(); - mod_config()->http2.downstream.callbacks = - create_http2_downstream_callbacks(); +Misc: + --add-x-forwarded-for + Append X-Forwarded-For header field to the + downstream request. + --strip-incoming-x-forwarded-for + Strip X-Forwarded-For header field from inbound + client requests. + --no-via Don't append to Via header field. If Via header + field is received, it is left unaltered. + --no-location-rewrite + Don't rewrite location header field on + --http2-bridge, --client and default mode. For + --http2-proxy and --client-proxy mode, location + header field will not be altered regardless of + this option. + --altsvc= + Specify protocol ID, port, host and origin of + alternative service. and 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: --altsvc=h2,443 + --add-response-header=
+ Specify additional header field to add to + response header set. This option just appends + header field and won't replace anything already + set. This option can be used several times to + specify multiple header fields. + Example: --add-response-header="foo: bar" + --frontend-http2-dump-request-header= + Dumps request headers received by HTTP/2 frontend + to the file denoted in . The output is + done in HTTP/1 header field format and each + header block is followed by an empty line. This + option is not thread safe and MUST NOT be used + with option -n, where >= 2. + --frontend-http2-dump-response-header= + Dumps response headers sent from HTTP/2 frontend + to the file denoted in . The output is + done in HTTP/1 header field format and each + header block is followed by an empty line. This + option is not thread safe and MUST NOT be used + with option -n, where >= 2. + -o, --frontend-frame-debug + Print HTTP/2 frames in frontend to stderr. This + option is not thread safe and MUST NOT be used + with option -n=N, where N >= 2. + -D, --daemon + Run in a background. If -D is used, the current + working directory is changed to '/'. + --pid-file= Set path to save PID of this program. + --user= Run this program as . This option is + intended to be used to drop root privileges. + --conf= Load configuration from . + Default: )" << get_config()->conf_path.get() << R"( + -v, --version Print version and exit. + -h, --help Print this help and exit.)" << std::endl; } } // namespace int main(int argc, char **argv) { - nghttp2::ssl::libssl_init(); - -#ifndef NOTHREADS - nghttp2::ssl::LibsslGlobalLock lock; -#endif // NOTHREADS - Log::set_severity_level(NOTICE); create_config(); fill_default_config(); - // make copy of stderr - util::store_original_fds(); - - // First open log files with default configuration, so that we can - // log errors/warnings while reading configuration files. - reopen_log_files(); - - mod_config()->original_argv = argv; - // We have to copy argv, since getopt_long may change its content. mod_config()->argc = argc; mod_config()->argv = new char *[argc]; for (int i = 0; i < argc; ++i) { mod_config()->argv[i] = strdup(argv[i]); - if (mod_config()->argv[i] == nullptr) { - auto error = errno; - LOG(FATAL) << "failed to copy argv: " << strerror(error); - exit(EXIT_FAILURE); - } } mod_config()->cwd = getcwd(nullptr, 0); @@ -2320,188 +1202,84 @@ exit(EXIT_FAILURE); } - std::vector> cmdcfgs; + std::vector> cmdcfgs; while (1) { static int flag = 0; static option long_options[] = { - {SHRPX_OPT_DAEMON.c_str(), no_argument, nullptr, 'D'}, - {SHRPX_OPT_LOG_LEVEL.c_str(), required_argument, nullptr, 'L'}, - {SHRPX_OPT_BACKEND.c_str(), required_argument, nullptr, 'b'}, - {SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS.c_str(), required_argument, - nullptr, 'c'}, - {SHRPX_OPT_FRONTEND.c_str(), required_argument, nullptr, 'f'}, + {"daemon", no_argument, nullptr, 'D'}, + {"log-level", required_argument, nullptr, 'L'}, + {"backend", required_argument, nullptr, 'b'}, + {"http2-max-concurrent-streams", required_argument, nullptr, 'c'}, + {"frontend", required_argument, nullptr, 'f'}, {"help", no_argument, nullptr, 'h'}, - {SHRPX_OPT_INSECURE.c_str(), no_argument, nullptr, 'k'}, - {SHRPX_OPT_WORKERS.c_str(), required_argument, nullptr, 'n'}, - {SHRPX_OPT_CLIENT_PROXY.c_str(), no_argument, nullptr, 'p'}, - {SHRPX_OPT_HTTP2_PROXY.c_str(), no_argument, nullptr, 's'}, + {"insecure", no_argument, nullptr, 'k'}, + {"workers", required_argument, nullptr, 'n'}, + {"client-proxy", no_argument, nullptr, 'p'}, + {"http2-proxy", no_argument, nullptr, 's'}, {"version", no_argument, nullptr, 'v'}, - {SHRPX_OPT_FRONTEND_FRAME_DEBUG.c_str(), no_argument, nullptr, 'o'}, - {SHRPX_OPT_ADD_X_FORWARDED_FOR.c_str(), no_argument, &flag, 1}, - {SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT.c_str(), required_argument, - &flag, 2}, - {SHRPX_OPT_FRONTEND_READ_TIMEOUT.c_str(), required_argument, &flag, 3}, - {SHRPX_OPT_FRONTEND_WRITE_TIMEOUT.c_str(), required_argument, &flag, 4}, - {SHRPX_OPT_BACKEND_READ_TIMEOUT.c_str(), required_argument, &flag, 5}, - {SHRPX_OPT_BACKEND_WRITE_TIMEOUT.c_str(), required_argument, &flag, 6}, - {SHRPX_OPT_ACCESSLOG_FILE.c_str(), required_argument, &flag, 7}, - {SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT.c_str(), required_argument, &flag, - 8}, - {SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS.c_str(), required_argument, &flag, - 9}, - {SHRPX_OPT_PID_FILE.c_str(), required_argument, &flag, 10}, - {SHRPX_OPT_USER.c_str(), required_argument, &flag, 11}, + {"frontend-frame-debug", no_argument, nullptr, 'o'}, + {"add-x-forwarded-for", no_argument, &flag, 1}, + {"frontend-http2-read-timeout", required_argument, &flag, 2}, + {"frontend-read-timeout", required_argument, &flag, 3}, + {"frontend-write-timeout", required_argument, &flag, 4}, + {"backend-read-timeout", required_argument, &flag, 5}, + {"backend-write-timeout", required_argument, &flag, 6}, + {"accesslog-file", required_argument, &flag, 7}, + {"backend-keep-alive-timeout", required_argument, &flag, 8}, + {"frontend-http2-window-bits", required_argument, &flag, 9}, + {"pid-file", required_argument, &flag, 10}, + {"user", required_argument, &flag, 11}, {"conf", required_argument, &flag, 12}, - {SHRPX_OPT_SYSLOG_FACILITY.c_str(), required_argument, &flag, 14}, - {SHRPX_OPT_BACKLOG.c_str(), required_argument, &flag, 15}, - {SHRPX_OPT_CIPHERS.c_str(), required_argument, &flag, 16}, - {SHRPX_OPT_CLIENT.c_str(), no_argument, &flag, 17}, - {SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS.c_str(), required_argument, &flag, - 18}, - {SHRPX_OPT_CACERT.c_str(), required_argument, &flag, 19}, - {SHRPX_OPT_BACKEND_IPV4.c_str(), no_argument, &flag, 20}, - {SHRPX_OPT_BACKEND_IPV6.c_str(), no_argument, &flag, 21}, - {SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE.c_str(), required_argument, &flag, - 22}, - {SHRPX_OPT_NO_VIA.c_str(), no_argument, &flag, 23}, - {SHRPX_OPT_SUBCERT.c_str(), required_argument, &flag, 24}, - {SHRPX_OPT_HTTP2_BRIDGE.c_str(), no_argument, &flag, 25}, - {SHRPX_OPT_BACKEND_HTTP_PROXY_URI.c_str(), required_argument, &flag, - 26}, - {SHRPX_OPT_BACKEND_NO_TLS.c_str(), no_argument, &flag, 27}, - {SHRPX_OPT_FRONTEND_NO_TLS.c_str(), no_argument, &flag, 29}, - {SHRPX_OPT_BACKEND_TLS_SNI_FIELD.c_str(), required_argument, &flag, 31}, - {SHRPX_OPT_DH_PARAM_FILE.c_str(), required_argument, &flag, 33}, - {SHRPX_OPT_READ_RATE.c_str(), required_argument, &flag, 34}, - {SHRPX_OPT_READ_BURST.c_str(), required_argument, &flag, 35}, - {SHRPX_OPT_WRITE_RATE.c_str(), required_argument, &flag, 36}, - {SHRPX_OPT_WRITE_BURST.c_str(), required_argument, &flag, 37}, - {SHRPX_OPT_NPN_LIST.c_str(), required_argument, &flag, 38}, - {SHRPX_OPT_VERIFY_CLIENT.c_str(), no_argument, &flag, 39}, - {SHRPX_OPT_VERIFY_CLIENT_CACERT.c_str(), required_argument, &flag, 40}, - {SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE.c_str(), required_argument, &flag, - 41}, - {SHRPX_OPT_CLIENT_CERT_FILE.c_str(), required_argument, &flag, 42}, - {SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER.c_str(), - required_argument, &flag, 43}, - {SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER.c_str(), - required_argument, &flag, 44}, - {SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING.c_str(), no_argument, &flag, 45}, - {SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS.c_str(), - required_argument, &flag, 46}, - {SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS.c_str(), - required_argument, &flag, 47}, - {SHRPX_OPT_TLS_PROTO_LIST.c_str(), required_argument, &flag, 48}, - {SHRPX_OPT_PADDING.c_str(), required_argument, &flag, 49}, - {SHRPX_OPT_WORKER_READ_RATE.c_str(), required_argument, &flag, 50}, - {SHRPX_OPT_WORKER_READ_BURST.c_str(), required_argument, &flag, 51}, - {SHRPX_OPT_WORKER_WRITE_RATE.c_str(), required_argument, &flag, 52}, - {SHRPX_OPT_WORKER_WRITE_BURST.c_str(), required_argument, &flag, 53}, - {SHRPX_OPT_ALTSVC.c_str(), required_argument, &flag, 54}, - {SHRPX_OPT_ADD_RESPONSE_HEADER.c_str(), required_argument, &flag, 55}, - {SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS.c_str(), required_argument, - &flag, 56}, - {SHRPX_OPT_ACCESSLOG_SYSLOG.c_str(), no_argument, &flag, 57}, - {SHRPX_OPT_ERRORLOG_FILE.c_str(), required_argument, &flag, 58}, - {SHRPX_OPT_ERRORLOG_SYSLOG.c_str(), no_argument, &flag, 59}, - {SHRPX_OPT_STREAM_READ_TIMEOUT.c_str(), required_argument, &flag, 60}, - {SHRPX_OPT_STREAM_WRITE_TIMEOUT.c_str(), required_argument, &flag, 61}, - {SHRPX_OPT_NO_LOCATION_REWRITE.c_str(), no_argument, &flag, 62}, - {SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST.c_str(), - required_argument, &flag, 63}, - {SHRPX_OPT_LISTENER_DISABLE_TIMEOUT.c_str(), required_argument, &flag, - 64}, - {SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR.c_str(), no_argument, &flag, - 65}, - {SHRPX_OPT_ACCESSLOG_FORMAT.c_str(), required_argument, &flag, 66}, - {SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND.c_str(), - required_argument, &flag, 67}, - {SHRPX_OPT_TLS_TICKET_KEY_FILE.c_str(), required_argument, &flag, 68}, - {SHRPX_OPT_RLIMIT_NOFILE.c_str(), required_argument, &flag, 69}, - {SHRPX_OPT_BACKEND_RESPONSE_BUFFER.c_str(), required_argument, &flag, - 71}, - {SHRPX_OPT_BACKEND_REQUEST_BUFFER.c_str(), required_argument, &flag, - 72}, - {SHRPX_OPT_NO_HOST_REWRITE.c_str(), no_argument, &flag, 73}, - {SHRPX_OPT_NO_SERVER_PUSH.c_str(), no_argument, &flag, 74}, - {SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER.c_str(), - required_argument, &flag, 76}, - {SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE.c_str(), required_argument, &flag, - 77}, - {SHRPX_OPT_OCSP_UPDATE_INTERVAL.c_str(), required_argument, &flag, 78}, - {SHRPX_OPT_NO_OCSP.c_str(), no_argument, &flag, 79}, - {SHRPX_OPT_HEADER_FIELD_BUFFER.c_str(), required_argument, &flag, 80}, - {SHRPX_OPT_MAX_HEADER_FIELDS.c_str(), required_argument, &flag, 81}, - {SHRPX_OPT_ADD_REQUEST_HEADER.c_str(), required_argument, &flag, 82}, - {SHRPX_OPT_INCLUDE.c_str(), required_argument, &flag, 83}, - {SHRPX_OPT_TLS_TICKET_KEY_CIPHER.c_str(), required_argument, &flag, 84}, - {SHRPX_OPT_HOST_REWRITE.c_str(), no_argument, &flag, 85}, - {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED.c_str(), required_argument, - &flag, 86}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED.c_str(), required_argument, &flag, - 87}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL.c_str(), required_argument, - &flag, 88}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY.c_str(), - required_argument, &flag, 89}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL.c_str(), required_argument, - &flag, 90}, - {SHRPX_OPT_MRUBY_FILE.c_str(), required_argument, &flag, 91}, - {SHRPX_OPT_ACCEPT_PROXY_PROTOCOL.c_str(), no_argument, &flag, 93}, - {SHRPX_OPT_FASTOPEN.c_str(), required_argument, &flag, 94}, - {SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD.c_str(), required_argument, - &flag, 95}, - {SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT.c_str(), required_argument, &flag, - 96}, - {SHRPX_OPT_ADD_FORWARDED.c_str(), required_argument, &flag, 97}, - {SHRPX_OPT_STRIP_INCOMING_FORWARDED.c_str(), no_argument, &flag, 98}, - {SHRPX_OPT_FORWARDED_BY.c_str(), required_argument, &flag, 99}, - {SHRPX_OPT_FORWARDED_FOR.c_str(), required_argument, &flag, 100}, - {SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER.c_str(), required_argument, - &flag, 101}, - {SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS.c_str(), required_argument, &flag, - 102}, - {SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST.c_str(), no_argument, &flag, 103}, - {SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER.c_str(), required_argument, - &flag, 104}, - {SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS.c_str(), required_argument, &flag, - 105}, - {SHRPX_OPT_BACKEND_HTTP1_TLS.c_str(), no_argument, &flag, 106}, - {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS.c_str(), no_argument, &flag, - 108}, - {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE.c_str(), - required_argument, &flag, 109}, - {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE.c_str(), - required_argument, &flag, 110}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS.c_str(), no_argument, &flag, - 111}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE.c_str(), - required_argument, &flag, 112}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE.c_str(), - required_argument, &flag, 113}, - {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY.c_str(), - required_argument, &flag, 114}, - {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY.c_str(), - required_argument, &flag, 115}, - {SHRPX_OPT_BACKEND_ADDRESS_FAMILY.c_str(), required_argument, &flag, - 116}, - {SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS.c_str(), - required_argument, &flag, 117}, - {SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS.c_str(), - required_argument, &flag, 118}, - {SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND.c_str(), required_argument, - &flag, 119}, - {SHRPX_OPT_BACKEND_TLS.c_str(), no_argument, &flag, 120}, - {SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST.c_str(), required_argument, - &flag, 121}, - {SHRPX_OPT_ERROR_PAGE.c_str(), required_argument, &flag, 122}, - {SHRPX_OPT_NO_KQUEUE.c_str(), no_argument, &flag, 123}, - {SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument, - &flag, 124}, - {SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument, - &flag, 125}, - {SHRPX_OPT_API_MAX_REQUEST_BODY.c_str(), required_argument, &flag, 126}, - {SHRPX_OPT_BACKEND_MAX_BACKOFF.c_str(), required_argument, &flag, 127}, + {"syslog-facility", required_argument, &flag, 14}, + {"backlog", required_argument, &flag, 15}, + {"ciphers", required_argument, &flag, 16}, + {"client", no_argument, &flag, 17}, + {"backend-http2-window-bits", required_argument, &flag, 18}, + {"cacert", required_argument, &flag, 19}, + {"backend-ipv4", no_argument, &flag, 20}, + {"backend-ipv6", no_argument, &flag, 21}, + {"private-key-passwd-file", required_argument, &flag, 22}, + {"no-via", no_argument, &flag, 23}, + {"subcert", required_argument, &flag, 24}, + {"http2-bridge", no_argument, &flag, 25}, + {"backend-http-proxy-uri", required_argument, &flag, 26}, + {"backend-no-tls", no_argument, &flag, 27}, + {"frontend-no-tls", no_argument, &flag, 29}, + {"backend-tls-sni-field", required_argument, &flag, 31}, + {"dh-param-file", required_argument, &flag, 33}, + {"read-rate", required_argument, &flag, 34}, + {"read-burst", required_argument, &flag, 35}, + {"write-rate", required_argument, &flag, 36}, + {"write-burst", required_argument, &flag, 37}, + {"npn-list", required_argument, &flag, 38}, + {"verify-client", no_argument, &flag, 39}, + {"verify-client-cacert", required_argument, &flag, 40}, + {"client-private-key-file", required_argument, &flag, 41}, + {"client-cert-file", required_argument, &flag, 42}, + {"frontend-http2-dump-request-header", required_argument, &flag, 43}, + {"frontend-http2-dump-response-header", required_argument, &flag, 44}, + {"http2-no-cookie-crumbling", no_argument, &flag, 45}, + {"frontend-http2-connection-window-bits", required_argument, &flag, 46}, + {"backend-http2-connection-window-bits", required_argument, &flag, 47}, + {"tls-proto-list", required_argument, &flag, 48}, + {"padding", required_argument, &flag, 49}, + {"worker-read-rate", required_argument, &flag, 50}, + {"worker-read-burst", required_argument, &flag, 51}, + {"worker-write-rate", required_argument, &flag, 52}, + {"worker-write-burst", required_argument, &flag, 53}, + {"altsvc", required_argument, &flag, 54}, + {"add-response-header", required_argument, &flag, 55}, + {"worker-frontend-connections", required_argument, &flag, 56}, + {"accesslog-syslog", no_argument, &flag, 57}, + {"errorlog-file", required_argument, &flag, 58}, + {"errorlog-syslog", no_argument, &flag, 59}, + {"stream-read-timeout", required_argument, &flag, 60}, + {"stream-write-timeout", required_argument, &flag, 61}, + {"no-location-rewrite", no_argument, &flag, 62}, + {"backend-connections-per-frontend", required_argument, &flag, 63}, + {"listener-disable-timeout", required_argument, &flag, 64}, + {"strip-incoming-x-forwarded-for", no_argument, &flag, 65}, + {"accesslog-format", required_argument, &flag, 66}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -2512,39 +1290,41 @@ } switch (c) { case 'D': - cmdcfgs.emplace_back(SHRPX_OPT_DAEMON, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_DAEMON, "yes"); break; case 'L': - cmdcfgs.emplace_back(SHRPX_OPT_LOG_LEVEL, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_LOG_LEVEL, optarg); break; case 'b': - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND, optarg); break; case 'c': - cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS, optarg); break; case 'f': - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND, optarg); break; case 'h': print_help(std::cout); exit(EXIT_SUCCESS); case 'k': - cmdcfgs.emplace_back(SHRPX_OPT_INSECURE, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_INSECURE, "yes"); break; case 'n': - cmdcfgs.emplace_back(SHRPX_OPT_WORKERS, StringRef{optarg}); +#ifdef NOTHREADS + LOG(WARN) << "Threading disabled at build time, no threads created."; +#else + cmdcfgs.emplace_back(SHRPX_OPT_WORKERS, optarg); +#endif // NOTHREADS break; case 'o': - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_FRAME_DEBUG, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_FRAME_DEBUG, "yes"); break; case 'p': - cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PROXY, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PROXY, "yes"); break; case 's': - cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_PROXY, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_PROXY, "yes"); break; case 'v': print_version(std::cout); @@ -2556,548 +1336,253 @@ switch (flag) { case 1: // --add-x-forwarded-for - cmdcfgs.emplace_back(SHRPX_OPT_ADD_X_FORWARDED_FOR, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_ADD_X_FORWARDED_FOR, "yes"); break; case 2: // --frontend-http2-read-timeout - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT, optarg); break; case 3: // --frontend-read-timeout - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_READ_TIMEOUT, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_READ_TIMEOUT, optarg); break; case 4: // --frontend-write-timeout - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_WRITE_TIMEOUT, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_WRITE_TIMEOUT, optarg); break; case 5: // --backend-read-timeout - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_READ_TIMEOUT, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_READ_TIMEOUT, optarg); break; case 6: // --backend-write-timeout - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_WRITE_TIMEOUT, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_WRITE_TIMEOUT, optarg); break; case 7: - cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FILE, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FILE, optarg); break; case 8: // --backend-keep-alive-timeout - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT, optarg); break; case 9: // --frontend-http2-window-bits - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS, optarg); break; case 10: - cmdcfgs.emplace_back(SHRPX_OPT_PID_FILE, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_PID_FILE, optarg); break; case 11: - cmdcfgs.emplace_back(SHRPX_OPT_USER, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_USER, optarg); break; case 12: // --conf - mod_config()->conf_path = optarg; + mod_config()->conf_path = strcopy(optarg); break; case 14: // --syslog-facility - cmdcfgs.emplace_back(SHRPX_OPT_SYSLOG_FACILITY, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_SYSLOG_FACILITY, optarg); break; case 15: // --backlog - cmdcfgs.emplace_back(SHRPX_OPT_BACKLOG, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_BACKLOG, optarg); break; case 16: // --ciphers - cmdcfgs.emplace_back(SHRPX_OPT_CIPHERS, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_CIPHERS, optarg); break; case 17: // --client - cmdcfgs.emplace_back(SHRPX_OPT_CLIENT, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_CLIENT, "yes"); break; case 18: // --backend-http2-window-bits - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS, optarg); break; case 19: // --cacert - cmdcfgs.emplace_back(SHRPX_OPT_CACERT, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_CACERT, optarg); break; case 20: // --backend-ipv4 - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV4, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV4, "yes"); break; case 21: // --backend-ipv6 - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV6, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV6, "yes"); break; case 22: // --private-key-passwd-file - cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE, optarg); break; case 23: // --no-via - cmdcfgs.emplace_back(SHRPX_OPT_NO_VIA, StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_VIA, "yes"); break; case 24: // --subcert - cmdcfgs.emplace_back(SHRPX_OPT_SUBCERT, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_SUBCERT, optarg); break; case 25: // --http2-bridge - cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_BRIDGE, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_BRIDGE, "yes"); break; case 26: // --backend-http-proxy-uri - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP_PROXY_URI, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP_PROXY_URI, optarg); break; case 27: // --backend-no-tls - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_NO_TLS, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_NO_TLS, "yes"); break; case 29: // --frontend-no-tls - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_NO_TLS, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_NO_TLS, "yes"); break; case 31: // --backend-tls-sni-field - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS_SNI_FIELD, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS_SNI_FIELD, optarg); break; case 33: // --dh-param-file - cmdcfgs.emplace_back(SHRPX_OPT_DH_PARAM_FILE, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_DH_PARAM_FILE, optarg); break; case 34: // --read-rate - cmdcfgs.emplace_back(SHRPX_OPT_READ_RATE, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_READ_RATE, optarg); break; case 35: // --read-burst - cmdcfgs.emplace_back(SHRPX_OPT_READ_BURST, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_READ_BURST, optarg); break; case 36: // --write-rate - cmdcfgs.emplace_back(SHRPX_OPT_WRITE_RATE, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_WRITE_RATE, optarg); break; case 37: // --write-burst - cmdcfgs.emplace_back(SHRPX_OPT_WRITE_BURST, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_WRITE_BURST, optarg); break; case 38: // --npn-list - cmdcfgs.emplace_back(SHRPX_OPT_NPN_LIST, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_NPN_LIST, optarg); break; case 39: // --verify-client - cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT, "yes"); break; case 40: // --verify-client-cacert - cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT_CACERT, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT_CACERT, optarg); break; case 41: // --client-private-key-file - cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE, optarg); break; case 42: // --client-cert-file - cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_CERT_FILE, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_CERT_FILE, optarg); break; case 43: // --frontend-http2-dump-request-header cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER, - StringRef{optarg}); + optarg); break; case 44: // --frontend-http2-dump-response-header cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER, - StringRef{optarg}); + optarg); break; case 45: // --http2-no-cookie-crumbling - cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING, "yes"); break; case 46: // --frontend-http2-connection-window-bits cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS, - StringRef{optarg}); + optarg); break; case 47: // --backend-http2-connection-window-bits cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS, - StringRef{optarg}); + optarg); break; case 48: // --tls-proto-list - cmdcfgs.emplace_back(SHRPX_OPT_TLS_PROTO_LIST, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_TLS_PROTO_LIST, optarg); break; case 49: // --padding - cmdcfgs.emplace_back(SHRPX_OPT_PADDING, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_PADDING, optarg); break; case 50: // --worker-read-rate - cmdcfgs.emplace_back(SHRPX_OPT_WORKER_READ_RATE, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_WORKER_READ_RATE, optarg); break; case 51: // --worker-read-burst - cmdcfgs.emplace_back(SHRPX_OPT_WORKER_READ_BURST, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_WORKER_READ_BURST, optarg); break; case 52: // --worker-write-rate - cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_RATE, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_RATE, optarg); break; case 53: // --worker-write-burst - cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_BURST, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_BURST, optarg); break; case 54: // --altsvc - cmdcfgs.emplace_back(SHRPX_OPT_ALTSVC, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_ALTSVC, optarg); break; case 55: // --add-response-header - cmdcfgs.emplace_back(SHRPX_OPT_ADD_RESPONSE_HEADER, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_ADD_RESPONSE_HEADER, optarg); break; case 56: // --worker-frontend-connections - cmdcfgs.emplace_back(SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS, optarg); break; case 57: // --accesslog-syslog - cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_SYSLOG, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_SYSLOG, "yes"); break; case 58: // --errorlog-file - cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_FILE, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_FILE, optarg); break; case 59: // --errorlog-syslog - cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_SYSLOG, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_SYSLOG, "yes"); break; case 60: // --stream-read-timeout - cmdcfgs.emplace_back(SHRPX_OPT_STREAM_READ_TIMEOUT, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_STREAM_READ_TIMEOUT, optarg); break; case 61: // --stream-write-timeout - cmdcfgs.emplace_back(SHRPX_OPT_STREAM_WRITE_TIMEOUT, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_STREAM_WRITE_TIMEOUT, optarg); break; case 62: // --no-location-rewrite - cmdcfgs.emplace_back(SHRPX_OPT_NO_LOCATION_REWRITE, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_NO_LOCATION_REWRITE, "yes"); break; case 63: - // --backend-http1-connections-per-host - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST, - StringRef{optarg}); + // --backend-connections-per-frontend + cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND, + optarg); break; case 64: // --listener-disable-timeout - cmdcfgs.emplace_back(SHRPX_OPT_LISTENER_DISABLE_TIMEOUT, - StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_LISTENER_DISABLE_TIMEOUT, optarg); break; case 65: // --strip-incoming-x-forwarded-for - cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR, - StringRef::from_lit("yes")); + cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR, "yes"); break; case 66: // --accesslog-format - cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FORMAT, StringRef{optarg}); - break; - case 67: - // --backend-http1-connections-per-frontend - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND, - StringRef{optarg}); - break; - case 68: - // --tls-ticket-key-file - cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_FILE, StringRef{optarg}); - break; - case 69: - // --rlimit-nofile - cmdcfgs.emplace_back(SHRPX_OPT_RLIMIT_NOFILE, StringRef{optarg}); - break; - case 71: - // --backend-response-buffer - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_RESPONSE_BUFFER, - StringRef{optarg}); - break; - case 72: - // --backend-request-buffer - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_REQUEST_BUFFER, - StringRef{optarg}); - break; - case 73: - // --no-host-rewrite - cmdcfgs.emplace_back(SHRPX_OPT_NO_HOST_REWRITE, - StringRef::from_lit("yes")); - break; - case 74: - // --no-server-push - cmdcfgs.emplace_back(SHRPX_OPT_NO_SERVER_PUSH, - StringRef::from_lit("yes")); - break; - case 76: - // --backend-http2-connections-per-worker - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER, - StringRef{optarg}); - break; - case 77: - // --fetch-ocsp-response-file - cmdcfgs.emplace_back(SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE, - StringRef{optarg}); - break; - case 78: - // --ocsp-update-interval - cmdcfgs.emplace_back(SHRPX_OPT_OCSP_UPDATE_INTERVAL, StringRef{optarg}); - break; - case 79: - // --no-ocsp - cmdcfgs.emplace_back(SHRPX_OPT_NO_OCSP, StringRef::from_lit("yes")); - break; - case 80: - // --header-field-buffer - cmdcfgs.emplace_back(SHRPX_OPT_HEADER_FIELD_BUFFER, StringRef{optarg}); - break; - case 81: - // --max-header-fields - cmdcfgs.emplace_back(SHRPX_OPT_MAX_HEADER_FIELDS, StringRef{optarg}); - break; - case 82: - // --add-request-header - cmdcfgs.emplace_back(SHRPX_OPT_ADD_REQUEST_HEADER, StringRef{optarg}); - break; - case 83: - // --include - cmdcfgs.emplace_back(SHRPX_OPT_INCLUDE, StringRef{optarg}); - break; - case 84: - // --tls-ticket-key-cipher - cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_CIPHER, - StringRef{optarg}); - break; - case 85: - // --host-rewrite - cmdcfgs.emplace_back(SHRPX_OPT_HOST_REWRITE, - StringRef::from_lit("yes")); - break; - case 86: - // --tls-session-cache-memcached - cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED, - StringRef{optarg}); - break; - case 87: - // --tls-ticket-key-memcached - cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED, - StringRef{optarg}); - break; - case 88: - // --tls-ticket-key-memcached-interval - cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL, - StringRef{optarg}); - break; - case 89: - // --tls-ticket-key-memcached-max-retry - cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY, - StringRef{optarg}); - break; - case 90: - // --tls-ticket-key-memcached-max-fail - cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL, - StringRef{optarg}); - break; - case 91: - // --mruby-file - cmdcfgs.emplace_back(SHRPX_OPT_MRUBY_FILE, StringRef{optarg}); - break; - case 93: - // --accept-proxy-protocol - cmdcfgs.emplace_back(SHRPX_OPT_ACCEPT_PROXY_PROTOCOL, - StringRef::from_lit("yes")); - break; - case 94: - // --fastopen - cmdcfgs.emplace_back(SHRPX_OPT_FASTOPEN, StringRef{optarg}); - break; - case 95: - // --tls-dyn-rec-warmup-threshold - cmdcfgs.emplace_back(SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD, - StringRef{optarg}); - break; - case 96: - // --tls-dyn-rec-idle-timeout - cmdcfgs.emplace_back(SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT, - StringRef{optarg}); - break; - case 97: - // --add-forwarded - cmdcfgs.emplace_back(SHRPX_OPT_ADD_FORWARDED, StringRef{optarg}); - break; - case 98: - // --strip-incoming-forwarded - cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_FORWARDED, - StringRef::from_lit("yes")); - break; - case 99: - // --forwarded-by - cmdcfgs.emplace_back(SHRPX_OPT_FORWARDED_BY, StringRef{optarg}); - break; - case 100: - // --forwarded-for - cmdcfgs.emplace_back(SHRPX_OPT_FORWARDED_FOR, StringRef{optarg}); - break; - case 101: - // --response-header-field-buffer - cmdcfgs.emplace_back(SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER, - StringRef{optarg}); - break; - case 102: - // --max-response-header-fields - cmdcfgs.emplace_back(SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS, - StringRef{optarg}); - break; - case 103: - // --no-http2-cipher-black-list - cmdcfgs.emplace_back(SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST, - StringRef::from_lit("yes")); - break; - case 104: - // --request-header-field-buffer - cmdcfgs.emplace_back(SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER, - StringRef{optarg}); - break; - case 105: - // --max-request-header-fields - cmdcfgs.emplace_back(SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS, - StringRef{optarg}); - break; - case 106: - // --backend-http1-tls - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_TLS, - StringRef::from_lit("yes")); - break; - case 108: - // --tls-session-cache-memcached-tls - cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS, - StringRef::from_lit("yes")); - break; - case 109: - // --tls-session-cache-memcached-cert-file - cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE, - StringRef{optarg}); - break; - case 110: - // --tls-session-cache-memcached-private-key-file - cmdcfgs.emplace_back( - SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE, - StringRef{optarg}); - break; - case 111: - // --tls-ticket-key-memcached-tls - cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS, - StringRef::from_lit("yes")); - break; - case 112: - // --tls-ticket-key-memcached-cert-file - cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE, - StringRef{optarg}); - break; - case 113: - // --tls-ticket-key-memcached-private-key-file - cmdcfgs.emplace_back( - SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE, - StringRef{optarg}); - break; - case 114: - // --tls-ticket-key-memcached-address-family - cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY, - StringRef{optarg}); - break; - case 115: - // --tls-session-cache-memcached-address-family - cmdcfgs.emplace_back( - SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY, - StringRef{optarg}); - break; - case 116: - // --backend-address-family - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_ADDRESS_FAMILY, - StringRef{optarg}); - break; - case 117: - // --frontend-http2-max-concurrent-streams - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS, - StringRef{optarg}); - break; - case 118: - // --backend-http2-max-concurrent-streams - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS, - StringRef{optarg}); - break; - case 119: - // --backend-connections-per-frontend - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND, - StringRef{optarg}); - break; - case 120: - // --backend-tls - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS, StringRef::from_lit("yes")); - break; - case 121: - // --backend-connections-per-host - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST, - StringRef{optarg}); - break; - case 122: - // --error-page - cmdcfgs.emplace_back(SHRPX_OPT_ERROR_PAGE, StringRef{optarg}); - break; - case 123: - // --no-kqueue - cmdcfgs.emplace_back(SHRPX_OPT_NO_KQUEUE, StringRef::from_lit("yes")); - break; - case 124: - // --frontend-http2-settings-timeout - cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT, - StringRef{optarg}); - break; - case 125: - // --backend-http2-settings-timeout - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT, - StringRef{optarg}); - break; - case 126: - // --api-max-request-body - cmdcfgs.emplace_back(SHRPX_OPT_API_MAX_REQUEST_BODY, StringRef{optarg}); - break; - case 127: - // --backend-max-backoff - cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_MAX_BACKOFF, StringRef{optarg}); + cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FORMAT, optarg); break; default: break; @@ -3108,19 +1593,267 @@ } } - process_options(argc, argv, cmdcfgs); + // Initialize OpenSSL before parsing options because we create + // SSL_CTX there. + OPENSSL_config(nullptr); + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); + SSL_library_init(); +#ifndef NOTHREADS + nghttp2::ssl::LibsslGlobalLock lock; +#endif // NOTHREADS - if (event_loop() != 0) { - return -1; + if (conf_exists(get_config()->conf_path.get())) { + if (load_config(get_config()->conf_path.get()) == -1) { + LOG(FATAL) << "Failed to load configuration from " + << get_config()->conf_path.get(); + exit(EXIT_FAILURE); + } } - LOG(NOTICE) << "Shutdown momentarily"; + if (argc - optind >= 2) { + cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_FILE, argv[optind++]); + cmdcfgs.emplace_back(SHRPX_OPT_CERTIFICATE_FILE, argv[optind++]); + } + + // First open default log files to deal with errors occurred while + // parsing option values. + reopen_log_files(); + + for (size_t i = 0, len = cmdcfgs.size(); i < len; ++i) { + if (parse_config(cmdcfgs[i].first, cmdcfgs[i].second) == -1) { + LOG(FATAL) << "Failed to parse command-line argument."; + exit(EXIT_FAILURE); + } + } + + if (get_config()->accesslog_syslog || get_config()->errorlog_syslog) { + openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID, + get_config()->syslog_facility); + } + + if (reopen_log_files() != 0) { + LOG(FATAL) << "Failed to open log file"; + exit(EXIT_FAILURE); + } + + if (get_config()->uid != 0) { + if (worker_config->accesslog_fd != -1 && + fchown(worker_config->accesslog_fd, get_config()->uid, + get_config()->gid) == -1) { + auto error = errno; + LOG(WARN) << "Changing owner of access log file failed: " + << strerror(error); + } + if (worker_config->errorlog_fd != -1 && + fchown(worker_config->errorlog_fd, get_config()->uid, + get_config()->gid) == -1) { + auto error = errno; + LOG(WARN) << "Changing owner of error log file failed: " + << strerror(error); + } + } + + if (get_config()->http2_upstream_dump_request_header_file) { + auto path = get_config()->http2_upstream_dump_request_header_file.get(); + auto f = open_file_for_write(path); + + if (f == nullptr) { + LOG(FATAL) << "Failed to open http2 upstream request header file: " + << path; + exit(EXIT_FAILURE); + } + + mod_config()->http2_upstream_dump_request_header = f; + + if (get_config()->uid != 0) { + if (chown(path, get_config()->uid, get_config()->gid) == -1) { + auto error = errno; + LOG(WARN) << "Changing owner of http2 upstream request header file " + << path << " failed: " << strerror(error); + } + } + } + + if (get_config()->http2_upstream_dump_response_header_file) { + auto path = get_config()->http2_upstream_dump_response_header_file.get(); + auto f = open_file_for_write(path); + + if (f == nullptr) { + LOG(FATAL) << "Failed to open http2 upstream response header file: " + << path; + exit(EXIT_FAILURE); + } + + mod_config()->http2_upstream_dump_response_header = f; + + if (get_config()->uid != 0) { + if (chown(path, get_config()->uid, get_config()->gid) == -1) { + auto error = errno; + LOG(WARN) << "Changing owner of http2 upstream response header file" + << " " << path << " failed: " << strerror(error); + } + } + } + + if (get_config()->npn_list.empty()) { + mod_config()->npn_list = parse_config_str_list(DEFAULT_NPN_LIST); + } + if (get_config()->tls_proto_list.empty()) { + mod_config()->tls_proto_list = + parse_config_str_list(DEFAULT_TLS_PROTO_LIST); + } + + mod_config()->tls_proto_mask = + ssl::create_tls_proto_mask(get_config()->tls_proto_list); - delete log_config(); + mod_config()->alpn_prefs = ssl::set_alpn_prefs(get_config()->npn_list); + + if (!get_config()->subcerts.empty()) { + mod_config()->cert_tree = ssl::cert_lookup_tree_new(); + } + + for (auto &keycert : get_config()->subcerts) { + auto ssl_ctx = + ssl::create_ssl_context(keycert.first.c_str(), keycert.second.c_str()); + if (ssl::cert_lookup_tree_add_cert_from_file( + get_config()->cert_tree, ssl_ctx, keycert.second.c_str()) == -1) { + LOG(FATAL) << "Failed to add sub certificate."; + exit(EXIT_FAILURE); + } + } + + if (get_config()->cert_file && get_config()->private_key_file) { + mod_config()->default_ssl_ctx = ssl::create_ssl_context( + get_config()->private_key_file.get(), get_config()->cert_file.get()); + if (get_config()->cert_tree) { + if (ssl::cert_lookup_tree_add_cert_from_file( + get_config()->cert_tree, get_config()->default_ssl_ctx, + get_config()->cert_file.get()) == -1) { + LOG(FATAL) << "Failed to parse command-line argument."; + exit(EXIT_FAILURE); + } + } + } + + if (get_config()->backend_ipv4 && get_config()->backend_ipv6) { + LOG(FATAL) << "--backend-ipv4 and --backend-ipv6 cannot be used at the " + << "same time."; + exit(EXIT_FAILURE); + } + + if (get_config()->worker_frontend_connections == 0) { + mod_config()->worker_frontend_connections = + std::numeric_limits::max(); + } + + if (get_config()->http2_proxy + get_config()->http2_bridge + + get_config()->client_proxy + get_config()->client > + 1) { + LOG(FATAL) << "--http2-proxy, --http2-bridge, --client-proxy and --client " + << "cannot be used at the same time."; + exit(EXIT_FAILURE); + } + + if (get_config()->client || get_config()->client_proxy) { + mod_config()->client_mode = true; + } + + if (get_config()->client_mode || get_config()->http2_bridge) { + mod_config()->downstream_proto = PROTO_HTTP2; + } else { + mod_config()->downstream_proto = PROTO_HTTP; + } + + if (!get_config()->client_mode && !get_config()->upstream_no_tls) { + if (!get_config()->private_key_file || !get_config()->cert_file) { + print_usage(std::cerr); + LOG(FATAL) << "Too few arguments"; + exit(EXIT_FAILURE); + } + } + + bool downstream_ipv6_addr = + is_ipv6_numeric_addr(get_config()->downstream_host.get()); + + { + std::string hostport; + + if (downstream_ipv6_addr) { + hostport += "["; + } + + hostport += get_config()->downstream_host.get(); + + if (downstream_ipv6_addr) { + hostport += "]"; + } + + hostport += ":"; + hostport += util::utos(get_config()->downstream_port); + + mod_config()->downstream_hostport = strcopy(hostport); + } + + if (LOG_ENABLED(INFO)) { + LOG(INFO) << "Resolving backend address"; + } + if (resolve_hostname( + &mod_config()->downstream_addr, &mod_config()->downstream_addrlen, + get_config()->downstream_host.get(), get_config()->downstream_port, + get_config()->backend_ipv4 + ? AF_INET + : (get_config()->backend_ipv6 ? AF_INET6 : AF_UNSPEC)) == -1) { + exit(EXIT_FAILURE); + } + + if (get_config()->downstream_http_proxy_host) { + if (LOG_ENABLED(INFO)) { + LOG(INFO) << "Resolving backend http proxy address"; + } + if (resolve_hostname(&mod_config()->downstream_http_proxy_addr, + &mod_config()->downstream_http_proxy_addrlen, + get_config()->downstream_http_proxy_host.get(), + get_config()->downstream_http_proxy_port, + AF_UNSPEC) == -1) { + exit(EXIT_FAILURE); + } + } + + mod_config()->rate_limit_cfg = ev_token_bucket_cfg_new( + get_rate_limit(get_config()->read_rate), + get_rate_limit(get_config()->read_burst), + get_rate_limit(get_config()->write_rate), + get_rate_limit(get_config()->write_burst), nullptr); + + mod_config()->worker_rate_limit_cfg = ev_token_bucket_cfg_new( + get_rate_limit(get_config()->worker_read_rate), + get_rate_limit(get_config()->worker_read_burst), + get_rate_limit(get_config()->worker_write_rate), + get_rate_limit(get_config()->worker_write_burst), nullptr); + + if (get_config()->upstream_frame_debug) { + // To make it sync to logging + set_output(stderr); + if (isatty(fileno(stdout))) { + set_color_output(true); + } + reset_timer(); + } + + struct sigaction act; + memset(&act, 0, sizeof(struct sigaction)); + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, nullptr); + sigaction(SIGCHLD, &act, nullptr); + + event_loop(); + + LOG(NOTICE) << "Shutdown momentarily"; return 0; } } // namespace shrpx -int main(int argc, char **argv) { return run_app(shrpx::main, argc, argv); } +int main(int argc, char **argv) { return shrpx::main(argc, argv); } diff -Nru nghttp2-1.13.0/src/shrpx_client_handler.cc nghttp2-0.6.7/src/shrpx_client_handler.cc --- nghttp2-1.13.0/src/shrpx_client_handler.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_client_handler.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,16 +24,7 @@ */ #include "shrpx_client_handler.h" -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H -#ifdef HAVE_SYS_SOCKET_H -#include -#endif // HAVE_SYS_SOCKET_H -#ifdef HAVE_NETDB_H -#include -#endif // HAVE_NETDB_H - #include #include "shrpx_upstream.h" @@ -44,262 +35,368 @@ #include "shrpx_http2_downstream_connection.h" #include "shrpx_ssl.h" #include "shrpx_worker.h" +#include "shrpx_worker_config.h" #include "shrpx_downstream_connection_pool.h" #include "shrpx_downstream.h" -#include "shrpx_http2_session.h" -#include "shrpx_connect_blocker.h" -#include "shrpx_api_downstream_connection.h" -#include "shrpx_health_monitor_downstream_connection.h" #ifdef HAVE_SPDYLAY #include "shrpx_spdy_upstream.h" #endif // HAVE_SPDYLAY #include "util.h" -#include "template.h" -#include "ssl.h" +#include "libevent_util.h" using namespace nghttp2; namespace shrpx { namespace { -void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - auto conn = static_cast(w->data); - auto handler = static_cast(conn->data); - - if (LOG_ENABLED(INFO)) { - CLOG(INFO, handler) << "Time out"; +void upstream_readcb(bufferevent *bev, void *arg) { + auto handler = static_cast(arg); + auto upstream = handler->get_upstream(); + if (upstream) { + upstream->reset_timeouts(); + } + int rv = handler->on_read(); + if (rv != 0) { + delete handler; } - - delete handler; } } // namespace namespace { -void shutdowncb(struct ev_loop *loop, ev_timer *w, int revents) { - auto handler = static_cast(w->data); +void upstream_writecb(bufferevent *bev, void *arg) { + auto handler = static_cast(arg); + auto upstream = handler->get_upstream(); + if (upstream) { + upstream->reset_timeouts(); + } - if (LOG_ENABLED(INFO)) { - CLOG(INFO, handler) << "Close connection due to TLS renegotiation"; + handler->update_last_write_time(); + + // We actually depend on write low-water mark == 0. + if (handler->get_outbuf_length() > 0) { + // Possibly because of deferred callback, we may get this callback + // when the output buffer is not empty. + return; + } + if (handler->get_should_close_after_write()) { + delete handler; + return; } - delete handler; + if (!upstream) { + return; + } + int rv = upstream->on_write(); + if (rv != 0) { + delete handler; + } } } // namespace namespace { -void readcb(struct ev_loop *loop, ev_io *w, int revents) { - auto conn = static_cast(w->data); - auto handler = static_cast(conn->data); - - if (handler->do_read() != 0) { - delete handler; - return; +void upstream_eventcb(bufferevent *bev, short events, void *arg) { + auto handler = static_cast(arg); + bool finish = false; + if (events & BEV_EVENT_EOF) { + if (LOG_ENABLED(INFO)) { + CLOG(INFO, handler) << "EOF"; + } + finish = true; + } + if (events & BEV_EVENT_ERROR) { + if (LOG_ENABLED(INFO)) { + CLOG(INFO, handler) << "Network error: " << evutil_socket_error_to_string( + EVUTIL_SOCKET_ERROR()); + } + finish = true; + } + if (events & BEV_EVENT_TIMEOUT) { + if (LOG_ENABLED(INFO)) { + CLOG(INFO, handler) << "Time out"; + } + finish = true; } - if (handler->do_write() != 0) { + if (finish) { delete handler; - return; + } else { + if (events & BEV_EVENT_CONNECTED) { + handler->set_tls_handshake(true); + if (LOG_ENABLED(INFO)) { + CLOG(INFO, handler) << "SSL/TLS handshake completed"; + } + if (handler->validate_next_proto() != 0) { + delete handler; + return; + } + if (LOG_ENABLED(INFO)) { + if (SSL_session_reused(handler->get_ssl())) { + CLOG(INFO, handler) << "SSL/TLS session reused"; + } + } + } } } } // namespace namespace { -void writecb(struct ev_loop *loop, ev_io *w, int revents) { - auto conn = static_cast(w->data); - auto handler = static_cast(conn->data); - - if (handler->do_write() != 0) { +void upstream_http2_connhd_readcb(bufferevent *bev, void *arg) { + // This callback assumes upstream is Http2Upstream. + auto handler = static_cast(arg); + if (handler->on_http2_connhd_read() != 0) { delete handler; - return; } } } // namespace -int ClientHandler::noop() { return 0; } - -int ClientHandler::read_clear() { - for (;;) { - if (rb_.rleft() && on_read() != 0) { - return -1; - } - if (rb_.rleft() == 0) { - rb_.reset(); - } else if (rb_.wleft() == 0) { - conn_.rlimit.stopw(); - return 0; - } +namespace { +void upstream_http1_connhd_readcb(bufferevent *bev, void *arg) { + // This callback assumes upstream is HttpsUpstream. + auto handler = static_cast(arg); + if (handler->on_http1_connhd_read() != 0) { + delete handler; + } +} +} // namespace - if (!ev_is_active(&conn_.rev)) { - return 0; - } +ClientHandler::ClientHandler(bufferevent *bev, + bufferevent_rate_limit_group *rate_limit_group, + int fd, SSL *ssl, const char *ipaddr, + const char *port, WorkerStat *worker_stat, + DownstreamConnectionPool *dconn_pool) + : ipaddr_(ipaddr), port_(port), dconn_pool_(dconn_pool), bev_(bev), + http2session_(nullptr), ssl_(ssl), reneg_shutdown_timerev_(nullptr), + worker_stat_(worker_stat), last_write_time_(0), warmup_writelen_(0), + left_connhd_len_(NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN), fd_(fd), + should_close_after_write_(false), tls_handshake_(false), + tls_renegotiation_(false) { + int rv; - auto nread = conn_.read_clear(rb_.last, rb_.wleft()); + ++worker_stat->num_connections; - if (nread == 0) { - return 0; - } + rv = bufferevent_set_rate_limit(bev_, get_config()->rate_limit_cfg); + if (rv == -1) { + CLOG(FATAL, this) << "bufferevent_set_rate_limit() failed"; + } - if (nread < 0) { - return -1; - } + rv = bufferevent_add_to_rate_limit_group(bev_, rate_limit_group); + if (rv == -1) { + CLOG(FATAL, this) << "bufferevent_add_to_rate_limit_group() failed"; + } - rb_.write(nread); + util::bev_enable_unless(bev_, EV_READ | EV_WRITE); + bufferevent_setwatermark(bev_, EV_READ, 0, SHRPX_READ_WATERMARK); + set_upstream_timeouts(&get_config()->upstream_read_timeout, + &get_config()->upstream_write_timeout); + if (ssl_) { + SSL_set_app_data(ssl_, reinterpret_cast(this)); + set_bev_cb(nullptr, upstream_writecb, upstream_eventcb); + } else { + // For non-TLS version, first create HttpsUpstream. It may be + // upgraded to HTTP/2 through HTTP Upgrade or direct HTTP/2 + // connection. + upstream_ = util::make_unique(this); + alpn_ = "http/1.1"; + set_bev_cb(upstream_http1_connhd_readcb, nullptr, upstream_eventcb); } } -int ClientHandler::write_clear() { - std::array iov; - - for (;;) { - if (on_write() != 0) { - return -1; - } - - auto iovcnt = upstream_->response_riovec(iov.data(), iov.size()); - if (iovcnt == 0) { - break; - } - - auto nwrite = conn_.writev_clear(iov.data(), iovcnt); - if (nwrite < 0) { - return -1; - } - - if (nwrite == 0) { - return 0; - } +ClientHandler::~ClientHandler() { + if (LOG_ENABLED(INFO)) { + CLOG(INFO, this) << "Deleting"; + } - upstream_->response_drain(nwrite); + if (upstream_) { + upstream_->on_handler_delete(); } - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); + --worker_stat_->num_connections; - return 0; -} + // TODO If backend is http/2, and it is in CONNECTED state, signal + // it and make it loopbreak when output is zero. + if (worker_config->graceful_shutdown && worker_stat_->num_connections == 0) { + event_base_loopbreak(get_evbase()); + } -int ClientHandler::tls_handshake() { - ev_timer_again(conn_.loop, &conn_.rt); + if (reneg_shutdown_timerev_) { + event_free(reneg_shutdown_timerev_); + } - ERR_clear_error(); + if (ssl_) { + SSL_set_app_data(ssl_, nullptr); + SSL_set_shutdown(ssl_, SSL_RECEIVED_SHUTDOWN); + SSL_shutdown(ssl_); + } - auto rv = conn_.tls_handshake(); + bufferevent_remove_from_rate_limit_group(bev_); - if (rv == SHRPX_ERR_INPROGRESS) { - return 0; - } + util::bev_disable_unless(bev_, EV_READ | EV_WRITE); + bufferevent_free(bev_); - if (rv < 0) { - return -1; + if (ssl_) { + SSL_free(ssl_); } + shutdown(fd_, SHUT_WR); + close(fd_); if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "SSL/TLS handshake completed"; + CLOG(INFO, this) << "Deleted"; } +} - if (validate_next_proto() != 0) { - return -1; - } +Upstream *ClientHandler::get_upstream() { return upstream_.get(); } - read_ = &ClientHandler::read_tls; - write_ = &ClientHandler::write_tls; +bufferevent *ClientHandler::get_bev() const { return bev_; } - return 0; +event_base *ClientHandler::get_evbase() const { + return bufferevent_get_base(bev_); } -int ClientHandler::read_tls() { - ERR_clear_error(); +void ClientHandler::set_bev_cb(bufferevent_data_cb readcb, + bufferevent_data_cb writecb, + bufferevent_event_cb eventcb) { + bufferevent_setcb(bev_, readcb, writecb, eventcb, this); +} - for (;;) { - // we should process buffered data first before we read EOF. - if (rb_.rleft() && on_read() != 0) { - return -1; - } - if (rb_.rleft() == 0) { - rb_.reset(); - } else if (rb_.wleft() == 0) { - conn_.rlimit.stopw(); - return 0; - } +void ClientHandler::set_upstream_timeouts(const timeval *read_timeout, + const timeval *write_timeout) { + bufferevent_set_timeouts(bev_, read_timeout, write_timeout); +} - if (!ev_is_active(&conn_.rev)) { - return 0; - } +int ClientHandler::validate_next_proto() { + const unsigned char *next_proto = nullptr; + unsigned int next_proto_len; + int rv; - auto nread = conn_.read_tls(rb_.last, rb_.wleft()); + // First set callback for catch all cases + set_bev_cb(upstream_readcb, upstream_writecb, upstream_eventcb); + SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len); + for (int i = 0; i < 2; ++i) { + if (next_proto) { + if (LOG_ENABLED(INFO)) { + std::string proto(next_proto, next_proto + next_proto_len); + CLOG(INFO, this) << "The negotiated next protocol: " << proto; + } + if (!ssl::in_proto_list(get_config()->npn_list, next_proto, + next_proto_len)) { + break; + } + if (util::check_h2_is_selected(next_proto, next_proto_len)) { - if (nread == 0) { - return 0; - } + set_bev_cb(upstream_http2_connhd_readcb, upstream_writecb, + upstream_eventcb); - if (nread < 0) { - return -1; - } + auto http2_upstream = util::make_unique(this); - rb_.write(nread); - } -} + if (!ssl::check_http2_requirement(ssl_)) { + rv = http2_upstream->terminate_session(NGHTTP2_INADEQUATE_SECURITY); -int ClientHandler::write_tls() { - struct iovec iov; + if (rv != 0) { + return -1; + } + } - ERR_clear_error(); + upstream_ = std::move(http2_upstream); + alpn_.assign(next_proto, next_proto + next_proto_len); - for (;;) { - if (on_write() != 0) { - return -1; - } + // At this point, input buffer is already filled with some + // bytes. The read callback is not called until new data + // come. So consume input buffer here. + if (on_http2_connhd_read() != 0) { + return -1; + } + + return 0; + } else { +#ifdef HAVE_SPDYLAY + uint16_t version = spdylay_npn_get_version(next_proto, next_proto_len); + if (version) { + upstream_ = util::make_unique(version, this); + + switch (version) { + case SPDYLAY_PROTO_SPDY2: + alpn_ = "spdy/2"; + break; + case SPDYLAY_PROTO_SPDY3: + alpn_ = "spdy/3"; + break; + case SPDYLAY_PROTO_SPDY3_1: + alpn_ = "spdy/3.1"; + break; + default: + alpn_ = "spdy/unknown"; + } + + // At this point, input buffer is already filled with some + // bytes. The read callback is not called until new data + // come. So consume input buffer here. + if (upstream_->on_read() != 0) { + return -1; + } + + return 0; + } +#endif // HAVE_SPDYLAY + if (next_proto_len == 8 && memcmp("http/1.1", next_proto, 8) == 0) { + upstream_ = util::make_unique(this); + alpn_ = "http/1.1"; + + // At this point, input buffer is already filled with some + // bytes. The read callback is not called until new data + // come. So consume input buffer here. + if (upstream_->on_read() != 0) { + return -1; + } - auto iovcnt = upstream_->response_riovec(&iov, 1); - if (iovcnt == 0) { - conn_.start_tls_write_idle(); + return 0; + } + } break; } - - auto nwrite = conn_.write_tls(iov.iov_base, iov.iov_len); - if (nwrite < 0) { - return -1; +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + SSL_get0_alpn_selected(ssl_, &next_proto, &next_proto_len); +#else // OPENSSL_VERSION_NUMBER < 0x10002000L + break; +#endif // OPENSSL_VERSION_NUMBER < 0x10002000L + } + if (!next_proto) { + if (LOG_ENABLED(INFO)) { + CLOG(INFO, this) << "No protocol negotiated. Fallback to HTTP/1.1"; } + upstream_ = util::make_unique(this); + alpn_ = "http/1.1"; - if (nwrite == 0) { - return 0; + // At this point, input buffer is already filled with some bytes. + // The read callback is not called until new data come. So consume + // input buffer here. + if (upstream_->on_read() != 0) { + return -1; } - upstream_->response_drain(nwrite); + return 0; } - - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - return 0; + if (LOG_ENABLED(INFO)) { + CLOG(INFO, this) << "The negotiated protocol is not supported"; + } + return -1; } -int ClientHandler::upstream_noop() { return 0; } +int ClientHandler::on_read() { return upstream_->on_read(); } -int ClientHandler::upstream_read() { - assert(upstream_); - if (upstream_->on_read() != 0) { - return -1; - } - return 0; -} +int ClientHandler::on_event() { return upstream_->on_event(); } -int ClientHandler::upstream_write() { - assert(upstream_); - if (upstream_->on_write() != 0) { - return -1; - } +int ClientHandler::on_http2_connhd_read() { + // This callback assumes upstream is Http2Upstream. + uint8_t data[NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN]; + auto input = bufferevent_get_input(bev_); + auto readlen = evbuffer_remove(input, data, left_connhd_len_); - if (get_should_close_after_write() && upstream_->response_empty()) { + if (readlen == -1) { return -1; } - return 0; -} - -int ClientHandler::upstream_http2_connhd_read() { - auto nread = std::min(left_connhd_len_, rb_.rleft()); - if (memcmp(NGHTTP2_CLIENT_MAGIC + NGHTTP2_CLIENT_MAGIC_LEN - left_connhd_len_, - rb_.pos, nread) != 0) { + if (memcmp(NGHTTP2_CLIENT_CONNECTION_PREFACE + + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - left_connhd_len_, + data, readlen) != 0) { // There is no downgrade path here. Just drop the connection. if (LOG_ENABLED(INFO)) { CLOG(INFO, this) << "invalid client connection header"; @@ -308,36 +405,43 @@ return -1; } - left_connhd_len_ -= nread; - rb_.drain(nread); - conn_.rlimit.startw(); - - if (left_connhd_len_ == 0) { - on_read_ = &ClientHandler::upstream_read; - // Run on_read to process data left in buffer since they are not - // notified further - if (on_read() != 0) { - return -1; - } + left_connhd_len_ -= readlen; + + if (left_connhd_len_ > 0) { return 0; } + set_bev_cb(upstream_readcb, upstream_writecb, upstream_eventcb); + + // Run on_read to process data left in buffer since they are not + // notified further + if (on_read() != 0) { + return -1; + } + return 0; } -int ClientHandler::upstream_http1_connhd_read() { - auto nread = std::min(left_connhd_len_, rb_.rleft()); - if (memcmp(NGHTTP2_CLIENT_MAGIC + NGHTTP2_CLIENT_MAGIC_LEN - left_connhd_len_, - rb_.pos, nread) != 0) { +int ClientHandler::on_http1_connhd_read() { + uint8_t data[NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN]; + auto input = bufferevent_get_input(bev_); + auto readlen = evbuffer_copyout(input, data, left_connhd_len_); + + if (readlen == -1) { + return -1; + } + + if (memcmp(NGHTTP2_CLIENT_CONNECTION_PREFACE + + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - left_connhd_len_, + data, readlen) != 0) { if (LOG_ENABLED(INFO)) { CLOG(INFO, this) << "This is HTTP/1.1 connection, " << "but may be upgraded to HTTP/2 later."; } // Reset header length for later HTTP/2 upgrade - left_connhd_len_ = NGHTTP2_CLIENT_MAGIC_LEN; - on_read_ = &ClientHandler::upstream_read; - on_write_ = &ClientHandler::upstream_write; + left_connhd_len_ = NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN; + set_bev_cb(upstream_readcb, upstream_writecb, upstream_eventcb); if (on_read() != 0) { return -1; @@ -346,1102 +450,271 @@ return 0; } - left_connhd_len_ -= nread; - rb_.drain(nread); - conn_.rlimit.startw(); + if (evbuffer_drain(input, readlen) == -1) { + return -1; + } - if (left_connhd_len_ == 0) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "direct HTTP/2 connection"; - } + left_connhd_len_ -= readlen; - direct_http2_upgrade(); - on_read_ = &ClientHandler::upstream_read; - on_write_ = &ClientHandler::upstream_write; + if (left_connhd_len_ > 0) { + return 0; + } - // Run on_read to process data left in buffer since they are not - // notified further - if (on_read() != 0) { - return -1; - } + if (LOG_ENABLED(INFO)) { + CLOG(INFO, this) << "direct HTTP/2 connection"; + } - return 0; + direct_http2_upgrade(); + set_bev_cb(upstream_readcb, upstream_writecb, upstream_eventcb); + + // Run on_read to process data left in buffer since they are not + // notified further + if (on_read() != 0) { + return -1; } return 0; } -ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl, - const char *ipaddr, const char *port, int family, - const UpstreamAddr *faddr) - : conn_(worker->get_loop(), fd, ssl, worker->get_mcpool(), - get_config()->conn.upstream.timeout.write, - get_config()->conn.upstream.timeout.read, - get_config()->conn.upstream.ratelimit.write, - get_config()->conn.upstream.ratelimit.read, writecb, readcb, - timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold, - get_config()->tls.dyn_rec.idle_timeout, PROTO_NONE), - ipaddr_(ipaddr), - port_(port), - faddr_(faddr), - worker_(worker), - left_connhd_len_(NGHTTP2_CLIENT_MAGIC_LEN), - affinity_hash_(0), - should_close_after_write_(false), - affinity_hash_computed_(false) { - - ++worker_->get_worker_stat()->num_connections; - - ev_timer_init(&reneg_shutdown_timer_, shutdowncb, 0., 0.); - - reneg_shutdown_timer_.data = this; - - conn_.rlimit.startw(); - ev_timer_again(conn_.loop, &conn_.rt); - - if (get_config()->conn.upstream.accept_proxy_protocol) { - read_ = &ClientHandler::read_clear; - write_ = &ClientHandler::noop; - on_read_ = &ClientHandler::proxy_protocol_read; - on_write_ = &ClientHandler::upstream_noop; - } else { - setup_upstream_io_callback(); - } +const std::string &ClientHandler::get_ipaddr() const { return ipaddr_; } - auto &fwdconf = get_config()->http.forwarded; +bool ClientHandler::get_should_close_after_write() const { + return should_close_after_write_; +} - if (fwdconf.params & FORWARDED_FOR) { - if (fwdconf.for_node_type == FORWARDED_NODE_OBFUSCATED) { - forwarded_for_ = "_"; - forwarded_for_ += util::random_alpha_digit(worker_->get_randgen(), - SHRPX_OBFUSCATED_NODE_LENGTH); - } else if (family == AF_INET6) { - forwarded_for_ = "["; - forwarded_for_ += ipaddr_; - forwarded_for_ += ']'; - } else { - // family == AF_INET or family == AF_UNIX - forwarded_for_ = ipaddr_; - } - } +void ClientHandler::set_should_close_after_write(bool f) { + should_close_after_write_ = f; } -void ClientHandler::setup_upstream_io_callback() { - if (conn_.tls.ssl) { - conn_.prepare_server_handshake(); - read_ = write_ = &ClientHandler::tls_handshake; - on_read_ = &ClientHandler::upstream_noop; - on_write_ = &ClientHandler::upstream_write; - } else { - // For non-TLS version, first create HttpsUpstream. It may be - // upgraded to HTTP/2 through HTTP Upgrade or direct HTTP/2 - // connection. - upstream_ = make_unique(this); - alpn_ = "http/1.1"; - read_ = &ClientHandler::read_clear; - write_ = &ClientHandler::write_clear; - on_read_ = &ClientHandler::upstream_http1_connhd_read; - on_write_ = &ClientHandler::upstream_noop; +void ClientHandler::pool_downstream_connection( + std::unique_ptr dconn) { + if (LOG_ENABLED(INFO)) { + CLOG(INFO, this) << "Pooling downstream connection DCONN:" << dconn.get(); } + dconn->set_client_handler(nullptr); + dconn_pool_->add_downstream_connection(std::move(dconn)); } -ClientHandler::~ClientHandler() { +void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn) { if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Deleting"; + CLOG(INFO, this) << "Removing downstream connection DCONN:" << dconn + << " from pool"; } + dconn_pool_->remove_downstream_connection(dconn); +} - if (upstream_) { - upstream_->on_handler_delete(); - } +std::unique_ptr +ClientHandler::get_downstream_connection() { + auto dconn = dconn_pool_->pop_downstream_connection(); - auto worker_stat = worker_->get_worker_stat(); - --worker_stat->num_connections; + if (!dconn) { + if (LOG_ENABLED(INFO)) { + CLOG(INFO, this) << "Downstream connection pool is empty." + << " Create new one"; + } - if (worker_stat->num_connections == 0) { - worker_->schedule_clear_mcpool(); + if (http2session_) { + dconn = util::make_unique(dconn_pool_, + http2session_); + } else { + dconn = util::make_unique(dconn_pool_); + } + dconn->set_client_handler(this); + return dconn; } - ev_timer_stop(conn_.loop, &reneg_shutdown_timer_); - - // TODO If backend is http/2, and it is in CONNECTED state, signal - // it and make it loopbreak when output is zero. - if (worker_->get_graceful_shutdown() && worker_stat->num_connections == 0) { - ev_break(conn_.loop); - } + dconn->set_client_handler(this); if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Deleted"; + CLOG(INFO, this) << "Reuse downstream connection DCONN:" << dconn.get() + << " from pool"; } + + return dconn; } -Upstream *ClientHandler::get_upstream() { return upstream_.get(); } +size_t ClientHandler::get_outbuf_length() { + return evbuffer_get_length(bufferevent_get_output(bev_)); +} + +SSL *ClientHandler::get_ssl() const { return ssl_; } -struct ev_loop *ClientHandler::get_loop() const { - return conn_.loop; +void ClientHandler::set_http2_session(Http2Session *http2session) { + http2session_ = http2session; } -void ClientHandler::reset_upstream_read_timeout(ev_tstamp t) { - conn_.rt.repeat = t; - if (ev_is_active(&conn_.rt)) { - ev_timer_again(conn_.loop, &conn_.rt); - } +Http2Session *ClientHandler::get_http2_session() const { return http2session_; } + +void ClientHandler::set_http1_connect_blocker( + ConnectBlocker *http1_connect_blocker) { + http1_connect_blocker_ = http1_connect_blocker; } -void ClientHandler::reset_upstream_write_timeout(ev_tstamp t) { - conn_.wt.repeat = t; - if (ev_is_active(&conn_.wt)) { - ev_timer_again(conn_.loop, &conn_.wt); - } +ConnectBlocker *ClientHandler::get_http1_connect_blocker() const { + return http1_connect_blocker_; } -void ClientHandler::repeat_read_timer() { - ev_timer_again(conn_.loop, &conn_.rt); +void ClientHandler::direct_http2_upgrade() { + upstream_ = util::make_unique(this); + // TODO We don't know exact h2 draft version in direct upgrade. We + // just use library default for now. + alpn_ = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID; + set_bev_cb(upstream_readcb, upstream_writecb, upstream_eventcb); } -void ClientHandler::stop_read_timer() { ev_timer_stop(conn_.loop, &conn_.rt); } +int ClientHandler::perform_http2_upgrade(HttpsUpstream *http) { + int rv; + auto upstream = util::make_unique(this); + if (upstream->upgrade_upstream(http) != 0) { + return -1; + } + // http pointer is now owned by upstream. + upstream_.release(); + upstream_ = std::move(upstream); + // TODO We might get other version id in HTTP2-settings, if we + // support aliasing for h2, but we just use library default for now. + alpn_ = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID; + set_bev_cb(upstream_http2_connhd_readcb, upstream_writecb, upstream_eventcb); + static char res[] = "HTTP/1.1 101 Switching Protocols\r\n" + "Connection: Upgrade\r\n" + "Upgrade: " NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "\r\n" + "\r\n"; + rv = bufferevent_write(bev_, res, sizeof(res) - 1); + if (rv != 0) { + CLOG(FATAL, this) << "bufferevent_write() faild"; + return -1; + } + return 0; +} -int ClientHandler::validate_next_proto() { - const unsigned char *next_proto = nullptr; - unsigned int next_proto_len = 0; +bool ClientHandler::get_http2_upgrade_allowed() const { return !ssl_; } - // First set callback for catch all cases - on_read_ = &ClientHandler::upstream_read; - - SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (next_proto == nullptr) { - SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - if (next_proto == nullptr) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "No protocol negotiated. Fallback to HTTP/1.1"; - } - - upstream_ = make_unique(this); - alpn_ = "http/1.1"; - - // At this point, input buffer is already filled with some bytes. - // The read callback is not called until new data come. So consume - // input buffer here. - if (on_read() != 0) { - return -1; - } - - return 0; - } - - auto proto = StringRef{next_proto, next_proto_len}; - - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "The negotiated next protocol: " << proto; - } - - if (!ssl::in_proto_list(get_config()->tls.npn_list, proto)) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "The negotiated protocol is not supported: " << proto; - } - return -1; - } - - if (util::check_h2_is_selected(proto)) { - on_read_ = &ClientHandler::upstream_http2_connhd_read; - - auto http2_upstream = make_unique(this); - - upstream_ = std::move(http2_upstream); - alpn_.assign(std::begin(proto), std::end(proto)); - - // At this point, input buffer is already filled with some bytes. - // The read callback is not called until new data come. So consume - // input buffer here. - if (on_read() != 0) { - return -1; - } - - return 0; - } - -#ifdef HAVE_SPDYLAY - auto spdy_version = spdylay_npn_get_version(proto.byte(), proto.size()); - if (spdy_version) { - upstream_ = make_unique(spdy_version, this); - - switch (spdy_version) { - case SPDYLAY_PROTO_SPDY2: - alpn_ = "spdy/2"; - break; - case SPDYLAY_PROTO_SPDY3: - alpn_ = "spdy/3"; - break; - case SPDYLAY_PROTO_SPDY3_1: - alpn_ = "spdy/3.1"; - break; - default: - alpn_ = "spdy/unknown"; - } - - // At this point, input buffer is already filled with some bytes. - // The read callback is not called until new data come. So consume - // input buffer here. - if (on_read() != 0) { - return -1; - } - - return 0; - } -#endif // HAVE_SPDYLAY - - if (proto == StringRef::from_lit("http/1.1")) { - upstream_ = make_unique(this); - alpn_ = proto.str(); - - // At this point, input buffer is already filled with some bytes. - // The read callback is not called until new data come. So consume - // input buffer here. - if (on_read() != 0) { - return -1; - } - - return 0; - } - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "The negotiated protocol is not supported"; - } - return -1; -} - -int ClientHandler::do_read() { return read_(*this); } -int ClientHandler::do_write() { return write_(*this); } - -int ClientHandler::on_read() { - auto rv = on_read_(*this); - if (rv != 0) { - return rv; +std::string ClientHandler::get_upstream_scheme() const { + if (ssl_) { + return "https"; + } else { + return "http"; } - conn_.handle_tls_pending_read(); - return 0; -} -int ClientHandler::on_write() { return on_write_(*this); } - -const std::string &ClientHandler::get_ipaddr() const { return ipaddr_; } - -bool ClientHandler::get_should_close_after_write() const { - return should_close_after_write_; -} - -void ClientHandler::set_should_close_after_write(bool f) { - should_close_after_write_ = f; } -void ClientHandler::pool_downstream_connection( - std::unique_ptr dconn) { - if (!dconn->poolable()) { - return; - } - - dconn->set_client_handler(nullptr); +void ClientHandler::set_tls_handshake(bool f) { tls_handshake_ = f; } - auto group = dconn->get_downstream_addr_group(); - - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Pooling downstream connection DCONN:" << dconn.get() - << " in group " << group; - } - - auto &shared_addr = group->shared_addr; - - if (shared_addr->affinity == AFFINITY_NONE) { - auto &dconn_pool = group->shared_addr->dconn_pool; - dconn_pool.add_downstream_connection(std::move(dconn)); - - return; - } - - auto addr = dconn->get_addr(); - auto &dconn_pool = addr->dconn_pool; - dconn_pool->add_downstream_connection(std::move(dconn)); -} - -void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Removing downstream connection DCONN:" << dconn - << " from pool"; - } - auto &dconn_pool = - dconn->get_downstream_addr_group()->shared_addr->dconn_pool; - dconn_pool.remove_downstream_connection(dconn); -} +bool ClientHandler::get_tls_handshake() const { return tls_handshake_; } namespace { -// Computes 32bits hash for session affinity for IP address |ip|. -uint32_t compute_affinity_from_ip(const StringRef &ip) { - int rv; - std::array buf; - - rv = util::sha256(buf.data(), ip); - if (rv != 0) { - // Not sure when sha256 failed. Just fall back to another - // function. - return util::hash32(ip); - } - - return (static_cast(buf[0]) << 24) | - (static_cast(buf[1]) << 16) | - (static_cast(buf[2]) << 8) | static_cast(buf[3]); -} -} // namespace - -Http2Session *ClientHandler::select_http2_session_with_affinity( - const std::shared_ptr &group, DownstreamAddr *addr) { - auto &shared_addr = group->shared_addr; +void shutdown_cb(evutil_socket_t fd, short what, void *arg) { + auto handler = static_cast(arg); if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Selected DownstreamAddr=" << addr - << ", index=" << (addr - shared_addr->addrs.data()); - } - - if (addr->http2_extra_freelist.size()) { - auto session = addr->http2_extra_freelist.head; - - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Use Http2Session " << session - << " from http2_extra_freelist"; - } - - if (session->max_concurrency_reached(1)) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Maximum streams are reached for Http2Session(" - << session << ")."; - } - - session->remove_from_freelist(); - } - return session; - } - - auto session = new Http2Session(conn_.loop, worker_->get_cl_ssl_ctx(), - worker_, group, addr); - - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Create new Http2Session " << session; + CLOG(INFO, handler) << "Close connection due to TLS renegotiation"; } - session->add_to_extra_freelist(); - - return session; -} - -namespace { -// Returns true if load of |lhs| is lighter than that of |rhs|. -// Currently, we assume that lesser streams means lesser load. -bool load_lighter(const DownstreamAddr *lhs, const DownstreamAddr *rhs) { - return lhs->num_dconn < rhs->num_dconn; + delete handler; } } // namespace -Http2Session *ClientHandler::select_http2_session( - const std::shared_ptr &group) { - auto &shared_addr = group->shared_addr; - - // First count the working backend addresses. - size_t min = 0; - for (const auto &addr : shared_addr->addrs) { - if (addr.proto != PROTO_HTTP2 || addr.connect_blocker->blocked()) { - continue; - } - - ++min; - } - - if (min == 0) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "No working backend address found"; - } - - return nullptr; - } - - auto &http2_avail_freelist = shared_addr->http2_avail_freelist; - - if (http2_avail_freelist.size() >= min) { - auto session = http2_avail_freelist.head; - session->remove_from_freelist(); - - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Use Http2Session " << session - << " from http2_avail_freelist"; - } - - if (session->max_concurrency_reached(1)) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Maximum streams are reached for Http2Session(" - << session << ")."; - } - } else { - session->add_to_avail_freelist(); - } - return session; - } - - DownstreamAddr *selected_addr = nullptr; - - for (auto &addr : shared_addr->addrs) { - if (addr.proto != PROTO_HTTP2 || (addr.http2_extra_freelist.size() == 0 && - addr.connect_blocker->blocked())) { - continue; - } - - if (addr.in_avail) { - continue; - } - - if (selected_addr == nullptr || load_lighter(&addr, selected_addr)) { - selected_addr = &addr; - } - } - - assert(selected_addr); - - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Selected DownstreamAddr=" << selected_addr - << ", index=" - << (selected_addr - shared_addr->addrs.data()); - } - - if (selected_addr->http2_extra_freelist.size()) { - auto session = selected_addr->http2_extra_freelist.head; - session->remove_from_freelist(); - +void ClientHandler::set_tls_renegotiation(bool f) { + if (tls_renegotiation_ == false) { if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Use Http2Session " << session - << " from http2_extra_freelist"; + CLOG(INFO, this) << "TLS renegotiation detected. " + << "Start shutdown timer now."; } - if (session->max_concurrency_reached(1)) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Maximum streams are reached for Http2Session(" - << session << ")."; - } - } else { - session->add_to_avail_freelist(); - } - return session; - } + reneg_shutdown_timerev_ = evtimer_new(get_evbase(), shutdown_cb, this); + event_priority_set(reneg_shutdown_timerev_, 0); - auto session = new Http2Session(conn_.loop, worker_->get_cl_ssl_ctx(), - worker_, group, selected_addr); + timeval timeout = {0, 0}; - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Create new Http2Session " << session; + // TODO What to do if this failed? + evtimer_add(reneg_shutdown_timerev_, &timeout); } - - session->add_to_avail_freelist(); - - return session; + tls_renegotiation_ = f; } -namespace { -// The chosen value is small enough for uint32_t, and large enough for -// the number of backend. -constexpr uint32_t WEIGHT_MAX = 65536; -} // namespace - -namespace { -bool pri_less(const WeightedPri &lhs, const WeightedPri &rhs) { - if (lhs.cycle < rhs.cycle) { - return rhs.cycle - lhs.cycle <= WEIGHT_MAX; - } - - return lhs.cycle - rhs.cycle > WEIGHT_MAX; -} -} // namespace +bool ClientHandler::get_tls_renegotiation() const { return tls_renegotiation_; } namespace { -uint32_t next_cycle(const WeightedPri &pri) { - return pri.cycle + WEIGHT_MAX / std::min(WEIGHT_MAX, pri.weight); -} +const size_t SHRPX_SMALL_WRITE_LIMIT = 1300; +const size_t SHRPX_WARMUP_THRESHOLD = 1 << 20; } // namespace -std::unique_ptr -ClientHandler::get_downstream_connection(Downstream *downstream) { - size_t group_idx; - auto &downstreamconf = *worker_->get_downstream_config(); - auto &routerconf = downstreamconf.router; - - auto catch_all = downstreamconf.addr_group_catch_all; - auto &groups = worker_->get_downstream_addr_groups(); - - const auto &req = downstream->request(); - - switch (faddr_->alt_mode) { - case ALTMODE_API: - return make_unique(worker_); - case ALTMODE_HEALTHMON: - return make_unique(); - } - - // Fast path. If we have one group, it must be catch-all group. - // proxy mode falls in this case. - if (groups.size() == 1) { - group_idx = 0; - } else if (req.method == HTTP_CONNECT) { - // We don't know how to treat CONNECT request in host-path - // mapping. It most likely appears in proxy scenario. Since we - // have dealt with proxy case already, just use catch-all group. - group_idx = catch_all; - } else { - auto &balloc = downstream->get_block_allocator(); - - if (!req.authority.empty()) { - group_idx = match_downstream_addr_group( - routerconf, req.authority, req.path, groups, catch_all, balloc); - } else { - auto h = req.fs.header(http2::HD_HOST); - if (h) { - group_idx = match_downstream_addr_group(routerconf, h->value, req.path, - groups, catch_all, balloc); - } else { - group_idx = match_downstream_addr_group( - routerconf, StringRef{}, req.path, groups, catch_all, balloc); - } - } - } - - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Downstream address group_idx: " << group_idx; - } - - auto &group = groups[group_idx]; - auto &shared_addr = group->shared_addr; - - if (shared_addr->affinity == AFFINITY_IP) { - if (!affinity_hash_computed_) { - affinity_hash_ = compute_affinity_from_ip(StringRef{ipaddr_}); - affinity_hash_computed_ = true; - } - - const auto &affinity_hash = shared_addr->affinity_hash; - - auto it = std::lower_bound( - std::begin(affinity_hash), std::end(affinity_hash), affinity_hash_, - [](const AffinityHash &lhs, uint32_t rhs) { return lhs.hash < rhs; }); - - if (it == std::end(affinity_hash)) { - it = std::begin(affinity_hash); - } - - auto idx = (*it).idx; - - auto &addr = shared_addr->addrs[idx]; - if (addr.proto == PROTO_HTTP2) { - auto http2session = select_http2_session_with_affinity(group, &addr); - - auto dconn = make_unique(http2session); - - dconn->set_client_handler(this); - - return std::move(dconn); - } - - auto &dconn_pool = addr.dconn_pool; - auto dconn = dconn_pool->pop_downstream_connection(); - - if (!dconn) { - dconn = make_unique(group, idx, conn_.loop, - worker_); - } - - dconn->set_client_handler(this); - - return dconn; - } - - auto http1_weight = shared_addr->http1_pri.weight; - auto http2_weight = shared_addr->http2_pri.weight; - - auto proto = PROTO_NONE; - - if (http1_weight > 0 && http2_weight > 0) { - // We only advance cycle if both weight has nonzero to keep its - // distance under WEIGHT_MAX. - if (pri_less(shared_addr->http1_pri, shared_addr->http2_pri)) { - proto = PROTO_HTTP1; - shared_addr->http1_pri.cycle = next_cycle(shared_addr->http1_pri); - } else { - proto = PROTO_HTTP2; - shared_addr->http2_pri.cycle = next_cycle(shared_addr->http2_pri); - } - } else if (http1_weight > 0) { - proto = PROTO_HTTP1; - } else if (http2_weight > 0) { - proto = PROTO_HTTP2; - } - - if (proto == PROTO_NONE) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "No working downstream address found"; - } - - return nullptr; - } - - if (proto == PROTO_HTTP2) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Downstream connection pool is empty." - << " Create new one"; - } - - auto http2session = select_http2_session(group); - - if (http2session == nullptr) { - return nullptr; - } - - auto dconn = make_unique(http2session); - - dconn->set_client_handler(this); - - return std::move(dconn); +ssize_t ClientHandler::get_write_limit() { + if (!ssl_) { + return -1; } - auto &dconn_pool = shared_addr->dconn_pool; - - // pool connection must be HTTP/1.1 connection - auto dconn = dconn_pool.pop_downstream_connection(); - - if (dconn) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Reuse downstream connection DCONN:" << dconn.get() - << " from pool"; - } - } else { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "Downstream connection pool is empty." - << " Create new one"; + timeval tv; + if (event_base_gettimeofday_cached(get_evbase(), &tv) == 0) { + auto now = util::to_time64(tv); + if (now - last_write_time_ > 1000000) { + // Time out, use small record size + warmup_writelen_ = 0; + return SHRPX_SMALL_WRITE_LIMIT; } - - dconn = - make_unique(group, -1, conn_.loop, worker_); } - dconn->set_client_handler(this); + // If event_base_gettimeofday_cached() failed, we just skip timer + // checking. Don't know how to treat this. - return dconn; -} - -MemchunkPool *ClientHandler::get_mcpool() { return worker_->get_mcpool(); } - -SSL *ClientHandler::get_ssl() const { return conn_.tls.ssl; } - -void ClientHandler::direct_http2_upgrade() { - upstream_ = make_unique(this); - alpn_ = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID; - on_read_ = &ClientHandler::upstream_read; - write_ = &ClientHandler::write_clear; -} - -int ClientHandler::perform_http2_upgrade(HttpsUpstream *http) { - auto upstream = make_unique(this); - - auto output = upstream->get_response_buf(); - - // We might have written non-final header in response_buf, in this - // case, response_state is still INITIAL. If this non-final header - // and upgrade header fit in output buffer, do upgrade. Otherwise, - // to avoid to send this non-final header as response body in HTTP/2 - // upstream, fail upgrade. - auto downstream = http->get_downstream(); - auto input = downstream->get_response_buf(); - - if (upstream->upgrade_upstream(http) != 0) { + if (warmup_writelen_ >= SHRPX_WARMUP_THRESHOLD) { return -1; } - // http pointer is now owned by upstream. - upstream_.release(); - // TODO We might get other version id in HTTP2-settings, if we - // support aliasing for h2, but we just use library default for now. - alpn_ = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID; - on_read_ = &ClientHandler::upstream_http2_connhd_read; - write_ = &ClientHandler::write_clear; - - input->remove(*output, input->rleft()); - - constexpr auto res = - StringRef::from_lit("HTTP/1.1 101 Switching Protocols\r\n" - "Connection: Upgrade\r\n" - "Upgrade: " NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "\r\n" - "\r\n"); - output->append(res); - upstream_ = std::move(upstream); - - signal_write(); - return 0; + return SHRPX_SMALL_WRITE_LIMIT; } -bool ClientHandler::get_http2_upgrade_allowed() const { return !conn_.tls.ssl; } - -StringRef ClientHandler::get_upstream_scheme() const { - if (conn_.tls.ssl) { - return StringRef::from_lit("https"); - } else { - return StringRef::from_lit("http"); +void ClientHandler::update_warmup_writelen(size_t n) { + if (warmup_writelen_ < SHRPX_WARMUP_THRESHOLD) { + warmup_writelen_ += n; } } -void ClientHandler::start_immediate_shutdown() { - ev_timer_start(conn_.loop, &reneg_shutdown_timer_); -} - -namespace { -// Construct absolute request URI from |Request|, mainly to log -// request URI for proxy request (HTTP/2 proxy or client proxy). This -// is mostly same routine found in -// HttpDownstreamConnection::push_request_headers(), but vastly -// simplified since we only care about absolute URI. -StringRef construct_absolute_request_uri(BlockAllocator &balloc, - const Request &req) { - if (req.authority.empty()) { - return req.path; - } - - auto len = req.authority.size() + req.path.size(); - if (req.scheme.empty()) { - len += str_size("http://"); - } else { - len += req.scheme.size() + str_size("://"); +void ClientHandler::update_last_write_time() { + timeval tv; + if (event_base_gettimeofday_cached(get_evbase(), &tv) == 0) { + last_write_time_ = util::to_time64(tv); } - - auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; - - if (req.scheme.empty()) { - // We may have to log the request which lacks scheme (e.g., - // http/1.1 with origin form). - p = util::copy_lit(p, "http://"); - } else { - p = std::copy(std::begin(req.scheme), std::end(req.scheme), p); - p = util::copy_lit(p, "://"); - } - p = std::copy(std::begin(req.authority), std::end(req.authority), p); - p = std::copy(std::begin(req.path), std::end(req.path), p); - *p = '\0'; - - return StringRef{iov.base, p}; } -} // namespace void ClientHandler::write_accesslog(Downstream *downstream) { - nghttp2::ssl::TLSSessionInfo tls_info; - const auto &req = downstream->request(); - const auto &resp = downstream->response(); - - auto &balloc = downstream->get_block_allocator(); - - upstream_accesslog( - get_config()->logging.access.format, - LogSpec{ - downstream, StringRef{ipaddr_}, http2::to_method_string(req.method), - - req.method == HTTP_CONNECT - ? StringRef(req.authority) - : get_config()->http2_proxy - ? StringRef(construct_absolute_request_uri(balloc, req)) - : req.path.empty() - ? req.method == HTTP_OPTIONS - ? StringRef::from_lit("*") - : StringRef::from_lit("-") - : StringRef(req.path), - - StringRef(alpn_), - nghttp2::ssl::get_tls_session_info(&tls_info, conn_.tls.ssl), - - std::chrono::system_clock::now(), // time_now - downstream->get_request_start_time(), // request_start_time - std::chrono::high_resolution_clock::now(), // request_end_time - - req.http_major, req.http_minor, resp.http_status, - downstream->response_sent_body_length, StringRef(port_), faddr_->port, - get_config()->pid, - }); -} - -void ClientHandler::write_accesslog(int major, int minor, unsigned int status, - int64_t body_bytes_sent) { - auto time_now = std::chrono::system_clock::now(); - auto highres_now = std::chrono::high_resolution_clock::now(); - nghttp2::ssl::TLSSessionInfo tls_info; - - upstream_accesslog(get_config()->logging.access.format, - LogSpec{ - nullptr, StringRef(ipaddr_), - StringRef::from_lit("-"), // method - StringRef::from_lit("-"), // path, - StringRef(alpn_), nghttp2::ssl::get_tls_session_info( - &tls_info, conn_.tls.ssl), - time_now, - highres_now, // request_start_time TODO is - // there a better value? - highres_now, // request_end_time - major, minor, // major, minor - status, body_bytes_sent, StringRef(port_), - faddr_->port, get_config()->pid, - }); -} - -ClientHandler::ReadBuf *ClientHandler::get_rb() { return &rb_; } - -void ClientHandler::signal_write() { conn_.wlimit.startw(); } - -RateLimit *ClientHandler::get_rlimit() { return &conn_.rlimit; } -RateLimit *ClientHandler::get_wlimit() { return &conn_.wlimit; } - -ev_io *ClientHandler::get_wev() { return &conn_.wev; } + LogSpec lgsp = { + downstream, ipaddr_.c_str(), downstream->get_request_method().c_str(), -Worker *ClientHandler::get_worker() const { return worker_; } + downstream->get_request_path().empty() + ? downstream->get_request_http2_authority().c_str() + : downstream->get_request_path().c_str(), -namespace { -ssize_t parse_proxy_line_port(const uint8_t *first, const uint8_t *last) { - auto p = first; - int32_t port = 0; - - if (p == last) { - return -1; - } + alpn_.c_str(), - if (*p == '0') { - if (p + 1 != last && util::is_digit(*(p + 1))) { - return -1; - } - return 1; - } + downstream->get_request_start_time(), + std::chrono::high_resolution_clock::now(), - for (; p != last && util::is_digit(*p); ++p) { - port *= 10; - port += *p - '0'; + downstream->get_request_major(), downstream->get_request_minor(), + downstream->get_response_http_status(), + downstream->get_response_sent_bodylen(), port_.c_str(), + get_config()->port, get_config()->pid, + }; - if (port > 65535) { - return -1; - } - } - - return p - first; + upstream_accesslog(get_config()->accesslog_format, &lgsp); } -} // namespace - -int ClientHandler::on_proxy_protocol_finish() { - if (conn_.tls.ssl) { - conn_.tls.rbuf.append(rb_.pos, rb_.rleft()); - rb_.reset(); - } - setup_upstream_io_callback(); - - // Run on_read to process data left in buffer since they are not - // notified further - if (on_read() != 0) { - return -1; - } - - return 0; -} - -// http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt -int ClientHandler::proxy_protocol_read() { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol: Started"; - } - - auto first = rb_.pos; - - // NULL character really destroys functions which expects NULL - // terminated string. We won't expect it in PROXY protocol line, so - // find it here. - auto chrs = std::array{{'\n', '\0'}}; - - constexpr size_t MAX_PROXY_LINELEN = 107; - - auto bufend = rb_.pos + std::min(MAX_PROXY_LINELEN, rb_.rleft()); - - auto end = - std::find_first_of(rb_.pos, bufend, std::begin(chrs), std::end(chrs)); - - if (end == bufend || *end == '\0' || end == rb_.pos || *(end - 1) != '\r') { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: No ending CR LF sequence found"; - } - return -1; - } - - --end; - - constexpr auto HEADER = StringRef::from_lit("PROXY "); - - if (static_cast(end - rb_.pos) < HEADER.size()) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: PROXY version 1 ID not found"; - } - return -1; - } - - if (!util::streq(HEADER, StringRef{rb_.pos, HEADER.size()})) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Bad PROXY protocol version 1 ID"; - } - return -1; - } - - rb_.drain(HEADER.size()); - - int family; - - if (rb_.pos[0] == 'T') { - if (end - rb_.pos < 5) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: INET protocol family not found"; - } - return -1; - } - - if (rb_.pos[1] != 'C' || rb_.pos[2] != 'P') { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Unknown INET protocol family"; - } - return -1; - } - - switch (rb_.pos[3]) { - case '4': - family = AF_INET; - break; - case '6': - family = AF_INET6; - break; - default: - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Unknown INET protocol family"; - } - return -1; - } - - rb_.drain(5); - } else { - if (end - rb_.pos < 7) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: INET protocol family not found"; - } - return -1; - } - if (!util::streq_l("UNKNOWN", rb_.pos, 7)) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Unknown INET protocol family"; - } - return -1; - } - - rb_.drain(end + 2 - rb_.pos); - - return on_proxy_protocol_finish(); - } - - // source address - auto token_end = std::find(rb_.pos, end, ' '); - if (token_end == end) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Source address not found"; - } - return -1; - } - - *token_end = '\0'; - if (!util::numeric_host(reinterpret_cast(rb_.pos), family)) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Invalid source address"; - } - return -1; - } - - auto src_addr = rb_.pos; - auto src_addrlen = token_end - rb_.pos; - - rb_.drain(token_end - rb_.pos + 1); - - // destination address - token_end = std::find(rb_.pos, end, ' '); - if (token_end == end) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Destination address not found"; - } - return -1; - } - - *token_end = '\0'; - if (!util::numeric_host(reinterpret_cast(rb_.pos), family)) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Invalid destination address"; - } - return -1; - } - - // Currently we don't use destination address - - rb_.drain(token_end - rb_.pos + 1); - - // source port - auto n = parse_proxy_line_port(rb_.pos, end); - if (n <= 0 || *(rb_.pos + n) != ' ') { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Invalid source port"; - } - return -1; - } - - rb_.pos[n] = '\0'; - auto src_port = rb_.pos; - auto src_portlen = n; - - rb_.drain(n + 1); - - // destination port - n = parse_proxy_line_port(rb_.pos, end); - if (n <= 0 || rb_.pos + n != end) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Invalid destination port"; - } - return -1; - } - - // Currently we don't use destination port - - rb_.drain(end + 2 - rb_.pos); - - ipaddr_.assign(src_addr, src_addr + src_addrlen); - port_.assign(src_port, src_port + src_portlen); - - if (LOG_ENABLED(INFO)) { - CLOG(INFO, this) << "PROXY-protocol-v1: Finished, " << (rb_.pos - first) - << " bytes read"; - } - - return on_proxy_protocol_finish(); -} - -StringRef ClientHandler::get_forwarded_by() const { - auto &fwdconf = get_config()->http.forwarded; - - if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED) { - return StringRef(fwdconf.by_obfuscated); - } - - return StringRef{faddr_->hostport}; -} +void ClientHandler::write_accesslog(int major, int minor, unsigned int status, + int64_t body_bytes_sent) { + LogSpec lgsp = { + nullptr, ipaddr_.c_str(), + "-", // method + "-", // path, + alpn_.c_str(), + std::chrono::high_resolution_clock::now(), // request_start_time TODO is + // there a better value? + std::chrono::high_resolution_clock::now(), // time_now + major, minor, // major, minor + status, body_bytes_sent, + port_.c_str(), get_config()->port, + get_config()->pid, + }; -StringRef ClientHandler::get_forwarded_for() const { - return StringRef{forwarded_for_}; + upstream_accesslog(get_config()->accesslog_format, &lgsp); } -const UpstreamAddr *ClientHandler::get_upstream_addr() const { return faddr_; } - } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_client_handler.h nghttp2-0.6.7/src/shrpx_client_handler.h --- nghttp2-1.13.0/src/shrpx_client_handler.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_client_handler.h 2014-11-30 14:15:07.000000000 +0000 @@ -29,66 +29,36 @@ #include -#include +#include +#include #include -#include "shrpx_rate_limit.h" -#include "shrpx_connection.h" -#include "buffer.h" -#include "memchunk.h" - -using namespace nghttp2; - namespace shrpx { class Upstream; class DownstreamConnection; +class Http2Session; class HttpsUpstream; class ConnectBlocker; class DownstreamConnectionPool; -class Worker; struct WorkerStat; -struct DownstreamAddrGroup; -struct DownstreamAddr; class ClientHandler { public: - ClientHandler(Worker *worker, int fd, SSL *ssl, const char *ipaddr, - const char *port, int family, const UpstreamAddr *faddr); + ClientHandler(bufferevent *bev, + bufferevent_rate_limit_group *rate_limit_group, int fd, + SSL *ssl, const char *ipaddr, const char *port, + WorkerStat *worker_stat, DownstreamConnectionPool *dconn_pool); ~ClientHandler(); - - int noop(); - // Performs clear text I/O - int read_clear(); - int write_clear(); - // Performs TLS handshake - int tls_handshake(); - // Performs TLS I/O - int read_tls(); - int write_tls(); - - int upstream_noop(); - int upstream_read(); - int upstream_http2_connhd_read(); - int upstream_http1_connhd_read(); - int upstream_write(); - - int proxy_protocol_read(); - int on_proxy_protocol_finish(); - - // Performs I/O operation. Internally calls on_read()/on_write(). - int do_read(); - int do_write(); - - // Processes buffers. No underlying I/O operation will be done. int on_read(); - int on_write(); - - struct ev_loop *get_loop() const; - void reset_upstream_read_timeout(ev_tstamp t); - void reset_upstream_write_timeout(ev_tstamp t); - + int on_event(); + bufferevent *get_bev() const; + event_base *get_evbase() const; + void set_bev_cb(bufferevent_data_cb readcb, bufferevent_data_cb writecb, + bufferevent_event_cb eventcb); + void set_upstream_timeouts(const timeval *read_timeout, + const timeval *write_timeout); int validate_next_proto(); const std::string &get_ipaddr() const; const std::string &get_port() const; @@ -98,10 +68,13 @@ void pool_downstream_connection(std::unique_ptr dconn); void remove_downstream_connection(DownstreamConnection *dconn); - std::unique_ptr - get_downstream_connection(Downstream *downstream); - MemchunkPool *get_mcpool(); + std::unique_ptr get_downstream_connection(); + size_t get_outbuf_length(); SSL *get_ssl() const; + void set_http2_session(Http2Session *http2session); + Http2Session *get_http2_session() const; + void set_http1_connect_blocker(ConnectBlocker *http1_connect_blocker); + ConnectBlocker *get_http1_connect_blocker() const; // Call this function when HTTP/2 connection header is received at // the start of the connection. void direct_http2_upgrade(); @@ -111,8 +84,27 @@ int perform_http2_upgrade(HttpsUpstream *http); bool get_http2_upgrade_allowed() const; // Returns upstream scheme, either "http" or "https" - StringRef get_upstream_scheme() const; - void start_immediate_shutdown(); + std::string get_upstream_scheme() const; + void set_tls_handshake(bool f); + bool get_tls_handshake() const; + void set_tls_renegotiation(bool f); + bool get_tls_renegotiation() const; + int on_http2_connhd_read(); + int on_http1_connhd_read(); + // Returns maximum chunk size for one evbuffer_add(). The intention + // of this chunk size is control the TLS record size. The actual + // SSL_write() call is done under libevent control. In + // libevent-2.0.21, libevent calls SSL_write() for each chunk inside + // evbuffer. This means that we can control TLS record size by + // adjusting the chunk size to evbuffer_add(). + // + // This function returns -1, if TLS is not enabled or no limitation + // is required. + ssize_t get_write_limit(); + // Updates the number of bytes written in warm up period. + void update_warmup_writelen(size_t n); + // Updates the time when last write was done. + void update_last_write_time(); // Writes upstream accesslog using |downstream|. The |downstream| // must not be nullptr. @@ -122,64 +114,30 @@ // corresponding Downstream object is not available. void write_accesslog(int major, int minor, unsigned int status, int64_t body_bytes_sent); - Worker *get_worker() const; - - using ReadBuf = Buffer<16_k>; - - ReadBuf *get_rb(); - - RateLimit *get_rlimit(); - RateLimit *get_wlimit(); - - void signal_write(); - ev_io *get_wev(); - - void setup_upstream_io_callback(); - - // Returns string suitable for use in "by" parameter of Forwarded - // header field. - StringRef get_forwarded_by() const; - // Returns string suitable for use in "for" parameter of Forwarded - // header field. - StringRef get_forwarded_for() const; - - Http2Session * - select_http2_session(const std::shared_ptr &group); - - Http2Session *select_http2_session_with_affinity( - const std::shared_ptr &group, DownstreamAddr *addr); - - const UpstreamAddr *get_upstream_addr() const; - - void repeat_read_timer(); - void stop_read_timer(); private: - Connection conn_; - ev_timer reneg_shutdown_timer_; std::unique_ptr upstream_; - // IP address of client. If UNIX domain socket is used, this is - // "localhost". std::string ipaddr_; std::string port_; // The ALPN identifier negotiated for this connection. std::string alpn_; - // The client address used in "for" parameter of Forwarded header - // field. - std::string forwarded_for_; - std::function read_, write_; - std::function on_read_, on_write_; - // Address of frontend listening socket - const UpstreamAddr *faddr_; - Worker *worker_; + DownstreamConnectionPool *dconn_pool_; + bufferevent *bev_; + // Shared HTTP2 session for each thread. NULL if backend is not + // HTTP2. Not deleted by this object. + Http2Session *http2session_; + ConnectBlocker *http1_connect_blocker_; + SSL *ssl_; + event *reneg_shutdown_timerev_; + WorkerStat *worker_stat_; + int64_t last_write_time_; + size_t warmup_writelen_; // The number of bytes of HTTP/2 client connection header to read size_t left_connhd_len_; - // hash for session affinity using client IP - uint32_t affinity_hash_; + int fd_; bool should_close_after_write_; - // true if affinity_hash_ is computed - bool affinity_hash_computed_; - ReadBuf rb_; + bool tls_handshake_; + bool tls_renegotiation_; }; } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_config.cc nghttp2-0.6.7/src/shrpx_config.cc --- nghttp2-1.13.0/src/shrpx_config.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_config.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,23 +24,12 @@ */ #include "shrpx_config.h" -#ifdef HAVE_PWD_H #include -#endif // HAVE_PWD_H -#ifdef HAVE_NETDB_H #include -#endif // HAVE_NETDB_H -#ifdef HAVE_SYSLOG_H #include -#endif // HAVE_SYSLOG_H #include #include -#ifdef HAVE_FCNTL_H -#include -#endif // HAVE_FCNTL_H -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H #include #include @@ -54,63 +43,142 @@ #include "shrpx_log.h" #include "shrpx_ssl.h" #include "shrpx_http.h" +#include "http2.h" #include "util.h" -#include "base64.h" + +using namespace nghttp2; namespace shrpx { +const char SHRPX_OPT_PRIVATE_KEY_FILE[] = "private-key-file"; +const char SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE[] = "private-key-passwd-file"; +const char SHRPX_OPT_CERTIFICATE_FILE[] = "certificate-file"; +const char SHRPX_OPT_DH_PARAM_FILE[] = "dh-param-file"; +const char SHRPX_OPT_SUBCERT[] = "subcert"; + +const char SHRPX_OPT_BACKEND[] = "backend"; +const char SHRPX_OPT_FRONTEND[] = "frontend"; +const char SHRPX_OPT_WORKERS[] = "workers"; +const char SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS[] = + "http2-max-concurrent-streams"; +const char SHRPX_OPT_LOG_LEVEL[] = "log-level"; +const char SHRPX_OPT_DAEMON[] = "daemon"; +const char SHRPX_OPT_HTTP2_PROXY[] = "http2-proxy"; +const char SHRPX_OPT_HTTP2_BRIDGE[] = "http2-bridge"; +const char SHRPX_OPT_CLIENT_PROXY[] = "client-proxy"; +const char SHRPX_OPT_ADD_X_FORWARDED_FOR[] = "add-x-forwarded-for"; +const char SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR[] = + "strip-incoming-x-forwarded-for"; +const char SHRPX_OPT_NO_VIA[] = "no-via"; +const char SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT[] = + "frontend-http2-read-timeout"; +const char SHRPX_OPT_FRONTEND_READ_TIMEOUT[] = "frontend-read-timeout"; +const char SHRPX_OPT_FRONTEND_WRITE_TIMEOUT[] = "frontend-write-timeout"; +const char SHRPX_OPT_BACKEND_READ_TIMEOUT[] = "backend-read-timeout"; +const char SHRPX_OPT_BACKEND_WRITE_TIMEOUT[] = "backend-write-timeout"; +const char SHRPX_OPT_STREAM_READ_TIMEOUT[] = "stream-read-timeout"; +const char SHRPX_OPT_STREAM_WRITE_TIMEOUT[] = "stream-write-timeout"; +const char SHRPX_OPT_ACCESSLOG_FILE[] = "accesslog-file"; +const char SHRPX_OPT_ACCESSLOG_SYSLOG[] = "accesslog-syslog"; +const char SHRPX_OPT_ACCESSLOG_FORMAT[] = "accesslog-format"; +const char SHRPX_OPT_ERRORLOG_FILE[] = "errorlog-file"; +const char SHRPX_OPT_ERRORLOG_SYSLOG[] = "errorlog-syslog"; +const char SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT[] = + "backend-keep-alive-timeout"; +const char SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS[] = + "frontend-http2-window-bits"; +const char SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS[] = "backend-http2-window-bits"; +const char SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS[] = + "frontend-http2-connection-window-bits"; +const char SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS[] = + "backend-http2-connection-window-bits"; +const char SHRPX_OPT_FRONTEND_NO_TLS[] = "frontend-no-tls"; +const char SHRPX_OPT_BACKEND_NO_TLS[] = "backend-no-tls"; +const char SHRPX_OPT_BACKEND_TLS_SNI_FIELD[] = "backend-tls-sni-field"; +const char SHRPX_OPT_PID_FILE[] = "pid-file"; +const char SHRPX_OPT_USER[] = "user"; +const char SHRPX_OPT_SYSLOG_FACILITY[] = "syslog-facility"; +const char SHRPX_OPT_BACKLOG[] = "backlog"; +const char SHRPX_OPT_CIPHERS[] = "ciphers"; +const char SHRPX_OPT_CLIENT[] = "client"; +const char SHRPX_OPT_INSECURE[] = "insecure"; +const char SHRPX_OPT_CACERT[] = "cacert"; +const char SHRPX_OPT_BACKEND_IPV4[] = "backend-ipv4"; +const char SHRPX_OPT_BACKEND_IPV6[] = "backend-ipv6"; +const char SHRPX_OPT_BACKEND_HTTP_PROXY_URI[] = "backend-http-proxy-uri"; +const char SHRPX_OPT_READ_RATE[] = "read-rate"; +const char SHRPX_OPT_READ_BURST[] = "read-burst"; +const char SHRPX_OPT_WRITE_RATE[] = "write-rate"; +const char SHRPX_OPT_WRITE_BURST[] = "write-burst"; +const char SHRPX_OPT_WORKER_READ_RATE[] = "worker-read-rate"; +const char SHRPX_OPT_WORKER_READ_BURST[] = "worker-read-burst"; +const char SHRPX_OPT_WORKER_WRITE_RATE[] = "worker-write-rate"; +const char SHRPX_OPT_WORKER_WRITE_BURST[] = "worker-write-burst"; +const char SHRPX_OPT_NPN_LIST[] = "npn-list"; +const char SHRPX_OPT_TLS_PROTO_LIST[] = "tls-proto-list"; +const char SHRPX_OPT_VERIFY_CLIENT[] = "verify-client"; +const char SHRPX_OPT_VERIFY_CLIENT_CACERT[] = "verify-client-cacert"; +const char SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE[] = "client-private-key-file"; +const char SHRPX_OPT_CLIENT_CERT_FILE[] = "client-cert-file"; +const char SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER[] = + "frontend-http2-dump-request-header"; +const char SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER[] = + "frontend-http2-dump-response-header"; +const char SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING[] = "http2-no-cookie-crumbling"; +const char SHRPX_OPT_FRONTEND_FRAME_DEBUG[] = "frontend-frame-debug"; +const char SHRPX_OPT_PADDING[] = "padding"; +const char SHRPX_OPT_ALTSVC[] = "altsvc"; +const char SHRPX_OPT_ADD_RESPONSE_HEADER[] = "add-response-header"; +const char SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS[] = + "worker-frontend-connections"; +const char SHRPX_OPT_NO_LOCATION_REWRITE[] = "no-location-rewrite"; +const char SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND[] = + "backend-connections-per-frontend"; +const char SHRPX_OPT_LISTENER_DISABLE_TIMEOUT[] = "listener-disable-timeout"; + namespace { Config *config = nullptr; } // namespace -constexpr auto SHRPX_UNIX_PATH_PREFIX = StringRef::from_lit("unix:"); - const Config *get_config() { return config; } Config *mod_config() { return config; } void create_config() { config = new Config(); } -TicketKeys::~TicketKeys() { - /* Erase keys from memory */ - for (auto &key : keys) { - memset(&key, 0, sizeof(key)); - } -} - namespace { int split_host_port(char *host, size_t hostlen, uint16_t *port_ptr, - const StringRef &hostport, const StringRef &opt) { + const char *hostport) { // host and port in |hostport| is separated by single ','. - auto sep = std::find(std::begin(hostport), std::end(hostport), ','); - if (sep == std::end(hostport)) { - LOG(ERROR) << opt << ": Invalid host, port: " << hostport; + const char *p = strchr(hostport, ','); + if (!p) { + LOG(ERROR) << "Invalid host, port: " << hostport; return -1; } - size_t len = sep - std::begin(hostport); + size_t len = p - hostport; if (hostlen < len + 1) { - LOG(ERROR) << opt << ": Hostname too long: " << hostport; + LOG(ERROR) << "Hostname too long: " << hostport; return -1; } - std::copy(std::begin(hostport), sep, host); + memcpy(host, hostport, len); host[len] = '\0'; - auto portstr = StringRef{sep + 1, std::end(hostport)}; - auto d = util::parse_uint(portstr); - if (1 <= d && d <= std::numeric_limits::max()) { + errno = 0; + unsigned long d = strtoul(p + 1, nullptr, 10); + if (errno == 0 && 1 <= d && d <= std::numeric_limits::max()) { *port_ptr = d; return 0; + } else { + LOG(ERROR) << "Port is invalid: " << p + 1; + return -1; } - - LOG(ERROR) << opt << ": Port is invalid: " << portstr; - return -1; } } // namespace namespace { -bool is_secure(const StringRef &filename) { +bool is_secure(const char *filename) { struct stat buf; - int rv = stat(filename.c_str(), &buf); + int rv = stat(filename, &buf); if (rv == 0) { if ((buf.st_mode & S_IRWXU) && !(buf.st_mode & S_IRWXG) && !(buf.st_mode & S_IRWXO)) { @@ -122,186 +190,120 @@ } } // namespace -std::unique_ptr -read_tls_ticket_key_file(const std::vector &files, - const EVP_CIPHER *cipher, const EVP_MD *hmac) { - auto ticket_keys = make_unique(); - auto &keys = ticket_keys->keys; - keys.resize(files.size()); - auto enc_keylen = EVP_CIPHER_key_length(cipher); - auto hmac_keylen = EVP_MD_size(hmac); - if (cipher == EVP_aes_128_cbc()) { - // backward compatibility, as a legacy of using same file format - // with nginx and apache. - hmac_keylen = 16; - } - auto expectedlen = keys[0].data.name.size() + enc_keylen + hmac_keylen; - char buf[256]; - assert(sizeof(buf) >= expectedlen); - - size_t i = 0; - for (auto &file : files) { - struct stat fst {}; - - if (stat(file.c_str(), &fst) == -1) { - auto error = errno; - LOG(ERROR) << "tls-ticket-key-file: could not stat file " << file - << ", errno=" << error; - return nullptr; - } - - if (static_cast(fst.st_size) != expectedlen) { - LOG(ERROR) << "tls-ticket-key-file: the expected file size is " - << expectedlen << ", the actual file size is " << fst.st_size; - return nullptr; - } - - std::ifstream f(file.c_str()); - if (!f) { - LOG(ERROR) << "tls-ticket-key-file: could not open file " << file; - return nullptr; - } - - f.read(buf, expectedlen); - if (static_cast(f.gcount()) != expectedlen) { - LOG(ERROR) << "tls-ticket-key-file: want to read " << expectedlen - << " bytes but only read " << f.gcount() << " bytes from " - << file; - return nullptr; - } - - auto &key = keys[i++]; - key.cipher = cipher; - key.hmac = hmac; - key.hmac_keylen = hmac_keylen; - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "enc_keylen=" << enc_keylen - << ", hmac_keylen=" << key.hmac_keylen; - } - - auto p = buf; - std::copy_n(p, key.data.name.size(), std::begin(key.data.name)); - p += key.data.name.size(); - std::copy_n(p, enc_keylen, std::begin(key.data.enc_key)); - p += enc_keylen; - std::copy_n(p, hmac_keylen, std::begin(key.data.hmac_key)); - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "session ticket key: " << util::format_hex(key.data.name); - } - } - return ticket_keys; -} - FILE *open_file_for_write(const char *filename) { -#if defined O_CLOEXEC - auto fd = open(filename, O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR); -#else - auto fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); - - // We get race condition if execve is called at the same time. - if (fd != -1) { - util::make_socket_closeonexec(fd); - } -#endif - if (fd == -1) { - LOG(ERROR) << "Failed to open " << filename - << " for writing. Cause: " << strerror(errno); - return nullptr; - } - auto f = fdopen(fd, "wb"); + auto f = fopen(filename, "wb"); if (f == nullptr) { LOG(ERROR) << "Failed to open " << filename << " for writing. Cause: " << strerror(errno); return nullptr; } + evutil_make_socket_closeonexec(fileno(f)); + return f; } -namespace { -// Read passwd from |filename| -std::string read_passwd_from_file(const StringRef &opt, - const StringRef &filename) { +std::string read_passwd_from_file(const char *filename) { std::string line; if (!is_secure(filename)) { - LOG(ERROR) << opt << ": Private key passwd file " << filename + LOG(ERROR) << "Private key passwd file " << filename << " has insecure mode."; return line; } - std::ifstream in(filename.c_str(), std::ios::binary); + std::ifstream in(filename, std::ios::binary); if (!in) { - LOG(ERROR) << opt << ": Could not open key passwd file " << filename; + LOG(ERROR) << "Could not open key passwd file " << filename; return line; } std::getline(in, line); return line; } -} // namespace -Headers::value_type parse_header(const StringRef &optarg) { - auto colon = std::find(std::begin(optarg), std::end(optarg), ':'); +std::unique_ptr strcopy(const char *val) { + return strcopy(val, strlen(val)); +} - if (colon == std::end(optarg) || colon == std::begin(optarg)) { - return {"", ""}; - } +std::unique_ptr strcopy(const char *val, size_t len) { + auto res = util::make_unique(len + 1); + memcpy(res.get(), val, len); + res[len] = '\0'; + return res; +} - auto value = colon + 1; - for (; *value == '\t' || *value == ' '; ++value) +std::unique_ptr strcopy(const std::string &val) { + return strcopy(val.c_str(), val.size()); +} + +std::vector parse_config_str_list(const char *s) { + size_t len = 1; + for (const char *first = s, *p = nullptr; (p = strchr(first, ',')); + ++len, first = p + 1) ; + auto list = std::vector(len); + auto first = strdup(s); + len = 0; + for (;;) { + auto p = strchr(first, ','); + if (p == nullptr) { + break; + } + list[len++] = first; + *p = '\0'; + first = p + 1; + } + list[len++] = first; + + return list; +} - auto p = Header(std::string{std::begin(optarg), colon}, - std::string{value, std::end(optarg)}); - util::inp_strlower(p.name); - - if (!nghttp2_check_header_name( - reinterpret_cast(p.name.c_str()), p.name.size()) || - !nghttp2_check_header_value( - reinterpret_cast(p.value.c_str()), p.value.size())) { - return Header{}; +void clear_config_str_list(std::vector &list) { + if (list.empty()) { + return; } - return p; + free(list[0]); + list.clear(); } -template -int parse_uint(T *dest, const StringRef &opt, const StringRef &optarg) { - auto val = util::parse_uint(optarg); - if (val == -1) { - LOG(ERROR) << opt << ": bad value. Specify an integer >= 0."; - return -1; +std::pair parse_header(const char *optarg) { + // We skip possible ":" at the start of optarg. + const auto *colon = strchr(optarg + 1, ':'); + + // name = ":" is not allowed + if (colon == nullptr || (optarg[0] == ':' && colon == optarg + 1)) { + return {"", ""}; } - *dest = val; + auto value = colon + 1; + for (; *value == '\t' || *value == ' '; ++value) + ; - return 0; + return {std::string(optarg, colon), std::string(value, strlen(value))}; } -namespace { template -int parse_uint_with_unit(T *dest, const StringRef &opt, - const StringRef &optarg) { - auto n = util::parse_uint_with_unit(optarg); - if (n == -1) { - LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; +int parse_uint(T *dest, const char *opt, const char *optarg) { + char *end = nullptr; + + errno = 0; + + auto val = strtol(optarg, &end, 10); + + if (!optarg[0] || errno != 0 || *end || val < 0) { + LOG(ERROR) << opt << ": bad value. Specify an integer >= 0."; return -1; } - *dest = n; + *dest = val; return 0; } -} // namespace -// Parses |optarg| as signed integer. This requires |optarg| to be -// NULL-terminated string. template -int parse_int(T *dest, const StringRef &opt, const char *optarg) { +int parse_int(T *dest, const char *opt, const char *optarg) { char *end = nullptr; errno = 0; @@ -319,137 +321,22 @@ } namespace { -// generated by gennghttpxfun.py -LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { - switch (namelen) { - case 3: - switch (name[2]) { - case 'd': - if (util::strieq_l("pi", name, 2)) { - return SHRPX_LOGF_PID; - } - break; - } - break; - case 4: - switch (name[3]) { - case 'n': - if (util::strieq_l("alp", name, 3)) { - return SHRPX_LOGF_ALPN; - } - break; - } - break; - case 6: - switch (name[5]) { - case 's': - if (util::strieq_l("statu", name, 5)) { - return SHRPX_LOGF_STATUS; - } - break; - } - break; - case 7: - switch (name[6]) { - case 't': - if (util::strieq_l("reques", name, 6)) { - return SHRPX_LOGF_REQUEST; - } - break; - } - break; - case 10: - switch (name[9]) { - case 'l': - if (util::strieq_l("time_loca", name, 9)) { - return SHRPX_LOGF_TIME_LOCAL; - } - break; - case 'r': - if (util::strieq_l("ssl_ciphe", name, 9)) { - return SHRPX_LOGF_SSL_CIPHER; - } - break; - } - break; - case 11: - switch (name[10]) { - case 'r': - if (util::strieq_l("remote_add", name, 10)) { - return SHRPX_LOGF_REMOTE_ADDR; - } - break; - case 't': - if (util::strieq_l("remote_por", name, 10)) { - return SHRPX_LOGF_REMOTE_PORT; - } - if (util::strieq_l("server_por", name, 10)) { - return SHRPX_LOGF_SERVER_PORT; - } - break; - } - break; - case 12: - switch (name[11]) { - case '1': - if (util::strieq_l("time_iso860", name, 11)) { - return SHRPX_LOGF_TIME_ISO8601; - } - break; - case 'e': - if (util::strieq_l("request_tim", name, 11)) { - return SHRPX_LOGF_REQUEST_TIME; - } - break; - case 'l': - if (util::strieq_l("ssl_protoco", name, 11)) { - return SHRPX_LOGF_SSL_PROTOCOL; - } - break; - } - break; - case 14: - switch (name[13]) { - case 'd': - if (util::strieq_l("ssl_session_i", name, 13)) { - return SHRPX_LOGF_SSL_SESSION_ID; - } - break; - } - break; - case 15: - switch (name[14]) { - case 't': - if (util::strieq_l("body_bytes_sen", name, 14)) { - return SHRPX_LOGF_BODY_BYTES_SENT; - } - break; - } - break; - case 18: - switch (name[17]) { - case 'd': - if (util::strieq_l("ssl_session_reuse", name, 17)) { - return SHRPX_LOGF_SSL_SESSION_REUSED; - } - break; - } - break; - } - return SHRPX_LOGF_NONE; +LogFragment make_log_fragment(LogFragmentType type, + std::unique_ptr value = nullptr) { + return LogFragment{type, std::move(value)}; } } // namespace namespace { bool var_token(char c) { - return util::is_alpha(c) || util::is_digit(c) || c == '_'; + return util::isAlpha(c) || util::isDigit(c) || c == '_'; } } // namespace -std::vector parse_log_format(const StringRef &optarg) { - auto literal_start = std::begin(optarg); - auto p = literal_start; - auto eop = std::end(optarg); +std::vector parse_log_format(const char *optarg) { + auto literal_start = optarg; + auto p = optarg; + auto eop = p + strlen(optarg); auto res = std::vector(); @@ -463,1460 +350,278 @@ ++p; - const char *var_name; - size_t var_namelen; - if (p != eop && *p == '{') { - var_name = ++p; - for (; p != eop && var_token(*p); ++p) - ; - - if (p == eop || *p != '}') { - LOG(WARN) << "Missing '}' after " << StringRef{var_start, p}; - continue; - } - - var_namelen = p - var_name; - ++p; - } else { - var_name = p; - for (; p != eop && var_token(*p); ++p) - ; + for (; p != eop && var_token(*p); ++p) + ; - var_namelen = p - var_name; - } + auto varlen = p - var_start; + auto type = SHRPX_LOGF_NONE; const char *value = nullptr; + size_t valuelen = 0; - auto type = log_var_lookup_token(var_name, var_namelen); - - if (type == SHRPX_LOGF_NONE) { - if (util::istarts_with_l(StringRef{var_name, var_namelen}, "http_")) { - if (util::streq_l("host", StringRef{var_name + str_size("http_"), - var_namelen - str_size("http_")})) { - // Special handling of host header field. We will use - // :authority header field if host header is missing. This - // is a typical case in HTTP/2. - type = SHRPX_LOGF_AUTHORITY; - } else { - type = SHRPX_LOGF_HTTP; - value = var_name + str_size("http_"); - } - } else { - LOG(WARN) << "Unrecognized log format variable: " - << StringRef{var_name, var_namelen}; - continue; - } + if (util::strieq("$remote_addr", var_start, varlen)) { + type = SHRPX_LOGF_REMOTE_ADDR; + } else if (util::strieq("$time_local", var_start, varlen)) { + type = SHRPX_LOGF_TIME_LOCAL; + } else if (util::strieq("$time_iso8601", var_start, varlen)) { + type = SHRPX_LOGF_TIME_ISO8601; + } else if (util::strieq("$request", var_start, varlen)) { + type = SHRPX_LOGF_REQUEST; + } else if (util::strieq("$status", var_start, varlen)) { + type = SHRPX_LOGF_STATUS; + } else if (util::strieq("$body_bytes_sent", var_start, varlen)) { + type = SHRPX_LOGF_BODY_BYTES_SENT; + } else if (util::istartsWith(var_start, varlen, "$http_")) { + type = SHRPX_LOGF_HTTP; + value = var_start + sizeof("$http_") - 1; + valuelen = varlen - (sizeof("$http_") - 1); + } else if (util::strieq("$remote_port", var_start, varlen)) { + type = SHRPX_LOGF_REMOTE_PORT; + } else if (util::strieq("$server_port", var_start, varlen)) { + type = SHRPX_LOGF_SERVER_PORT; + } else if (util::strieq("$request_time", var_start, varlen)) { + type = SHRPX_LOGF_REQUEST_TIME; + } else if (util::strieq("$pid", var_start, varlen)) { + type = SHRPX_LOGF_PID; + } else if (util::strieq("$alpn", var_start, varlen)) { + type = SHRPX_LOGF_ALPN; + } else { + LOG(WARN) << "Unrecognized log format variable: " + << std::string(var_start, varlen); + continue; } if (literal_start < var_start) { - res.emplace_back(SHRPX_LOGF_LITERAL, - ImmutableString(literal_start, var_start)); + res.push_back( + make_log_fragment(SHRPX_LOGF_LITERAL, + strcopy(literal_start, var_start - literal_start))); } - literal_start = p; - if (value == nullptr) { - res.emplace_back(type); - continue; - } - - auto name = std::string(value, var_name + var_namelen); - for (auto &c : name) { - if (c == '_') { - c = '-'; + res.push_back(make_log_fragment(type)); + } else { + res.push_back(make_log_fragment(type, strcopy(value, valuelen))); + auto &v = res.back().value; + for (size_t i = 0; v[i]; ++i) { + if (v[i] == '_') { + v[i] = '-'; + } } } - res.emplace_back(type, ImmutableString(name)); + literal_start = var_start + varlen; } if (literal_start != eop) { - res.emplace_back(SHRPX_LOGF_LITERAL, ImmutableString(literal_start, eop)); + res.push_back(make_log_fragment( + SHRPX_LOGF_LITERAL, strcopy(literal_start, eop - literal_start))); } return res; } namespace { -int parse_address_family(int *dest, const StringRef &opt, - const StringRef &optarg) { - if (util::strieq_l("auto", optarg)) { - *dest = AF_UNSPEC; - return 0; - } - if (util::strieq_l("IPv4", optarg)) { - *dest = AF_INET; - return 0; - } - if (util::strieq_l("IPv6", optarg)) { - *dest = AF_INET6; - return 0; - } - - LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; - return -1; -} -} // namespace +int parse_timeval(timeval *dest, const char *opt, const char *optarg) { + time_t sec; -namespace { -int parse_duration(ev_tstamp *dest, const StringRef &opt, - const StringRef &optarg) { - auto t = util::parse_duration_with_unit(optarg); - if (t == std::numeric_limits::infinity()) { - LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; + if (parse_uint(&sec, opt, optarg) != 0) { return -1; } - *dest = t; + dest->tv_sec = sec; + dest->tv_usec = 0; return 0; } } // namespace -struct MemcachedConnectionParams { - bool tls; -}; - -namespace { -// Parses memcached connection configuration parameter |src_params|, -// and stores parsed results into |out|. This function returns 0 if -// it succeeds, or -1. -int parse_memcached_connection_params(MemcachedConnectionParams &out, - const StringRef &src_params, - const StringRef &opt) { - auto last = std::end(src_params); - for (auto first = std::begin(src_params); first != last;) { - auto end = std::find(first, last, ';'); - auto param = StringRef{first, end}; - - if (util::strieq_l("tls", param)) { - out.tls = true; - } else if (util::strieq_l("no-tls", param)) { - out.tls = false; - } else if (!param.empty()) { - LOG(ERROR) << opt << ": " << param << ": unknown keyword"; +int parse_config(const char *opt, const char *optarg) { + char host[NI_MAXHOST]; + uint16_t port; + if (util::strieq(opt, SHRPX_OPT_BACKEND)) { + if (split_host_port(host, sizeof(host), &port, optarg) == -1) { return -1; } - if (end == last) { - break; - } + mod_config()->downstream_host = strcopy(host); + mod_config()->downstream_port = port; - first = end + 1; + return 0; } - return 0; -} -} // namespace - -struct UpstreamParams { - int alt_mode; - bool tls; -}; - -namespace { -// Parses upstream configuration parameter |src_params|, and stores -// parsed results into |out|. This function returns 0 if it succeeds, -// or -1. -int parse_upstream_params(UpstreamParams &out, const StringRef &src_params) { - auto last = std::end(src_params); - for (auto first = std::begin(src_params); first != last;) { - auto end = std::find(first, last, ';'); - auto param = StringRef{first, end}; - - if (util::strieq_l("tls", param)) { - out.tls = true; - } else if (util::strieq_l("no-tls", param)) { - out.tls = false; - } else if (util::strieq_l("api", param)) { - if (out.alt_mode && out.alt_mode != ALTMODE_API) { - LOG(ERROR) << "frontend: api and healthmon are mutually exclusive"; - return -1; - } - out.alt_mode = ALTMODE_API; - } else if (util::strieq_l("healthmon", param)) { - if (out.alt_mode && out.alt_mode != ALTMODE_HEALTHMON) { - LOG(ERROR) << "frontend: api and healthmon are mutually exclusive"; - return -1; - } - out.alt_mode = ALTMODE_HEALTHMON; - } else if (!param.empty()) { - LOG(ERROR) << "frontend: " << param << ": unknown keyword"; + if (util::strieq(opt, SHRPX_OPT_FRONTEND)) { + if (split_host_port(host, sizeof(host), &port, optarg) == -1) { return -1; } - if (end == last) { - break; - } + mod_config()->host = strcopy(host); + mod_config()->port = port; - first = end + 1; + return 0; } - return 0; -} -} // namespace + if (util::strieq(opt, SHRPX_OPT_WORKERS)) { + return parse_uint(&mod_config()->num_worker, opt, optarg); + } -struct DownstreamParams { - StringRef sni; - size_t fall; - size_t rise; - shrpx_proto proto; - shrpx_session_affinity affinity; - bool tls; -}; + if (util::strieq(opt, SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS)) { + return parse_uint(&mod_config()->http2_max_concurrent_streams, opt, optarg); + } -namespace { -// Parses downstream configuration parameter |src_params|, and stores -// parsed results into |out|. This function returns 0 if it succeeds, -// or -1. -int parse_downstream_params(DownstreamParams &out, - const StringRef &src_params) { - auto last = std::end(src_params); - for (auto first = std::begin(src_params); first != last;) { - auto end = std::find(first, last, ';'); - auto param = StringRef{first, end}; - - if (util::istarts_with_l(param, "proto=")) { - auto protostr = StringRef{first + str_size("proto="), end}; - if (protostr.empty()) { - LOG(ERROR) << "backend: proto: protocol is empty"; - return -1; - } + if (util::strieq(opt, SHRPX_OPT_LOG_LEVEL)) { + if (Log::set_severity_level_by_name(optarg) == -1) { + LOG(ERROR) << opt << ": Invalid severity level: " << optarg; + return -1; + } - if (util::streq_l("h2", std::begin(protostr), protostr.size())) { - out.proto = PROTO_HTTP2; - } else if (util::streq_l("http/1.1", std::begin(protostr), - protostr.size())) { - out.proto = PROTO_HTTP1; - } else { - LOG(ERROR) << "backend: proto: unknown protocol " << protostr; - return -1; - } - } else if (util::istarts_with_l(param, "fall=")) { - auto valstr = StringRef{first + str_size("fall="), end}; - if (valstr.empty()) { - LOG(ERROR) << "backend: fall: non-negative integer is expected"; - return -1; - } + return 0; + } - auto n = util::parse_uint(valstr); - if (n == -1) { - LOG(ERROR) << "backend: fall: non-negative integer is expected"; - return -1; - } + if (util::strieq(opt, SHRPX_OPT_DAEMON)) { + mod_config()->daemon = util::strieq(optarg, "yes"); - out.fall = n; - } else if (util::istarts_with_l(param, "rise=")) { - auto valstr = StringRef{first + str_size("rise="), end}; - if (valstr.empty()) { - LOG(ERROR) << "backend: rise: non-negative integer is expected"; - return -1; - } + return 0; + } - auto n = util::parse_uint(valstr); - if (n == -1) { - LOG(ERROR) << "backend: rise: non-negative integer is expected"; - return -1; - } + if (util::strieq(opt, SHRPX_OPT_HTTP2_PROXY)) { + mod_config()->http2_proxy = util::strieq(optarg, "yes"); - out.rise = n; - } else if (util::strieq_l("tls", param)) { - out.tls = true; - } else if (util::strieq_l("no-tls", param)) { - out.tls = false; - } else if (util::istarts_with_l(param, "sni=")) { - out.sni = StringRef{first + str_size("sni="), end}; - } else if (util::istarts_with_l(param, "affinity=")) { - auto valstr = StringRef{first + str_size("affinity="), end}; - if (util::strieq_l("none", valstr)) { - out.affinity = AFFINITY_NONE; - } else if (util::strieq_l("ip", valstr)) { - out.affinity = AFFINITY_IP; - } else { - LOG(ERROR) << "backend: affinity: value must be either none or ip"; - return -1; - } - } else if (!param.empty()) { - LOG(ERROR) << "backend: " << param << ": unknown keyword"; - return -1; - } + return 0; + } - if (end == last) { - break; - } + if (util::strieq(opt, SHRPX_OPT_HTTP2_BRIDGE)) { + mod_config()->http2_bridge = util::strieq(optarg, "yes"); - first = end + 1; + return 0; } - return 0; -} -} // namespace + if (util::strieq(opt, SHRPX_OPT_CLIENT_PROXY)) { + mod_config()->client_proxy = util::strieq(optarg, "yes"); -namespace { -// Parses host-path mapping patterns in |src_pattern|, and stores -// mappings in config. We will store each host-path pattern found in -// |src| with |addr|. |addr| will be copied accordingly. Also we -// make a group based on the pattern. The "/" pattern is considered -// as catch-all. We also parse protocol specified in |src_proto|. -// -// This function returns 0 if it succeeds, or -1. -int parse_mapping(Config *config, DownstreamAddrConfig addr, - const StringRef &src_pattern, const StringRef &src_params) { - // This returns at least 1 element (it could be empty string). We - // will append '/' to all patterns, so it becomes catch-all pattern. - auto mapping = util::split_str(src_pattern, ':'); - assert(!mapping.empty()); - auto &downstreamconf = *config->conn.downstream; - auto &addr_groups = downstreamconf.addr_groups; + return 0; + } - DownstreamParams params{}; - params.proto = PROTO_HTTP1; + if (util::strieq(opt, SHRPX_OPT_ADD_X_FORWARDED_FOR)) { + mod_config()->add_x_forwarded_for = util::strieq(optarg, "yes"); - if (parse_downstream_params(params, src_params) != 0) { - return -1; + return 0; } - addr.fall = params.fall; - addr.rise = params.rise; - addr.proto = params.proto; - addr.tls = params.tls; - addr.sni = ImmutableString{std::begin(params.sni), std::end(params.sni)}; - - auto &routerconf = downstreamconf.router; - auto &router = routerconf.router; - auto &rw_router = routerconf.rev_wildcard_router; - auto &wildcard_patterns = routerconf.wildcard_patterns; - - for (const auto &raw_pattern : mapping) { - auto done = false; - std::string pattern; - auto slash = std::find(std::begin(raw_pattern), std::end(raw_pattern), '/'); - if (slash == std::end(raw_pattern)) { - // This effectively makes empty pattern to "/". - pattern.assign(std::begin(raw_pattern), std::end(raw_pattern)); - util::inp_strlower(pattern); - pattern += '/'; - } else { - pattern.assign(std::begin(raw_pattern), slash); - util::inp_strlower(pattern); - pattern += http2::normalize_path(StringRef{slash, std::end(raw_pattern)}, - StringRef{}); - } - for (auto &g : addr_groups) { - if (g.pattern == pattern) { - // Last value wins if we have multiple different affinity - // value under one group. - if (params.affinity != AFFINITY_NONE) { - g.affinity = params.affinity; - } - g.addrs.push_back(addr); - done = true; - break; - } - } - if (done) { - continue; - } + if (util::strieq(opt, SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR)) { + mod_config()->strip_incoming_x_forwarded_for = util::strieq(optarg, "yes"); - auto idx = addr_groups.size(); - addr_groups.emplace_back(StringRef{pattern}); - auto &g = addr_groups.back(); - g.addrs.push_back(addr); - g.affinity = params.affinity; - - if (pattern[0] == '*') { - // wildcard pattern - auto path_first = - std::find(std::begin(g.pattern), std::end(g.pattern), '/'); - - auto host = StringRef{std::begin(g.pattern) + 1, path_first}; - auto path = StringRef{path_first, std::end(g.pattern)}; - - auto it = std::find_if( - std::begin(wildcard_patterns), std::end(wildcard_patterns), - [&host](const WildcardPattern &wp) { return wp.host == host; }); - - if (it == std::end(wildcard_patterns)) { - wildcard_patterns.emplace_back(host); + return 0; + } - auto &router = wildcard_patterns.back().router; - router.add_route(path, idx); + if (util::strieq(opt, SHRPX_OPT_NO_VIA)) { + mod_config()->no_via = util::strieq(optarg, "yes"); - auto rev_host = host.str(); - std::reverse(std::begin(rev_host), std::end(rev_host)); + return 0; + } - rw_router.add_route(StringRef{rev_host}, wildcard_patterns.size() - 1); - } else { - (*it).router.add_route(path, idx); - } + if (util::strieq(opt, SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT)) { + return parse_timeval(&mod_config()->http2_upstream_read_timeout, opt, + optarg); + } - continue; - } + if (util::strieq(opt, SHRPX_OPT_FRONTEND_READ_TIMEOUT)) { + return parse_timeval(&mod_config()->upstream_read_timeout, opt, optarg); + } - router.add_route(StringRef{g.pattern}, idx); + if (util::strieq(opt, SHRPX_OPT_FRONTEND_WRITE_TIMEOUT)) { + return parse_timeval(&mod_config()->upstream_write_timeout, opt, optarg); } - return 0; -} -} // namespace -namespace { -int parse_forwarded_node_type(const StringRef &optarg) { - if (util::strieq_l("obfuscated", optarg)) { - return FORWARDED_NODE_OBFUSCATED; + if (util::strieq(opt, SHRPX_OPT_BACKEND_READ_TIMEOUT)) { + return parse_timeval(&mod_config()->downstream_read_timeout, opt, optarg); } - if (util::strieq_l("ip", optarg)) { - return FORWARDED_NODE_IP; + if (util::strieq(opt, SHRPX_OPT_BACKEND_WRITE_TIMEOUT)) { + return parse_timeval(&mod_config()->downstream_write_timeout, opt, optarg); } - if (optarg.size() < 2 || optarg[0] != '_') { - return -1; + if (util::strieq(opt, SHRPX_OPT_STREAM_READ_TIMEOUT)) { + return parse_timeval(&mod_config()->stream_read_timeout, opt, optarg); } - if (std::find_if_not(std::begin(optarg), std::end(optarg), [](char c) { - return util::is_alpha(c) || util::is_digit(c) || c == '.' || c == '_' || - c == '-'; - }) != std::end(optarg)) { - return -1; + if (util::strieq(opt, SHRPX_OPT_STREAM_WRITE_TIMEOUT)) { + return parse_timeval(&mod_config()->stream_write_timeout, opt, optarg); } - return FORWARDED_NODE_OBFUSCATED; -} -} // namespace + if (util::strieq(opt, SHRPX_OPT_ACCESSLOG_FILE)) { + mod_config()->accesslog_file = strcopy(optarg); -namespace { -int parse_error_page(std::vector &error_pages, const StringRef &opt, - const StringRef &optarg) { - auto eq = std::find(std::begin(optarg), std::end(optarg), '='); - if (eq == std::end(optarg) || eq + 1 == std::end(optarg)) { - LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; - return -1; + return 0; } - auto codestr = StringRef{std::begin(optarg), eq}; - unsigned int code; + if (util::strieq(opt, SHRPX_OPT_ACCESSLOG_SYSLOG)) { + mod_config()->accesslog_syslog = util::strieq(optarg, "yes"); - if (codestr == StringRef::from_lit("*")) { - code = 0; - } else { - auto n = util::parse_uint(codestr); + return 0; + } - if (n == -1 || n < 400 || n > 599) { - LOG(ERROR) << opt << ": bad code: '" << codestr << "'"; - return -1; - } + if (util::strieq(opt, SHRPX_OPT_ACCESSLOG_FORMAT)) { + mod_config()->accesslog_format = parse_log_format(optarg); - code = static_cast(n); + return 0; } - auto path = StringRef{eq + 1, std::end(optarg)}; + if (util::strieq(opt, SHRPX_OPT_ERRORLOG_FILE)) { + mod_config()->errorlog_file = strcopy(optarg); - std::vector content; - auto fd = open(path.c_str(), O_RDONLY); - if (fd == -1) { - auto error = errno; - LOG(ERROR) << opt << ": " << optarg << ": " << strerror(error); - return -1; + return 0; } - auto fd_closer = defer(close, fd); + if (util::strieq(opt, SHRPX_OPT_ERRORLOG_SYSLOG)) { + mod_config()->errorlog_syslog = util::strieq(optarg, "yes"); - std::array buf; - for (;;) { - auto n = read(fd, buf.data(), buf.size()); - if (n == -1) { - auto error = errno; - LOG(ERROR) << opt << ": " << optarg << ": " << strerror(error); + return 0; + } + + if (util::strieq(opt, SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT)) { + return parse_timeval(&mod_config()->downstream_idle_read_timeout, opt, + optarg); + } + + if (util::strieq(opt, SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS) || + util::strieq(opt, SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS)) { + + size_t *resp; + + if (util::strieq(opt, SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS)) { + resp = &mod_config()->http2_upstream_window_bits; + } else { + resp = &mod_config()->http2_downstream_window_bits; + } + + errno = 0; + + int n; + + if (parse_uint(&n, opt, optarg) != 0) { return -1; } - if (n == 0) { - break; + + if (n >= 31) { + LOG(ERROR) << opt + << ": specify the integer in the range [0, 30], inclusive"; + return -1; } - content.insert(std::end(content), std::begin(buf), std::begin(buf) + n); + + *resp = n; + + return 0; } - error_pages.push_back(ErrorPage{std::move(content), code}); + if (util::strieq(opt, SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS) || + util::strieq(opt, SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS)) { - return 0; -} -} // namespace - -// generated by gennghttpxfun.py -int option_lookup_token(const char *name, size_t namelen) { - switch (namelen) { - case 4: - switch (name[3]) { - case 'f': - if (util::strieq_l("con", name, 3)) { - return SHRPX_OPTID_CONF; - } - break; - case 'r': - if (util::strieq_l("use", name, 3)) { - return SHRPX_OPTID_USER; - } - break; - } - break; - case 6: - switch (name[5]) { - case 'a': - if (util::strieq_l("no-vi", name, 5)) { - return SHRPX_OPTID_NO_VIA; - } - break; - case 'c': - if (util::strieq_l("altsv", name, 5)) { - return SHRPX_OPTID_ALTSVC; - } - break; - case 'n': - if (util::strieq_l("daemo", name, 5)) { - return SHRPX_OPTID_DAEMON; - } - break; - case 't': - if (util::strieq_l("cacer", name, 5)) { - return SHRPX_OPTID_CACERT; - } - if (util::strieq_l("clien", name, 5)) { - return SHRPX_OPTID_CLIENT; - } - break; - } - break; - case 7: - switch (name[6]) { - case 'd': - if (util::strieq_l("backen", name, 6)) { - return SHRPX_OPTID_BACKEND; - } - break; - case 'e': - if (util::strieq_l("includ", name, 6)) { - return SHRPX_OPTID_INCLUDE; - } - break; - case 'g': - if (util::strieq_l("backlo", name, 6)) { - return SHRPX_OPTID_BACKLOG; - } - if (util::strieq_l("paddin", name, 6)) { - return SHRPX_OPTID_PADDING; - } - break; - case 'p': - if (util::strieq_l("no-ocs", name, 6)) { - return SHRPX_OPTID_NO_OCSP; - } - break; - case 's': - if (util::strieq_l("cipher", name, 6)) { - return SHRPX_OPTID_CIPHERS; - } - if (util::strieq_l("worker", name, 6)) { - return SHRPX_OPTID_WORKERS; - } - break; - case 't': - if (util::strieq_l("subcer", name, 6)) { - return SHRPX_OPTID_SUBCERT; - } - break; - } - break; - case 8: - switch (name[7]) { - case 'd': - if (util::strieq_l("fronten", name, 7)) { - return SHRPX_OPTID_FRONTEND; - } - break; - case 'e': - if (util::strieq_l("insecur", name, 7)) { - return SHRPX_OPTID_INSECURE; - } - if (util::strieq_l("pid-fil", name, 7)) { - return SHRPX_OPTID_PID_FILE; - } - break; - case 'n': - if (util::strieq_l("fastope", name, 7)) { - return SHRPX_OPTID_FASTOPEN; - } - break; - case 't': - if (util::strieq_l("npn-lis", name, 7)) { - return SHRPX_OPTID_NPN_LIST; - } - break; - } - break; - case 9: - switch (name[8]) { - case 'e': - if (util::strieq_l("no-kqueu", name, 8)) { - return SHRPX_OPTID_NO_KQUEUE; - } - if (util::strieq_l("read-rat", name, 8)) { - return SHRPX_OPTID_READ_RATE; - } - break; - case 'l': - if (util::strieq_l("log-leve", name, 8)) { - return SHRPX_OPTID_LOG_LEVEL; - } - break; - } - break; - case 10: - switch (name[9]) { - case 'e': - if (util::strieq_l("error-pag", name, 9)) { - return SHRPX_OPTID_ERROR_PAGE; - } - if (util::strieq_l("mruby-fil", name, 9)) { - return SHRPX_OPTID_MRUBY_FILE; - } - if (util::strieq_l("write-rat", name, 9)) { - return SHRPX_OPTID_WRITE_RATE; - } - break; - case 't': - if (util::strieq_l("read-burs", name, 9)) { - return SHRPX_OPTID_READ_BURST; - } - break; - } - break; - case 11: - switch (name[10]) { - case 's': - if (util::strieq_l("backend-tl", name, 10)) { - return SHRPX_OPTID_BACKEND_TLS; - } - break; - case 't': - if (util::strieq_l("write-burs", name, 10)) { - return SHRPX_OPTID_WRITE_BURST; - } - break; - case 'y': - if (util::strieq_l("http2-prox", name, 10)) { - return SHRPX_OPTID_HTTP2_PROXY; - } - break; - } - break; - case 12: - switch (name[11]) { - case '4': - if (util::strieq_l("backend-ipv", name, 11)) { - return SHRPX_OPTID_BACKEND_IPV4; - } - break; - case '6': - if (util::strieq_l("backend-ipv", name, 11)) { - return SHRPX_OPTID_BACKEND_IPV6; - } - break; - case 'e': - if (util::strieq_l("host-rewrit", name, 11)) { - return SHRPX_OPTID_HOST_REWRITE; - } - if (util::strieq_l("http2-bridg", name, 11)) { - return SHRPX_OPTID_HTTP2_BRIDGE; - } - break; - case 'y': - if (util::strieq_l("client-prox", name, 11)) { - return SHRPX_OPTID_CLIENT_PROXY; - } - if (util::strieq_l("forwarded-b", name, 11)) { - return SHRPX_OPTID_FORWARDED_BY; - } - break; - } - break; - case 13: - switch (name[12]) { - case 'd': - if (util::strieq_l("add-forwarde", name, 12)) { - return SHRPX_OPTID_ADD_FORWARDED; - } - break; - case 'e': - if (util::strieq_l("dh-param-fil", name, 12)) { - return SHRPX_OPTID_DH_PARAM_FILE; - } - if (util::strieq_l("errorlog-fil", name, 12)) { - return SHRPX_OPTID_ERRORLOG_FILE; - } - if (util::strieq_l("rlimit-nofil", name, 12)) { - return SHRPX_OPTID_RLIMIT_NOFILE; - } - break; - case 'r': - if (util::strieq_l("forwarded-fo", name, 12)) { - return SHRPX_OPTID_FORWARDED_FOR; - } - break; - case 't': - if (util::strieq_l("verify-clien", name, 12)) { - return SHRPX_OPTID_VERIFY_CLIENT; - } - break; - } - break; - case 14: - switch (name[13]) { - case 'e': - if (util::strieq_l("accesslog-fil", name, 13)) { - return SHRPX_OPTID_ACCESSLOG_FILE; - } - break; - case 'h': - if (util::strieq_l("no-server-pus", name, 13)) { - return SHRPX_OPTID_NO_SERVER_PUSH; - } - break; - case 's': - if (util::strieq_l("backend-no-tl", name, 13)) { - return SHRPX_OPTID_BACKEND_NO_TLS; - } - break; - case 't': - if (util::strieq_l("tls-proto-lis", name, 13)) { - return SHRPX_OPTID_TLS_PROTO_LIST; - } - break; - } - break; - case 15: - switch (name[14]) { - case 'e': - if (util::strieq_l("no-host-rewrit", name, 14)) { - return SHRPX_OPTID_NO_HOST_REWRITE; - } - break; - case 'g': - if (util::strieq_l("errorlog-syslo", name, 14)) { - return SHRPX_OPTID_ERRORLOG_SYSLOG; - } - break; - case 's': - if (util::strieq_l("frontend-no-tl", name, 14)) { - return SHRPX_OPTID_FRONTEND_NO_TLS; - } - break; - case 'y': - if (util::strieq_l("syslog-facilit", name, 14)) { - return SHRPX_OPTID_SYSLOG_FACILITY; - } - break; - } - break; - case 16: - switch (name[15]) { - case 'e': - if (util::strieq_l("certificate-fil", name, 15)) { - return SHRPX_OPTID_CERTIFICATE_FILE; - } - if (util::strieq_l("client-cert-fil", name, 15)) { - return SHRPX_OPTID_CLIENT_CERT_FILE; - } - if (util::strieq_l("private-key-fil", name, 15)) { - return SHRPX_OPTID_PRIVATE_KEY_FILE; - } - if (util::strieq_l("worker-read-rat", name, 15)) { - return SHRPX_OPTID_WORKER_READ_RATE; - } - break; - case 'g': - if (util::strieq_l("accesslog-syslo", name, 15)) { - return SHRPX_OPTID_ACCESSLOG_SYSLOG; - } - break; - case 't': - if (util::strieq_l("accesslog-forma", name, 15)) { - return SHRPX_OPTID_ACCESSLOG_FORMAT; - } - break; - } - break; - case 17: - switch (name[16]) { - case 'e': - if (util::strieq_l("worker-write-rat", name, 16)) { - return SHRPX_OPTID_WORKER_WRITE_RATE; - } - break; - case 's': - if (util::strieq_l("backend-http1-tl", name, 16)) { - return SHRPX_OPTID_BACKEND_HTTP1_TLS; - } - if (util::strieq_l("max-header-field", name, 16)) { - return SHRPX_OPTID_MAX_HEADER_FIELDS; - } - break; - case 't': - if (util::strieq_l("worker-read-burs", name, 16)) { - return SHRPX_OPTID_WORKER_READ_BURST; - } - break; - } - break; - case 18: - switch (name[17]) { - case 'r': - if (util::strieq_l("add-request-heade", name, 17)) { - return SHRPX_OPTID_ADD_REQUEST_HEADER; - } - break; - case 't': - if (util::strieq_l("worker-write-burs", name, 17)) { - return SHRPX_OPTID_WORKER_WRITE_BURST; - } - break; - } - break; - case 19: - switch (name[18]) { - case 'e': - if (util::strieq_l("no-location-rewrit", name, 18)) { - return SHRPX_OPTID_NO_LOCATION_REWRITE; - } - if (util::strieq_l("tls-ticket-key-fil", name, 18)) { - return SHRPX_OPTID_TLS_TICKET_KEY_FILE; - } - break; - case 'f': - if (util::strieq_l("backend-max-backof", name, 18)) { - return SHRPX_OPTID_BACKEND_MAX_BACKOFF; - } - break; - case 'r': - if (util::strieq_l("add-response-heade", name, 18)) { - return SHRPX_OPTID_ADD_RESPONSE_HEADER; - } - if (util::strieq_l("add-x-forwarded-fo", name, 18)) { - return SHRPX_OPTID_ADD_X_FORWARDED_FOR; - } - if (util::strieq_l("header-field-buffe", name, 18)) { - return SHRPX_OPTID_HEADER_FIELD_BUFFER; - } - break; - case 't': - if (util::strieq_l("stream-read-timeou", name, 18)) { - return SHRPX_OPTID_STREAM_READ_TIMEOUT; - } - break; - } - break; - case 20: - switch (name[19]) { - case 'g': - if (util::strieq_l("frontend-frame-debu", name, 19)) { - return SHRPX_OPTID_FRONTEND_FRAME_DEBUG; - } - break; - case 'l': - if (util::strieq_l("ocsp-update-interva", name, 19)) { - return SHRPX_OPTID_OCSP_UPDATE_INTERVAL; - } - break; - case 't': - if (util::strieq_l("backend-read-timeou", name, 19)) { - return SHRPX_OPTID_BACKEND_READ_TIMEOUT; - } - if (util::strieq_l("stream-write-timeou", name, 19)) { - return SHRPX_OPTID_STREAM_WRITE_TIMEOUT; - } - if (util::strieq_l("verify-client-cacer", name, 19)) { - return SHRPX_OPTID_VERIFY_CLIENT_CACERT; - } - break; - case 'y': - if (util::strieq_l("api-max-request-bod", name, 19)) { - return SHRPX_OPTID_API_MAX_REQUEST_BODY; - } - break; - } - break; - case 21: - switch (name[20]) { - case 'd': - if (util::strieq_l("backend-tls-sni-fiel", name, 20)) { - return SHRPX_OPTID_BACKEND_TLS_SNI_FIELD; - } - break; - case 'l': - if (util::strieq_l("accept-proxy-protoco", name, 20)) { - return SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL; - } - break; - case 'r': - if (util::strieq_l("tls-ticket-key-ciphe", name, 20)) { - return SHRPX_OPTID_TLS_TICKET_KEY_CIPHER; - } - break; - case 't': - if (util::strieq_l("backend-write-timeou", name, 20)) { - return SHRPX_OPTID_BACKEND_WRITE_TIMEOUT; - } - if (util::strieq_l("frontend-read-timeou", name, 20)) { - return SHRPX_OPTID_FRONTEND_READ_TIMEOUT; - } - break; - } - break; - case 22: - switch (name[21]) { - case 'i': - if (util::strieq_l("backend-http-proxy-ur", name, 21)) { - return SHRPX_OPTID_BACKEND_HTTP_PROXY_URI; - } - break; - case 'r': - if (util::strieq_l("backend-request-buffe", name, 21)) { - return SHRPX_OPTID_BACKEND_REQUEST_BUFFER; - } - break; - case 't': - if (util::strieq_l("frontend-write-timeou", name, 21)) { - return SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT; - } - break; - case 'y': - if (util::strieq_l("backend-address-famil", name, 21)) { - return SHRPX_OPTID_BACKEND_ADDRESS_FAMILY; - } - break; - } - break; - case 23: - switch (name[22]) { - case 'e': - if (util::strieq_l("client-private-key-fil", name, 22)) { - return SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE; - } - if (util::strieq_l("private-key-passwd-fil", name, 22)) { - return SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE; - } - break; - case 'r': - if (util::strieq_l("backend-response-buffe", name, 22)) { - return SHRPX_OPTID_BACKEND_RESPONSE_BUFFER; - } - break; - } - break; - case 24: - switch (name[23]) { - case 'd': - if (util::strieq_l("strip-incoming-forwarde", name, 23)) { - return SHRPX_OPTID_STRIP_INCOMING_FORWARDED; - } - if (util::strieq_l("tls-ticket-key-memcache", name, 23)) { - return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED; - } - break; - case 'e': - if (util::strieq_l("fetch-ocsp-response-fil", name, 23)) { - return SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE; - } - break; - case 't': - if (util::strieq_l("listener-disable-timeou", name, 23)) { - return SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT; - } - if (util::strieq_l("tls-dyn-rec-idle-timeou", name, 23)) { - return SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT; - } - break; - } - break; - case 25: - switch (name[24]) { - case 'g': - if (util::strieq_l("http2-no-cookie-crumblin", name, 24)) { - return SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING; - } - break; - case 's': - if (util::strieq_l("backend-http2-window-bit", name, 24)) { - return SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS; - } - if (util::strieq_l("max-request-header-field", name, 24)) { - return SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS; - } - break; - } - break; - case 26: - switch (name[25]) { - case 's': - if (util::strieq_l("frontend-http2-window-bit", name, 25)) { - return SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS; - } - if (util::strieq_l("max-response-header-field", name, 25)) { - return SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS; - } - break; - case 't': - if (util::strieq_l("backend-keep-alive-timeou", name, 25)) { - return SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT; - } - if (util::strieq_l("no-http2-cipher-black-lis", name, 25)) { - return SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST; - } - break; - } - break; - case 27: - switch (name[26]) { - case 'd': - if (util::strieq_l("tls-session-cache-memcache", name, 26)) { - return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED; - } - break; - case 'r': - if (util::strieq_l("request-header-field-buffe", name, 26)) { - return SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER; - } - break; - case 's': - if (util::strieq_l("worker-frontend-connection", name, 26)) { - return SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS; - } - break; - case 't': - if (util::strieq_l("frontend-http2-read-timeou", name, 26)) { - return SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT; - } - break; - } - break; - case 28: - switch (name[27]) { - case 'd': - if (util::strieq_l("tls-dyn-rec-warmup-threshol", name, 27)) { - return SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD; - } - break; - case 'r': - if (util::strieq_l("response-header-field-buffe", name, 27)) { - return SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER; - } - break; - case 's': - if (util::strieq_l("http2-max-concurrent-stream", name, 27)) { - return SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS; - } - if (util::strieq_l("tls-ticket-key-memcached-tl", name, 27)) { - return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS; - } - break; - case 't': - if (util::strieq_l("backend-connections-per-hos", name, 27)) { - return SHRPX_OPTID_BACKEND_CONNECTIONS_PER_HOST; - } - break; - } - break; - case 30: - switch (name[29]) { - case 'r': - if (util::strieq_l("strip-incoming-x-forwarded-fo", name, 29)) { - return SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR; - } - break; - case 't': - if (util::strieq_l("backend-http2-settings-timeou", name, 29)) { - return SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT; - } - break; - } - break; - case 31: - switch (name[30]) { - case 's': - if (util::strieq_l("tls-session-cache-memcached-tl", name, 30)) { - return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS; - } - break; - case 't': - if (util::strieq_l("frontend-http2-settings-timeou", name, 30)) { - return SHRPX_OPTID_FRONTEND_HTTP2_SETTINGS_TIMEOUT; - } - break; - } - break; - case 32: - switch (name[31]) { - case 'd': - if (util::strieq_l("backend-connections-per-fronten", name, 31)) { - return SHRPX_OPTID_BACKEND_CONNECTIONS_PER_FRONTEND; - } - break; - } - break; - case 33: - switch (name[32]) { - case 'l': - if (util::strieq_l("tls-ticket-key-memcached-interva", name, 32)) { - return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL; - } - if (util::strieq_l("tls-ticket-key-memcached-max-fai", name, 32)) { - return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL; - } - break; - } - break; - case 34: - switch (name[33]) { - case 'e': - if (util::strieq_l("tls-ticket-key-memcached-cert-fil", name, 33)) { - return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE; - } - break; - case 'r': - if (util::strieq_l("frontend-http2-dump-request-heade", name, 33)) { - return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER; - } - break; - case 't': - if (util::strieq_l("backend-http1-connections-per-hos", name, 33)) { - return SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_HOST; - } - break; - case 'y': - if (util::strieq_l("tls-ticket-key-memcached-max-retr", name, 33)) { - return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY; - } - break; - } - break; - case 35: - switch (name[34]) { - case 'r': - if (util::strieq_l("frontend-http2-dump-response-heade", name, 34)) { - return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER; - } - break; - } - break; - case 36: - switch (name[35]) { - case 'r': - if (util::strieq_l("backend-http2-connections-per-worke", name, 35)) { - return SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER; - } - break; - case 's': - if (util::strieq_l("backend-http2-connection-window-bit", name, 35)) { - return SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS; - } - if (util::strieq_l("backend-http2-max-concurrent-stream", name, 35)) { - return SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS; - } - break; - } - break; - case 37: - switch (name[36]) { - case 'e': - if (util::strieq_l("tls-session-cache-memcached-cert-fil", name, 36)) { - return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE; - } - break; - case 's': - if (util::strieq_l("frontend-http2-connection-window-bit", name, 36)) { - return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS; - } - if (util::strieq_l("frontend-http2-max-concurrent-stream", name, 36)) { - return SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS; - } - break; - } - break; - case 38: - switch (name[37]) { - case 'd': - if (util::strieq_l("backend-http1-connections-per-fronten", name, 37)) { - return SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND; - } - break; - } - break; - case 39: - switch (name[38]) { - case 'y': - if (util::strieq_l("tls-ticket-key-memcached-address-famil", name, 38)) { - return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY; - } - break; - } - break; - case 41: - switch (name[40]) { - case 'e': - if (util::strieq_l("tls-ticket-key-memcached-private-key-fil", name, - 40)) { - return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE; - } - break; - } - break; - case 42: - switch (name[41]) { - case 'y': - if (util::strieq_l("tls-session-cache-memcached-address-famil", name, - 41)) { - return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY; - } - break; - } - break; - case 44: - switch (name[43]) { - case 'e': - if (util::strieq_l("tls-session-cache-memcached-private-key-fil", name, - 43)) { - return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE; - } - break; - } - break; - } - return -1; -} - -int parse_config(Config *config, const StringRef &opt, const StringRef &optarg, - std::set &included_set) { - auto optid = option_lookup_token(opt.c_str(), opt.size()); - return parse_config(config, optid, opt, optarg, included_set); -} - -int parse_config(Config *config, int optid, const StringRef &opt, - const StringRef &optarg, std::set &included_set) { - char host[NI_MAXHOST]; - uint16_t port; - - switch (optid) { - case SHRPX_OPTID_BACKEND: { - auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';'); - - DownstreamAddrConfig addr{}; - if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) { - auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size(); - addr.host = ImmutableString(path, addr_end); - addr.host_unix = true; - } else { - if (split_host_port(host, sizeof(host), &port, - StringRef{std::begin(optarg), addr_end}, opt) == -1) { - return -1; - } - - addr.host = ImmutableString(host); - addr.port = port; - } - - auto mapping = addr_end == std::end(optarg) ? addr_end : addr_end + 1; - auto mapping_end = std::find(mapping, std::end(optarg), ';'); - - auto params = - mapping_end == std::end(optarg) ? mapping_end : mapping_end + 1; - - if (parse_mapping(config, addr, StringRef{mapping, mapping_end}, - StringRef{params, std::end(optarg)}) != 0) { - return -1; - } - - return 0; - } - case SHRPX_OPTID_FRONTEND: { - auto &listenerconf = config->conn.listener; - auto &apiconf = config->api; - - auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';'); - auto src_params = StringRef{addr_end, std::end(optarg)}; - - UpstreamParams params{}; - params.tls = true; - - if (parse_upstream_params(params, src_params) != 0) { - return -1; - } - - UpstreamAddr addr{}; - addr.fd = -1; - addr.tls = params.tls; - addr.alt_mode = params.alt_mode; - - if (addr.alt_mode == ALTMODE_API) { - apiconf.enabled = true; - } - - if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) { - auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size(); - addr.host = ImmutableString{path, addr_end}; - addr.host_unix = true; - - listenerconf.addrs.push_back(std::move(addr)); - - return 0; - } - - if (split_host_port(host, sizeof(host), &port, - StringRef{std::begin(optarg), addr_end}, opt) == -1) { - return -1; - } - - addr.host = ImmutableString(host); - addr.port = port; - - if (util::numeric_host(host, AF_INET)) { - addr.family = AF_INET; - listenerconf.addrs.push_back(std::move(addr)); - return 0; - } - - if (util::numeric_host(host, AF_INET6)) { - addr.family = AF_INET6; - listenerconf.addrs.push_back(std::move(addr)); - return 0; - } - - addr.family = AF_INET; - listenerconf.addrs.push_back(addr); - - addr.family = AF_INET6; - listenerconf.addrs.push_back(std::move(addr)); - - return 0; - } - case SHRPX_OPTID_WORKERS: -#ifdef NOTHREADS - LOG(WARN) << "Threading disabled at build time, no threads created."; - return 0; -#else // !NOTHREADS - return parse_uint(&config->num_worker, opt, optarg); -#endif // !NOTHREADS - case SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS: { - LOG(WARN) << opt << ": deprecated. Use " - << SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS << " and " - << SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS << " instead."; - size_t n; - if (parse_uint(&n, opt, optarg) != 0) { - return -1; - } - auto &http2conf = config->http2; - http2conf.upstream.max_concurrent_streams = n; - http2conf.downstream.max_concurrent_streams = n; - - return 0; - } - case SHRPX_OPTID_LOG_LEVEL: - if (Log::set_severity_level_by_name(optarg) == -1) { - LOG(ERROR) << opt << ": Invalid severity level: " << optarg; - return -1; - } - - return 0; - case SHRPX_OPTID_DAEMON: - config->daemon = util::strieq_l("yes", optarg); - - return 0; - case SHRPX_OPTID_HTTP2_PROXY: - config->http2_proxy = util::strieq_l("yes", optarg); - - return 0; - case SHRPX_OPTID_HTTP2_BRIDGE: - LOG(ERROR) << opt - << ": deprecated. Use backend=,;;proto=h2;tls"; - return -1; - case SHRPX_OPTID_CLIENT_PROXY: - LOG(ERROR) - << opt - << ": deprecated. Use http2-proxy, frontend=,;no-tls " - "and backend=,;;proto=h2;tls"; - return -1; - case SHRPX_OPTID_ADD_X_FORWARDED_FOR: - config->http.xff.add = util::strieq_l("yes", optarg); - - return 0; - case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR: - config->http.xff.strip_incoming = util::strieq_l("yes", optarg); - - return 0; - case SHRPX_OPTID_NO_VIA: - config->http.no_via = util::strieq_l("yes", optarg); - - return 0; - case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT: - return parse_duration(&config->conn.upstream.timeout.http2_read, opt, - optarg); - case SHRPX_OPTID_FRONTEND_READ_TIMEOUT: - return parse_duration(&config->conn.upstream.timeout.read, opt, optarg); - case SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT: - return parse_duration(&config->conn.upstream.timeout.write, opt, optarg); - case SHRPX_OPTID_BACKEND_READ_TIMEOUT: - return parse_duration(&config->conn.downstream->timeout.read, opt, optarg); - case SHRPX_OPTID_BACKEND_WRITE_TIMEOUT: - return parse_duration(&config->conn.downstream->timeout.write, opt, optarg); - case SHRPX_OPTID_STREAM_READ_TIMEOUT: - return parse_duration(&config->http2.timeout.stream_read, opt, optarg); - case SHRPX_OPTID_STREAM_WRITE_TIMEOUT: - return parse_duration(&config->http2.timeout.stream_write, opt, optarg); - case SHRPX_OPTID_ACCESSLOG_FILE: - config->logging.access.file = - ImmutableString{std::begin(optarg), std::end(optarg)}; - - return 0; - case SHRPX_OPTID_ACCESSLOG_SYSLOG: - config->logging.access.syslog = util::strieq_l("yes", optarg); - - return 0; - case SHRPX_OPTID_ACCESSLOG_FORMAT: - config->logging.access.format = parse_log_format(optarg); - - return 0; - case SHRPX_OPTID_ERRORLOG_FILE: - config->logging.error.file = - ImmutableString{std::begin(optarg), std::end(optarg)}; - - return 0; - case SHRPX_OPTID_ERRORLOG_SYSLOG: - config->logging.error.syslog = util::strieq_l("yes", optarg); - - return 0; - case SHRPX_OPTID_FASTOPEN: { - int n; - if (parse_int(&n, opt, optarg.c_str()) != 0) { - return -1; - } - - if (n < 0) { - LOG(ERROR) << opt << ": " << optarg << " is not allowed"; - return -1; - } - - config->conn.listener.fastopen = n; - - return 0; - } - case SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT: - return parse_duration(&config->conn.downstream->timeout.idle_read, opt, - optarg); - case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS: - case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS: { size_t *resp; - if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) { - resp = &config->http2.upstream.window_bits; + if (util::strieq(opt, SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS)) { + resp = &mod_config()->http2_upstream_connection_window_bits; } else { - resp = &config->http2.downstream.window_bits; + resp = &mod_config()->http2_downstream_connection_window_bits; } errno = 0; @@ -1927,9 +632,9 @@ return -1; } - if (n >= 31) { + if (n < 16 || n >= 31) { LOG(ERROR) << opt - << ": specify the integer in the range [0, 30], inclusive"; + << ": specify the integer in the range [16, 30], inclusive"; return -1; } @@ -1937,130 +642,99 @@ return 0; } - case SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS: - case SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS: { - size_t *resp; - if (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS) { - resp = &config->http2.upstream.connection_window_bits; - } else { - resp = &config->http2.downstream.connection_window_bits; - } + if (util::strieq(opt, SHRPX_OPT_FRONTEND_NO_TLS)) { + mod_config()->upstream_no_tls = util::strieq(optarg, "yes"); - errno = 0; + return 0; + } - int n; + if (util::strieq(opt, SHRPX_OPT_BACKEND_NO_TLS)) { + mod_config()->downstream_no_tls = util::strieq(optarg, "yes"); - if (parse_uint(&n, opt, optarg) != 0) { - return -1; - } - - if (n < 16 || n >= 31) { - LOG(ERROR) << opt - << ": specify the integer in the range [16, 30], inclusive"; - return -1; - } + return 0; + } - *resp = n; + if (util::strieq(opt, SHRPX_OPT_BACKEND_TLS_SNI_FIELD)) { + mod_config()->backend_tls_sni_name = strcopy(optarg); return 0; } - case SHRPX_OPTID_FRONTEND_NO_TLS: - LOG(WARN) << opt << ": deprecated. Use no-tls keyword in " - << SHRPX_OPT_FRONTEND; - return 0; - case SHRPX_OPTID_BACKEND_NO_TLS: - LOG(WARN) << opt << ": deprecated. backend connection is not encrypted by " - "default. See also " << SHRPX_OPT_BACKEND_TLS; - return 0; - case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD: - LOG(WARN) << opt << ": deprecated. Use sni keyword in --backend option. " - "For now, all sni values of all backends are " - "overridden by the given value " << optarg; - config->tls.backend_sni_name = optarg.str(); - return 0; - case SHRPX_OPTID_PID_FILE: - config->pid_file = ImmutableString{std::begin(optarg), std::end(optarg)}; + if (util::strieq(opt, SHRPX_OPT_PID_FILE)) { + mod_config()->pid_file = strcopy(optarg); return 0; - case SHRPX_OPTID_USER: { - auto pwd = getpwnam(optarg.c_str()); + } + + if (util::strieq(opt, SHRPX_OPT_USER)) { + auto pwd = getpwnam(optarg); if (!pwd) { LOG(ERROR) << opt << ": failed to get uid from " << optarg << ": " << strerror(errno); return -1; } - config->user = pwd->pw_name; - config->uid = pwd->pw_uid; - config->gid = pwd->pw_gid; + mod_config()->uid = pwd->pw_uid; + mod_config()->gid = pwd->pw_gid; return 0; } - case SHRPX_OPTID_PRIVATE_KEY_FILE: - config->tls.private_key_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; + + if (util::strieq(opt, SHRPX_OPT_PRIVATE_KEY_FILE)) { + mod_config()->private_key_file = strcopy(optarg); return 0; - case SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE: { - auto passwd = read_passwd_from_file(opt, optarg); + } + + if (util::strieq(opt, SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE)) { + auto passwd = read_passwd_from_file(optarg); if (passwd.empty()) { LOG(ERROR) << opt << ": Couldn't read key file's passwd from " << optarg; return -1; } - config->tls.private_key_passwd = passwd; + mod_config()->private_key_passwd = strcopy(passwd); return 0; } - case SHRPX_OPTID_CERTIFICATE_FILE: - config->tls.cert_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; - return 0; - case SHRPX_OPTID_DH_PARAM_FILE: - config->tls.dh_param_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; + if (util::strieq(opt, SHRPX_OPT_CERTIFICATE_FILE)) { + mod_config()->cert_file = strcopy(optarg); return 0; - case SHRPX_OPTID_SUBCERT: { - // Private Key file and certificate file separated by ':'. - auto sp = std::find(std::begin(optarg), std::end(optarg), ':'); - if (sp == std::end(optarg)) { - LOG(ERROR) << opt << ": missing ':' in " << optarg; - return -1; - } - - auto private_key_file = StringRef{std::begin(optarg), sp}; + } - if (private_key_file.empty()) { - LOG(ERROR) << opt << ": missing private key file: " << optarg; - return -1; - } + if (util::strieq(opt, SHRPX_OPT_DH_PARAM_FILE)) { + mod_config()->dh_param_file = strcopy(optarg); - auto cert_file = StringRef{sp + 1, std::end(optarg)}; + return 0; + } - if (cert_file.empty()) { - LOG(ERROR) << opt << ": missing certificate file: " << optarg; - return -1; + if (util::strieq(opt, SHRPX_OPT_SUBCERT)) { + // Private Key file and certificate file separated by ':'. + const char *sp = strchr(optarg, ':'); + if (sp) { + std::string keyfile(optarg, sp); + // TODO Do we need private key for subcert? + mod_config()->subcerts.emplace_back(keyfile, sp + 1); } - config->tls.subcerts.emplace_back(private_key_file.str(), cert_file.str()); - return 0; } - case SHRPX_OPTID_SYSLOG_FACILITY: { + + if (util::strieq(opt, SHRPX_OPT_SYSLOG_FACILITY)) { int facility = int_syslog_facility(optarg); if (facility == -1) { LOG(ERROR) << opt << ": Unknown syslog facility: " << optarg; return -1; } - config->logging.syslog_facility = facility; + mod_config()->syslog_facility = facility; return 0; } - case SHRPX_OPTID_BACKLOG: { + + if (util::strieq(opt, SHRPX_OPT_BACKLOG)) { int n; - if (parse_int(&n, opt, optarg.c_str()) != 0) { + if (parse_int(&n, opt, optarg) != 0) { return -1; } @@ -2070,65 +744,72 @@ return -1; } - config->conn.listener.backlog = n; + mod_config()->backlog = n; return 0; } - case SHRPX_OPTID_CIPHERS: - config->tls.ciphers = ImmutableString{std::begin(optarg), std::end(optarg)}; + + if (util::strieq(opt, SHRPX_OPT_CIPHERS)) { + mod_config()->ciphers = strcopy(optarg); return 0; - case SHRPX_OPTID_CLIENT: - LOG(ERROR) << opt << ": deprecated. Use frontend=,;no-tls, " - "backend=,;;proto=h2;tls"; - return -1; - case SHRPX_OPTID_INSECURE: - config->tls.insecure = util::strieq_l("yes", optarg); + } + + if (util::strieq(opt, SHRPX_OPT_CLIENT)) { + mod_config()->client = util::strieq(optarg, "yes"); + + return 0; + } + + if (util::strieq(opt, SHRPX_OPT_INSECURE)) { + mod_config()->insecure = util::strieq(optarg, "yes"); return 0; - case SHRPX_OPTID_CACERT: - config->tls.cacert = ImmutableString{std::begin(optarg), std::end(optarg)}; + } + + if (util::strieq(opt, SHRPX_OPT_CACERT)) { + mod_config()->cacert = strcopy(optarg); return 0; - case SHRPX_OPTID_BACKEND_IPV4: - LOG(WARN) << opt - << ": deprecated. Use backend-address-family=IPv4 instead."; + } - config->conn.downstream->family = AF_INET; + if (util::strieq(opt, SHRPX_OPT_BACKEND_IPV4)) { + mod_config()->backend_ipv4 = util::strieq(optarg, "yes"); return 0; - case SHRPX_OPTID_BACKEND_IPV6: - LOG(WARN) << opt - << ": deprecated. Use backend-address-family=IPv6 instead."; + } - config->conn.downstream->family = AF_INET6; + if (util::strieq(opt, SHRPX_OPT_BACKEND_IPV6)) { + mod_config()->backend_ipv6 = util::strieq(optarg, "yes"); return 0; - case SHRPX_OPTID_BACKEND_HTTP_PROXY_URI: { - auto &proxy = config->downstream_http_proxy; - // Reset here so that multiple option occurrence does not merge - // the results. - proxy = {}; + } + + if (util::strieq(opt, SHRPX_OPT_BACKEND_HTTP_PROXY_URI)) { // parse URI and get hostname, port and optionally userinfo. - http_parser_url u{}; - int rv = http_parser_parse_url(optarg.c_str(), optarg.size(), 0, &u); + http_parser_url u; + memset(&u, 0, sizeof(u)); + int rv = http_parser_parse_url(optarg, strlen(optarg), 0, &u); if (rv == 0) { + std::string val; if (u.field_set & UF_USERINFO) { - auto uf = util::get_uri_field(optarg.c_str(), u, UF_USERINFO); + http2::copy_url_component(val, &u, UF_USERINFO, optarg); // Surprisingly, u.field_set & UF_USERINFO is nonzero even if // userinfo component is empty string. - if (!uf.empty()) { - proxy.userinfo = util::percent_decode(std::begin(uf), std::end(uf)); + if (!val.empty()) { + val = util::percentDecode(val.begin(), val.end()); + mod_config()->downstream_http_proxy_userinfo = strcopy(val); } } if (u.field_set & UF_HOST) { - http2::copy_url_component(proxy.host, &u, UF_HOST, optarg.c_str()); + http2::copy_url_component(val, &u, UF_HOST, optarg); + mod_config()->downstream_http_proxy_host = strcopy(val); } else { LOG(ERROR) << opt << ": no hostname specified"; return -1; } if (u.field_set & UF_PORT) { - proxy.port = u.port; + mod_config()->downstream_http_proxy_port = u.port; } else { LOG(ERROR) << opt << ": no port specified"; return -1; @@ -2140,504 +821,214 @@ return 0; } - case SHRPX_OPTID_READ_RATE: - return parse_uint_with_unit(&config->conn.upstream.ratelimit.read.rate, opt, - optarg); - case SHRPX_OPTID_READ_BURST: - return parse_uint_with_unit(&config->conn.upstream.ratelimit.read.burst, - opt, optarg); - case SHRPX_OPTID_WRITE_RATE: - return parse_uint_with_unit(&config->conn.upstream.ratelimit.write.rate, - opt, optarg); - case SHRPX_OPTID_WRITE_BURST: - return parse_uint_with_unit(&config->conn.upstream.ratelimit.write.burst, - opt, optarg); - case SHRPX_OPTID_WORKER_READ_RATE: - LOG(WARN) << opt << ": not implemented yet"; - return 0; - case SHRPX_OPTID_WORKER_READ_BURST: - LOG(WARN) << opt << ": not implemented yet"; - return 0; - case SHRPX_OPTID_WORKER_WRITE_RATE: - LOG(WARN) << opt << ": not implemented yet"; - return 0; - case SHRPX_OPTID_WORKER_WRITE_BURST: - LOG(WARN) << opt << ": not implemented yet"; - return 0; - case SHRPX_OPTID_NPN_LIST: - config->tls.npn_list = util::parse_config_str_list(optarg); - - return 0; - case SHRPX_OPTID_TLS_PROTO_LIST: - config->tls.tls_proto_list = util::parse_config_str_list(optarg); - - return 0; - case SHRPX_OPTID_VERIFY_CLIENT: - config->tls.client_verify.enabled = util::strieq_l("yes", optarg); - - return 0; - case SHRPX_OPTID_VERIFY_CLIENT_CACERT: - config->tls.client_verify.cacert = - ImmutableString{std::begin(optarg), std::end(optarg)}; - return 0; - case SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE: - config->tls.client.private_key_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; + if (util::strieq(opt, SHRPX_OPT_READ_RATE)) { + return parse_uint(&mod_config()->read_rate, opt, optarg); + } - return 0; - case SHRPX_OPTID_CLIENT_CERT_FILE: - config->tls.client.cert_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; + if (util::strieq(opt, SHRPX_OPT_READ_BURST)) { + int n; - return 0; - case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER: - config->http2.upstream.debug.dump.request_header_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; + if (parse_uint(&n, opt, optarg) != 0) { + return -1; + } - return 0; - case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER: - config->http2.upstream.debug.dump.response_header_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; + if (n == 0) { + LOG(ERROR) << opt << ": specify integer strictly larger than 0"; - return 0; - case SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING: - config->http2.no_cookie_crumbling = util::strieq_l("yes", optarg); + return -1; + } - return 0; - case SHRPX_OPTID_FRONTEND_FRAME_DEBUG: - config->http2.upstream.debug.frame_debug = util::strieq_l("yes", optarg); + mod_config()->read_burst = n; return 0; - case SHRPX_OPTID_PADDING: - return parse_uint(&config->padding, opt, optarg); - case SHRPX_OPTID_ALTSVC: { - auto tokens = util::split_str(optarg, ','); + } - if (tokens.size() < 2) { - // Requires at least protocol_id and port - LOG(ERROR) << opt << ": too few parameters: " << optarg; - return -1; - } + if (util::strieq(opt, SHRPX_OPT_WRITE_RATE)) { + return parse_uint(&mod_config()->write_rate, opt, optarg); + } - if (tokens.size() > 4) { - // We only need protocol_id, port, host and origin - LOG(ERROR) << opt << ": too many parameters: " << optarg; - return -1; - } + if (util::strieq(opt, SHRPX_OPT_WRITE_BURST)) { + return parse_uint(&mod_config()->write_burst, opt, optarg); + } - int port; + if (util::strieq(opt, SHRPX_OPT_WORKER_READ_RATE)) { + return parse_uint(&mod_config()->worker_read_rate, opt, optarg); + } - if (parse_uint(&port, opt, tokens[1]) != 0) { - return -1; - } + if (util::strieq(opt, SHRPX_OPT_WORKER_READ_BURST)) { + return parse_uint(&mod_config()->worker_read_burst, opt, optarg); + } - if (port < 1 || - port > static_cast(std::numeric_limits::max())) { - LOG(ERROR) << opt << ": port is invalid: " << tokens[1]; - return -1; - } + if (util::strieq(opt, SHRPX_OPT_WORKER_WRITE_RATE)) { + return parse_uint(&mod_config()->worker_write_rate, opt, optarg); + } - AltSvc altsvc{}; + if (util::strieq(opt, SHRPX_OPT_WORKER_WRITE_BURST)) { + return parse_uint(&mod_config()->worker_write_burst, opt, optarg); + } - altsvc.protocol_id = tokens[0].str(); + if (util::strieq(opt, SHRPX_OPT_NPN_LIST)) { + clear_config_str_list(mod_config()->npn_list); - altsvc.port = port; - altsvc.service = tokens[1].str(); + mod_config()->npn_list = parse_config_str_list(optarg); - if (tokens.size() > 2) { - altsvc.host = tokens[2].str(); + return 0; + } - if (tokens.size() > 3) { - altsvc.origin = tokens[3].str(); - } - } + if (util::strieq(opt, SHRPX_OPT_TLS_PROTO_LIST)) { + clear_config_str_list(mod_config()->tls_proto_list); - config->http.altsvcs.push_back(std::move(altsvc)); + mod_config()->tls_proto_list = parse_config_str_list(optarg); return 0; } - case SHRPX_OPTID_ADD_REQUEST_HEADER: - case SHRPX_OPTID_ADD_RESPONSE_HEADER: { - auto p = parse_header(optarg); - if (p.name.empty()) { - LOG(ERROR) << opt << ": invalid header field: " << optarg; - return -1; - } - if (optid == SHRPX_OPTID_ADD_REQUEST_HEADER) { - config->http.add_request_headers.push_back(std::move(p)); - } else { - config->http.add_response_headers.push_back(std::move(p)); - } + + if (util::strieq(opt, SHRPX_OPT_VERIFY_CLIENT)) { + mod_config()->verify_client = util::strieq(optarg, "yes"); + return 0; } - case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS: - return parse_uint(&config->conn.upstream.worker_connections, opt, optarg); - case SHRPX_OPTID_NO_LOCATION_REWRITE: - config->http.no_location_rewrite = util::strieq_l("yes", optarg); - return 0; - case SHRPX_OPTID_NO_HOST_REWRITE: - LOG(WARN) << SHRPX_OPT_NO_HOST_REWRITE - << ": deprecated. :authority and host header fields are NOT " - "altered by default. To rewrite these headers, use " - "--host-rewrite option."; + if (util::strieq(opt, SHRPX_OPT_VERIFY_CLIENT_CACERT)) { + mod_config()->verify_client_cacert = strcopy(optarg); return 0; - case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_HOST: - LOG(WARN) << opt - << ": deprecated. Use backend-connections-per-host instead."; - // fall through - case SHRPX_OPTID_BACKEND_CONNECTIONS_PER_HOST: { - int n; - - if (parse_uint(&n, opt, optarg) != 0) { - return -1; - } + } - if (n == 0) { - LOG(ERROR) << opt << ": specify an integer strictly more than 0"; + if (util::strieq(opt, SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE)) { + mod_config()->client_private_key_file = strcopy(optarg); - return -1; - } + return 0; + } - config->conn.downstream->connections_per_host = n; + if (util::strieq(opt, SHRPX_OPT_CLIENT_CERT_FILE)) { + mod_config()->client_cert_file = strcopy(optarg); return 0; } - case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND: - LOG(WARN) << opt << ": deprecated. Use " - << SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND << " instead."; - // fall through - case SHRPX_OPTID_BACKEND_CONNECTIONS_PER_FRONTEND: - return parse_uint(&config->conn.downstream->connections_per_frontend, opt, - optarg); - case SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT: - return parse_duration(&config->conn.listener.timeout.sleep, opt, optarg); - case SHRPX_OPTID_TLS_TICKET_KEY_FILE: - config->tls.ticket.files.push_back(optarg.str()); - return 0; - case SHRPX_OPTID_RLIMIT_NOFILE: { - int n; - - if (parse_uint(&n, opt, optarg) != 0) { - return -1; - } - if (n < 0) { - LOG(ERROR) << opt << ": specify the integer more than or equal to 0"; + if (util::strieq(opt, SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER)) { + mod_config()->http2_upstream_dump_request_header_file = strcopy(optarg); - return -1; - } + return 0; + } - config->rlimit_nofile = n; + if (util::strieq(opt, SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER)) { + mod_config()->http2_upstream_dump_response_header_file = strcopy(optarg); return 0; } - case SHRPX_OPTID_BACKEND_REQUEST_BUFFER: - case SHRPX_OPTID_BACKEND_RESPONSE_BUFFER: { - size_t n; - if (parse_uint_with_unit(&n, opt, optarg) != 0) { - return -1; - } - if (n == 0) { - LOG(ERROR) << opt << ": specify an integer strictly more than 0"; + if (util::strieq(opt, SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING)) { + mod_config()->http2_no_cookie_crumbling = util::strieq(optarg, "yes"); - return -1; - } + return 0; + } - if (optid == SHRPX_OPTID_BACKEND_REQUEST_BUFFER) { - config->conn.downstream->request_buffer_size = n; - } else { - config->conn.downstream->response_buffer_size = n; - } + if (util::strieq(opt, SHRPX_OPT_FRONTEND_FRAME_DEBUG)) { + mod_config()->upstream_frame_debug = util::strieq(optarg, "yes"); return 0; } - case SHRPX_OPTID_NO_SERVER_PUSH: - config->http2.no_server_push = util::strieq_l("yes", optarg); + if (util::strieq(opt, SHRPX_OPT_PADDING)) { + return parse_uint(&mod_config()->padding, opt, optarg); + } - return 0; - case SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER: - LOG(WARN) << opt << ": deprecated."; - return 0; - case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE: - config->tls.ocsp.fetch_ocsp_response_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; + if (util::strieq(opt, SHRPX_OPT_ALTSVC)) { + auto tokens = parse_config_str_list(optarg); - return 0; - case SHRPX_OPTID_OCSP_UPDATE_INTERVAL: - return parse_duration(&config->tls.ocsp.update_interval, opt, optarg); - case SHRPX_OPTID_NO_OCSP: - config->tls.ocsp.disabled = util::strieq_l("yes", optarg); + if (tokens.size() < 2) { + // Requires at least protocol_id and port + LOG(ERROR) << opt << ": too few parameters: " << optarg; + return -1; + } - return 0; - case SHRPX_OPTID_HEADER_FIELD_BUFFER: - LOG(WARN) << opt - << ": deprecated. Use request-header-field-buffer instead."; - // fall through - case SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER: - return parse_uint_with_unit(&config->http.request_header_field_buffer, opt, - optarg); - case SHRPX_OPTID_MAX_HEADER_FIELDS: - LOG(WARN) << opt << ": deprecated. Use max-request-header-fields instead."; - // fall through - case SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS: - return parse_uint(&config->http.max_request_header_fields, opt, optarg); - case SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER: - return parse_uint_with_unit(&config->http.response_header_field_buffer, opt, - optarg); - case SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS: - return parse_uint(&config->http.max_response_header_fields, opt, optarg); - case SHRPX_OPTID_INCLUDE: { - if (included_set.count(optarg)) { - LOG(ERROR) << opt << ": " << optarg << " has already been included"; + if (tokens.size() > 4) { + // We only need protocol_id, port, host and origin + LOG(ERROR) << opt << ": too many parameters: " << optarg; return -1; } - included_set.insert(optarg); - auto rv = load_config(optarg.c_str(), included_set); - included_set.erase(optarg); + int port; - if (rv != 0) { + if (parse_uint(&port, opt, tokens[1]) != 0) { return -1; } - return 0; - } - case SHRPX_OPTID_TLS_TICKET_KEY_CIPHER: - if (util::strieq_l("aes-128-cbc", optarg)) { - config->tls.ticket.cipher = EVP_aes_128_cbc(); - } else if (util::strieq_l("aes-256-cbc", optarg)) { - config->tls.ticket.cipher = EVP_aes_256_cbc(); - } else { - LOG(ERROR) << opt - << ": unsupported cipher for ticket encryption: " << optarg; + if (port < 1 || + port > static_cast(std::numeric_limits::max())) { + LOG(ERROR) << opt << ": port is invalid: " << tokens[1]; return -1; } - config->tls.ticket.cipher_given = true; - return 0; - case SHRPX_OPTID_HOST_REWRITE: - config->http.no_host_rewrite = !util::strieq_l("yes", optarg); + AltSvc altsvc; - return 0; - case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: - case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: { - auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';'); - auto src_params = StringRef{addr_end, std::end(optarg)}; + altsvc.port = port; - MemcachedConnectionParams params{}; - if (parse_memcached_connection_params(params, src_params, StringRef{opt}) != - 0) { - return -1; - } + altsvc.protocol_id = tokens[0]; + altsvc.protocol_id_len = strlen(altsvc.protocol_id); - if (split_host_port(host, sizeof(host), &port, - StringRef{std::begin(optarg), addr_end}, opt) == -1) { - return -1; - } + if (tokens.size() > 2) { + altsvc.host = tokens[2]; + altsvc.host_len = strlen(altsvc.host); - switch (optid) { - case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: { - auto &memcachedconf = config->tls.session_cache.memcached; - memcachedconf.host = host; - memcachedconf.port = port; - memcachedconf.tls = params.tls; - break; - } - case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: { - auto &memcachedconf = config->tls.ticket.memcached; - memcachedconf.host = host; - memcachedconf.port = port; - memcachedconf.tls = params.tls; - break; + if (tokens.size() > 3) { + altsvc.origin = tokens[3]; + altsvc.origin_len = strlen(altsvc.origin); + } } - }; + + mod_config()->altsvcs.push_back(std::move(altsvc)); return 0; } - case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL: - return parse_duration(&config->tls.ticket.memcached.interval, opt, optarg); - case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY: { - int n; - if (parse_uint(&n, opt, optarg) != 0) { - return -1; - } - if (n > 30) { - LOG(ERROR) << opt << ": must be smaller than or equal to 30"; + if (util::strieq(opt, SHRPX_OPT_ADD_RESPONSE_HEADER)) { + auto p = parse_header(optarg); + if (p.first.empty()) { + LOG(ERROR) << opt << ": header field name is empty: " << optarg; return -1; } + mod_config()->add_response_headers.push_back(std::move(p)); - config->tls.ticket.memcached.max_retry = n; return 0; } - case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL: - return parse_uint(&config->tls.ticket.memcached.max_fail, opt, optarg); - case SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD: { - size_t n; - if (parse_uint_with_unit(&n, opt, optarg) != 0) { - return -1; - } - - config->tls.dyn_rec.warmup_threshold = n; - return 0; + if (util::strieq(opt, SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS)) { + return parse_uint(&mod_config()->worker_frontend_connections, opt, optarg); } - case SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT: - return parse_duration(&config->tls.dyn_rec.idle_timeout, opt, optarg); - - case SHRPX_OPTID_MRUBY_FILE: -#ifdef HAVE_MRUBY - config->mruby_file = ImmutableString{std::begin(optarg), std::end(optarg)}; -#else // !HAVE_MRUBY - LOG(WARN) << opt - << ": ignored because mruby support is disabled at build time."; -#endif // !HAVE_MRUBY - return 0; - case SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL: - config->conn.upstream.accept_proxy_protocol = util::strieq_l("yes", optarg); + if (util::strieq(opt, SHRPX_OPT_NO_LOCATION_REWRITE)) { + mod_config()->no_location_rewrite = util::strieq(optarg, "yes"); return 0; - case SHRPX_OPTID_ADD_FORWARDED: { - auto &fwdconf = config->http.forwarded; - fwdconf.params = FORWARDED_NONE; - for (const auto ¶m : util::split_str(optarg, ',')) { - if (util::strieq_l("by", param)) { - fwdconf.params |= FORWARDED_BY; - continue; - } - if (util::strieq_l("for", param)) { - fwdconf.params |= FORWARDED_FOR; - continue; - } - if (util::strieq_l("host", param)) { - fwdconf.params |= FORWARDED_HOST; - continue; - } - if (util::strieq_l("proto", param)) { - fwdconf.params |= FORWARDED_PROTO; - continue; - } + } - LOG(ERROR) << opt << ": unknown parameter " << optarg; + if (util::strieq(opt, SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND)) { + int n; + if (parse_uint(&n, opt, optarg) != 0) { return -1; } - return 0; - } - case SHRPX_OPTID_STRIP_INCOMING_FORWARDED: - config->http.forwarded.strip_incoming = util::strieq_l("yes", optarg); - - return 0; - case SHRPX_OPTID_FORWARDED_BY: - case SHRPX_OPTID_FORWARDED_FOR: { - auto type = parse_forwarded_node_type(optarg); + if (n < 1) { + LOG(ERROR) << opt << ": specify the integer more than or equal to 1"; - if (type == -1 || - (optid == SHRPX_OPTID_FORWARDED_FOR && optarg[0] == '_')) { - LOG(ERROR) << opt << ": unknown node type or illegal obfuscated string " - << optarg; return -1; } - auto &fwdconf = config->http.forwarded; - - switch (optid) { - case SHRPX_OPTID_FORWARDED_BY: - fwdconf.by_node_type = static_cast(type); - if (optarg[0] == '_') { - fwdconf.by_obfuscated = optarg.str(); - } else { - fwdconf.by_obfuscated = ""; - } - break; - case SHRPX_OPTID_FORWARDED_FOR: - fwdconf.for_node_type = static_cast(type); - break; - } + mod_config()->max_downstream_connections = n; return 0; } - case SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST: - config->tls.no_http2_cipher_black_list = util::strieq_l("yes", optarg); - return 0; - case SHRPX_OPTID_BACKEND_HTTP1_TLS: - case SHRPX_OPTID_BACKEND_TLS: - LOG(WARN) << opt << ": deprecated. Use tls keyword in " - << SHRPX_OPT_BACKEND << " instead."; - return 0; - case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS: - LOG(WARN) << opt << ": deprecated. Use tls keyword in " - << SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED; - return 0; - case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE: - config->tls.session_cache.memcached.cert_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; - - return 0; - case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE: - config->tls.session_cache.memcached.private_key_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; - - return 0; - case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS: - LOG(WARN) << opt << ": deprecated. Use tls keyword in " - << SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED; - return 0; - case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE: - config->tls.ticket.memcached.cert_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; - - return 0; - case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE: - config->tls.ticket.memcached.private_key_file = - ImmutableString{std::begin(optarg), std::end(optarg)}; - - return 0; - case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY: - return parse_address_family(&config->tls.ticket.memcached.family, opt, - optarg); - case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY: - return parse_address_family(&config->tls.session_cache.memcached.family, - opt, optarg); - case SHRPX_OPTID_BACKEND_ADDRESS_FAMILY: - return parse_address_family(&config->conn.downstream->family, opt, optarg); - case SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS: - return parse_uint(&config->http2.upstream.max_concurrent_streams, opt, - optarg); - case SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS: - return parse_uint(&config->http2.downstream.max_concurrent_streams, opt, - optarg); - case SHRPX_OPTID_ERROR_PAGE: - return parse_error_page(config->http.error_pages, opt, optarg); - case SHRPX_OPTID_NO_KQUEUE: - if ((ev_supported_backends() & EVBACKEND_KQUEUE) == 0) { - LOG(WARN) << opt << ": kqueue is not supported on this platform"; - return 0; - } - - config->ev_loop_flags = ev_recommended_backends() & ~EVBACKEND_KQUEUE; - - return 0; - case SHRPX_OPTID_FRONTEND_HTTP2_SETTINGS_TIMEOUT: - return parse_duration(&config->http2.upstream.timeout.settings, opt, - optarg); - case SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT: - return parse_duration(&config->http2.downstream.timeout.settings, opt, - optarg); - case SHRPX_OPTID_API_MAX_REQUEST_BODY: - return parse_uint_with_unit(&config->api.max_request_body, opt, optarg); - case SHRPX_OPTID_BACKEND_MAX_BACKOFF: - return parse_duration(&config->conn.downstream->timeout.max_backoff, opt, - optarg); - case SHRPX_OPTID_CONF: + if (util::strieq(opt, SHRPX_OPT_LISTENER_DISABLE_TIMEOUT)) { + return parse_timeval(&mod_config()->listener_disable_timeout, opt, optarg); + } + + if (util::strieq(opt, "conf")) { LOG(WARN) << "conf: ignored"; return 0; @@ -2648,7 +1039,7 @@ return -1; } -int load_config(const char *filename, std::set &include_set) { +int load_config(const char *filename) { std::ifstream in(filename, std::ios::binary); if (!in) { LOG(ERROR) << "Could not open config file " << filename; @@ -2661,410 +1052,150 @@ if (line.empty() || line[0] == '#') { continue; } - auto eq = std::find(std::begin(line), std::end(line), '='); - if (eq == std::end(line)) { - LOG(ERROR) << "Bad configuration format in " << filename << " at line " - << linenum; + size_t i; + size_t size = line.size(); + for (i = 0; i < size && line[i] != '='; ++i) + ; + if (i == size) { + LOG(ERROR) << "Bad configuration format at line " << linenum; return -1; } - *eq = '\0'; - - if (parse_config(mod_config(), StringRef{std::begin(line), eq}, - StringRef{eq + 1, std::end(line)}, include_set) != 0) { + line[i] = '\0'; + auto s = line.c_str(); + if (parse_config(s, s + i + 1) == -1) { return -1; } } return 0; } -StringRef str_syslog_facility(int facility) { +const char *str_syslog_facility(int facility) { switch (facility) { case (LOG_AUTH): - return StringRef::from_lit("auth"); -#ifdef LOG_AUTHPRIV + return "auth"; case (LOG_AUTHPRIV): - return StringRef::from_lit("authpriv"); -#endif // LOG_AUTHPRIV + return "authpriv"; case (LOG_CRON): - return StringRef::from_lit("cron"); + return "cron"; case (LOG_DAEMON): - return StringRef::from_lit("daemon"); -#ifdef LOG_FTP + return "daemon"; case (LOG_FTP): - return StringRef::from_lit("ftp"); -#endif // LOG_FTP + return "ftp"; case (LOG_KERN): - return StringRef::from_lit("kern"); + return "kern"; case (LOG_LOCAL0): - return StringRef::from_lit("local0"); + return "local0"; case (LOG_LOCAL1): - return StringRef::from_lit("local1"); + return "local1"; case (LOG_LOCAL2): - return StringRef::from_lit("local2"); + return "local2"; case (LOG_LOCAL3): - return StringRef::from_lit("local3"); + return "local3"; case (LOG_LOCAL4): - return StringRef::from_lit("local4"); + return "local4"; case (LOG_LOCAL5): - return StringRef::from_lit("local5"); + return "local5"; case (LOG_LOCAL6): - return StringRef::from_lit("local6"); + return "local6"; case (LOG_LOCAL7): - return StringRef::from_lit("local7"); + return "local7"; case (LOG_LPR): - return StringRef::from_lit("lpr"); + return "lpr"; case (LOG_MAIL): - return StringRef::from_lit("mail"); + return "mail"; case (LOG_SYSLOG): - return StringRef::from_lit("syslog"); + return "syslog"; case (LOG_USER): - return StringRef::from_lit("user"); + return "user"; case (LOG_UUCP): - return StringRef::from_lit("uucp"); + return "uucp"; default: - return StringRef::from_lit("(unknown)"); + return "(unknown)"; } } -int int_syslog_facility(const StringRef &strfacility) { - if (util::strieq_l("auth", strfacility)) { +int int_syslog_facility(const char *strfacility) { + if (util::strieq(strfacility, "auth")) { return LOG_AUTH; } -#ifdef LOG_AUTHPRIV - if (util::strieq_l("authpriv", strfacility)) { + if (util::strieq(strfacility, "authpriv")) { return LOG_AUTHPRIV; } -#endif // LOG_AUTHPRIV - if (util::strieq_l("cron", strfacility)) { + if (util::strieq(strfacility, "cron")) { return LOG_CRON; } - if (util::strieq_l("daemon", strfacility)) { + if (util::strieq(strfacility, "daemon")) { return LOG_DAEMON; } -#ifdef LOG_FTP - if (util::strieq_l("ftp", strfacility)) { + if (util::strieq(strfacility, "ftp")) { return LOG_FTP; } -#endif // LOG_FTP - if (util::strieq_l("kern", strfacility)) { + if (util::strieq(strfacility, "kern")) { return LOG_KERN; } - if (util::strieq_l("local0", strfacility)) { + if (util::strieq(strfacility, "local0")) { return LOG_LOCAL0; } - if (util::strieq_l("local1", strfacility)) { + if (util::strieq(strfacility, "local1")) { return LOG_LOCAL1; } - if (util::strieq_l("local2", strfacility)) { + if (util::strieq(strfacility, "local2")) { return LOG_LOCAL2; } - if (util::strieq_l("local3", strfacility)) { + if (util::strieq(strfacility, "local3")) { return LOG_LOCAL3; } - if (util::strieq_l("local4", strfacility)) { + if (util::strieq(strfacility, "local4")) { return LOG_LOCAL4; } - if (util::strieq_l("local5", strfacility)) { + if (util::strieq(strfacility, "local5")) { return LOG_LOCAL5; } - if (util::strieq_l("local6", strfacility)) { + if (util::strieq(strfacility, "local6")) { return LOG_LOCAL6; } - if (util::strieq_l("local7", strfacility)) { + if (util::strieq(strfacility, "local7")) { return LOG_LOCAL7; } - if (util::strieq_l("lpr", strfacility)) { + if (util::strieq(strfacility, "lpr")) { return LOG_LPR; } - if (util::strieq_l("mail", strfacility)) { + if (util::strieq(strfacility, "mail")) { return LOG_MAIL; } - if (util::strieq_l("news", strfacility)) { + if (util::strieq(strfacility, "news")) { return LOG_NEWS; } - if (util::strieq_l("syslog", strfacility)) { + if (util::strieq(strfacility, "syslog")) { return LOG_SYSLOG; } - if (util::strieq_l("user", strfacility)) { + if (util::strieq(strfacility, "user")) { return LOG_USER; } - if (util::strieq_l("uucp", strfacility)) { + if (util::strieq(strfacility, "uucp")) { return LOG_UUCP; } return -1; } -StringRef strproto(shrpx_proto proto) { - switch (proto) { - case PROTO_NONE: - return StringRef::from_lit("none"); - case PROTO_HTTP1: - return StringRef::from_lit("http/1.1"); - case PROTO_HTTP2: - return StringRef::from_lit("h2"); - case PROTO_MEMCACHED: - return StringRef::from_lit("memcached"); - } - - // gcc needs this. - assert(0); -} - -namespace { -// Consistent hashing method described in -// https://github.com/RJ/ketama. Generate 160 32-bit hashes per |s|, -// which is usually backend address. The each hash is associated to -// index of backend address. When all hashes for every backend -// address are calculated, sort it in ascending order of hash. To -// choose the index, compute 32-bit hash based on client IP address, -// and do lower bound search in the array. The returned index is the -// backend to use. -int compute_affinity_hash(std::vector &res, size_t idx, - const StringRef &s) { - int rv; - std::array buf; - - for (auto i = 0; i < 20; ++i) { - auto t = s.str(); - t += i; - - rv = util::sha256(buf.data(), StringRef{t}); - if (rv != 0) { - return -1; - } - - for (int i = 0; i < 8; ++i) { - auto h = (static_cast(buf[4 * i]) << 24) | - (static_cast(buf[4 * i + 1]) << 16) | - (static_cast(buf[4 * i + 2]) << 8) | - static_cast(buf[4 * i + 3]); - - res.emplace_back(idx, h); - } - } - - return 0; -} -} // namespace - -// Configures the following member in |config|: -// conn.downstream_router, conn.downstream.addr_groups, -// conn.downstream.addr_group_catch_all. -int configure_downstream_group(Config *config, bool http2_proxy, - bool numeric_addr_only, - const TLSConfig &tlsconf) { - int rv; - - auto &downstreamconf = *config->conn.downstream; - auto &addr_groups = downstreamconf.addr_groups; - auto &routerconf = downstreamconf.router; - auto &router = routerconf.router; - - if (addr_groups.empty()) { - DownstreamAddrConfig addr{}; - addr.host = ImmutableString::from_lit(DEFAULT_DOWNSTREAM_HOST); - addr.port = DEFAULT_DOWNSTREAM_PORT; - addr.proto = PROTO_HTTP1; - - DownstreamAddrGroupConfig g(StringRef::from_lit("/")); - g.addrs.push_back(std::move(addr)); - router.add_route(StringRef{g.pattern}, addr_groups.size()); - addr_groups.push_back(std::move(g)); - } else if (http2_proxy) { - // We don't support host mapping in these cases. Move all - // non-catch-all patterns to catch-all pattern. - DownstreamAddrGroupConfig catch_all(StringRef::from_lit("/")); - for (auto &g : addr_groups) { - std::move(std::begin(g.addrs), std::end(g.addrs), - std::back_inserter(catch_all.addrs)); - } - std::vector().swap(addr_groups); - // maybe not necessary? - routerconf = RouterConfig{}; - router.add_route(StringRef{catch_all.pattern}, addr_groups.size()); - addr_groups.push_back(std::move(catch_all)); - } - - // backward compatibility: override all SNI fields with the option - // value --backend-tls-sni-field - if (!tlsconf.backend_sni_name.empty()) { - auto &sni = tlsconf.backend_sni_name; - for (auto &addr_group : addr_groups) { - for (auto &addr : addr_group.addrs) { - addr.sni = sni; - } - } - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Resolving backend address"; - } - - ssize_t catch_all_group = -1; - for (size_t i = 0; i < addr_groups.size(); ++i) { - auto &g = addr_groups[i]; - if (g.pattern == StringRef::from_lit("/")) { - catch_all_group = i; - } - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Host-path pattern: group " << i << ": '" << g.pattern - << "'"; - for (auto &addr : g.addrs) { - LOG(INFO) << "group " << i << " -> " << addr.host.c_str() - << (addr.host_unix ? "" : ":" + util::utos(addr.port)) - << ", proto=" << strproto(addr.proto) - << (addr.tls ? ", tls" : ""); - } - } - } - - if (catch_all_group == -1) { - LOG(FATAL) << "backend: No catch-all backend address is configured"; - return -1; - } - - downstreamconf.addr_group_catch_all = catch_all_group; - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Catch-all pattern is group " << catch_all_group; - } - - auto resolve_flags = numeric_addr_only ? AI_NUMERICHOST | AI_NUMERICSERV : 0; - - for (auto &g : addr_groups) { - for (auto &addr : g.addrs) { - - if (addr.host_unix) { - // for AF_UNIX socket, we use "localhost" as host for backend - // hostport. This is used as Host header field to backend and - // not going to be passed to any syscalls. - addr.hostport = "localhost"; - - auto path = addr.host.c_str(); - auto pathlen = addr.host.size(); - - if (pathlen + 1 > sizeof(addr.addr.su.un.sun_path)) { - LOG(FATAL) << "UNIX domain socket path " << path << " is too long > " - << sizeof(addr.addr.su.un.sun_path); - return -1; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Use UNIX domain socket path " << path - << " for backend connection"; - } - - addr.addr.su.un.sun_family = AF_UNIX; - // copy path including terminal NULL - std::copy_n(path, pathlen + 1, addr.addr.su.un.sun_path); - addr.addr.len = sizeof(addr.addr.su.un); - - continue; - } - - addr.hostport = ImmutableString( - util::make_http_hostport(StringRef(addr.host), addr.port)); - - auto hostport = util::make_hostport(StringRef{addr.host}, addr.port); - - if (resolve_hostname(&addr.addr, addr.host.c_str(), addr.port, - downstreamconf.family, resolve_flags) == -1) { - LOG(FATAL) << "Resolving backend address failed: " << hostport; - return -1; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Resolved backend address: " << hostport << " -> " - << util::to_numeric_addr(&addr.addr); - } - } - - if (g.affinity == AFFINITY_IP) { - size_t idx = 0; - for (auto &addr : g.addrs) { - auto p = reinterpret_cast(&addr.addr.su); - rv = compute_affinity_hash(g.affinity_hash, idx, - StringRef{p, addr.addr.len}); - if (rv != 0) { - return -1; - } - - ++idx; - } - - std::sort(std::begin(g.affinity_hash), std::end(g.affinity_hash), - [](const AffinityHash &lhs, const AffinityHash &rhs) { - return lhs.hash < rhs.hash; - }); - } - } - - return 0; -} - -int resolve_hostname(Address *addr, const char *hostname, uint16_t port, - int family, int additional_flags) { - int rv; - - auto service = util::utos(port); - - addrinfo hints{}; - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags |= additional_flags; -#ifdef AI_ADDRCONFIG - hints.ai_flags |= AI_ADDRCONFIG; -#endif // AI_ADDRCONFIG - addrinfo *res; - - rv = getaddrinfo(hostname, service.c_str(), &hints, &res); - if (rv != 0) { - LOG(FATAL) << "Unable to resolve address for " << hostname << ": " - << gai_strerror(rv); - return -1; - } - - auto res_d = defer(freeaddrinfo, res); - - char host[NI_MAXHOST]; - rv = getnameinfo(res->ai_addr, res->ai_addrlen, host, sizeof(host), nullptr, - 0, NI_NUMERICHOST); - if (rv != 0) { - LOG(FATAL) << "Address resolution for " << hostname - << " failed: " << gai_strerror(rv); - - return -1; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Address resolution for " << hostname - << " succeeded: " << host; - } - - memcpy(&addr->su, res->ai_addr, res->ai_addrlen); - addr->len = res->ai_addrlen; - - return 0; -} - } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_config.h nghttp2-0.6.7/src/shrpx_config.h --- nghttp2-1.13.0/src/shrpx_config.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_config.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,908 +27,313 @@ #include "shrpx.h" +#include #include -#ifdef HAVE_SYS_SOCKET_H #include -#endif // HAVE_SYS_SOCKET_H -#include -#ifdef HAVE_NETINET_IN_H #include -#endif // HAVE_NETINET_IN_H -#ifdef HAVE_ARPA_INET_H #include -#endif // HAVE_ARPA_INET_H -#include #include #include #include -#include +#include +#include #include -#include - #include -#include "shrpx_router.h" -#include "template.h" -#include "http2.h" -#include "network.h" - -using namespace nghttp2; - namespace shrpx { struct LogFragment; -class ConnectBlocker; -class Http2Session; namespace ssl { -class CertLookupTree; +struct CertLookupTree; } // namespace ssl -constexpr auto SHRPX_OPT_PRIVATE_KEY_FILE = - StringRef::from_lit("private-key-file"); -constexpr auto SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE = - StringRef::from_lit("private-key-passwd-file"); -constexpr auto SHRPX_OPT_CERTIFICATE_FILE = - StringRef::from_lit("certificate-file"); -constexpr auto SHRPX_OPT_DH_PARAM_FILE = StringRef::from_lit("dh-param-file"); -constexpr auto SHRPX_OPT_SUBCERT = StringRef::from_lit("subcert"); -constexpr auto SHRPX_OPT_BACKEND = StringRef::from_lit("backend"); -constexpr auto SHRPX_OPT_FRONTEND = StringRef::from_lit("frontend"); -constexpr auto SHRPX_OPT_WORKERS = StringRef::from_lit("workers"); -constexpr auto SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS = - StringRef::from_lit("http2-max-concurrent-streams"); -constexpr auto SHRPX_OPT_LOG_LEVEL = StringRef::from_lit("log-level"); -constexpr auto SHRPX_OPT_DAEMON = StringRef::from_lit("daemon"); -constexpr auto SHRPX_OPT_HTTP2_PROXY = StringRef::from_lit("http2-proxy"); -constexpr auto SHRPX_OPT_HTTP2_BRIDGE = StringRef::from_lit("http2-bridge"); -constexpr auto SHRPX_OPT_CLIENT_PROXY = StringRef::from_lit("client-proxy"); -constexpr auto SHRPX_OPT_ADD_X_FORWARDED_FOR = - StringRef::from_lit("add-x-forwarded-for"); -constexpr auto SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR = - StringRef::from_lit("strip-incoming-x-forwarded-for"); -constexpr auto SHRPX_OPT_NO_VIA = StringRef::from_lit("no-via"); -constexpr auto SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT = - StringRef::from_lit("frontend-http2-read-timeout"); -constexpr auto SHRPX_OPT_FRONTEND_READ_TIMEOUT = - StringRef::from_lit("frontend-read-timeout"); -constexpr auto SHRPX_OPT_FRONTEND_WRITE_TIMEOUT = - StringRef::from_lit("frontend-write-timeout"); -constexpr auto SHRPX_OPT_BACKEND_READ_TIMEOUT = - StringRef::from_lit("backend-read-timeout"); -constexpr auto SHRPX_OPT_BACKEND_WRITE_TIMEOUT = - StringRef::from_lit("backend-write-timeout"); -constexpr auto SHRPX_OPT_STREAM_READ_TIMEOUT = - StringRef::from_lit("stream-read-timeout"); -constexpr auto SHRPX_OPT_STREAM_WRITE_TIMEOUT = - StringRef::from_lit("stream-write-timeout"); -constexpr auto SHRPX_OPT_ACCESSLOG_FILE = StringRef::from_lit("accesslog-file"); -constexpr auto SHRPX_OPT_ACCESSLOG_SYSLOG = - StringRef::from_lit("accesslog-syslog"); -constexpr auto SHRPX_OPT_ACCESSLOG_FORMAT = - StringRef::from_lit("accesslog-format"); -constexpr auto SHRPX_OPT_ERRORLOG_FILE = StringRef::from_lit("errorlog-file"); -constexpr auto SHRPX_OPT_ERRORLOG_SYSLOG = - StringRef::from_lit("errorlog-syslog"); -constexpr auto SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT = - StringRef::from_lit("backend-keep-alive-timeout"); -constexpr auto SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS = - StringRef::from_lit("frontend-http2-window-bits"); -constexpr auto SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS = - StringRef::from_lit("backend-http2-window-bits"); -constexpr auto SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS = - StringRef::from_lit("frontend-http2-connection-window-bits"); -constexpr auto SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS = - StringRef::from_lit("backend-http2-connection-window-bits"); -constexpr auto SHRPX_OPT_FRONTEND_NO_TLS = - StringRef::from_lit("frontend-no-tls"); -constexpr auto SHRPX_OPT_BACKEND_NO_TLS = StringRef::from_lit("backend-no-tls"); -constexpr auto SHRPX_OPT_BACKEND_TLS_SNI_FIELD = - StringRef::from_lit("backend-tls-sni-field"); -constexpr auto SHRPX_OPT_PID_FILE = StringRef::from_lit("pid-file"); -constexpr auto SHRPX_OPT_USER = StringRef::from_lit("user"); -constexpr auto SHRPX_OPT_SYSLOG_FACILITY = - StringRef::from_lit("syslog-facility"); -constexpr auto SHRPX_OPT_BACKLOG = StringRef::from_lit("backlog"); -constexpr auto SHRPX_OPT_CIPHERS = StringRef::from_lit("ciphers"); -constexpr auto SHRPX_OPT_CLIENT = StringRef::from_lit("client"); -constexpr auto SHRPX_OPT_INSECURE = StringRef::from_lit("insecure"); -constexpr auto SHRPX_OPT_CACERT = StringRef::from_lit("cacert"); -constexpr auto SHRPX_OPT_BACKEND_IPV4 = StringRef::from_lit("backend-ipv4"); -constexpr auto SHRPX_OPT_BACKEND_IPV6 = StringRef::from_lit("backend-ipv6"); -constexpr auto SHRPX_OPT_BACKEND_HTTP_PROXY_URI = - StringRef::from_lit("backend-http-proxy-uri"); -constexpr auto SHRPX_OPT_READ_RATE = StringRef::from_lit("read-rate"); -constexpr auto SHRPX_OPT_READ_BURST = StringRef::from_lit("read-burst"); -constexpr auto SHRPX_OPT_WRITE_RATE = StringRef::from_lit("write-rate"); -constexpr auto SHRPX_OPT_WRITE_BURST = StringRef::from_lit("write-burst"); -constexpr auto SHRPX_OPT_WORKER_READ_RATE = - StringRef::from_lit("worker-read-rate"); -constexpr auto SHRPX_OPT_WORKER_READ_BURST = - StringRef::from_lit("worker-read-burst"); -constexpr auto SHRPX_OPT_WORKER_WRITE_RATE = - StringRef::from_lit("worker-write-rate"); -constexpr auto SHRPX_OPT_WORKER_WRITE_BURST = - StringRef::from_lit("worker-write-burst"); -constexpr auto SHRPX_OPT_NPN_LIST = StringRef::from_lit("npn-list"); -constexpr auto SHRPX_OPT_TLS_PROTO_LIST = StringRef::from_lit("tls-proto-list"); -constexpr auto SHRPX_OPT_VERIFY_CLIENT = StringRef::from_lit("verify-client"); -constexpr auto SHRPX_OPT_VERIFY_CLIENT_CACERT = - StringRef::from_lit("verify-client-cacert"); -constexpr auto SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE = - StringRef::from_lit("client-private-key-file"); -constexpr auto SHRPX_OPT_CLIENT_CERT_FILE = - StringRef::from_lit("client-cert-file"); -constexpr auto SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER = - StringRef::from_lit("frontend-http2-dump-request-header"); -constexpr auto SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER = - StringRef::from_lit("frontend-http2-dump-response-header"); -constexpr auto SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING = - StringRef::from_lit("http2-no-cookie-crumbling"); -constexpr auto SHRPX_OPT_FRONTEND_FRAME_DEBUG = - StringRef::from_lit("frontend-frame-debug"); -constexpr auto SHRPX_OPT_PADDING = StringRef::from_lit("padding"); -constexpr auto SHRPX_OPT_ALTSVC = StringRef::from_lit("altsvc"); -constexpr auto SHRPX_OPT_ADD_REQUEST_HEADER = - StringRef::from_lit("add-request-header"); -constexpr auto SHRPX_OPT_ADD_RESPONSE_HEADER = - StringRef::from_lit("add-response-header"); -constexpr auto SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS = - StringRef::from_lit("worker-frontend-connections"); -constexpr auto SHRPX_OPT_NO_LOCATION_REWRITE = - StringRef::from_lit("no-location-rewrite"); -constexpr auto SHRPX_OPT_NO_HOST_REWRITE = - StringRef::from_lit("no-host-rewrite"); -constexpr auto SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST = - StringRef::from_lit("backend-http1-connections-per-host"); -constexpr auto SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND = - StringRef::from_lit("backend-http1-connections-per-frontend"); -constexpr auto SHRPX_OPT_LISTENER_DISABLE_TIMEOUT = - StringRef::from_lit("listener-disable-timeout"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_FILE = - StringRef::from_lit("tls-ticket-key-file"); -constexpr auto SHRPX_OPT_RLIMIT_NOFILE = StringRef::from_lit("rlimit-nofile"); -constexpr auto SHRPX_OPT_BACKEND_REQUEST_BUFFER = - StringRef::from_lit("backend-request-buffer"); -constexpr auto SHRPX_OPT_BACKEND_RESPONSE_BUFFER = - StringRef::from_lit("backend-response-buffer"); -constexpr auto SHRPX_OPT_NO_SERVER_PUSH = StringRef::from_lit("no-server-push"); -constexpr auto SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER = - StringRef::from_lit("backend-http2-connections-per-worker"); -constexpr auto SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE = - StringRef::from_lit("fetch-ocsp-response-file"); -constexpr auto SHRPX_OPT_OCSP_UPDATE_INTERVAL = - StringRef::from_lit("ocsp-update-interval"); -constexpr auto SHRPX_OPT_NO_OCSP = StringRef::from_lit("no-ocsp"); -constexpr auto SHRPX_OPT_HEADER_FIELD_BUFFER = - StringRef::from_lit("header-field-buffer"); -constexpr auto SHRPX_OPT_MAX_HEADER_FIELDS = - StringRef::from_lit("max-header-fields"); -constexpr auto SHRPX_OPT_INCLUDE = StringRef::from_lit("include"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_CIPHER = - StringRef::from_lit("tls-ticket-key-cipher"); -constexpr auto SHRPX_OPT_HOST_REWRITE = StringRef::from_lit("host-rewrite"); -constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED = - StringRef::from_lit("tls-session-cache-memcached"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED = - StringRef::from_lit("tls-ticket-key-memcached"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL = - StringRef::from_lit("tls-ticket-key-memcached-interval"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY = - StringRef::from_lit("tls-ticket-key-memcached-max-retry"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL = - StringRef::from_lit("tls-ticket-key-memcached-max-fail"); -constexpr auto SHRPX_OPT_MRUBY_FILE = StringRef::from_lit("mruby-file"); -constexpr auto SHRPX_OPT_ACCEPT_PROXY_PROTOCOL = - StringRef::from_lit("accept-proxy-protocol"); -constexpr auto SHRPX_OPT_FASTOPEN = StringRef::from_lit("fastopen"); -constexpr auto SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD = - StringRef::from_lit("tls-dyn-rec-warmup-threshold"); -constexpr auto SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT = - StringRef::from_lit("tls-dyn-rec-idle-timeout"); -constexpr auto SHRPX_OPT_ADD_FORWARDED = StringRef::from_lit("add-forwarded"); -constexpr auto SHRPX_OPT_STRIP_INCOMING_FORWARDED = - StringRef::from_lit("strip-incoming-forwarded"); -constexpr auto SHRPX_OPT_FORWARDED_BY = StringRef::from_lit("forwarded-by"); -constexpr auto SHRPX_OPT_FORWARDED_FOR = StringRef::from_lit("forwarded-for"); -constexpr auto SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER = - StringRef::from_lit("request-header-field-buffer"); -constexpr auto SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS = - StringRef::from_lit("max-request-header-fields"); -constexpr auto SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER = - StringRef::from_lit("response-header-field-buffer"); -constexpr auto SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS = - StringRef::from_lit("max-response-header-fields"); -constexpr auto SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST = - StringRef::from_lit("no-http2-cipher-black-list"); -constexpr auto SHRPX_OPT_BACKEND_HTTP1_TLS = - StringRef::from_lit("backend-http1-tls"); -constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS = - StringRef::from_lit("tls-session-cache-memcached-tls"); -constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE = - StringRef::from_lit("tls-session-cache-memcached-cert-file"); -constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE = - StringRef::from_lit("tls-session-cache-memcached-private-key-file"); -constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY = - StringRef::from_lit("tls-session-cache-memcached-address-family"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS = - StringRef::from_lit("tls-ticket-key-memcached-tls"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE = - StringRef::from_lit("tls-ticket-key-memcached-cert-file"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE = - StringRef::from_lit("tls-ticket-key-memcached-private-key-file"); -constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY = - StringRef::from_lit("tls-ticket-key-memcached-address-family"); -constexpr auto SHRPX_OPT_BACKEND_ADDRESS_FAMILY = - StringRef::from_lit("backend-address-family"); -constexpr auto SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS = - StringRef::from_lit("frontend-http2-max-concurrent-streams"); -constexpr auto SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS = - StringRef::from_lit("backend-http2-max-concurrent-streams"); -constexpr auto SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND = - StringRef::from_lit("backend-connections-per-frontend"); -constexpr auto SHRPX_OPT_BACKEND_TLS = StringRef::from_lit("backend-tls"); -constexpr auto SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST = - StringRef::from_lit("backend-connections-per-host"); -constexpr auto SHRPX_OPT_ERROR_PAGE = StringRef::from_lit("error-page"); -constexpr auto SHRPX_OPT_NO_KQUEUE = StringRef::from_lit("no-kqueue"); -constexpr auto SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT = - StringRef::from_lit("frontend-http2-settings-timeout"); -constexpr auto SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT = - StringRef::from_lit("backend-http2-settings-timeout"); -constexpr auto SHRPX_OPT_API_MAX_REQUEST_BODY = - StringRef::from_lit("api-max-request-body"); -constexpr auto SHRPX_OPT_BACKEND_MAX_BACKOFF = - StringRef::from_lit("backend-max-backoff"); - -constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; - -constexpr char DEFAULT_DOWNSTREAM_HOST[] = "127.0.0.1"; -constexpr int16_t DEFAULT_DOWNSTREAM_PORT = 80; - -enum shrpx_proto { PROTO_NONE, PROTO_HTTP1, PROTO_HTTP2, PROTO_MEMCACHED }; - -enum shrpx_session_affinity { - // No session affinity - AFFINITY_NONE, - // Client IP affinity - AFFINITY_IP, +extern const char SHRPX_OPT_PRIVATE_KEY_FILE[]; +extern const char SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE[]; +extern const char SHRPX_OPT_CERTIFICATE_FILE[]; +extern const char SHRPX_OPT_DH_PARAM_FILE[]; +extern const char SHRPX_OPT_SUBCERT[]; +extern const char SHRPX_OPT_BACKEND[]; +extern const char SHRPX_OPT_FRONTEND[]; +extern const char SHRPX_OPT_WORKERS[]; +extern const char SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS[]; +extern const char SHRPX_OPT_LOG_LEVEL[]; +extern const char SHRPX_OPT_DAEMON[]; +extern const char SHRPX_OPT_HTTP2_PROXY[]; +extern const char SHRPX_OPT_HTTP2_BRIDGE[]; +extern const char SHRPX_OPT_CLIENT_PROXY[]; +extern const char SHRPX_OPT_ADD_X_FORWARDED_FOR[]; +extern const char SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR[]; +extern const char SHRPX_OPT_NO_VIA[]; +extern const char SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT[]; +extern const char SHRPX_OPT_FRONTEND_READ_TIMEOUT[]; +extern const char SHRPX_OPT_FRONTEND_WRITE_TIMEOUT[]; +extern const char SHRPX_OPT_BACKEND_READ_TIMEOUT[]; +extern const char SHRPX_OPT_BACKEND_WRITE_TIMEOUT[]; +extern const char SHRPX_OPT_STREAM_READ_TIMEOUT[]; +extern const char SHRPX_OPT_STREAM_WRITE_TIMEOUT[]; +extern const char SHRPX_OPT_ACCESSLOG_FILE[]; +extern const char SHRPX_OPT_ACCESSLOG_SYSLOG[]; +extern const char SHRPX_OPT_ACCESSLOG_FORMAT[]; +extern const char SHRPX_OPT_ERRORLOG_FILE[]; +extern const char SHRPX_OPT_ERRORLOG_SYSLOG[]; +extern const char SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT[]; +extern const char SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS[]; +extern const char SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS[]; +extern const char SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS[]; +extern const char SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS[]; +extern const char SHRPX_OPT_FRONTEND_NO_TLS[]; +extern const char SHRPX_OPT_BACKEND_NO_TLS[]; +extern const char SHRPX_OPT_PID_FILE[]; +extern const char SHRPX_OPT_USER[]; +extern const char SHRPX_OPT_SYSLOG_FACILITY[]; +extern const char SHRPX_OPT_BACKLOG[]; +extern const char SHRPX_OPT_CIPHERS[]; +extern const char SHRPX_OPT_CLIENT[]; +extern const char SHRPX_OPT_INSECURE[]; +extern const char SHRPX_OPT_CACERT[]; +extern const char SHRPX_OPT_BACKEND_IPV4[]; +extern const char SHRPX_OPT_BACKEND_IPV6[]; +extern const char SHRPX_OPT_BACKEND_HTTP_PROXY_URI[]; +extern const char SHRPX_OPT_BACKEND_TLS_SNI_FIELD[]; +extern const char SHRPX_OPT_READ_RATE[]; +extern const char SHRPX_OPT_READ_BURST[]; +extern const char SHRPX_OPT_WRITE_RATE[]; +extern const char SHRPX_OPT_WRITE_BURST[]; +extern const char SHRPX_OPT_WORKER_READ_RATE[]; +extern const char SHRPX_OPT_WORKER_READ_BURST[]; +extern const char SHRPX_OPT_WORKER_WRITE_RATE[]; +extern const char SHRPX_OPT_WORKER_WRITE_BURST[]; +extern const char SHRPX_OPT_NPN_LIST[]; +extern const char SHRPX_OPT_TLS_PROTO_LIST[]; +extern const char SHRPX_OPT_VERIFY_CLIENT[]; +extern const char SHRPX_OPT_VERIFY_CLIENT_CACERT[]; +extern const char SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE[]; +extern const char SHRPX_OPT_CLIENT_CERT_FILE[]; +extern const char SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER[]; +extern const char SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER[]; +extern const char SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING[]; +extern const char SHRPX_OPT_FRONTEND_FRAME_DEBUG[]; +extern const char SHRPX_OPT_PADDING[]; +extern const char SHRPX_OPT_ALTSVC[]; +extern const char SHRPX_OPT_ADD_RESPONSE_HEADER[]; +extern const char SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS[]; +extern const char SHRPX_OPT_NO_LOCATION_REWRITE[]; +extern const char SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND[]; +extern const char SHRPX_OPT_LISTENER_DISABLE_TIMEOUT[]; + +union sockaddr_union { + sockaddr sa; + sockaddr_storage storage; + sockaddr_in6 in6; + sockaddr_in in; }; -enum shrpx_forwarded_param { - FORWARDED_NONE = 0, - FORWARDED_BY = 0x1, - FORWARDED_FOR = 0x2, - FORWARDED_HOST = 0x4, - FORWARDED_PROTO = 0x8, -}; - -enum shrpx_forwarded_node_type { - FORWARDED_NODE_OBFUSCATED, - FORWARDED_NODE_IP, -}; +enum shrpx_proto { PROTO_HTTP2, PROTO_HTTP }; struct AltSvc { - std::string protocol_id, host, origin, service; - - uint16_t port; -}; - -enum UpstreamAltMode { - // No alternative mode - ALTMODE_NONE, - // API processing mode - ALTMODE_API, - // Health monitor mode - ALTMODE_HEALTHMON, -}; + AltSvc() + : protocol_id(nullptr), host(nullptr), origin(nullptr), + protocol_id_len(0), host_len(0), origin_len(0), port(0) {} + + char *protocol_id; + char *host; + char *origin; + + size_t protocol_id_len; + size_t host_len; + size_t origin_len; -struct UpstreamAddr { - // The frontend address (e.g., FQDN, hostname, IP address). If - // |host_unix| is true, this is UNIX domain socket path. - ImmutableString host; - // For TCP socket, this is :. For IPv6 address, - // address is surrounded by square brackets. If socket is UNIX - // domain socket, this is "localhost". - ImmutableString hostport; - // frontend port. 0 if |host_unix| is true. uint16_t port; - // For TCP socket, this is either AF_INET or AF_INET6. For UNIX - // domain socket, this is 0. - int family; - // Alternate mode - int alt_mode; - // true if |host| contains UNIX domain socket path. - bool host_unix; - // true if TLS is enabled. - bool tls; - int fd; }; -struct DownstreamAddrConfig { - Address addr; - // backend address. If |host_unix| is true, this is UNIX domain - // socket path. - ImmutableString host; - // :. This does not treat 80 and 443 specially. If - // |host_unix| is true, this is "localhost". - ImmutableString hostport; - // hostname sent as SNI field - ImmutableString sni; - size_t fall; - size_t rise; - // Application protocol used in this group - shrpx_proto proto; - // backend port. 0 if |host_unix| is true. - uint16_t port; - // true if |host| contains UNIX domain socket path. - bool host_unix; - bool tls; -}; - -// Mapping hash to idx which is an index into -// DownstreamAddrGroupConfig::addrs. -struct AffinityHash { - AffinityHash(size_t idx, uint32_t hash) : idx(idx), hash(hash) {} - - size_t idx; - uint32_t hash; -}; - -struct DownstreamAddrGroupConfig { - DownstreamAddrGroupConfig(const StringRef &pattern) - : pattern(pattern.c_str(), pattern.size()), affinity(AFFINITY_NONE) {} - - ImmutableString pattern; - std::vector addrs; - // Bunch of session affinity hash. Only used if affinity == - // AFFINITY_IP. - std::vector affinity_hash; - // Session affinity - shrpx_session_affinity affinity; -}; - -struct TicketKey { - const EVP_CIPHER *cipher; - const EVP_MD *hmac; - size_t hmac_keylen; - struct { - // name of this ticket configuration - std::array name; - // encryption key for |cipher| - std::array enc_key; - // hmac key for |hmac| - std::array hmac_key; - } data; -}; - -struct TicketKeys { - ~TicketKeys(); - std::vector keys; -}; - -struct HttpProxy { - Address addr; - // host in http proxy URI - std::string host; - // userinfo in http proxy URI, not percent-encoded form - std::string userinfo; - // port in http proxy URI - uint16_t port; -}; - -struct TLSConfig { - // RFC 5077 Session ticket related configurations - struct { - struct { - Address addr; - uint16_t port; - // Hostname of memcached server. This is also used as SNI field - // if TLS is enabled. - ImmutableString host; - // Client private key and certificate for authentication - ImmutableString private_key_file; - ImmutableString cert_file; - ev_tstamp interval; - // Maximum number of retries when getting TLS ticket key from - // mamcached, due to network error. - size_t max_retry; - // Maximum number of consecutive error from memcached, when this - // limit reached, TLS ticket is disabled. - size_t max_fail; - // Address family of memcached connection. One of either - // AF_INET, AF_INET6 or AF_UNSPEC. - int family; - bool tls; - } memcached; - std::vector files; - const EVP_CIPHER *cipher; - // true if --tls-ticket-key-cipher is used - bool cipher_given; - } ticket; - - // Session cache related configurations - struct { - struct { - Address addr; - uint16_t port; - // Hostname of memcached server. This is also used as SNI field - // if TLS is enabled. - ImmutableString host; - // Client private key and certificate for authentication - ImmutableString private_key_file; - ImmutableString cert_file; - // Address family of memcached connection. One of either - // AF_INET, AF_INET6 or AF_UNSPEC. - int family; - bool tls; - } memcached; - } session_cache; - - // Dynamic record sizing configurations - struct { - size_t warmup_threshold; - ev_tstamp idle_timeout; - } dyn_rec; - - // OCSP realted configurations - struct { - ev_tstamp update_interval; - ImmutableString fetch_ocsp_response_file; - bool disabled; - } ocsp; - - // Client verification configurations - struct { - // Path to file containing CA certificate solely used for client - // certificate validation - ImmutableString cacert; - bool enabled; - } client_verify; - - // Client private key and certificate used in backend connections. - struct { - ImmutableString private_key_file; - ImmutableString cert_file; - } client; - +struct Config { // The list of (private key file, certificate file) pair std::vector> subcerts; + std::vector altsvcs; + std::vector> add_response_headers; std::vector alpn_prefs; + std::vector accesslog_format; + std::shared_ptr cached_time; + sockaddr_union downstream_addr; + // binary form of http proxy host and port + sockaddr_union downstream_http_proxy_addr; + timeval http2_upstream_read_timeout; + timeval upstream_read_timeout; + timeval upstream_write_timeout; + timeval downstream_read_timeout; + timeval downstream_write_timeout; + timeval stream_read_timeout; + timeval stream_write_timeout; + timeval downstream_idle_read_timeout; + timeval listener_disable_timeout; + std::unique_ptr host; + std::unique_ptr private_key_file; + std::unique_ptr private_key_passwd; + std::unique_ptr cert_file; + std::unique_ptr dh_param_file; + SSL_CTX *default_ssl_ctx; + ssl::CertLookupTree *cert_tree; + const char *server_name; + std::unique_ptr downstream_host; + std::unique_ptr downstream_hostport; + std::unique_ptr backend_tls_sni_name; + std::unique_ptr pid_file; + std::unique_ptr conf_path; + std::unique_ptr ciphers; + std::unique_ptr cacert; + // userinfo in http proxy URI, not percent-encoded form + std::unique_ptr downstream_http_proxy_userinfo; + // host in http proxy URI + std::unique_ptr downstream_http_proxy_host; + std::unique_ptr http2_upstream_dump_request_header_file; + std::unique_ptr http2_upstream_dump_response_header_file; + // Rate limit configuration per connection + ev_token_bucket_cfg *rate_limit_cfg; + // Rate limit configuration per worker (thread) + ev_token_bucket_cfg *worker_rate_limit_cfg; // list of supported NPN/ALPN protocol strings in the order of - // preference. - std::vector npn_list; - // list of supported SSL/TLS protocol strings. - std::vector tls_proto_list; - BIO_METHOD *bio_method; - // Bit mask to disable SSL/TLS protocol versions. This will be - // passed to SSL_CTX_set_options(). - long int tls_proto_mask; - std::string backend_sni_name; - std::chrono::seconds session_timeout; - ImmutableString private_key_file; - ImmutableString private_key_passwd; - ImmutableString cert_file; - ImmutableString dh_param_file; - ImmutableString ciphers; - ImmutableString cacert; - bool insecure; - bool no_http2_cipher_black_list; -}; - -// custom error page -struct ErrorPage { - // not NULL-terminated - std::vector content; - // 0 is special value, and it matches all HTTP status code. - unsigned int http_status; -}; - -struct HttpConfig { - struct { - // obfuscated value used in "by" parameter of Forwarded header - // field. This is only used when user defined static obfuscated - // string is provided. - std::string by_obfuscated; - // bitwise-OR of one or more of shrpx_forwarded_param values. - uint32_t params; - // type of value recorded in "by" parameter of Forwarded header - // field. - shrpx_forwarded_node_type by_node_type; - // type of value recorded in "for" parameter of Forwarded header - // field. - shrpx_forwarded_node_type for_node_type; - bool strip_incoming; - } forwarded; - struct { - bool add; - bool strip_incoming; - } xff; - std::vector altsvcs; - std::vector error_pages; - Headers add_request_headers; - Headers add_response_headers; - StringRef server_name; - size_t request_header_field_buffer; - size_t max_request_header_fields; - size_t response_header_field_buffer; - size_t max_response_header_fields; - bool no_via; - bool no_location_rewrite; - bool no_host_rewrite; -}; - -struct Http2Config { - struct { - struct { - struct { - ImmutableString request_header_file; - ImmutableString response_header_file; - FILE *request_header; - FILE *response_header; - } dump; - bool frame_debug; - } debug; - struct { - ev_tstamp settings; - } timeout; - nghttp2_option *option; - nghttp2_option *alt_mode_option; - nghttp2_session_callbacks *callbacks; - size_t window_bits; - size_t connection_window_bits; - size_t max_concurrent_streams; - } upstream; - struct { - struct { - ev_tstamp settings; - } timeout; - nghttp2_option *option; - nghttp2_session_callbacks *callbacks; - size_t window_bits; - size_t connection_window_bits; - size_t max_concurrent_streams; - } downstream; - struct { - ev_tstamp stream_read; - ev_tstamp stream_write; - } timeout; - bool no_cookie_crumbling; - bool no_server_push; -}; - -struct LoggingConfig { - struct { - std::vector format; - ImmutableString file; - // Send accesslog to syslog, ignoring accesslog_file. - bool syslog; - } access; - struct { - ImmutableString file; - // Send errorlog to syslog, ignoring errorlog_file. - bool syslog; - } error; - int syslog_facility; -}; - -struct RateLimitConfig { - size_t rate; - size_t burst; -}; - -// Wildcard host pattern routing. We strips left most '*' from host -// field. router includes all path patterns sharing the same wildcard -// host. -struct WildcardPattern { - WildcardPattern(const StringRef &host) - : host(std::begin(host), std::end(host)) {} - - ImmutableString host; - Router router; -}; - -// Configuration to select backend to forward request -struct RouterConfig { - Router router; - // Router for reversed wildcard hosts. Since this router has - // wildcard hosts reversed without '*', one should call match() - // function with reversed host stripping last character. This is - // because we require at least one character must match for '*'. - // The index stored in this router is index of wildcard_patterns. - Router rev_wildcard_router; - std::vector wildcard_patterns; -}; - -struct DownstreamConfig { - struct { - ev_tstamp read; - ev_tstamp write; - ev_tstamp idle_read; - // The maximum backoff while checking health check for offline - // backend or while detaching failed backend from load balancing - // group temporarily. - ev_tstamp max_backoff; - } timeout; - RouterConfig router; - std::vector addr_groups; - // The index of catch-all group in downstream_addr_groups. - size_t addr_group_catch_all; - size_t connections_per_host; - size_t connections_per_frontend; - size_t request_buffer_size; - size_t response_buffer_size; - // Address family of backend connection. One of either AF_INET, - // AF_INET6 or AF_UNSPEC. This is ignored if backend connection - // is made via Unix domain socket. - int family; -}; - -struct ConnectionConfig { - struct { - struct { - ev_tstamp sleep; - } timeout; - // address of frontend acceptors - std::vector addrs; - int backlog; - // TCP fastopen. If this is positive, it is passed to - // setsockopt() along with TCP_FASTOPEN. - int fastopen; - } listener; - - struct { - struct { - ev_tstamp http2_read; - ev_tstamp read; - ev_tstamp write; - } timeout; - struct { - RateLimitConfig read; - RateLimitConfig write; - } ratelimit; - size_t worker_connections; - bool accept_proxy_protocol; - } upstream; - - std::shared_ptr downstream; -}; - -struct APIConfig { - // Maximum request body size for one API request - size_t max_request_body; - // true if at least one of UpstreamAddr has api enabled - bool enabled; -}; - -struct Config { - HttpProxy downstream_http_proxy; - HttpConfig http; - Http2Config http2; - TLSConfig tls; - LoggingConfig logging; - ConnectionConfig conn; - APIConfig api; - ImmutableString pid_file; - ImmutableString conf_path; - ImmutableString user; - ImmutableString mruby_file; - char **original_argv; + // preference. The each element of this list is a NULL-terminated + // string. + std::vector npn_list; + // list of supported SSL/TLS protocol strings. The each element of + // this list is a NULL-terminated string. + std::vector tls_proto_list; + // Path to file containing CA certificate solely used for client + // certificate validation + std::unique_ptr verify_client_cacert; + std::unique_ptr client_private_key_file; + std::unique_ptr client_cert_file; + std::unique_ptr accesslog_file; + std::unique_ptr errorlog_file; + FILE *http2_upstream_dump_request_header; + FILE *http2_upstream_dump_response_header; + nghttp2_option *http2_option; char **argv; char *cwd; + size_t downstream_addrlen; size_t num_worker; + size_t http2_max_concurrent_streams; + size_t http2_upstream_window_bits; + size_t http2_downstream_window_bits; + size_t http2_upstream_connection_window_bits; + size_t http2_downstream_connection_window_bits; + size_t max_downstream_connections; + // actual size of downstream_http_proxy_addr + size_t downstream_http_proxy_addrlen; + size_t read_rate; + size_t read_burst; + size_t write_rate; + size_t write_burst; + size_t worker_read_rate; + size_t worker_read_burst; + size_t worker_write_rate; + size_t worker_write_burst; size_t padding; - size_t rlimit_nofile; + size_t worker_frontend_connections; + // Bit mask to disable SSL/TLS protocol versions. This will be + // passed to SSL_CTX_set_options(). + long int tls_proto_mask; + // downstream protocol; this will be determined by given options. + shrpx_proto downstream_proto; + int syslog_facility; + int backlog; int argc; uid_t uid; gid_t gid; pid_t pid; + uint16_t port; + uint16_t downstream_port; + // port in http proxy URI + uint16_t downstream_http_proxy_port; bool verbose; bool daemon; + bool verify_client; bool http2_proxy; - // flags passed to ev_default_loop() and ev_loop_new() - int ev_loop_flags; + bool http2_bridge; + bool client_proxy; + bool add_x_forwarded_for; + bool strip_incoming_x_forwarded_for; + bool no_via; + bool upstream_no_tls; + bool downstream_no_tls; + // Send accesslog to syslog, ignoring accesslog_file. + bool accesslog_syslog; + // Send errorlog to syslog, ignoring errorlog_file. + bool errorlog_syslog; + bool client; + // true if --client or --client-proxy are enabled. + bool client_mode; + bool insecure; + bool backend_ipv4; + bool backend_ipv6; + bool http2_no_cookie_crumbling; + bool upstream_frame_debug; + bool no_location_rewrite; }; const Config *get_config(); Config *mod_config(); void create_config(); -// generated by gennghttpxfun.py -enum { - SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL, - SHRPX_OPTID_ACCESSLOG_FILE, - SHRPX_OPTID_ACCESSLOG_FORMAT, - SHRPX_OPTID_ACCESSLOG_SYSLOG, - SHRPX_OPTID_ADD_FORWARDED, - SHRPX_OPTID_ADD_REQUEST_HEADER, - SHRPX_OPTID_ADD_RESPONSE_HEADER, - SHRPX_OPTID_ADD_X_FORWARDED_FOR, - SHRPX_OPTID_ALTSVC, - SHRPX_OPTID_API_MAX_REQUEST_BODY, - SHRPX_OPTID_BACKEND, - SHRPX_OPTID_BACKEND_ADDRESS_FAMILY, - SHRPX_OPTID_BACKEND_CONNECTIONS_PER_FRONTEND, - SHRPX_OPTID_BACKEND_CONNECTIONS_PER_HOST, - SHRPX_OPTID_BACKEND_HTTP_PROXY_URI, - SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND, - SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_HOST, - SHRPX_OPTID_BACKEND_HTTP1_TLS, - SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS, - SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER, - SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS, - SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT, - SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS, - SHRPX_OPTID_BACKEND_IPV4, - SHRPX_OPTID_BACKEND_IPV6, - SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT, - SHRPX_OPTID_BACKEND_MAX_BACKOFF, - SHRPX_OPTID_BACKEND_NO_TLS, - SHRPX_OPTID_BACKEND_READ_TIMEOUT, - SHRPX_OPTID_BACKEND_REQUEST_BUFFER, - SHRPX_OPTID_BACKEND_RESPONSE_BUFFER, - SHRPX_OPTID_BACKEND_TLS, - SHRPX_OPTID_BACKEND_TLS_SNI_FIELD, - SHRPX_OPTID_BACKEND_WRITE_TIMEOUT, - SHRPX_OPTID_BACKLOG, - SHRPX_OPTID_CACERT, - SHRPX_OPTID_CERTIFICATE_FILE, - SHRPX_OPTID_CIPHERS, - SHRPX_OPTID_CLIENT, - SHRPX_OPTID_CLIENT_CERT_FILE, - SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE, - SHRPX_OPTID_CLIENT_PROXY, - SHRPX_OPTID_CONF, - SHRPX_OPTID_DAEMON, - SHRPX_OPTID_DH_PARAM_FILE, - SHRPX_OPTID_ERROR_PAGE, - SHRPX_OPTID_ERRORLOG_FILE, - SHRPX_OPTID_ERRORLOG_SYSLOG, - SHRPX_OPTID_FASTOPEN, - SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE, - SHRPX_OPTID_FORWARDED_BY, - SHRPX_OPTID_FORWARDED_FOR, - SHRPX_OPTID_FRONTEND, - SHRPX_OPTID_FRONTEND_FRAME_DEBUG, - SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS, - SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER, - SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER, - SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS, - SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT, - SHRPX_OPTID_FRONTEND_HTTP2_SETTINGS_TIMEOUT, - SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS, - SHRPX_OPTID_FRONTEND_NO_TLS, - SHRPX_OPTID_FRONTEND_READ_TIMEOUT, - SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT, - SHRPX_OPTID_HEADER_FIELD_BUFFER, - SHRPX_OPTID_HOST_REWRITE, - SHRPX_OPTID_HTTP2_BRIDGE, - SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS, - SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING, - SHRPX_OPTID_HTTP2_PROXY, - SHRPX_OPTID_INCLUDE, - SHRPX_OPTID_INSECURE, - SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT, - SHRPX_OPTID_LOG_LEVEL, - SHRPX_OPTID_MAX_HEADER_FIELDS, - SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS, - SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS, - SHRPX_OPTID_MRUBY_FILE, - SHRPX_OPTID_NO_HOST_REWRITE, - SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST, - SHRPX_OPTID_NO_KQUEUE, - SHRPX_OPTID_NO_LOCATION_REWRITE, - SHRPX_OPTID_NO_OCSP, - SHRPX_OPTID_NO_SERVER_PUSH, - SHRPX_OPTID_NO_VIA, - SHRPX_OPTID_NPN_LIST, - SHRPX_OPTID_OCSP_UPDATE_INTERVAL, - SHRPX_OPTID_PADDING, - SHRPX_OPTID_PID_FILE, - SHRPX_OPTID_PRIVATE_KEY_FILE, - SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE, - SHRPX_OPTID_READ_BURST, - SHRPX_OPTID_READ_RATE, - SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER, - SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER, - SHRPX_OPTID_RLIMIT_NOFILE, - SHRPX_OPTID_STREAM_READ_TIMEOUT, - SHRPX_OPTID_STREAM_WRITE_TIMEOUT, - SHRPX_OPTID_STRIP_INCOMING_FORWARDED, - SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR, - SHRPX_OPTID_SUBCERT, - SHRPX_OPTID_SYSLOG_FACILITY, - SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT, - SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD, - SHRPX_OPTID_TLS_PROTO_LIST, - SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED, - SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY, - SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE, - SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE, - SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS, - SHRPX_OPTID_TLS_TICKET_KEY_CIPHER, - SHRPX_OPTID_TLS_TICKET_KEY_FILE, - SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED, - SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY, - SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE, - SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL, - SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL, - SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY, - SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE, - SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS, - SHRPX_OPTID_USER, - SHRPX_OPTID_VERIFY_CLIENT, - SHRPX_OPTID_VERIFY_CLIENT_CACERT, - SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS, - SHRPX_OPTID_WORKER_READ_BURST, - SHRPX_OPTID_WORKER_READ_RATE, - SHRPX_OPTID_WORKER_WRITE_BURST, - SHRPX_OPTID_WORKER_WRITE_RATE, - SHRPX_OPTID_WORKERS, - SHRPX_OPTID_WRITE_BURST, - SHRPX_OPTID_WRITE_RATE, - SHRPX_OPTID_MAXIDX, -}; - -// Looks up token for given option name |name| of length |namelen|. -int option_lookup_token(const char *name, size_t namelen); - // Parses option name |opt| and value |optarg|. The results are -// stored into the object pointed by |config|. This function returns 0 -// if it succeeds, or -1. The |included_set| contains the all paths -// already included while processing this configuration, to avoid loop -// in --include option. -int parse_config(Config *config, const StringRef &opt, const StringRef &optarg, - std::set &included_set); - -// Similar to parse_config() above, but additional |optid| which -// should be the return value of option_lookup_token(opt). -int parse_config(Config *config, int optid, const StringRef &opt, - const StringRef &optarg, std::set &included_set); +// stored into statically allocated Config object. This function +// returns 0 if it succeeds, or -1. +int parse_config(const char *opt, const char *optarg); // Loads configurations from |filename| and stores them in statically // allocated Config object. This function returns 0 if it succeeds, or -// -1. See parse_config() for |include_set|. -int load_config(const char *filename, std::set &include_set); +// -1. +int load_config(const char *filename); + +// Read passwd from |filename| +std::string read_passwd_from_file(const char *filename); + +// Parses comma delimited strings in |s| and returns the array of +// pointers, each element points to the each substring in |s|. The +// |s| must be comma delimited list of strings. The strings must be +// delimited by a single comma and any white spaces around it are +// treated as a part of protocol strings. This function may modify +// |s| and the caller must leave it as is after this call. This +// function copies |s| and first element in the return value points to +// it. It is caller's responsibility to deallocate its memory. +std::vector parse_config_str_list(const char *s); + +// Clears all elements of |list|, which is returned by +// parse_config_str_list(). If list is not empty, list[0] is freed by +// free(2). After this call, list.empty() must be true. +void clear_config_str_list(std::vector &list); // Parses header field in |optarg|. We expect header field is formed // like "NAME: VALUE". We require that NAME is non empty string. ":" // is allowed at the start of the NAME, but NAME == ":" is not // allowed. This function returns pair of NAME and VALUE. -Headers::value_type parse_header(const StringRef &optarg); +std::pair parse_header(const char *optarg); -std::vector parse_log_format(const StringRef &optarg); +std::vector parse_log_format(const char *optarg); + +// Returns a copy of NULL-terminated string |val|. +std::unique_ptr strcopy(const char *val); + +// Returns a copy of string |val| of length |n|. The returned string +// will be NULL-terminated. +std::unique_ptr strcopy(const char *val, size_t n); + +// Returns a copy of val.c_str(). +std::unique_ptr strcopy(const std::string &val); // Returns string for syslog |facility|. -StringRef str_syslog_facility(int facility); +const char *str_syslog_facility(int facility); // Returns integer value of syslog |facility| string. -int int_syslog_facility(const StringRef &strfacility); +int int_syslog_facility(const char *strfacility); FILE *open_file_for_write(const char *filename); -// Reads TLS ticket key file in |files| and returns TicketKey which -// stores read key data. The given |cipher| and |hmac| determine the -// expected file size. This function returns TicketKey if it -// succeeds, or nullptr. -std::unique_ptr -read_tls_ticket_key_file(const std::vector &files, - const EVP_CIPHER *cipher, const EVP_MD *hmac); - -// Returns string representation of |proto|. -StringRef strproto(shrpx_proto proto); - -int configure_downstream_group(Config *config, bool http2_proxy, - bool numeric_addr_only, - const TLSConfig &tlsconf); - -int resolve_hostname(Address *addr, const char *hostname, uint16_t port, - int family, int additional_flags = 0); - } // namespace shrpx #endif // SHRPX_CONFIG_H diff -Nru nghttp2-1.13.0/src/shrpx_config_test.cc nghttp2-0.6.7/src/shrpx_config_test.cc --- nghttp2-1.13.0/src/shrpx_config_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_config_test.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,218 +24,112 @@ */ #include "shrpx_config_test.h" -#ifdef HAVE_UNISTD_H -#include -#endif // HAVE_UNISTD_H - -#include - #include #include "shrpx_config.h" namespace shrpx { -void test_shrpx_config_parse_header(void) { - auto p = parse_header(StringRef::from_lit("a: b")); - CU_ASSERT("a" == p.name); - CU_ASSERT("b" == p.value); - - p = parse_header(StringRef::from_lit("a: b")); - CU_ASSERT("a" == p.name); - CU_ASSERT("b" == p.value); - - p = parse_header(StringRef::from_lit(":a: b")); - CU_ASSERT(p.name.empty()); - - p = parse_header(StringRef::from_lit("a: :b")); - CU_ASSERT("a" == p.name); - CU_ASSERT(":b" == p.value); +void test_shrpx_config_parse_config_str_list(void) { + auto res = parse_config_str_list("a"); + CU_ASSERT(1 == res.size()); + CU_ASSERT(0 == strcmp("a", res[0])); + clear_config_str_list(res); - p = parse_header(StringRef::from_lit(": b")); - CU_ASSERT(p.name.empty()); + res = parse_config_str_list("a,"); + CU_ASSERT(2 == res.size()); + CU_ASSERT(0 == strcmp("a", res[0])); + CU_ASSERT(0 == strcmp("", res[1])); + clear_config_str_list(res); + + res = parse_config_str_list(",a,,"); + CU_ASSERT(4 == res.size()); + CU_ASSERT(0 == strcmp("", res[0])); + CU_ASSERT(0 == strcmp("a", res[1])); + CU_ASSERT(0 == strcmp("", res[2])); + CU_ASSERT(0 == strcmp("", res[3])); + clear_config_str_list(res); - p = parse_header(StringRef::from_lit("alpha: bravo charlie")); - CU_ASSERT("alpha" == p.name); - CU_ASSERT("bravo charlie" == p.value); + res = parse_config_str_list(""); + CU_ASSERT(1 == res.size()); + CU_ASSERT(0 == strcmp("", res[0])); + clear_config_str_list(res); - p = parse_header(StringRef::from_lit("a,: b")); - CU_ASSERT(p.name.empty()); + res = parse_config_str_list("alpha,bravo,charlie"); + CU_ASSERT(3 == res.size()); + CU_ASSERT(0 == strcmp("alpha", res[0])); + CU_ASSERT(0 == strcmp("bravo", res[1])); + CU_ASSERT(0 == strcmp("charlie", res[2])); + clear_config_str_list(res); +} - p = parse_header(StringRef::from_lit("a: b\x0a")); - CU_ASSERT(p.name.empty()); +void test_shrpx_config_parse_header(void) { + auto p = parse_header("a: b"); + CU_ASSERT("a" == p.first); + CU_ASSERT("b" == p.second); + + p = parse_header("a: b"); + CU_ASSERT("a" == p.first); + CU_ASSERT("b" == p.second); + + p = parse_header(":a: b"); + CU_ASSERT(":a" == p.first); + CU_ASSERT("b" == p.second); + + p = parse_header("a: :b"); + CU_ASSERT("a" == p.first); + CU_ASSERT(":b" == p.second); + + p = parse_header(": b"); + CU_ASSERT(p.first.empty()); + + p = parse_header("alpha: bravo charlie"); + CU_ASSERT("alpha" == p.first); + CU_ASSERT("bravo charlie" == p.second); } void test_shrpx_config_parse_log_format(void) { - auto res = parse_log_format(StringRef::from_lit( - R"($remote_addr - $remote_user [$time_local] )" - R"("$request" $status $body_bytes_sent )" - R"("${http_referer}" $http_host "$http_user_agent")")); - CU_ASSERT(16 == res.size()); + auto res = parse_log_format("$remote_addr - $remote_user [$time_local] " + "\"$request\" $status $body_bytes_sent " + "\"$http_referer\" \"$http_user_agent\""); + CU_ASSERT(14 == res.size()); CU_ASSERT(SHRPX_LOGF_REMOTE_ADDR == res[0].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[1].type); - CU_ASSERT(" - $remote_user [" == res[1].value); + CU_ASSERT(0 == strcmp(" - $remote_user [", res[1].value.get())); CU_ASSERT(SHRPX_LOGF_TIME_LOCAL == res[2].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[3].type); - CU_ASSERT("] \"" == res[3].value); + CU_ASSERT(0 == strcmp("] \"", res[3].value.get())); CU_ASSERT(SHRPX_LOGF_REQUEST == res[4].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[5].type); - CU_ASSERT("\" " == res[5].value); + CU_ASSERT(0 == strcmp("\" ", res[5].value.get())); CU_ASSERT(SHRPX_LOGF_STATUS == res[6].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[7].type); - CU_ASSERT(" " == res[7].value); + CU_ASSERT(0 == strcmp(" ", res[7].value.get())); CU_ASSERT(SHRPX_LOGF_BODY_BYTES_SENT == res[8].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[9].type); - CU_ASSERT(" \"" == res[9].value); + CU_ASSERT(0 == strcmp(" \"", res[9].value.get())); CU_ASSERT(SHRPX_LOGF_HTTP == res[10].type); - CU_ASSERT("referer" == res[10].value); + CU_ASSERT(0 == strcmp("referer", res[10].value.get())); CU_ASSERT(SHRPX_LOGF_LITERAL == res[11].type); - CU_ASSERT("\" " == res[11].value); + CU_ASSERT(0 == strcmp("\" \"", res[11].value.get())); - CU_ASSERT(SHRPX_LOGF_AUTHORITY == res[12].type); + CU_ASSERT(SHRPX_LOGF_HTTP == res[12].type); + CU_ASSERT(0 == strcmp("user-agent", res[12].value.get())); CU_ASSERT(SHRPX_LOGF_LITERAL == res[13].type); - CU_ASSERT(" \"" == res[13].value); - - CU_ASSERT(SHRPX_LOGF_HTTP == res[14].type); - CU_ASSERT("user-agent" == res[14].value); - - CU_ASSERT(SHRPX_LOGF_LITERAL == res[15].type); - CU_ASSERT("\"" == res[15].value); - - res = parse_log_format(StringRef::from_lit("$")); - - CU_ASSERT(1 == res.size()); - - CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type); - CU_ASSERT("$" == res[0].value); - - res = parse_log_format(StringRef::from_lit("${")); - - CU_ASSERT(1 == res.size()); - - CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type); - CU_ASSERT("${" == res[0].value); - - res = parse_log_format(StringRef::from_lit("${a")); - - CU_ASSERT(1 == res.size()); - - CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type); - CU_ASSERT("${a" == res[0].value); - - res = parse_log_format(StringRef::from_lit("${a ")); - - CU_ASSERT(1 == res.size()); - - CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type); - CU_ASSERT("${a " == res[0].value); - - res = parse_log_format(StringRef::from_lit("$$remote_addr")); - - CU_ASSERT(2 == res.size()); - - CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type); - CU_ASSERT("$" == res[0].value); - - CU_ASSERT(SHRPX_LOGF_REMOTE_ADDR == res[1].type); - CU_ASSERT("" == res[1].value); -} - -void test_shrpx_config_read_tls_ticket_key_file(void) { - char file1[] = "/tmp/nghttpx-unittest.XXXXXX"; - auto fd1 = mkstemp(file1); - assert(fd1 != -1); - assert(48 == - write(fd1, "0..............12..............34..............5", 48)); - char file2[] = "/tmp/nghttpx-unittest.XXXXXX"; - auto fd2 = mkstemp(file2); - assert(fd2 != -1); - assert(48 == - write(fd2, "6..............78..............9a..............b", 48)); - - close(fd1); - close(fd2); - auto ticket_keys = - read_tls_ticket_key_file({file1, file2}, EVP_aes_128_cbc(), EVP_sha256()); - unlink(file1); - unlink(file2); - CU_ASSERT(ticket_keys.get() != nullptr); - CU_ASSERT(2 == ticket_keys->keys.size()); - auto key = &ticket_keys->keys[0]; - CU_ASSERT(std::equal(std::begin(key->data.name), std::end(key->data.name), - "0..............1")); - CU_ASSERT(std::equal(std::begin(key->data.enc_key), - std::begin(key->data.enc_key) + 16, "2..............3")); - CU_ASSERT(std::equal(std::begin(key->data.hmac_key), - std::begin(key->data.hmac_key) + 16, - "4..............5")); - CU_ASSERT(16 == key->hmac_keylen); - - key = &ticket_keys->keys[1]; - CU_ASSERT(std::equal(std::begin(key->data.name), std::end(key->data.name), - "6..............7")); - CU_ASSERT(std::equal(std::begin(key->data.enc_key), - std::begin(key->data.enc_key) + 16, "8..............9")); - CU_ASSERT(std::equal(std::begin(key->data.hmac_key), - std::begin(key->data.hmac_key) + 16, - "a..............b")); - CU_ASSERT(16 == key->hmac_keylen); -} - -void test_shrpx_config_read_tls_ticket_key_file_aes_256(void) { - char file1[] = "/tmp/nghttpx-unittest.XXXXXX"; - auto fd1 = mkstemp(file1); - assert(fd1 != -1); - assert(80 == write(fd1, "0..............12..............................34..." - "...........................5", - 80)); - char file2[] = "/tmp/nghttpx-unittest.XXXXXX"; - auto fd2 = mkstemp(file2); - assert(fd2 != -1); - assert(80 == write(fd2, "6..............78..............................9a..." - "...........................b", - 80)); - - close(fd1); - close(fd2); - auto ticket_keys = - read_tls_ticket_key_file({file1, file2}, EVP_aes_256_cbc(), EVP_sha256()); - unlink(file1); - unlink(file2); - CU_ASSERT(ticket_keys.get() != nullptr); - CU_ASSERT(2 == ticket_keys->keys.size()); - auto key = &ticket_keys->keys[0]; - CU_ASSERT(std::equal(std::begin(key->data.name), std::end(key->data.name), - "0..............1")); - CU_ASSERT(std::equal(std::begin(key->data.enc_key), - std::end(key->data.enc_key), - "2..............................3")); - CU_ASSERT(std::equal(std::begin(key->data.hmac_key), - std::end(key->data.hmac_key), - "4..............................5")); - - key = &ticket_keys->keys[1]; - CU_ASSERT(std::equal(std::begin(key->data.name), std::end(key->data.name), - "6..............7")); - CU_ASSERT(std::equal(std::begin(key->data.enc_key), - std::end(key->data.enc_key), - "8..............................9")); - CU_ASSERT(std::equal(std::begin(key->data.hmac_key), - std::end(key->data.hmac_key), - "a..............................b")); + CU_ASSERT(0 == strcmp("\"", res[13].value.get())); } } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_config_test.h nghttp2-0.6.7/src/shrpx_config_test.h --- nghttp2-1.13.0/src/shrpx_config_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_config_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,17 +25,11 @@ #ifndef SHRPX_CONFIG_TEST_H #define SHRPX_CONFIG_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - namespace shrpx { +void test_shrpx_config_parse_config_str_list(void); void test_shrpx_config_parse_header(void); void test_shrpx_config_parse_log_format(void); -void test_shrpx_config_read_tls_ticket_key_file(void); -void test_shrpx_config_read_tls_ticket_key_file_aes_256(void); -void test_shrpx_config_match_downstream_addr_group(void); } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_connect_blocker.cc nghttp2-0.6.7/src/shrpx_connect_blocker.cc --- nghttp2-1.13.0/src/shrpx_connect_blocker.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_connect_blocker.cc 2014-11-30 14:15:07.000000000 +0000 @@ -23,112 +23,59 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "shrpx_connect_blocker.h" -#include "shrpx_config.h" namespace shrpx { namespace { -void connect_blocker_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto connect_blocker = static_cast(w->data); - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Unblock"; - } - - connect_blocker->call_unblock_func(); -} +const int INITIAL_SLEEP = 2; } // namespace -ConnectBlocker::ConnectBlocker(std::mt19937 &gen, struct ev_loop *loop, - std::function block_func, - std::function unblock_func) - : gen_(gen), - block_func_(block_func), - unblock_func_(unblock_func), - loop_(loop), - fail_count_(0), - offline_(false) { - ev_timer_init(&timer_, connect_blocker_cb, 0., 0.); - timer_.data = this; -} - -ConnectBlocker::~ConnectBlocker() { ev_timer_stop(loop_, &timer_); } - -bool ConnectBlocker::blocked() const { return ev_is_active(&timer_); } +ConnectBlocker::ConnectBlocker() : timerev_(nullptr), sleep_(INITIAL_SLEEP) {} -void ConnectBlocker::on_success() { - if (ev_is_active(&timer_)) { - return; +ConnectBlocker::~ConnectBlocker() { + if (timerev_) { + event_free(timerev_); } - - fail_count_ = 0; } -// Use the similar backoff algorithm described in -// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md namespace { -constexpr size_t MAX_BACKOFF_EXP = 10; -constexpr auto MULTIPLIER = 1.6; -constexpr auto JITTER = 0.2; -} // namespace - -void ConnectBlocker::on_failure() { - if (ev_is_active(&timer_)) { - return; +void connect_blocker_cb(evutil_socket_t sig, short events, void *arg) { + if (LOG_ENABLED(INFO)) { + LOG(INFO) << "unblock downstream connection"; } - - call_block_func(); - - ++fail_count_; - - auto base_backoff = - util::int_pow(MULTIPLIER, std::min(MAX_BACKOFF_EXP, fail_count_)); - auto dist = std::uniform_real_distribution<>(-JITTER * base_backoff, - JITTER * base_backoff); - - auto &downstreamconf = *get_config()->conn.downstream; - - auto backoff = - std::min(downstreamconf.timeout.max_backoff, base_backoff + dist(gen_)); - - LOG(WARN) << "Could not connect " << fail_count_ - << " times in a row; sleep for " << backoff << " seconds"; - - ev_timer_set(&timer_, backoff, 0.); - ev_timer_start(loop_, &timer_); } +} // namespace -size_t ConnectBlocker::get_fail_count() const { return fail_count_; } +int ConnectBlocker::init(event_base *evbase) { + timerev_ = evtimer_new(evbase, connect_blocker_cb, this); -void ConnectBlocker::offline() { - if (offline_) { - return; + if (timerev_ == nullptr) { + return -1; } - if (!ev_is_active(&timer_)) { - call_block_func(); - } - - offline_ = true; + return 0; +} - ev_timer_stop(loop_, &timer_); - ev_timer_set(&timer_, std::numeric_limits::max(), 0.); - ev_timer_start(loop_, &timer_); +bool ConnectBlocker::blocked() const { + return evtimer_pending(timerev_, nullptr); } -void ConnectBlocker::online() { - ev_timer_stop(loop_, &timer_); +void ConnectBlocker::on_success() { sleep_ = INITIAL_SLEEP; } - call_unblock_func(); +void ConnectBlocker::on_failure() { + int rv; - fail_count_ = 0; + sleep_ = std::min(128, sleep_ * 2); - offline_ = false; -} + LOG(WARN) << "connect failure, start sleeping " << sleep_; -bool ConnectBlocker::in_offline() const { return offline_; } + timeval t = {sleep_, 0}; -void ConnectBlocker::call_block_func() { block_func_(); } + rv = evtimer_add(timerev_, &t); -void ConnectBlocker::call_unblock_func() { unblock_func_(); } + if (rv == -1) { + LOG(ERROR) << "evtimer_add for ConnectBlocker timerev_ failed"; + } +} } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_connect_blocker.h nghttp2-0.6.7/src/shrpx_connect_blocker.h --- nghttp2-1.13.0/src/shrpx_connect_blocker.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_connect_blocker.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,57 +27,28 @@ #include "shrpx.h" -#include - -#include +#include namespace shrpx { class ConnectBlocker { public: - ConnectBlocker(std::mt19937 &gen, struct ev_loop *loop, - std::function block_func, - std::function unblock_func); + ConnectBlocker(); ~ConnectBlocker(); + int init(event_base *evbase); // Returns true if making connection is not allowed. bool blocked() const; // Call this function if connect operation succeeded. This will // reset sleep_ to minimum value. void on_success(); - // Call this function if connect operations failed. This will start - // timer and blocks connection establishment with exponential - // backoff. + // Call this function if connect operation failed. This will start + // timer and blocks connection establishment for sleep_ seconds. void on_failure(); - size_t get_fail_count() const; - - // Peer is now considered offline. This effectively means that the - // connection is blocked until online() is called. - void offline(); - - // Peer is now considered online - void online(); - - // Returns true if peer is considered offline. - bool in_offline() const; - - void call_block_func(); - void call_unblock_func(); - private: - std::mt19937 &gen_; - // Called when blocking is started - std::function block_func_; - // Called when unblocked - std::function unblock_func_; - ev_timer timer_; - struct ev_loop *loop_; - // The number of consecutive connection failure. Reset to 0 on - // success. - size_t fail_count_; - // true if peer is considered offline. - bool offline_; + event *timerev_; + int sleep_; }; } // namespace diff -Nru nghttp2-1.13.0/src/shrpx_connection.cc nghttp2-0.6.7/src/shrpx_connection.cc --- nghttp2-1.13.0/src/shrpx_connection.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_connection.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,764 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_connection.h" - -#ifdef HAVE_UNISTD_H -#include -#endif // HAVE_UNISTD_H - -#include - -#include - -#include "shrpx_ssl.h" -#include "shrpx_memcached_request.h" -#include "memchunk.h" -#include "util.h" -#include "ssl_compat.h" - -using namespace nghttp2; - -namespace shrpx { - -#if !OPENSSL_101_API - -void *BIO_get_data(BIO *bio) { return bio->ptr; } -void BIO_set_data(BIO *bio, void *ptr) { bio->ptr = ptr; } -void BIO_set_init(BIO *bio, int init) { bio->init = init; } - -#endif // !OPENSSL_101_API - -Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl, - MemchunkPool *mcpool, ev_tstamp write_timeout, - ev_tstamp read_timeout, - const RateLimitConfig &write_limit, - const RateLimitConfig &read_limit, IOCb writecb, - IOCb readcb, TimerCb timeoutcb, void *data, - size_t tls_dyn_rec_warmup_threshold, - ev_tstamp tls_dyn_rec_idle_timeout, shrpx_proto proto) - : tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool)}, - wlimit(loop, &wev, write_limit.rate, write_limit.burst), - rlimit(loop, &rev, read_limit.rate, read_limit.burst, this), - loop(loop), - data(data), - fd(fd), - tls_dyn_rec_warmup_threshold(tls_dyn_rec_warmup_threshold), - tls_dyn_rec_idle_timeout(tls_dyn_rec_idle_timeout), - proto(proto) { - - ev_io_init(&wev, writecb, fd, EV_WRITE); - ev_io_init(&rev, readcb, fd, EV_READ); - - wev.data = this; - rev.data = this; - - ev_timer_init(&wt, timeoutcb, 0., write_timeout); - ev_timer_init(&rt, timeoutcb, 0., read_timeout); - - wt.data = this; - rt.data = this; - - // set 0. to double field explicitly just in case - tls.last_write_idle = 0.; - - if (ssl) { - set_ssl(ssl); - } -} - -Connection::~Connection() { disconnect(); } - -void Connection::disconnect() { - if (tls.ssl) { - SSL_set_shutdown(tls.ssl, SSL_RECEIVED_SHUTDOWN); - ERR_clear_error(); - - if (tls.cached_session) { - SSL_SESSION_free(tls.cached_session); - tls.cached_session = nullptr; - } - - if (tls.cached_session_lookup_req) { - tls.cached_session_lookup_req->canceled = true; - tls.cached_session_lookup_req = nullptr; - } - - SSL_shutdown(tls.ssl); - SSL_free(tls.ssl); - tls.ssl = nullptr; - - tls.wbuf.reset(); - tls.rbuf.reset(); - tls.last_write_idle = 0.; - tls.warmup_writelen = 0; - tls.last_writelen = 0; - tls.last_readlen = 0; - tls.handshake_state = 0; - tls.initial_handshake_done = false; - tls.reneg_started = false; - } - - if (fd != -1) { - shutdown(fd, SHUT_WR); - close(fd); - fd = -1; - } - - // Stop watchers here because they could be activated in - // SSL_shutdown(). - ev_timer_stop(loop, &rt); - ev_timer_stop(loop, &wt); - - rlimit.stopw(); - wlimit.stopw(); -} - -void Connection::prepare_client_handshake() { SSL_set_connect_state(tls.ssl); } - -void Connection::prepare_server_handshake() { SSL_set_accept_state(tls.ssl); } - -// BIO implementation is inspired by openldap implementation: -// http://www.openldap.org/devel/cvsweb.cgi/~checkout~/libraries/libldap/tls_o.c -namespace { -int shrpx_bio_write(BIO *b, const char *buf, int len) { - if (buf == nullptr || len <= 0) { - return 0; - } - - auto conn = static_cast(BIO_get_data(b)); - auto &wbuf = conn->tls.wbuf; - - BIO_clear_retry_flags(b); - - if (conn->tls.initial_handshake_done) { - // After handshake finished, send |buf| of length |len| to the - // socket directly. - - // Only when TLS session was prematurely ended before server sent - // all handshake message, this condition is true. This could be - // alert from SSL_shutdown(). Since connection is already down, - // just return error. - if (wbuf.rleft()) { - return -1; - } - auto nwrite = conn->write_clear(buf, len); - if (nwrite < 0) { - return -1; - } - - if (nwrite == 0) { - BIO_set_retry_write(b); - return -1; - } - - return nwrite; - } - - wbuf.append(buf, len); - - return len; -} -} // namespace - -namespace { -int shrpx_bio_read(BIO *b, char *buf, int len) { - if (buf == nullptr || len <= 0) { - return 0; - } - - auto conn = static_cast(BIO_get_data(b)); - auto &rbuf = conn->tls.rbuf; - - BIO_clear_retry_flags(b); - - if (conn->tls.initial_handshake_done && rbuf.rleft() == 0) { - auto nread = conn->read_clear(buf, len); - if (nread < 0) { - return -1; - } - if (nread == 0) { - BIO_set_retry_read(b); - return -1; - } - return nread; - } - - if (rbuf.rleft() == 0) { - BIO_set_retry_read(b); - return -1; - } - - return rbuf.remove(buf, len); -} -} // namespace - -namespace { -int shrpx_bio_puts(BIO *b, const char *str) { - return shrpx_bio_write(b, str, strlen(str)); -} -} // namespace - -namespace { -int shrpx_bio_gets(BIO *b, char *buf, int len) { return -1; } -} // namespace - -namespace { -long shrpx_bio_ctrl(BIO *b, int cmd, long num, void *ptr) { - switch (cmd) { - case BIO_CTRL_FLUSH: - return 1; - } - - return 0; -} -} // namespace - -namespace { -int shrpx_bio_create(BIO *b) { -#if OPENSSL_101_API - BIO_set_init(b, 1); -#else // !OPENSSL_101_API - b->init = 1; - b->num = 0; - b->ptr = nullptr; - b->flags = 0; -#endif // !OPENSSL_101_API - return 1; -} -} // namespace - -namespace { -int shrpx_bio_destroy(BIO *b) { - if (b == nullptr) { - return 0; - } - -#if !OPENSSL_101_API - b->ptr = nullptr; - b->init = 0; - b->flags = 0; -#endif // !OPENSSL_101_API - - return 1; -} -} // namespace - -#if OPENSSL_101_API - -BIO_METHOD *create_bio_method() { - auto meth = BIO_meth_new(BIO_TYPE_FD, "nghttpx-bio"); - BIO_meth_set_write(meth, shrpx_bio_write); - BIO_meth_set_read(meth, shrpx_bio_read); - BIO_meth_set_puts(meth, shrpx_bio_puts); - BIO_meth_set_gets(meth, shrpx_bio_gets); - BIO_meth_set_ctrl(meth, shrpx_bio_ctrl); - BIO_meth_set_create(meth, shrpx_bio_create); - BIO_meth_set_destroy(meth, shrpx_bio_destroy); - - return meth; -} - -void delete_bio_method(BIO_METHOD *bio_method) { BIO_meth_free(bio_method); } - -#else // !OPENSSL_101_API - -BIO_METHOD *create_bio_method() { - static BIO_METHOD shrpx_bio_method = { - BIO_TYPE_FD, "nghttpx-bio", shrpx_bio_write, - shrpx_bio_read, shrpx_bio_puts, shrpx_bio_gets, - shrpx_bio_ctrl, shrpx_bio_create, shrpx_bio_destroy, - }; - - return &shrpx_bio_method; -} - -void delete_bio_method(BIO_METHOD *bio_method) {} - -#endif // !OPENSSL_101_API - -void Connection::set_ssl(SSL *ssl) { - tls.ssl = ssl; - - auto &tlsconf = get_config()->tls; - auto bio = BIO_new(tlsconf.bio_method); - BIO_set_data(bio, this); - SSL_set_bio(tls.ssl, bio, bio); - SSL_set_app_data(tls.ssl, this); -} - -namespace { -// We should buffer at least full encrypted TLS record here. -// Theoretically, peer can send client hello in several TLS records, -// which could exeed this limit, but it is not portable, and we don't -// have to handle such exotic behaviour. -bool read_buffer_full(DefaultPeekMemchunks &rbuf) { - return rbuf.rleft_buffered() >= 20_k; -} -} // namespace - -int Connection::tls_handshake() { - wlimit.stopw(); - ev_timer_stop(loop, &wt); - - if (ev_is_active(&rev)) { - std::array buf; - auto nread = read_clear(buf.data(), buf.size()); - if (nread < 0) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "tls: handshake read error"; - } - return -1; - } - tls.rbuf.append(buf.data(), nread); - if (read_buffer_full(tls.rbuf)) { - rlimit.stopw(); - } - } - - if (tls.initial_handshake_done) { - return write_tls_pending_handshake(); - } - - switch (tls.handshake_state) { - case TLS_CONN_WAIT_FOR_SESSION_CACHE: - return SHRPX_ERR_INPROGRESS; - case TLS_CONN_GOT_SESSION_CACHE: { - // Use the same trick invented by @kazuho in h2o project. - - // Discard all outgoing data. - tls.wbuf.reset(); - // Rewind buffered incoming data to replay client hello. - tls.rbuf.disable_peek(false); - - auto ssl_ctx = SSL_get_SSL_CTX(tls.ssl); - auto ssl_opts = SSL_get_options(tls.ssl); - SSL_free(tls.ssl); - - auto ssl = ssl::create_ssl(ssl_ctx); - if (!ssl) { - return -1; - } - if (ssl_opts & SSL_OP_NO_TICKET) { - SSL_set_options(ssl, SSL_OP_NO_TICKET); - } - - set_ssl(ssl); - - SSL_set_accept_state(tls.ssl); - - tls.handshake_state = TLS_CONN_NORMAL; - break; - } - case TLS_CONN_CANCEL_SESSION_CACHE: - tls.handshake_state = TLS_CONN_NORMAL; - break; - } - - auto rv = SSL_do_handshake(tls.ssl); - - if (rv <= 0) { - auto err = SSL_get_error(tls.ssl, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - if (read_buffer_full(tls.rbuf)) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "tls: handshake message is too large"; - } - return -1; - } - break; - case SSL_ERROR_WANT_WRITE: - break; - case SSL_ERROR_SSL: - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "tls: handshake libssl error: " - << ERR_error_string(ERR_get_error(), nullptr); - } - return SHRPX_ERR_NETWORK; - default: - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "tls: handshake libssl error " << err; - } - return SHRPX_ERR_NETWORK; - } - } - - if (tls.handshake_state == TLS_CONN_WAIT_FOR_SESSION_CACHE) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "tls: handshake is still in progress"; - } - return SHRPX_ERR_INPROGRESS; - } - - // Don't send handshake data if handshake was completed in OpenSSL - // routine. We have to check HTTP/2 requirement if HTTP/2 was - // negotiated before sending finished message to the peer. - if (rv != 1 && tls.wbuf.rleft()) { - // First write indicates that resumption stuff has done. - if (tls.handshake_state != TLS_CONN_WRITE_STARTED) { - tls.handshake_state = TLS_CONN_WRITE_STARTED; - // If peek has already disabled, this is noop. - tls.rbuf.disable_peek(true); - } - std::array iov; - auto iovcnt = tls.wbuf.riovec(iov.data(), iov.size()); - auto nwrite = writev_clear(iov.data(), iovcnt); - if (nwrite < 0) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "tls: handshake write error"; - } - return -1; - } - tls.wbuf.drain(nwrite); - - if (tls.wbuf.rleft()) { - wlimit.startw(); - ev_timer_again(loop, &wt); - } - } - - if (!read_buffer_full(tls.rbuf)) { - // We may have stopped reading - rlimit.startw(); - } - - if (rv != 1) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "tls: handshake is still in progress"; - } - return SHRPX_ERR_INPROGRESS; - } - - // Handshake was done - - rv = check_http2_requirement(); - if (rv != 0) { - return -1; - } - - // Just in case - tls.rbuf.disable_peek(true); - - tls.initial_handshake_done = true; - - return write_tls_pending_handshake(); -} - -int Connection::write_tls_pending_handshake() { - // Send handshake data left in the buffer - while (tls.wbuf.rleft()) { - std::array iov; - auto iovcnt = tls.wbuf.riovec(iov.data(), iov.size()); - auto nwrite = writev_clear(iov.data(), iovcnt); - if (nwrite < 0) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "tls: handshake write error"; - } - return -1; - } - if (nwrite == 0) { - wlimit.startw(); - ev_timer_again(loop, &wt); - - return SHRPX_ERR_INPROGRESS; - } - tls.wbuf.drain(nwrite); - } - - // We have to start read watcher, since later stage of code expects - // this. - rlimit.startw(); - - // We may have whole request in tls.rbuf. This means that we don't - // get notified further read event. This is especially true for - // HTTP/1.1. - handle_tls_pending_read(); - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "SSL/TLS handshake completed"; - if (SSL_session_reused(tls.ssl)) { - LOG(INFO) << "SSL/TLS session reused"; - } - } - - return 0; -} - -int Connection::check_http2_requirement() { - const unsigned char *next_proto = nullptr; - unsigned int next_proto_len; - - SSL_get0_next_proto_negotiated(tls.ssl, &next_proto, &next_proto_len); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (next_proto == nullptr) { - SSL_get0_alpn_selected(tls.ssl, &next_proto, &next_proto_len); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - if (next_proto == nullptr || - !util::check_h2_is_selected(StringRef{next_proto, next_proto_len})) { - return 0; - } - if (!nghttp2::ssl::check_http2_tls_version(tls.ssl)) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "TLSv1.2 was not negotiated. HTTP/2 must not be used."; - } - return -1; - } - if (!get_config()->tls.no_http2_cipher_black_list && - nghttp2::ssl::check_http2_cipher_black_list(tls.ssl)) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "The negotiated cipher suite is in HTTP/2 cipher suite " - "black list. HTTP/2 must not be used."; - } - return -1; - } - - return 0; -} - -namespace { -const size_t SHRPX_SMALL_WRITE_LIMIT = 1300; -} // namespace - -size_t Connection::get_tls_write_limit() { - - if (tls_dyn_rec_warmup_threshold == 0) { - return std::numeric_limits::max(); - } - - auto t = ev_now(loop); - - if (tls.last_write_idle >= 0. && - t - tls.last_write_idle > tls_dyn_rec_idle_timeout) { - // Time out, use small record size - tls.warmup_writelen = 0; - return SHRPX_SMALL_WRITE_LIMIT; - } - - if (tls.warmup_writelen >= tls_dyn_rec_warmup_threshold) { - return std::numeric_limits::max(); - } - - return SHRPX_SMALL_WRITE_LIMIT; -} - -void Connection::update_tls_warmup_writelen(size_t n) { - if (tls.warmup_writelen < tls_dyn_rec_warmup_threshold) { - tls.warmup_writelen += n; - } -} - -void Connection::start_tls_write_idle() { - if (tls.last_write_idle < 0.) { - tls.last_write_idle = ev_now(loop); - } -} - -ssize_t Connection::write_tls(const void *data, size_t len) { - // SSL_write requires the same arguments (buf pointer and its - // length) on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. - // get_write_limit() may return smaller length than previously - // passed to SSL_write, which violates OpenSSL assumption. To avoid - // this, we keep last legnth passed to SSL_write to - // tls.last_writelen if SSL_write indicated I/O blocking. - if (tls.last_writelen == 0) { - len = std::min(len, wlimit.avail()); - len = std::min(len, get_tls_write_limit()); - if (len == 0) { - return 0; - } - } else { - len = tls.last_writelen; - tls.last_writelen = 0; - } - - tls.last_write_idle = -1.; - - auto rv = SSL_write(tls.ssl, data, len); - - if (rv <= 0) { - auto err = SSL_get_error(tls.ssl, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Close connection due to TLS renegotiation"; - } - return SHRPX_ERR_NETWORK; - case SSL_ERROR_WANT_WRITE: - tls.last_writelen = len; - // starting write watcher and timer is done in write_clear via - // bio. - return 0; - case SSL_ERROR_SSL: - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "SSL_write: " << ERR_error_string(ERR_get_error(), - nullptr); - } - return SHRPX_ERR_NETWORK; - default: - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "SSL_write: SSL_get_error returned " << err; - } - return SHRPX_ERR_NETWORK; - } - } - - wlimit.drain(rv); - - update_tls_warmup_writelen(rv); - - return rv; -} - -ssize_t Connection::read_tls(void *data, size_t len) { - // SSL_read requires the same arguments (buf pointer and its - // length) on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. - // rlimit_.avail() or rlimit_.avail() may return different length - // than the length previously passed to SSL_read, which violates - // OpenSSL assumption. To avoid this, we keep last legnth passed - // to SSL_read to tls_last_readlen_ if SSL_read indicated I/O - // blocking. - if (tls.last_readlen == 0) { - len = std::min(len, rlimit.avail()); - if (len == 0) { - return 0; - } - } else { - len = tls.last_readlen; - tls.last_readlen = 0; - } - - auto rv = SSL_read(tls.ssl, data, len); - - if (rv <= 0) { - auto err = SSL_get_error(tls.ssl, rv); - switch (err) { - case SSL_ERROR_WANT_READ: - tls.last_readlen = len; - return 0; - case SSL_ERROR_WANT_WRITE: - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Close connection due to TLS renegotiation"; - } - return SHRPX_ERR_NETWORK; - case SSL_ERROR_ZERO_RETURN: - return SHRPX_ERR_EOF; - case SSL_ERROR_SSL: - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "SSL_read: " << ERR_error_string(ERR_get_error(), nullptr); - } - return SHRPX_ERR_NETWORK; - default: - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "SSL_read: SSL_get_error returned " << err; - } - return SHRPX_ERR_NETWORK; - } - } - - rlimit.drain(rv); - - return rv; -} - -ssize_t Connection::write_clear(const void *data, size_t len) { - len = std::min(len, wlimit.avail()); - if (len == 0) { - return 0; - } - - ssize_t nwrite; - while ((nwrite = write(fd, data, len)) == -1 && errno == EINTR) - ; - if (nwrite == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - wlimit.startw(); - ev_timer_again(loop, &wt); - return 0; - } - return SHRPX_ERR_NETWORK; - } - - wlimit.drain(nwrite); - - return nwrite; -} - -ssize_t Connection::writev_clear(struct iovec *iov, int iovcnt) { - iovcnt = limit_iovec(iov, iovcnt, wlimit.avail()); - if (iovcnt == 0) { - return 0; - } - - ssize_t nwrite; - while ((nwrite = writev(fd, iov, iovcnt)) == -1 && errno == EINTR) - ; - if (nwrite == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - wlimit.startw(); - ev_timer_again(loop, &wt); - return 0; - } - return SHRPX_ERR_NETWORK; - } - - wlimit.drain(nwrite); - - return nwrite; -} - -ssize_t Connection::read_clear(void *data, size_t len) { - len = std::min(len, rlimit.avail()); - if (len == 0) { - return 0; - } - - ssize_t nread; - while ((nread = read(fd, data, len)) == -1 && errno == EINTR) - ; - if (nread == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - return 0; - } - return SHRPX_ERR_NETWORK; - } - - if (nread == 0) { - return SHRPX_ERR_EOF; - } - - rlimit.drain(nread); - - return nread; -} - -void Connection::handle_tls_pending_read() { - if (!ev_is_active(&rev)) { - return; - } - rlimit.handle_tls_pending_read(); -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_connection.h nghttp2-0.6.7/src/shrpx_connection.h --- nghttp2-1.13.0/src/shrpx_connection.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_connection.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_CONNECTION_H -#define SHRPX_CONNECTION_H - -#include "shrpx_config.h" - -#include - -#include - -#include - -#include "shrpx_rate_limit.h" -#include "shrpx_error.h" -#include "memchunk.h" - -namespace shrpx { - -struct MemcachedRequest; - -enum { - TLS_CONN_NORMAL, - TLS_CONN_WAIT_FOR_SESSION_CACHE, - TLS_CONN_GOT_SESSION_CACHE, - TLS_CONN_CANCEL_SESSION_CACHE, - TLS_CONN_WRITE_STARTED, -}; - -struct TLSConnection { - DefaultMemchunks wbuf; - DefaultPeekMemchunks rbuf; - SSL *ssl; - SSL_SESSION *cached_session; - MemcachedRequest *cached_session_lookup_req; - ev_tstamp last_write_idle; - size_t warmup_writelen; - // length passed to SSL_write and SSL_read last time. This is - // required since these functions require the exact same parameters - // on non-blocking I/O. - size_t last_writelen, last_readlen; - int handshake_state; - bool initial_handshake_done; - bool reneg_started; -}; - -template using EVCb = void (*)(struct ev_loop *, T *, int); - -using IOCb = EVCb; -using TimerCb = EVCb; - -struct Connection { - Connection(struct ev_loop *loop, int fd, SSL *ssl, MemchunkPool *mcpool, - ev_tstamp write_timeout, ev_tstamp read_timeout, - const RateLimitConfig &write_limit, - const RateLimitConfig &read_limit, IOCb writecb, IOCb readcb, - TimerCb timeoutcb, void *data, size_t tls_dyn_rec_warmup_threshold, - ev_tstamp tls_dyn_rec_idle_timeout, shrpx_proto proto); - ~Connection(); - - void disconnect(); - - void prepare_client_handshake(); - void prepare_server_handshake(); - - int tls_handshake(); - int write_tls_pending_handshake(); - - int check_http2_requirement(); - - // All write_* and writev_clear functions return number of bytes - // written. If nothing cannot be written (e.g., there is no - // allowance in RateLimit or underlying connection blocks), return - // 0. SHRPX_ERR_NETWORK is returned in case of error. - // - // All read_* functions return number of bytes read. If nothing - // cannot be read (e.g., there is no allowance in Ratelimit or - // underlying connection blocks), return 0. SHRPX_ERR_EOF is - // returned in case of EOF and no data was read. Otherwise - // SHRPX_ERR_NETWORK is return in case of error. - ssize_t write_tls(const void *data, size_t len); - ssize_t read_tls(void *data, size_t len); - - size_t get_tls_write_limit(); - // Updates the number of bytes written in warm up period. - void update_tls_warmup_writelen(size_t n); - // Tells there is no immediate write now. This triggers timer to - // determine fallback to short record size mode. - void start_tls_write_idle(); - - ssize_t write_clear(const void *data, size_t len); - ssize_t writev_clear(struct iovec *iov, int iovcnt); - ssize_t read_clear(void *data, size_t len); - - void handle_tls_pending_read(); - - void set_ssl(SSL *ssl); - - TLSConnection tls; - ev_io wev; - ev_io rev; - ev_timer wt; - ev_timer rt; - RateLimit wlimit; - RateLimit rlimit; - struct ev_loop *loop; - void *data; - int fd; - size_t tls_dyn_rec_warmup_threshold; - ev_tstamp tls_dyn_rec_idle_timeout; - // Application protocol used over the connection. This field is not - // used in this object at the moment. The rest of the program may - // use this value when it is useful. - shrpx_proto proto; -}; - -// Creates BIO_method shared by all SSL objects. If nghttp2 is built -// with OpenSSL < 1.1.0, this returns statically allocated object. -// Otherwise, it returns new BIO_METHOD object every time. -BIO_METHOD *create_bio_method(); - -// Deletes given |bio_method|. If nghttp2 is built with OpenSSL < -// 1.1.0, this function is noop. -void delete_bio_method(BIO_METHOD *bio_method); - -} // namespace shrpx - -#endif // SHRPX_CONNECTION_H diff -Nru nghttp2-1.13.0/src/shrpx_connection_handler.cc nghttp2-0.6.7/src/shrpx_connection_handler.cc --- nghttp2-1.13.0/src/shrpx_connection_handler.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_connection_handler.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,893 +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. - */ -#include "shrpx_connection_handler.h" - -#ifdef HAVE_UNISTD_H -#include -#endif // HAVE_UNISTD_H -#include -#include - -#include -#include -#include - -#include "shrpx_client_handler.h" -#include "shrpx_ssl.h" -#include "shrpx_worker.h" -#include "shrpx_config.h" -#include "shrpx_http2_session.h" -#include "shrpx_connect_blocker.h" -#include "shrpx_downstream_connection.h" -#include "shrpx_accept_handler.h" -#include "shrpx_memcached_dispatcher.h" -#include "shrpx_signal.h" -#include "util.h" -#include "template.h" - -using namespace nghttp2; - -namespace shrpx { - -namespace { -void acceptor_disable_cb(struct ev_loop *loop, ev_timer *w, int revent) { - auto h = static_cast(w->data); - - // If we are in graceful shutdown period, we must not enable - // acceptors again. - if (h->get_graceful_shutdown()) { - return; - } - - h->enable_acceptor(); -} -} // namespace - -namespace { -void ocsp_cb(struct ev_loop *loop, ev_timer *w, int revent) { - auto h = static_cast(w->data); - - // If we are in graceful shutdown period, we won't do ocsp query. - if (h->get_graceful_shutdown()) { - return; - } - - LOG(NOTICE) << "Start ocsp update"; - - h->proceed_next_cert_ocsp(); -} -} // namespace - -namespace { -void ocsp_read_cb(struct ev_loop *loop, ev_io *w, int revent) { - auto h = static_cast(w->data); - - h->read_ocsp_chunk(); -} -} // namespace - -namespace { -void ocsp_chld_cb(struct ev_loop *loop, ev_child *w, int revent) { - auto h = static_cast(w->data); - - h->handle_ocsp_complete(); -} -} // namespace - -namespace { -void thread_join_async_cb(struct ev_loop *loop, ev_async *w, int revent) { - ev_break(loop); -} -} // namespace - -namespace { -void serial_event_async_cb(struct ev_loop *loop, ev_async *w, int revent) { - auto h = static_cast(w->data); - - h->handle_serial_event(); -} -} // namespace - -ConnectionHandler::ConnectionHandler(struct ev_loop *loop, std::mt19937 &gen) - : gen_(gen), - single_worker_(nullptr), - loop_(loop), - tls_ticket_key_memcached_get_retry_count_(0), - tls_ticket_key_memcached_fail_count_(0), - worker_round_robin_cnt_(get_config()->api.enabled ? 1 : 0), - graceful_shutdown_(false) { - ev_timer_init(&disable_acceptor_timer_, acceptor_disable_cb, 0., 0.); - disable_acceptor_timer_.data = this; - - ev_timer_init(&ocsp_timer_, ocsp_cb, 0., 0.); - ocsp_timer_.data = this; - - ev_io_init(&ocsp_.rev, ocsp_read_cb, -1, EV_READ); - ocsp_.rev.data = this; - - ev_async_init(&thread_join_asyncev_, thread_join_async_cb); - - ev_async_init(&serial_event_asyncev_, serial_event_async_cb); - serial_event_asyncev_.data = this; - - ev_async_start(loop_, &serial_event_asyncev_); - - ev_child_init(&ocsp_.chldev, ocsp_chld_cb, 0, 0); - ocsp_.chldev.data = this; - - ocsp_.next = 0; - ocsp_.fd = -1; - - reset_ocsp(); -} - -ConnectionHandler::~ConnectionHandler() { - ev_child_stop(loop_, &ocsp_.chldev); - ev_async_stop(loop_, &serial_event_asyncev_); - ev_async_stop(loop_, &thread_join_asyncev_); - ev_io_stop(loop_, &ocsp_.rev); - ev_timer_stop(loop_, &ocsp_timer_); - ev_timer_stop(loop_, &disable_acceptor_timer_); - - for (auto ssl_ctx : all_ssl_ctx_) { - auto tls_ctx_data = - static_cast(SSL_CTX_get_app_data(ssl_ctx)); - if (tls_ctx_data) { - delete tls_ctx_data; - } - SSL_CTX_free(ssl_ctx); - } - - // Free workers before destroying ev_loop - workers_.clear(); - - for (auto loop : worker_loops_) { - ev_loop_destroy(loop); - } -} - -void ConnectionHandler::set_ticket_keys_to_worker( - const std::shared_ptr &ticket_keys) { - for (auto &worker : workers_) { - worker->set_ticket_keys(ticket_keys); - } -} - -void ConnectionHandler::worker_reopen_log_files() { - WorkerEvent wev{}; - - wev.type = REOPEN_LOG; - - for (auto &worker : workers_) { - worker->send(wev); - } -} - -void ConnectionHandler::worker_replace_downstream( - std::shared_ptr downstreamconf) { - WorkerEvent wev{}; - - wev.type = REPLACE_DOWNSTREAM; - wev.downstreamconf = std::move(downstreamconf); - - for (auto &worker : workers_) { - worker->send(wev); - } -} - -int ConnectionHandler::create_single_worker() { - cert_tree_ = ssl::create_cert_lookup_tree(); - auto sv_ssl_ctx = ssl::setup_server_ssl_context(all_ssl_ctx_, cert_tree_.get() -#ifdef HAVE_NEVERBLEED - , - nb_.get() -#endif // HAVE_NEVERBLEED - ); - auto cl_ssl_ctx = ssl::setup_downstream_client_ssl_context( -#ifdef HAVE_NEVERBLEED - nb_.get() -#endif // HAVE_NEVERBLEED - ); - - if (cl_ssl_ctx) { - all_ssl_ctx_.push_back(cl_ssl_ctx); - } - - auto &tlsconf = get_config()->tls; - auto &memcachedconf = get_config()->tls.session_cache.memcached; - - SSL_CTX *session_cache_ssl_ctx = nullptr; - if (memcachedconf.tls) { - session_cache_ssl_ctx = ssl::create_ssl_client_context( -#ifdef HAVE_NEVERBLEED - nb_.get(), -#endif // HAVE_NEVERBLEED - StringRef{tlsconf.cacert}, StringRef{memcachedconf.cert_file}, - StringRef{memcachedconf.private_key_file}, nullptr); - all_ssl_ctx_.push_back(session_cache_ssl_ctx); - } - - single_worker_ = make_unique( - loop_, sv_ssl_ctx, cl_ssl_ctx, session_cache_ssl_ctx, cert_tree_.get(), - ticket_keys_, this, get_config()->conn.downstream); -#ifdef HAVE_MRUBY - if (single_worker_->create_mruby_context() != 0) { - return -1; - } -#endif // HAVE_MRUBY - - return 0; -} - -int ConnectionHandler::create_worker_thread(size_t num) { -#ifndef NOTHREADS - assert(workers_.size() == 0); - - cert_tree_ = ssl::create_cert_lookup_tree(); - auto sv_ssl_ctx = ssl::setup_server_ssl_context(all_ssl_ctx_, cert_tree_.get() -#ifdef HAVE_NEVERBLEED - , - nb_.get() -#endif // HAVE_NEVERBLEED - ); - auto cl_ssl_ctx = ssl::setup_downstream_client_ssl_context( -#ifdef HAVE_NEVERBLEED - nb_.get() -#endif // HAVE_NEVERBLEED - ); - - if (cl_ssl_ctx) { - all_ssl_ctx_.push_back(cl_ssl_ctx); - } - - auto &tlsconf = get_config()->tls; - auto &memcachedconf = get_config()->tls.session_cache.memcached; - auto &apiconf = get_config()->api; - - // We have dedicated worker for API request processing. - if (apiconf.enabled) { - ++num; - } - - for (size_t i = 0; i < num; ++i) { - auto loop = ev_loop_new(get_config()->ev_loop_flags); - - SSL_CTX *session_cache_ssl_ctx = nullptr; - if (memcachedconf.tls) { - session_cache_ssl_ctx = ssl::create_ssl_client_context( -#ifdef HAVE_NEVERBLEED - nb_.get(), -#endif // HAVE_NEVERBLEED - StringRef{tlsconf.cacert}, StringRef{memcachedconf.cert_file}, - StringRef{memcachedconf.private_key_file}, nullptr); - all_ssl_ctx_.push_back(session_cache_ssl_ctx); - } - auto worker = make_unique( - loop, sv_ssl_ctx, cl_ssl_ctx, session_cache_ssl_ctx, cert_tree_.get(), - ticket_keys_, this, get_config()->conn.downstream); -#ifdef HAVE_MRUBY - if (worker->create_mruby_context() != 0) { - return -1; - } -#endif // HAVE_MRUBY - - workers_.push_back(std::move(worker)); - worker_loops_.push_back(loop); - - LLOG(NOTICE, this) << "Created worker thread #" << workers_.size() - 1; - } - - for (auto &worker : workers_) { - worker->run_async(); - } - -#endif // NOTHREADS - - return 0; -} - -void ConnectionHandler::join_worker() { -#ifndef NOTHREADS - int n = 0; - - if (LOG_ENABLED(INFO)) { - LLOG(INFO, this) << "Waiting for worker thread to join: n=" - << workers_.size(); - } - - for (auto &worker : workers_) { - worker->wait(); - if (LOG_ENABLED(INFO)) { - LLOG(INFO, this) << "Thread #" << n << " joined"; - } - ++n; - } -#endif // NOTHREADS -} - -void ConnectionHandler::graceful_shutdown_worker() { - if (get_config()->num_worker == 1) { - return; - } - - WorkerEvent wev{}; - wev.type = GRACEFUL_SHUTDOWN; - - if (LOG_ENABLED(INFO)) { - LLOG(INFO, this) << "Sending graceful shutdown signal to worker"; - } - - for (auto &worker : workers_) { - worker->send(wev); - } - -#ifndef NOTHREADS - ev_async_start(loop_, &thread_join_asyncev_); - - thread_join_fut_ = std::async(std::launch::async, [this]() { - (void)reopen_log_files(); - join_worker(); - ev_async_send(get_loop(), &thread_join_asyncev_); - delete log_config(); - }); -#endif // NOTHREADS -} - -int ConnectionHandler::handle_connection(int fd, sockaddr *addr, int addrlen, - const UpstreamAddr *faddr) { - if (LOG_ENABLED(INFO)) { - LLOG(INFO, this) << "Accepted connection. fd=" << fd; - } - - if (get_config()->num_worker == 1) { - auto &upstreamconf = get_config()->conn.upstream; - if (single_worker_->get_worker_stat()->num_connections >= - upstreamconf.worker_connections) { - - if (LOG_ENABLED(INFO)) { - LLOG(INFO, this) << "Too many connections >=" - << upstreamconf.worker_connections; - } - - close(fd); - return -1; - } - - auto client = - ssl::accept_connection(single_worker_.get(), fd, addr, addrlen, faddr); - if (!client) { - LLOG(ERROR, this) << "ClientHandler creation failed"; - - close(fd); - return -1; - } - - return 0; - } - - Worker *worker; - - if (faddr->alt_mode == ALTMODE_API) { - worker = workers_[0].get(); - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Dispatch connection to API worker #0"; - } - } else { - worker = workers_[worker_round_robin_cnt_].get(); - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Dispatch connection to worker #" << worker_round_robin_cnt_; - } - - if (++worker_round_robin_cnt_ == workers_.size()) { - auto &apiconf = get_config()->api; - - if (apiconf.enabled) { - worker_round_robin_cnt_ = 1; - } else { - worker_round_robin_cnt_ = 0; - } - } - } - - WorkerEvent wev{}; - wev.type = NEW_CONNECTION; - wev.client_fd = fd; - memcpy(&wev.client_addr, addr, addrlen); - wev.client_addrlen = addrlen; - wev.faddr = faddr; - - worker->send(wev); - - return 0; -} - -struct ev_loop *ConnectionHandler::get_loop() const { - return loop_; -} - -Worker *ConnectionHandler::get_single_worker() const { - return single_worker_.get(); -} - -void ConnectionHandler::add_acceptor(std::unique_ptr h) { - acceptors_.push_back(std::move(h)); -} - -void ConnectionHandler::enable_acceptor() { - for (auto &a : acceptors_) { - a->enable(); - } -} - -void ConnectionHandler::disable_acceptor() { - for (auto &a : acceptors_) { - a->disable(); - } -} - -void ConnectionHandler::sleep_acceptor(ev_tstamp t) { - if (t == 0. || ev_is_active(&disable_acceptor_timer_)) { - return; - } - - disable_acceptor(); - - ev_timer_set(&disable_acceptor_timer_, t, 0.); - ev_timer_start(loop_, &disable_acceptor_timer_); -} - -void ConnectionHandler::accept_pending_connection() { - for (auto &a : acceptors_) { - a->accept_connection(); - } -} - -void ConnectionHandler::set_ticket_keys( - std::shared_ptr ticket_keys) { - ticket_keys_ = std::move(ticket_keys); - if (single_worker_) { - single_worker_->set_ticket_keys(ticket_keys_); - } -} - -const std::shared_ptr &ConnectionHandler::get_ticket_keys() const { - return ticket_keys_; -} - -void ConnectionHandler::set_graceful_shutdown(bool f) { - graceful_shutdown_ = f; - if (single_worker_) { - single_worker_->set_graceful_shutdown(f); - } -} - -bool ConnectionHandler::get_graceful_shutdown() const { - return graceful_shutdown_; -} - -void ConnectionHandler::cancel_ocsp_update() { - if (ocsp_.pid == 0) { - return; - } - - kill(ocsp_.pid, SIGTERM); -} - -// inspired by h2o_read_command function from h2o project: -// https://github.com/h2o/h2o -int ConnectionHandler::start_ocsp_update(const char *cert_file) { - int rv; - int pfd[2]; - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Start ocsp update for " << cert_file; - } - - assert(!ev_is_active(&ocsp_.rev)); - assert(!ev_is_active(&ocsp_.chldev)); - - char *const argv[] = { - const_cast( - get_config()->tls.ocsp.fetch_ocsp_response_file.c_str()), - const_cast(cert_file), nullptr}; - -#ifdef O_CLOEXEC - if (pipe2(pfd, O_CLOEXEC) == -1) { - return -1; - } -#else // !O_CLOEXEC - if (pipe(pfd) == -1) { - return -1; - } - util::make_socket_closeonexec(pfd[0]); - util::make_socket_closeonexec(pfd[1]); -#endif // !O_CLOEXEC - - auto closer = defer([&pfd]() { - if (pfd[0] != -1) { - close(pfd[0]); - } - - if (pfd[1] != -1) { - close(pfd[1]); - } - }); - - sigset_t oldset; - - rv = shrpx_signal_block_all(&oldset); - if (rv != 0) { - auto error = errno; - LOG(ERROR) << "Blocking all signals failed: " << strerror(error); - - return -1; - } - - auto pid = fork(); - - if (pid == 0) { - // child process - shrpx_signal_unset_worker_proc_ign_handler(); - - rv = shrpx_signal_unblock_all(); - if (rv != 0) { - auto error = errno; - LOG(FATAL) << "Unblocking all signals failed: " << strerror(error); - - _Exit(EXIT_FAILURE); - } - - dup2(pfd[1], 1); - close(pfd[0]); - - rv = execv(argv[0], argv); - if (rv == -1) { - auto error = errno; - LOG(ERROR) << "Could not execute ocsp query command: " << argv[0] - << ", execve() faild, errno=" << error; - _Exit(EXIT_FAILURE); - } - // unreachable - } - - // parent process - if (pid == -1) { - auto error = errno; - LOG(ERROR) << "Could not execute ocsp query command for " << cert_file - << ": " << argv[0] << ", fork() failed, errno=" << error; - } - - rv = shrpx_signal_set(&oldset); - if (rv != 0) { - auto error = errno; - LOG(FATAL) << "Restoring all signals failed: " << strerror(error); - - _Exit(EXIT_FAILURE); - } - - if (pid == -1) { - return -1; - } - - close(pfd[1]); - pfd[1] = -1; - - ocsp_.pid = pid; - ocsp_.fd = pfd[0]; - pfd[0] = -1; - - util::make_socket_nonblocking(ocsp_.fd); - ev_io_set(&ocsp_.rev, ocsp_.fd, EV_READ); - ev_io_start(loop_, &ocsp_.rev); - - ev_child_set(&ocsp_.chldev, ocsp_.pid, 0); - ev_child_start(loop_, &ocsp_.chldev); - - return 0; -} - -void ConnectionHandler::read_ocsp_chunk() { - std::array buf; - for (;;) { - ssize_t n; - while ((n = read(ocsp_.fd, buf.data(), buf.size())) == -1 && errno == EINTR) - ; - - if (n == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - return; - } - auto error = errno; - LOG(WARN) << "Reading from ocsp query command failed: errno=" << error; - ocsp_.error = error; - - break; - } - - if (n == 0) { - break; - } - - std::copy_n(std::begin(buf), n, std::back_inserter(ocsp_.resp)); - } - - ev_io_stop(loop_, &ocsp_.rev); -} - -void ConnectionHandler::handle_ocsp_complete() { - ev_io_stop(loop_, &ocsp_.rev); - ev_child_stop(loop_, &ocsp_.chldev); - - assert(ocsp_.next < all_ssl_ctx_.size()); - - auto ssl_ctx = all_ssl_ctx_[ocsp_.next]; - auto tls_ctx_data = - static_cast(SSL_CTX_get_app_data(ssl_ctx)); - - auto rstatus = ocsp_.chldev.rstatus; - auto status = WEXITSTATUS(rstatus); - if (ocsp_.error || !WIFEXITED(rstatus) || status != 0) { - LOG(WARN) << "ocsp query command for " << tls_ctx_data->cert_file - << " failed: error=" << ocsp_.error << ", rstatus=" << rstatus - << ", status=" << status; - ++ocsp_.next; - proceed_next_cert_ocsp(); - return; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "ocsp update for " << tls_ctx_data->cert_file - << " finished successfully"; - } - -#ifndef OPENSSL_IS_BORINGSSL - { - std::lock_guard g(tls_ctx_data->mu); - tls_ctx_data->ocsp_data = - std::make_shared>(std::move(ocsp_.resp)); - } -#else // OPENSSL_IS_BORINGSSL - SSL_CTX_set_ocsp_response(ssl_ctx, ocsp_.resp.data(), ocsp_.resp.size()); -#endif // OPENSSL_IS_BORINGSSL - - ++ocsp_.next; - proceed_next_cert_ocsp(); -} - -void ConnectionHandler::reset_ocsp() { - if (ocsp_.fd != -1) { - close(ocsp_.fd); - } - - ocsp_.fd = -1; - ocsp_.pid = 0; - ocsp_.error = 0; - ocsp_.resp = std::vector(); -} - -void ConnectionHandler::proceed_next_cert_ocsp() { - for (;;) { - reset_ocsp(); - if (ocsp_.next == all_ssl_ctx_.size()) { - ocsp_.next = 0; - // We have updated all ocsp response, and schedule next update. - ev_timer_set(&ocsp_timer_, get_config()->tls.ocsp.update_interval, 0.); - ev_timer_start(loop_, &ocsp_timer_); - return; - } - - auto ssl_ctx = all_ssl_ctx_[ocsp_.next]; - auto tls_ctx_data = - static_cast(SSL_CTX_get_app_data(ssl_ctx)); - - // client SSL_CTX is also included in all_ssl_ctx_, but has no - // tls_ctx_data. - if (!tls_ctx_data) { - ++ocsp_.next; - continue; - } - - auto cert_file = tls_ctx_data->cert_file; - - if (start_ocsp_update(cert_file) != 0) { - ++ocsp_.next; - continue; - } - - break; - } -} - -void ConnectionHandler::set_tls_ticket_key_memcached_dispatcher( - std::unique_ptr dispatcher) { - tls_ticket_key_memcached_dispatcher_ = std::move(dispatcher); -} - -MemcachedDispatcher * -ConnectionHandler::get_tls_ticket_key_memcached_dispatcher() const { - return tls_ticket_key_memcached_dispatcher_.get(); -} - -// Use the similar backoff algorithm described in -// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md -namespace { -constexpr size_t MAX_BACKOFF_EXP = 10; -constexpr auto MULTIPLIER = 3.2; -constexpr auto JITTER = 0.2; -} // namespace - -void ConnectionHandler::on_tls_ticket_key_network_error(ev_timer *w) { - if (++tls_ticket_key_memcached_get_retry_count_ >= - get_config()->tls.ticket.memcached.max_retry) { - LOG(WARN) << "Memcached: tls ticket get retry all failed " - << tls_ticket_key_memcached_get_retry_count_ << " times."; - - on_tls_ticket_key_not_found(w); - return; - } - - auto base_backoff = util::int_pow( - MULTIPLIER, - std::min(MAX_BACKOFF_EXP, tls_ticket_key_memcached_get_retry_count_)); - auto dist = std::uniform_real_distribution<>(-JITTER * base_backoff, - JITTER * base_backoff); - - auto backoff = base_backoff + dist(gen_); - - LOG(WARN) - << "Memcached: tls ticket get failed due to network error, retrying in " - << backoff << " seconds"; - - ev_timer_set(w, backoff, 0.); - ev_timer_start(loop_, w); -} - -void ConnectionHandler::on_tls_ticket_key_not_found(ev_timer *w) { - tls_ticket_key_memcached_get_retry_count_ = 0; - - if (++tls_ticket_key_memcached_fail_count_ >= - get_config()->tls.ticket.memcached.max_fail) { - LOG(WARN) << "Memcached: could not get tls ticket; disable tls ticket"; - - tls_ticket_key_memcached_fail_count_ = 0; - - set_ticket_keys(nullptr); - set_ticket_keys_to_worker(nullptr); - } - - LOG(WARN) << "Memcached: tls ticket get failed, schedule next"; - schedule_next_tls_ticket_key_memcached_get(w); -} - -void ConnectionHandler::on_tls_ticket_key_get_success( - const std::shared_ptr &ticket_keys, ev_timer *w) { - LOG(NOTICE) << "Memcached: tls ticket get success"; - - tls_ticket_key_memcached_get_retry_count_ = 0; - tls_ticket_key_memcached_fail_count_ = 0; - - schedule_next_tls_ticket_key_memcached_get(w); - - if (!ticket_keys || ticket_keys->keys.empty()) { - LOG(WARN) << "Memcached: tls ticket keys are empty; tls ticket disabled"; - set_ticket_keys(nullptr); - set_ticket_keys_to_worker(nullptr); - return; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "ticket keys get done"; - LOG(INFO) << 0 << " enc+dec: " - << util::format_hex(ticket_keys->keys[0].data.name); - for (size_t i = 1; i < ticket_keys->keys.size(); ++i) { - auto &key = ticket_keys->keys[i]; - LOG(INFO) << i << " dec: " << util::format_hex(key.data.name); - } - } - - set_ticket_keys(ticket_keys); - set_ticket_keys_to_worker(ticket_keys); -} - -void ConnectionHandler::schedule_next_tls_ticket_key_memcached_get( - ev_timer *w) { - ev_timer_set(w, get_config()->tls.ticket.memcached.interval, 0.); - ev_timer_start(loop_, w); -} - -SSL_CTX *ConnectionHandler::create_tls_ticket_key_memcached_ssl_ctx() { - auto &tlsconf = get_config()->tls; - auto &memcachedconf = get_config()->tls.ticket.memcached; - - auto ssl_ctx = ssl::create_ssl_client_context( -#ifdef HAVE_NEVERBLEED - nb_.get(), -#endif // HAVE_NEVERBLEED - StringRef{tlsconf.cacert}, StringRef{memcachedconf.cert_file}, - StringRef{memcachedconf.private_key_file}, nullptr); - - all_ssl_ctx_.push_back(ssl_ctx); - - return ssl_ctx; -} - -#ifdef HAVE_NEVERBLEED -void ConnectionHandler::set_neverbleed(std::unique_ptr nb) { - nb_ = std::move(nb); -} - -neverbleed_t *ConnectionHandler::get_neverbleed() const { return nb_.get(); } - -#endif // HAVE_NEVERBLEED - -void ConnectionHandler::handle_serial_event() { - std::vector q; - { - std::lock_guard g(serial_event_mu_); - q.swap(serial_events_); - } - - for (auto &sev : q) { - switch (sev.type) { - case SEV_REPLACE_DOWNSTREAM: - // Mmake sure that none of worker uses - // get_config()->conn.downstream - mod_config()->conn.downstream = sev.downstreamconf; - - if (single_worker_) { - single_worker_->replace_downstream_config(sev.downstreamconf); - - break; - } - - worker_replace_downstream(sev.downstreamconf); - - break; - } - } -} - -void ConnectionHandler::send_replace_downstream( - const std::shared_ptr &downstreamconf) { - send_serial_event(SerialEvent(SEV_REPLACE_DOWNSTREAM, downstreamconf)); -} - -void ConnectionHandler::send_serial_event(SerialEvent ev) { - { - std::lock_guard g(serial_event_mu_); - - serial_events_.push_back(std::move(ev)); - } - - ev_async_send(loop_, &serial_event_asyncev_); -} - -SSL_CTX *ConnectionHandler::get_ssl_ctx(size_t idx) const { - return all_ssl_ctx_[idx]; -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_connection_handler.h nghttp2-0.6.7/src/shrpx_connection_handler.h --- nghttp2-1.13.0/src/shrpx_connection_handler.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_connection_handler.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,220 +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 SHRPX_CONNECTION_HANDLER_H -#define SHRPX_CONNECTION_HANDLER_H - -#include "shrpx.h" - -#include -#ifdef HAVE_SYS_SOCKET_H -#include -#endif // HAVE_SYS_SOCKET_H - -#include -#include -#include -#include -#ifndef NOTHREADS -#include -#endif // NOTHREADS - -#include - -#include - -#ifdef HAVE_NEVERBLEED -#include -#endif // HAVE_NEVERBLEED - -#include "shrpx_downstream_connection_pool.h" -#include "shrpx_config.h" - -namespace shrpx { - -class Http2Session; -class ConnectBlocker; -class AcceptHandler; -class Worker; -struct WorkerStat; -struct TicketKeys; -class MemcachedDispatcher; -struct UpstreamAddr; - -namespace ssl { - -class CertLookupTree; - -} // namespace ssl - -struct OCSPUpdateContext { - // ocsp response buffer - std::vector resp; - // index to ConnectionHandler::all_ssl_ctx_, which points to next - // SSL_CTX to update ocsp response cache. - size_t next; - ev_child chldev; - ev_io rev; - // fd to read response from fetch-ocsp-response script - int fd; - // errno encountered while processing response - int error; - // pid of forked fetch-ocsp-response script process - pid_t pid; -}; - -// SerialEvent is an event sent from Worker thread. -enum SerialEventType { - SEV_NONE, - SEV_REPLACE_DOWNSTREAM, -}; - -struct SerialEvent { - // ctor for event uses DownstreamConfig - SerialEvent(int type, const std::shared_ptr &downstreamconf) - : type(type), downstreamconf(downstreamconf) {} - - int type; - std::shared_ptr downstreamconf; -}; - -class ConnectionHandler { -public: - ConnectionHandler(struct ev_loop *loop, std::mt19937 &gen); - ~ConnectionHandler(); - int handle_connection(int fd, sockaddr *addr, int addrlen, - const UpstreamAddr *faddr); - // Creates Worker object for single threaded configuration. - int create_single_worker(); - // Creates |num| Worker objects for multi threaded configuration. - // The |num| must be strictly more than 1. - int create_worker_thread(size_t num); - void - set_ticket_keys_to_worker(const std::shared_ptr &ticket_keys); - void worker_reopen_log_files(); - void set_ticket_keys(std::shared_ptr ticket_keys); - const std::shared_ptr &get_ticket_keys() const; - struct ev_loop *get_loop() const; - Worker *get_single_worker() const; - void add_acceptor(std::unique_ptr h); - void enable_acceptor(); - void disable_acceptor(); - void sleep_acceptor(ev_tstamp t); - void accept_pending_connection(); - void graceful_shutdown_worker(); - void set_graceful_shutdown(bool f); - bool get_graceful_shutdown() const; - void join_worker(); - - // Cancels ocsp update process - void cancel_ocsp_update(); - // Starts ocsp update for certficate |cert_file|. - int start_ocsp_update(const char *cert_file); - // Reads incoming data from ocsp update process - void read_ocsp_chunk(); - // Handles the completion of one ocsp update - void handle_ocsp_complete(); - // Resets ocsp_; - void reset_ocsp(); - // Proceeds to the next certificate's ocsp update. If all - // certificates' ocsp update has been done, schedule next ocsp - // update. - void proceed_next_cert_ocsp(); - - void set_tls_ticket_key_memcached_dispatcher( - std::unique_ptr dispatcher); - - MemcachedDispatcher *get_tls_ticket_key_memcached_dispatcher() const; - void on_tls_ticket_key_network_error(ev_timer *w); - void on_tls_ticket_key_not_found(ev_timer *w); - void - on_tls_ticket_key_get_success(const std::shared_ptr &ticket_keys, - ev_timer *w); - void schedule_next_tls_ticket_key_memcached_get(ev_timer *w); - SSL_CTX *create_tls_ticket_key_memcached_ssl_ctx(); - // Returns the SSL_CTX at all_ssl_ctx_[idx]. This does not perform - // array bound checking. - SSL_CTX *get_ssl_ctx(size_t idx) const; - -#ifdef HAVE_NEVERBLEED - void set_neverbleed(std::unique_ptr nb); - neverbleed_t *get_neverbleed() const; -#endif // HAVE_NEVERBLEED - - // Send SerialEvent SEV_REPLACE_DOWNSTREAM to this object. - void send_replace_downstream( - const std::shared_ptr &downstreamconf); - // Internal function to send |ev| to this object. - void send_serial_event(SerialEvent ev); - // Handles SerialEvents received. - void handle_serial_event(); - // Sends WorkerEvent to make them replace downstream. - void - worker_replace_downstream(std::shared_ptr downstreamconf); - -private: - // Stores all SSL_CTX objects. - std::vector all_ssl_ctx_; - OCSPUpdateContext ocsp_; - std::mt19937 gen_; - // ev_loop for each worker - std::vector worker_loops_; - // Worker instances when multi threaded mode (-nN, N >= 2) is used. - // If at least one frontend enables API request, we allocate 1 - // additional worker dedicated to API request . - std::vector> workers_; - // mutex for serial event resive buffer handling - std::mutex serial_event_mu_; - // SerialEvent receive buffer - std::vector serial_events_; - // Worker instance used when single threaded mode (-n1) is used. - // Otherwise, nullptr and workers_ has instances of Worker instead. - std::unique_ptr single_worker_; - std::unique_ptr cert_tree_; - std::unique_ptr tls_ticket_key_memcached_dispatcher_; - // Current TLS session ticket keys. Note that TLS connection does - // not refer to this field directly. They use TicketKeys object in - // Worker object. - std::shared_ptr ticket_keys_; - struct ev_loop *loop_; - std::vector> acceptors_; -#ifdef HAVE_NEVERBLEED - std::unique_ptr nb_; -#endif // HAVE_NEVERBLEED - ev_timer disable_acceptor_timer_; - ev_timer ocsp_timer_; - ev_async thread_join_asyncev_; - ev_async serial_event_asyncev_; -#ifndef NOTHREADS - std::future thread_join_fut_; -#endif // NOTHREADS - size_t tls_ticket_key_memcached_get_retry_count_; - size_t tls_ticket_key_memcached_fail_count_; - unsigned int worker_round_robin_cnt_; - bool graceful_shutdown_; -}; - -} // namespace shrpx - -#endif // SHRPX_CONNECTION_HANDLER_H diff -Nru nghttp2-1.13.0/src/shrpx_downstream.cc nghttp2-0.6.7/src/shrpx_downstream.cc --- nghttp2-1.13.0/src/shrpx_downstream.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_downstream.cc 2014-11-30 14:15:07.000000000 +0000 @@ -33,159 +33,50 @@ #include "shrpx_config.h" #include "shrpx_error.h" #include "shrpx_downstream_connection.h" -#include "shrpx_downstream_queue.h" -#include "shrpx_worker.h" -#include "shrpx_http2_session.h" -#ifdef HAVE_MRUBY -#include "shrpx_mruby.h" -#endif // HAVE_MRUBY #include "util.h" #include "http2.h" namespace shrpx { -namespace { -void upstream_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - auto downstream = static_cast(w->data); - auto upstream = downstream->get_upstream(); - - auto which = revents == EV_READ ? "read" : "write"; - - if (LOG_ENABLED(INFO)) { - DLOG(INFO, downstream) << "upstream timeout stream_id=" - << downstream->get_stream_id() << " event=" << which; - } - - downstream->disable_upstream_rtimer(); - downstream->disable_upstream_wtimer(); - - upstream->on_timeout(downstream); -} -} // namespace - -namespace { -void upstream_rtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - upstream_timeoutcb(loop, w, EV_READ); -} -} // namespace - -namespace { -void upstream_wtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - upstream_timeoutcb(loop, w, EV_WRITE); -} -} // namespace - -namespace { -void downstream_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - auto downstream = static_cast(w->data); - - auto which = revents == EV_READ ? "read" : "write"; - - if (LOG_ENABLED(INFO)) { - DLOG(INFO, downstream) << "downstream timeout stream_id=" - << downstream->get_downstream_stream_id() - << " event=" << which; - } - - downstream->disable_downstream_rtimer(); - downstream->disable_downstream_wtimer(); - - auto dconn = downstream->get_downstream_connection(); - - if (dconn) { - dconn->on_timeout(); - } -} -} // namespace - -namespace { -void downstream_rtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - downstream_timeoutcb(loop, w, EV_READ); -} -} // namespace - -namespace { -void downstream_wtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - downstream_timeoutcb(loop, w, EV_WRITE); -} -} // namespace - -// upstream could be nullptr for unittests -Downstream::Downstream(Upstream *upstream, MemchunkPool *mcpool, - int32_t stream_id) - : dlnext(nullptr), - dlprev(nullptr), - response_sent_body_length(0), - balloc_(1024, 1024), - req_(balloc_), - resp_(balloc_), - request_start_time_(std::chrono::high_resolution_clock::now()), - request_buf_(mcpool), - response_buf_(mcpool), - upstream_(upstream), - blocked_link_(nullptr), - num_retry_(0), - stream_id_(stream_id), - assoc_stream_id_(-1), +Downstream::Downstream(Upstream *upstream, int32_t stream_id, int32_t priority) + : request_bodylen_(0), response_bodylen_(0), response_sent_bodylen_(0), + upstream_(upstream), response_body_buf_(nullptr), + upstream_rtimerev_(nullptr), upstream_wtimerev_(nullptr), + downstream_rtimerev_(nullptr), downstream_wtimerev_(nullptr), + request_headers_sum_(0), response_headers_sum_(0), request_datalen_(0), + response_datalen_(0), stream_id_(stream_id), priority_(priority), downstream_stream_id_(-1), response_rst_stream_error_code_(NGHTTP2_NO_ERROR), - request_state_(INITIAL), - response_state_(INITIAL), - dispatch_state_(DISPATCH_NONE), - upgraded_(false), - chunked_request_(false), - chunked_response_(false), - expect_final_response_(false), - request_pending_(false) { - - auto &timeoutconf = get_config()->http2.timeout; - - ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0., - timeoutconf.stream_read); - ev_timer_init(&upstream_wtimer_, &upstream_wtimeoutcb, 0., - timeoutconf.stream_write); - ev_timer_init(&downstream_rtimer_, &downstream_rtimeoutcb, 0., - timeoutconf.stream_read); - ev_timer_init(&downstream_wtimer_, &downstream_wtimeoutcb, 0., - timeoutconf.stream_write); - - upstream_rtimer_.data = this; - upstream_wtimer_.data = this; - downstream_rtimer_.data = this; - downstream_wtimer_.data = this; -} + request_state_(INITIAL), request_major_(1), request_minor_(1), + response_state_(INITIAL), response_http_status_(0), response_major_(1), + response_minor_(1), upgrade_request_(false), upgraded_(false), + http2_upgrade_seen_(false), http2_settings_seen_(false), + chunked_request_(false), request_connection_close_(false), + request_header_key_prev_(false), request_http2_expect_body_(false), + chunked_response_(false), response_connection_close_(false), + response_header_key_prev_(false), expect_final_response_(false), + request_headers_normalized_(false) {} Downstream::~Downstream() { if (LOG_ENABLED(INFO)) { DLOG(INFO, this) << "Deleting"; } - - // check nullptr for unittest - if (upstream_) { - auto loop = upstream_->get_client_handler()->get_loop(); - - ev_timer_stop(loop, &upstream_rtimer_); - ev_timer_stop(loop, &upstream_wtimer_); - ev_timer_stop(loop, &downstream_rtimer_); - ev_timer_stop(loop, &downstream_wtimer_); - -#ifdef HAVE_MRUBY - auto handler = upstream_->get_client_handler(); - auto worker = handler->get_worker(); - auto mruby_ctx = worker->get_mruby_context(); - - mruby_ctx->delete_downstream(this); -#endif // HAVE_MRUBY - } - - // DownstreamConnection may refer to this object. Delete it now - // explicitly. - dconn_.reset(); - - for (auto rcbuf : rcbufs_) { - nghttp2_rcbuf_decref(rcbuf); + if (response_body_buf_) { + // Passing NULL to evbuffer_free() causes segmentation fault. + evbuffer_free(response_body_buf_); + } + if (upstream_rtimerev_) { + event_free(upstream_rtimerev_); + } + if (upstream_wtimerev_) { + event_free(upstream_wtimerev_); + } + if (downstream_rtimerev_) { + event_free(downstream_rtimerev_); + } + if (downstream_wtimerev_) { + event_free(downstream_wtimerev_); } - if (LOG_ENABLED(INFO)) { DLOG(INFO, this) << "Deleted"; } @@ -215,6 +106,8 @@ std::unique_ptr(dconn_.release())); } +void Downstream::release_downstream_connection() { dconn_.release(); } + DownstreamConnection *Downstream::get_downstream_connection() { return dconn_.get(); } @@ -244,228 +137,195 @@ } namespace { -const HeaderRefs::value_type * -search_header_linear_backwards(const HeaderRefs &headers, - const StringRef &name) { - for (auto it = headers.rbegin(); it != headers.rend(); ++it) { - auto &kv = *it; - if (kv.name == name) { - return &kv; - } +Headers::const_iterator get_norm_header(const Headers &headers, + const std::string &name) { + auto i = std::lower_bound(std::begin(headers), std::end(headers), + Header(name, ""), http2::name_less); + if (i != std::end(headers) && (*i).name == name) { + return i; } - return nullptr; + return std::end(headers); } } // namespace -StringRef Downstream::assemble_request_cookie() { - size_t len = 0; - - for (auto &kv : req_.fs.headers()) { - if (kv.token != http2::HD_COOKIE || kv.value.empty()) { - continue; - } - - len += kv.value.size() + str_size("; "); +namespace { +Headers::iterator get_norm_header(Headers &headers, const std::string &name) { + auto i = std::lower_bound(std::begin(headers), std::end(headers), + Header(name, ""), http2::name_less); + if (i != std::end(headers) && (*i).name == name) { + return i; } + return std::end(headers); +} +} // namespace - auto iov = make_byte_ref(balloc_, len + 1); - auto p = iov.base; +namespace { +Headers::const_iterator get_header_linear(const Headers &headers, + const std::string &name) { + auto i = std::find_if( + std::begin(headers), std::end(headers), + [&name](const Header &header) { return header.name == name; }); + return i; +} +} // namespace - for (auto &kv : req_.fs.headers()) { - if (kv.token != http2::HD_COOKIE || kv.value.empty()) { - continue; - } +const Headers &Downstream::get_request_headers() const { + return request_headers_; +} - auto end = std::end(kv.value); - for (auto it = std::begin(kv.value) + kv.value.size(); - it != std::begin(kv.value); --it) { - auto c = *(it - 1); - if (c == ' ' || c == ';') { - continue; +void Downstream::assemble_request_cookie() { + std::string &cookie = assembled_request_cookie_; + cookie = ""; + for (auto &kv : request_headers_) { + if (util::strieq("cookie", kv.name.c_str())) { + auto end = kv.value.find_last_not_of(" ;"); + if (end == std::string::npos) { + cookie += kv.value; + } else { + cookie.append(std::begin(kv.value), std::begin(kv.value) + end + 1); } - end = it; - break; + cookie += "; "; } - - p = std::copy(std::begin(kv.value), end, p); - p = util::copy_lit(p, "; "); } - - // cut trailing "; " - if (p - iov.base >= 2) { - p -= 2; + if (cookie.size() >= 2) { + cookie.erase(cookie.size() - 2); } - - return StringRef{iov.base, p}; } -size_t Downstream::count_crumble_request_cookie() { - size_t n = 0; - for (auto &kv : req_.fs.headers()) { - if (kv.name.size() != 6 || kv.name[5] != 'e' || - !util::streq_l("cooki", kv.name.c_str(), 5)) { - continue; - } - - for (auto it = std::begin(kv.value); it != std::end(kv.value);) { - if (*it == '\t' || *it == ' ' || *it == ';') { - ++it; - continue; +void Downstream::crumble_request_cookie() { + Headers cookie_hdrs; + for (auto &kv : request_headers_) { + if (util::strieq("cookie", kv.name.c_str())) { + size_t last = kv.value.size(); + size_t num = 0; + std::string rep_cookie; + + for (size_t j = 0; j < last;) { + j = kv.value.find_first_not_of("\t ;", j); + if (j == std::string::npos) { + break; + } + auto first = j; + + j = kv.value.find(';', j); + if (j == std::string::npos) { + j = last; + } + + if (num == 0) { + if (first == 0 && j == last) { + break; + } + rep_cookie = kv.value.substr(first, j - first); + } else { + cookie_hdrs.push_back( + Header("cookie", kv.value.substr(first, j - first), kv.no_index)); + } + ++num; + } + if (num > 0) { + kv.value = std::move(rep_cookie); } - - it = std::find(it, std::end(kv.value), ';'); - - ++n; } } - return n; + request_headers_.insert(std::end(request_headers_), + std::make_move_iterator(std::begin(cookie_hdrs)), + std::make_move_iterator(std::end(cookie_hdrs))); + if (request_headers_normalized_) { + normalize_request_headers(); + } } -void Downstream::crumble_request_cookie(std::vector &nva) { - for (auto &kv : req_.fs.headers()) { - if (kv.name.size() != 6 || kv.name[5] != 'e' || - !util::streq_l("cooki", kv.name.c_str(), 5)) { - continue; - } - - for (auto it = std::begin(kv.value); it != std::end(kv.value);) { - if (*it == '\t' || *it == ' ' || *it == ';') { - ++it; - continue; - } - - auto first = it; - - it = std::find(it, std::end(kv.value), ';'); - - nva.push_back({(uint8_t *)"cookie", (uint8_t *)first, str_size("cookie"), - (size_t)(it - first), - (uint8_t)(NGHTTP2_NV_FLAG_NO_COPY_NAME | - NGHTTP2_NV_FLAG_NO_COPY_VALUE | - (kv.no_index ? NGHTTP2_NV_FLAG_NO_INDEX : 0))}); - } - } +const std::string &Downstream::get_assembled_request_cookie() const { + return assembled_request_cookie_; } -namespace { -void add_header(bool &key_prev, size_t &sum, HeaderRefs &headers, - const StringRef &name, const StringRef &value, bool no_index, - int32_t token) { - key_prev = true; - sum += name.size() + value.size(); - headers.emplace_back(name, value, no_index, token); +void Downstream::normalize_request_headers() { + http2::normalize_headers(request_headers_); + request_headers_normalized_ = true; } -} // namespace -namespace { -void append_last_header_key(BlockAllocator &balloc, bool &key_prev, size_t &sum, - HeaderRefs &headers, const char *data, size_t len) { - assert(key_prev); - sum += len; - auto &item = headers.back(); - auto iov = make_byte_ref(balloc, item.name.size() + len + 1); - auto p = iov.base; - p = std::copy(std::begin(item.name), std::end(item.name), p); - p = std::copy_n(data, len, p); - util::inp_strlower(p - len, p); - *p = '\0'; +Headers::const_iterator +Downstream::get_norm_request_header(const std::string &name) const { + return get_norm_header(request_headers_, name); +} - item.name = StringRef{iov.base, p}; +Headers::const_iterator +Downstream::get_request_header(const std::string &name) const { + if (request_headers_normalized_) { + return get_norm_request_header(name); + } - item.token = http2::lookup_token(item.name); + return get_header_linear(request_headers_, name); } -} // namespace -namespace { -void append_last_header_value(BlockAllocator &balloc, bool &key_prev, - size_t &sum, HeaderRefs &headers, - const char *data, size_t len) { - key_prev = false; - sum += len; - auto &item = headers.back(); - item.value = concat_string_ref(balloc, item.value, StringRef{data, len}); +bool Downstream::get_request_headers_normalized() const { + return request_headers_normalized_; } -} // namespace - -int FieldStore::parse_content_length() { - content_length = -1; - for (auto &kv : headers_) { - if (kv.token != http2::HD_CONTENT_LENGTH) { - continue; - } +void Downstream::add_request_header(std::string name, std::string value) { + request_header_key_prev_ = true; + request_headers_sum_ += name.size() + value.size(); + request_headers_.emplace_back(std::move(name), std::move(value)); +} - auto len = util::parse_uint(kv.value); - if (len == -1) { - return -1; - } - if (content_length != -1) { - return -1; - } - content_length = len; - } - return 0; +void Downstream::set_last_request_header_value(std::string value) { + request_header_key_prev_ = false; + request_headers_sum_ += value.size(); + Headers::value_type &item = request_headers_.back(); + item.value = std::move(value); } -const HeaderRefs::value_type *FieldStore::header(int32_t token) const { - for (auto it = headers_.rbegin(); it != headers_.rend(); ++it) { - auto &kv = *it; - if (kv.token == token) { - return &kv; - } - } - return nullptr; +void Downstream::split_add_request_header(const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, + bool no_index) { + request_headers_sum_ += namelen + valuelen; + http2::add_header(request_headers_, name, namelen, value, valuelen, no_index); } -HeaderRefs::value_type *FieldStore::header(int32_t token) { - for (auto it = headers_.rbegin(); it != headers_.rend(); ++it) { - auto &kv = *it; - if (kv.token == token) { - return &kv; - } - } - return nullptr; +bool Downstream::get_request_header_key_prev() const { + return request_header_key_prev_; } -const HeaderRefs::value_type *FieldStore::header(const StringRef &name) const { - return search_header_linear_backwards(headers_, name); +void Downstream::append_last_request_header_key(const char *data, size_t len) { + assert(request_header_key_prev_); + request_headers_sum_ += len; + auto &item = request_headers_.back(); + item.name.append(data, len); } -void FieldStore::add_header_token(const StringRef &name, const StringRef &value, - bool no_index, int32_t token) { - shrpx::add_header(header_key_prev_, buffer_size_, headers_, name, value, - no_index, token); +void Downstream::append_last_request_header_value(const char *data, + size_t len) { + assert(!request_header_key_prev_); + request_headers_sum_ += len; + auto &item = request_headers_.back(); + item.value.append(data, len); } -void FieldStore::append_last_header_key(const char *data, size_t len) { - shrpx::append_last_header_key(balloc_, header_key_prev_, buffer_size_, - headers_, data, len); +void Downstream::clear_request_headers() { Headers().swap(request_headers_); } + +size_t Downstream::get_request_headers_sum() const { + return request_headers_sum_; } -void FieldStore::append_last_header_value(const char *data, size_t len) { - shrpx::append_last_header_value(balloc_, header_key_prev_, buffer_size_, - headers_, data, len); +void Downstream::set_request_method(std::string method) { + request_method_ = std::move(method); } -void FieldStore::clear_headers() { headers_.clear(); } +const std::string &Downstream::get_request_method() const { + return request_method_; +} -void FieldStore::add_trailer_token(const StringRef &name, - const StringRef &value, bool no_index, - int32_t token) { - // Header size limit should be applied to all header and trailer - // fields combined. - shrpx::add_header(trailer_key_prev_, buffer_size_, trailers_, name, value, - no_index, token); +void Downstream::set_request_path(std::string path) { + request_path_ = std::move(path); } -void FieldStore::append_last_trailer_key(const char *data, size_t len) { - shrpx::append_last_header_key(balloc_, trailer_key_prev_, buffer_size_, - trailers_, data, len); +void Downstream::append_request_path(const char *data, size_t len) { + request_path_.append(data, len); } -void FieldStore::append_last_trailer_value(const char *data, size_t len) { - shrpx::append_last_header_value(balloc_, trailer_key_prev_, buffer_size_, - trailers_, data, len); +const std::string &Downstream::get_request_path() const { + return request_path_; } void Downstream::set_request_start_time( @@ -478,6 +338,30 @@ return request_start_time_; } +const std::string &Downstream::get_request_http2_scheme() const { + return request_http2_scheme_; +} + +void Downstream::set_request_http2_scheme(std::string scheme) { + request_http2_scheme_ = std::move(scheme); +} + +const std::string &Downstream::get_request_http2_authority() const { + return request_http2_authority_; +} + +void Downstream::set_request_http2_authority(std::string authority) { + request_http2_authority_ = std::move(authority); +} + +void Downstream::set_request_major(int major) { request_major_ = major; } + +void Downstream::set_request_minor(int minor) { request_minor_ = minor; } + +int Downstream::get_request_major() const { return request_major_; } + +int Downstream::get_request_minor() const { return request_minor_; } + void Downstream::reset_upstream(Upstream *upstream) { upstream_ = upstream; if (dconn_) { @@ -499,25 +383,29 @@ void Downstream::set_chunked_request(bool f) { chunked_request_ = f; } -bool Downstream::request_buf_full() { - auto handler = upstream_->get_client_handler(); - auto faddr = handler->get_upstream_addr(); - auto worker = handler->get_worker(); +bool Downstream::get_request_connection_close() const { + return request_connection_close_; +} - // We don't check buffer size here for API endpoint. - if (faddr->alt_mode == ALTMODE_API) { - return false; - } +void Downstream::set_request_connection_close(bool f) { + request_connection_close_ = f; +} - if (dconn_) { - auto &downstreamconf = *worker->get_downstream_config(); - return request_buf_.rleft() >= downstreamconf.request_buffer_size; - } +bool Downstream::get_request_http2_expect_body() const { + return request_http2_expect_body_; +} - return false; +void Downstream::set_request_http2_expect_body(bool f) { + request_http2_expect_body_ = f; } -DefaultMemchunks *Downstream::get_request_buf() { return &request_buf_; } +bool Downstream::get_output_buffer_full() { + if (dconn_) { + return dconn_->get_output_buffer_full(); + } else { + return false; + } +} // Call this function after this object is attached to // Downstream. Otherwise, the program will crash. @@ -530,19 +418,18 @@ } int Downstream::push_upload_data_chunk(const uint8_t *data, size_t datalen) { - req_.recv_body_length += datalen; - // Assumes that request headers have already been pushed to output // buffer using push_request_headers(). if (!dconn_) { DLOG(INFO, this) << "dconn_ is NULL"; return -1; } + request_bodylen_ += datalen; if (dconn_->push_upload_data_chunk(data, datalen) != 0) { return -1; } - req_.unconsumed_body_length += datalen; + request_datalen_ += datalen; return 0; } @@ -555,38 +442,129 @@ return dconn_->end_upload_data(); } -void Downstream::rewrite_location_response_header( - const StringRef &upstream_scheme) { - auto hd = resp_.fs.header(http2::HD_LOCATION); - if (!hd) { - return; - } +const Headers &Downstream::get_response_headers() const { + return response_headers_; +} + +void Downstream::normalize_response_headers() { + http2::normalize_headers(response_headers_); +} - if (request_downstream_host_.empty() || req_.authority.empty()) { +Headers::const_iterator +Downstream::get_norm_response_header(const std::string &name) const { + return get_norm_header(response_headers_, name); +} + +void Downstream::rewrite_norm_location_response_header( + const std::string &upstream_scheme, uint16_t upstream_port) { + auto hd = get_norm_header(response_headers_, "location"); + if (hd == std::end(response_headers_)) { return; } - - http_parser_url u{}; - auto rv = http_parser_parse_url(hd->value.c_str(), hd->value.size(), 0, &u); + http_parser_url u; + memset(&u, 0, sizeof(u)); + int rv = + http_parser_parse_url((*hd).value.c_str(), (*hd).value.size(), 0, &u); if (rv != 0) { return; } - - auto new_uri = http2::rewrite_location_uri(balloc_, hd->value, u, - request_downstream_host_, - req_.authority, upstream_scheme); - + std::string new_uri; + if (!request_http2_authority_.empty()) { + new_uri = + http2::rewrite_location_uri((*hd).value, u, request_http2_authority_, + upstream_scheme, upstream_port); + } if (new_uri.empty()) { - return; + auto host = get_norm_request_header("host"); + if (host == std::end(request_headers_)) { + return; + } + new_uri = http2::rewrite_location_uri((*hd).value, u, (*host).value, + upstream_scheme, upstream_port); } + if (!new_uri.empty()) { + (*hd).value = std::move(new_uri); + } +} + +void Downstream::add_response_header(std::string name, std::string value) { + response_header_key_prev_ = true; + response_headers_sum_ += name.size() + value.size(); + response_headers_.emplace_back(std::move(name), std::move(value)); +} + +void Downstream::set_last_response_header_value(std::string value) { + response_header_key_prev_ = false; + response_headers_sum_ += value.size(); + auto &item = response_headers_.back(); + item.value = std::move(value); +} + +void Downstream::split_add_response_header(const uint8_t *name, size_t namelen, + const uint8_t *value, + size_t valuelen, bool no_index) { + response_headers_sum_ += namelen + valuelen; + http2::add_header(response_headers_, name, namelen, value, valuelen, + no_index); +} + +bool Downstream::get_response_header_key_prev() const { + return response_header_key_prev_; +} + +void Downstream::append_last_response_header_key(const char *data, size_t len) { + assert(response_header_key_prev_); + response_headers_sum_ += len; + auto &item = response_headers_.back(); + item.name.append(data, len); +} - hd->value = new_uri; +void Downstream::append_last_response_header_value(const char *data, + size_t len) { + assert(!response_header_key_prev_); + response_headers_sum_ += len; + auto &item = response_headers_.back(); + item.value.append(data, len); +} + +void Downstream::clear_response_headers() { Headers().swap(response_headers_); } + +size_t Downstream::get_response_headers_sum() const { + return response_headers_sum_; +} + +unsigned int Downstream::get_response_http_status() const { + return response_http_status_; +} + +void Downstream::set_response_http_status(unsigned int status) { + response_http_status_ = status; +} + +void Downstream::set_response_major(int major) { response_major_ = major; } + +void Downstream::set_response_minor(int minor) { response_minor_ = minor; } + +int Downstream::get_response_major() const { return response_major_; } + +int Downstream::get_response_minor() const { return response_minor_; } + +int Downstream::get_response_version() const { + return response_major_ * 100 + response_minor_; } bool Downstream::get_chunked_response() const { return chunked_response_; } void Downstream::set_chunked_response(bool f) { chunked_response_ = f; } +bool Downstream::get_response_connection_close() const { + return response_connection_close_; +} + +void Downstream::set_response_connection_close(bool f) { + response_connection_close_ = f; +} + int Downstream::on_read() { if (!dconn_) { DLOG(INFO, this) << "dconn_ is NULL"; @@ -595,137 +573,128 @@ return dconn_->on_read(); } +int Downstream::change_priority(int32_t pri) { + if (!dconn_) { + DLOG(INFO, this) << "dconn_ is NULL"; + return -1; + } + return dconn_->on_priority_change(pri); +} + void Downstream::set_response_state(int state) { response_state_ = state; } int Downstream::get_response_state() const { return response_state_; } -DefaultMemchunks *Downstream::get_response_buf() { return &response_buf_; } - -bool Downstream::response_buf_full() { - if (dconn_) { - auto handler = upstream_->get_client_handler(); - auto worker = handler->get_worker(); - auto &downstreamconf = *worker->get_downstream_config(); - - return response_buf_.rleft() >= downstreamconf.response_buffer_size; +int Downstream::init_response_body_buf() { + if (!response_body_buf_) { + response_body_buf_ = evbuffer_new(); + if (response_body_buf_ == nullptr) { + DIE(); + } } - - return false; + return 0; } -bool Downstream::validate_request_recv_body_length() const { - if (req_.fs.content_length == -1) { - return true; - } - - if (req_.fs.content_length != req_.recv_body_length) { - if (LOG_ENABLED(INFO)) { - DLOG(INFO, this) << "request invalid bodylen: content-length=" - << req_.fs.content_length - << ", received=" << req_.recv_body_length; - } - return false; - } +evbuffer *Downstream::get_response_body_buf() { return response_body_buf_; } - return true; +void Downstream::add_response_bodylen(size_t amount) { + response_bodylen_ += amount; } -bool Downstream::validate_response_recv_body_length() const { - if (!expect_response_body() || resp_.fs.content_length == -1) { - return true; - } +int64_t Downstream::get_response_bodylen() const { return response_bodylen_; } - if (resp_.fs.content_length != resp_.recv_body_length) { - if (LOG_ENABLED(INFO)) { - DLOG(INFO, this) << "response invalid bodylen: content-length=" - << resp_.fs.content_length - << ", received=" << resp_.recv_body_length; - } - return false; - } +void Downstream::add_response_sent_bodylen(size_t amount) { + response_sent_bodylen_ += amount; +} - return true; +int64_t Downstream::get_response_sent_bodylen() const { + return response_sent_bodylen_; } +void Downstream::set_priority(int32_t pri) { priority_ = pri; } + +int32_t Downstream::get_priority() const { return priority_; } + void Downstream::check_upgrade_fulfilled() { - if (req_.method == HTTP_CONNECT) { - upgraded_ = 200 <= resp_.http_status && resp_.http_status < 300; + if (request_method_ == "CONNECT") { + upgraded_ = 200 <= response_http_status_ && response_http_status_ < 300; return; } - if (resp_.http_status == 101) { + if (response_http_status_ == 101) { // TODO Do more strict checking for upgrade headers - upgraded_ = req_.upgrade_request; + upgraded_ = upgrade_request_; return; } } void Downstream::inspect_http2_request() { - if (req_.method == HTTP_CONNECT) { - req_.upgrade_request = true; + if (request_method_ == "CONNECT") { + upgrade_request_ = true; } } void Downstream::inspect_http1_request() { - if (req_.method == HTTP_CONNECT) { - req_.upgrade_request = true; - } else { - auto upgrade = req_.fs.header(http2::HD_UPGRADE); - if (upgrade) { - const auto &val = upgrade->value; + if (request_method_ == "CONNECT") { + upgrade_request_ = true; + } + + for (auto &hd : request_headers_) { + if (!upgrade_request_ && util::strieq("upgrade", hd.name.c_str())) { // TODO Perform more strict checking for upgrade headers - if (util::streq_l(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, val.c_str(), - val.size())) { - req_.http2_upgrade_seen = true; - } else { - req_.upgrade_request = true; + upgrade_request_ = true; + + if (util::streq(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, hd.value.c_str(), + hd.value.size())) { + http2_upgrade_seen_ = true; + } + } else if (!http2_settings_seen_ && + util::strieq(hd.name.c_str(), "http2-settings")) { + + http2_settings_seen_ = true; + http2_settings_ = hd.value; + } else if (!chunked_request_ && + util::strieq(hd.name.c_str(), "transfer-encoding")) { + if (util::strifind(hd.value.c_str(), "chunked")) { + chunked_request_ = true; } - } - } - auto transfer_encoding = req_.fs.header(http2::HD_TRANSFER_ENCODING); - if (transfer_encoding) { - req_.fs.content_length = -1; - if (util::iends_with_l(transfer_encoding->value, "chunked")) { - chunked_request_ = true; } } } void Downstream::inspect_http1_response() { - auto transfer_encoding = resp_.fs.header(http2::HD_TRANSFER_ENCODING); - if (transfer_encoding) { - resp_.fs.content_length = -1; - if (util::iends_with_l(transfer_encoding->value, "chunked")) { - chunked_response_ = true; + for (auto &hd : response_headers_) { + if (!chunked_response_ && + util::strieq(hd.name.c_str(), "transfer-encoding")) { + if (util::strifind(hd.value.c_str(), "chunked")) { + chunked_response_ = true; + } } } } void Downstream::reset_response() { - resp_.http_status = 0; - resp_.http_major = 1; - resp_.http_minor = 1; + response_http_status_ = 0; + response_major_ = 1; + response_minor_ = 1; } bool Downstream::get_non_final_response() const { - return !upgraded_ && resp_.http_status / 100 == 1; + return response_http_status_ / 100 == 1; } bool Downstream::get_upgraded() const { return upgraded_; } +bool Downstream::get_upgrade_request() const { return upgrade_request_; } + bool Downstream::get_http2_upgrade_request() const { - return req_.http2_upgrade_seen && req_.fs.header(http2::HD_HTTP2_SETTINGS) && - response_state_ == INITIAL; + return request_bodylen_ == 0 && http2_upgrade_seen_ && http2_settings_seen_; } -StringRef Downstream::get_http2_settings() const { - auto http2_settings = req_.fs.header(http2::HD_HTTP2_SETTINGS); - if (!http2_settings) { - return StringRef{}; - } - return http2_settings->value; +const std::string &Downstream::get_http2_settings() const { + return http2_settings_; } void Downstream::set_downstream_stream_id(int32_t stream_id) { @@ -752,195 +721,244 @@ return expect_final_response_; } -bool Downstream::expect_response_body() const { - return !resp_.headers_only && - http2::expect_response_body(req_.method, resp_.http_status); +size_t Downstream::get_request_datalen() const { return request_datalen_; } + +void Downstream::dec_request_datalen(size_t len) { + assert(request_datalen_ >= len); + request_datalen_ -= len; +} + +void Downstream::reset_request_datalen() { request_datalen_ = 0; } + +void Downstream::add_response_datalen(size_t len) { response_datalen_ += len; } + +void Downstream::dec_response_datalen(size_t len) { + assert(response_datalen_ >= len); + response_datalen_ -= len; } -bool Downstream::expect_response_trailer() const { - // In HTTP/2, if final response HEADERS does not bear END_STREAM it - // is possible trailer fields might come, regardless of request - // method or status code. - return !resp_.headers_only && resp_.http_major == 2; +size_t Downstream::get_response_datalen() const { return response_datalen_; } + +void Downstream::reset_response_datalen() { response_datalen_ = 0; } + +bool Downstream::expect_response_body() const { + return request_method_ != "HEAD" && response_http_status_ / 100 != 1 && + response_http_status_ != 304 && response_http_status_ != 204; } namespace { -void reset_timer(struct ev_loop *loop, ev_timer *w) { ev_timer_again(loop, w); } +bool pseudo_header_allowed(const Headers &headers) { + if (headers.empty()) { + return true; + } + + return headers.back().name.c_str()[0] == ':'; +} } // namespace +bool Downstream::request_pseudo_header_allowed() const { + return pseudo_header_allowed(request_headers_); +} + +bool Downstream::response_pseudo_header_allowed() const { + return pseudo_header_allowed(response_headers_); +} + namespace { -void try_reset_timer(struct ev_loop *loop, ev_timer *w) { - if (!ev_is_active(w)) { - return; +void upstream_timeoutcb(evutil_socket_t fd, short event, void *arg) { + auto downstream = static_cast(arg); + auto upstream = downstream->get_upstream(); + + auto which = event == EV_READ ? "read" : "write"; + + if (LOG_ENABLED(INFO)) { + DLOG(INFO, downstream) << "upstream timeout stream_id=" + << downstream->get_stream_id() << " event=" << which; } - ev_timer_again(loop, w); + + downstream->disable_upstream_rtimer(); + downstream->disable_upstream_wtimer(); + + upstream->on_timeout(downstream); } } // namespace namespace { -void ensure_timer(struct ev_loop *loop, ev_timer *w) { - if (ev_is_active(w)) { - return; - } - ev_timer_again(loop, w); +void upstream_rtimeoutcb(evutil_socket_t fd, short event, void *arg) { + upstream_timeoutcb(fd, EV_READ, arg); } } // namespace namespace { -void disable_timer(struct ev_loop *loop, ev_timer *w) { - ev_timer_stop(loop, w); +void upstream_wtimeoutcb(evutil_socket_t fd, short event, void *arg) { + upstream_timeoutcb(fd, EV_WRITE, arg); } } // namespace -void Downstream::reset_upstream_rtimer() { - if (get_config()->http2.timeout.stream_read == 0.) { - return; +namespace { +event *init_timer(event_base *evbase, event_callback_fn cb, void *arg) { + auto timerev = evtimer_new(evbase, cb, arg); + + if (timerev == nullptr) { + LOG(WARN) << "timer initialization failed"; + return nullptr; } - auto loop = upstream_->get_client_handler()->get_loop(); - reset_timer(loop, &upstream_rtimer_); + + return timerev; } +} // namespace -void Downstream::reset_upstream_wtimer() { - auto loop = upstream_->get_client_handler()->get_loop(); - auto &timeoutconf = get_config()->http2.timeout; +void Downstream::init_upstream_timer() { + auto evbase = upstream_->get_client_handler()->get_evbase(); - if (timeoutconf.stream_write != 0.) { - reset_timer(loop, &upstream_wtimer_); - } - if (timeoutconf.stream_read != 0.) { - try_reset_timer(loop, &upstream_rtimer_); + if (get_config()->stream_read_timeout.tv_sec > 0) { + upstream_rtimerev_ = init_timer(evbase, upstream_rtimeoutcb, this); } -} -void Downstream::ensure_upstream_wtimer() { - if (get_config()->http2.timeout.stream_write == 0.) { - return; + if (get_config()->stream_write_timeout.tv_sec > 0) { + upstream_wtimerev_ = init_timer(evbase, upstream_wtimeoutcb, this); } - auto loop = upstream_->get_client_handler()->get_loop(); - ensure_timer(loop, &upstream_wtimer_); } -void Downstream::disable_upstream_rtimer() { - if (get_config()->http2.timeout.stream_read == 0.) { +namespace { +void reset_timer(event *timer, const timeval *timeout) { + if (!timer) { return; } - auto loop = upstream_->get_client_handler()->get_loop(); - disable_timer(loop, &upstream_rtimer_); + + event_add(timer, timeout); } +} // namespace -void Downstream::disable_upstream_wtimer() { - if (get_config()->http2.timeout.stream_write == 0.) { +namespace { +void try_reset_timer(event *timer, const timeval *timeout) { + if (!timer) { return; } - auto loop = upstream_->get_client_handler()->get_loop(); - disable_timer(loop, &upstream_wtimer_); -} -void Downstream::reset_downstream_rtimer() { - if (get_config()->http2.timeout.stream_read == 0.) { + if (!evtimer_pending(timer, nullptr)) { return; } - auto loop = upstream_->get_client_handler()->get_loop(); - reset_timer(loop, &downstream_rtimer_); -} - -void Downstream::reset_downstream_wtimer() { - auto loop = upstream_->get_client_handler()->get_loop(); - auto &timeoutconf = get_config()->http2.timeout; - if (timeoutconf.stream_write != 0.) { - reset_timer(loop, &downstream_wtimer_); - } - if (timeoutconf.stream_read != 0.) { - try_reset_timer(loop, &downstream_rtimer_); - } + event_add(timer, timeout); } +} // namespace -void Downstream::ensure_downstream_wtimer() { - if (get_config()->http2.timeout.stream_write == 0.) { +namespace { +void ensure_timer(event *timer, const timeval *timeout) { + if (!timer) { return; } - auto loop = upstream_->get_client_handler()->get_loop(); - ensure_timer(loop, &downstream_wtimer_); -} -void Downstream::disable_downstream_rtimer() { - if (get_config()->http2.timeout.stream_read == 0.) { + if (evtimer_pending(timer, nullptr)) { return; } - auto loop = upstream_->get_client_handler()->get_loop(); - disable_timer(loop, &downstream_rtimer_); + + event_add(timer, timeout); } +} // namespace -void Downstream::disable_downstream_wtimer() { - if (get_config()->http2.timeout.stream_write == 0.) { +namespace { +void disable_timer(event *timer) { + if (!timer) { return; } - auto loop = upstream_->get_client_handler()->get_loop(); - disable_timer(loop, &downstream_wtimer_); + + event_del(timer); } +} // namespace -bool Downstream::accesslog_ready() const { return resp_.http_status > 0; } +void Downstream::reset_upstream_rtimer() { + reset_timer(upstream_rtimerev_, &get_config()->stream_read_timeout); + try_reset_timer(upstream_wtimerev_, &get_config()->stream_write_timeout); +} -void Downstream::add_retry() { ++num_retry_; } +void Downstream::reset_upstream_wtimer() { + reset_timer(upstream_wtimerev_, &get_config()->stream_write_timeout); + try_reset_timer(upstream_rtimerev_, &get_config()->stream_read_timeout); +} -bool Downstream::no_more_retry() const { return num_retry_ > 5; } +void Downstream::ensure_upstream_wtimer() { + ensure_timer(upstream_wtimerev_, &get_config()->stream_write_timeout); +} -void Downstream::set_request_downstream_host(const StringRef &host) { - request_downstream_host_ = host; +void Downstream::disable_upstream_rtimer() { + disable_timer(upstream_rtimerev_); } -void Downstream::set_request_pending(bool f) { request_pending_ = f; } +void Downstream::disable_upstream_wtimer() { + disable_timer(upstream_wtimerev_); +} -bool Downstream::get_request_pending() const { return request_pending_; } +namespace { +void downstream_timeoutcb(evutil_socket_t fd, short event, void *arg) { + auto downstream = static_cast(arg); -bool Downstream::request_submission_ready() const { - return (request_state_ == Downstream::HEADER_COMPLETE || - request_state_ == Downstream::MSG_COMPLETE) && - request_pending_ && response_state_ == Downstream::INITIAL; -} + auto which = event == EV_READ ? "read" : "write"; -int Downstream::get_dispatch_state() const { return dispatch_state_; } + if (LOG_ENABLED(INFO)) { + DLOG(INFO, downstream) << "downstream timeout stream_id=" + << downstream->get_downstream_stream_id() + << " event=" << which; + } -void Downstream::set_dispatch_state(int s) { dispatch_state_ = s; } + downstream->disable_downstream_rtimer(); + downstream->disable_downstream_wtimer(); -void Downstream::attach_blocked_link(BlockedLink *l) { - assert(!blocked_link_); + auto dconn = downstream->get_downstream_connection(); + + if (dconn) { + dconn->on_timeout(); + } +} +} // namespace - l->downstream = this; - blocked_link_ = l; +namespace { +void downstream_rtimeoutcb(evutil_socket_t fd, short event, void *arg) { + downstream_timeoutcb(fd, EV_READ, arg); } +} // namespace -BlockedLink *Downstream::detach_blocked_link() { - auto link = blocked_link_; - blocked_link_ = nullptr; - return link; +namespace { +void downstream_wtimeoutcb(evutil_socket_t fd, short event, void *arg) { + downstream_timeoutcb(fd, EV_WRITE, arg); } +} // namespace + +void Downstream::init_downstream_timer() { + auto evbase = upstream_->get_client_handler()->get_evbase(); + + if (get_config()->stream_read_timeout.tv_sec > 0) { + downstream_rtimerev_ = init_timer(evbase, downstream_rtimeoutcb, this); + } -bool Downstream::can_detach_downstream_connection() const { - // We should check request and response buffer. If request buffer - // is not empty, then we might leave downstream connection in weird - // state, especially for HTTP/1.1 - return dconn_ && response_state_ == Downstream::MSG_COMPLETE && - request_state_ == Downstream::MSG_COMPLETE && !upgraded_ && - !resp_.connection_close && request_buf_.rleft() == 0; + if (get_config()->stream_write_timeout.tv_sec > 0) { + downstream_wtimerev_ = init_timer(evbase, downstream_wtimeoutcb, this); + } } -DefaultMemchunks Downstream::pop_response_buf() { - return std::move(response_buf_); +void Downstream::reset_downstream_rtimer() { + reset_timer(downstream_rtimerev_, &get_config()->stream_read_timeout); + try_reset_timer(downstream_wtimerev_, &get_config()->stream_write_timeout); } -void Downstream::set_assoc_stream_id(int32_t stream_id) { - assoc_stream_id_ = stream_id; +void Downstream::reset_downstream_wtimer() { + reset_timer(downstream_wtimerev_, &get_config()->stream_write_timeout); + try_reset_timer(downstream_rtimerev_, &get_config()->stream_read_timeout); } -int32_t Downstream::get_assoc_stream_id() const { return assoc_stream_id_; } +void Downstream::ensure_downstream_wtimer() { + ensure_timer(downstream_wtimerev_, &get_config()->stream_write_timeout); +} -BlockAllocator &Downstream::get_block_allocator() { return balloc_; } +void Downstream::disable_downstream_rtimer() { + disable_timer(downstream_rtimerev_); +} -void Downstream::add_rcbuf(nghttp2_rcbuf *rcbuf) { - nghttp2_rcbuf_incref(rcbuf); - rcbufs_.push_back(rcbuf); +void Downstream::disable_downstream_wtimer() { + disable_timer(downstream_wtimerev_); } +bool Downstream::accesslog_ready() const { return response_http_status_ > 0; } + } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_downstream_connection.cc nghttp2-0.6.7/src/shrpx_downstream_connection.cc --- nghttp2-1.13.0/src/shrpx_downstream_connection.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_downstream_connection.cc 2014-11-30 14:15:07.000000000 +0000 @@ -26,11 +26,12 @@ #include "shrpx_client_handler.h" #include "shrpx_downstream.h" +#include "shrpx_downstream_connection_pool.h" namespace shrpx { -DownstreamConnection::DownstreamConnection() - : client_handler_(nullptr), downstream_(nullptr) {} +DownstreamConnection::DownstreamConnection(DownstreamConnectionPool *dconn_pool) + : dconn_pool_(dconn_pool), client_handler_(nullptr), downstream_(nullptr) {} DownstreamConnection::~DownstreamConnection() {} @@ -44,4 +45,8 @@ Downstream *DownstreamConnection::get_downstream() { return downstream_; } +DownstreamConnectionPool *DownstreamConnection::get_dconn_pool() const { + return dconn_pool_; +} + } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_downstream_connection.h nghttp2-0.6.7/src/shrpx_downstream_connection.h --- nghttp2-1.13.0/src/shrpx_downstream_connection.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_downstream_connection.h 2014-11-30 14:15:07.000000000 +0000 @@ -34,12 +34,11 @@ class ClientHandler; class Upstream; class Downstream; -struct DownstreamAddrGroup; -struct DownstreamAddr; +class DownstreamConnectionPool; class DownstreamConnection { public: - DownstreamConnection(); + DownstreamConnection(DownstreamConnectionPool *dconn_pool); virtual ~DownstreamConnection(); virtual int attach_downstream(Downstream *downstream) = 0; virtual void detach_downstream(Downstream *downstream) = 0; @@ -52,23 +51,22 @@ virtual int resume_read(IOCtrlReason reason, size_t consumed) = 0; virtual void force_resume_read() = 0; + virtual bool get_output_buffer_full() = 0; + virtual int on_read() = 0; virtual int on_write() = 0; virtual int on_timeout() { return 0; } virtual void on_upstream_change(Upstream *uptream) = 0; - - // true if this object is poolable. - virtual bool poolable() const = 0; - - virtual DownstreamAddrGroup *get_downstream_addr_group() const = 0; - virtual DownstreamAddr *get_addr() const = 0; + virtual int on_priority_change(int32_t pri) = 0; void set_client_handler(ClientHandler *client_handler); ClientHandler *get_client_handler(); Downstream *get_downstream(); + DownstreamConnectionPool *get_dconn_pool() const; protected: + DownstreamConnectionPool *dconn_pool_; ClientHandler *client_handler_; Downstream *downstream_; }; diff -Nru nghttp2-1.13.0/src/shrpx_downstream_connection_pool.cc nghttp2-0.6.7/src/shrpx_downstream_connection_pool.cc --- nghttp2-1.13.0/src/shrpx_downstream_connection_pool.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_downstream_connection_pool.cc 2014-11-30 14:15:07.000000000 +0000 @@ -29,14 +29,10 @@ DownstreamConnectionPool::DownstreamConnectionPool() {} -DownstreamConnectionPool::~DownstreamConnectionPool() { remove_all(); } - -void DownstreamConnectionPool::remove_all() { +DownstreamConnectionPool::~DownstreamConnectionPool() { for (auto dconn : pool_) { delete dconn; } - - pool_.clear(); } void DownstreamConnectionPool::add_downstream_connection( @@ -50,10 +46,8 @@ return nullptr; } - auto it = std::begin(pool_); - auto dconn = std::unique_ptr(*it); - pool_.erase(it); - + auto dconn = std::unique_ptr(*std::begin(pool_)); + pool_.erase(std::begin(pool_)); return dconn; } diff -Nru nghttp2-1.13.0/src/shrpx_downstream_connection_pool.h nghttp2-0.6.7/src/shrpx_downstream_connection_pool.h --- nghttp2-1.13.0/src/shrpx_downstream_connection_pool.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_downstream_connection_pool.h 2014-11-30 14:15:07.000000000 +0000 @@ -42,7 +42,6 @@ void add_downstream_connection(std::unique_ptr dconn); std::unique_ptr pop_downstream_connection(); void remove_downstream_connection(DownstreamConnection *dconn); - void remove_all(); private: std::set pool_; diff -Nru nghttp2-1.13.0/src/shrpx_downstream.h nghttp2-0.6.7/src/shrpx_downstream.h --- nghttp2-1.13.0/src/shrpx_downstream.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_downstream.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,20 +27,20 @@ #include "shrpx.h" -#include +#include + #include #include #include #include -#include +#include +#include #include #include "shrpx_io_control.h" #include "http2.h" -#include "memchunk.h" -#include "allocator.h" using namespace nghttp2; @@ -48,177 +48,17 @@ class Upstream; class DownstreamConnection; -struct BlockedLink; - -class FieldStore { -public: - FieldStore(BlockAllocator &balloc, size_t headers_initial_capacity) - : content_length(-1), - balloc_(balloc), - buffer_size_(0), - header_key_prev_(false), - trailer_key_prev_(false) { - headers_.reserve(headers_initial_capacity); - } - - const HeaderRefs &headers() const { return headers_; } - const HeaderRefs &trailers() const { return trailers_; } - - HeaderRefs &headers() { return headers_; } - - const void add_extra_buffer_size(size_t n) { buffer_size_ += n; } - size_t buffer_size() const { return buffer_size_; } - - size_t num_fields() const { return headers_.size() + trailers_.size(); } - - // Returns pointer to the header field with the name |name|. If - // multiple header have |name| as name, return last occurrence from - // the beginning. If no such header is found, returns nullptr. - // This function must be called after headers are indexed - const HeaderRefs::value_type *header(int32_t token) const; - HeaderRefs::value_type *header(int32_t token); - // Returns pointer to the header field with the name |name|. If no - // such header is found, returns nullptr. - const HeaderRefs::value_type *header(const StringRef &name) const; - - void add_header_token(const StringRef &name, const StringRef &value, - bool no_index, int32_t token); - - void append_last_header_key(const char *data, size_t len); - void append_last_header_value(const char *data, size_t len); - - bool header_key_prev() const { return header_key_prev_; } - - // Parses content-length, and records it in the field. If there are - // multiple Content-Length, returns -1. - int parse_content_length(); - - // Empties headers. - void clear_headers(); - - void add_trailer_token(const StringRef &name, const StringRef &value, - bool no_index, int32_t token); - - void append_last_trailer_key(const char *data, size_t len); - void append_last_trailer_value(const char *data, size_t len); - - bool trailer_key_prev() const { return trailer_key_prev_; } - - // content-length, -1 if it is unknown. - int64_t content_length; - -private: - BlockAllocator &balloc_; - HeaderRefs headers_; - // trailer fields. For HTTP/1.1, trailer fields are only included - // with chunked encoding. For HTTP/2, there is no such limit. - HeaderRefs trailers_; - // Sum of the length of name and value in headers_ and trailers_. - // This could also be increased by add_extra_buffer_size() to take - // into account for request URI in case of HTTP/1.x request. - size_t buffer_size_; - bool header_key_prev_; - bool trailer_key_prev_; -}; - -struct Request { - Request(BlockAllocator &balloc) - : fs(balloc, 16), - recv_body_length(0), - unconsumed_body_length(0), - method(-1), - http_major(1), - http_minor(1), - upgrade_request(false), - http2_upgrade_seen(false), - connection_close(false), - http2_expect_body(false), - no_authority(false) {} - - void consume(size_t len) { - assert(unconsumed_body_length >= len); - unconsumed_body_length -= len; - } - - FieldStore fs; - // Request scheme. For HTTP/2, this is :scheme header field value. - // For HTTP/1.1, this is deduced from URI or connection. - StringRef scheme; - // Request authority. This is HTTP/2 :authority header field value - // or host header field value. We may deduce it from absolute-form - // HTTP/1 request. We also store authority-form HTTP/1 request. - // This could be empty if request comes from HTTP/1.0 without Host - // header field and origin-form. - StringRef authority; - // Request path, including query component. For HTTP/1.1, this is - // request-target. For HTTP/2, this is :path header field value. - // For CONNECT request, this is empty. - StringRef path; - // the length of request body received so far - int64_t recv_body_length; - // The number of bytes not consumed by the application yet. - size_t unconsumed_body_length; - int method; - // HTTP major and minor version - int http_major, http_minor; - // Returns true if the request is HTTP upgrade (HTTP Upgrade or - // CONNECT method). Upgrade to HTTP/2 is excluded. For HTTP/2 - // Upgrade, check get_http2_upgrade_request(). - bool upgrade_request; - // true if h2c is seen in Upgrade header field. - bool http2_upgrade_seen; - bool connection_close; - // true if this is HTTP/2, and request body is expected. Note that - // we don't take into account HTTP method here. - bool http2_expect_body; - // true if request does not have any information about authority. - // This happens when: For HTTP/2 request, :authority is missing. - // For HTTP/1 request, origin or asterisk form is used. - bool no_authority; -}; - -struct Response { - Response(BlockAllocator &balloc) - : fs(balloc, 32), - recv_body_length(0), - unconsumed_body_length(0), - http_status(0), - http_major(1), - http_minor(1), - connection_close(false), - headers_only(false) {} - - void consume(size_t len) { - assert(unconsumed_body_length >= len); - unconsumed_body_length -= len; - } - - FieldStore fs; - // the length of response body received so far - int64_t recv_body_length; - // The number of bytes not consumed by the application yet. This is - // mainly for HTTP/2 backend. - size_t unconsumed_body_length; - // HTTP status code - unsigned int http_status; - int http_major, http_minor; - bool connection_close; - // true if response only consists of HEADERS, and it bears - // END_STREAM. This is used to tell Http2Upstream that it can send - // response with single HEADERS with END_STREAM flag only. - bool headers_only; -}; class Downstream { public: - Downstream(Upstream *upstream, MemchunkPool *mcpool, int32_t stream_id); + Downstream(Upstream *upstream, int32_t stream_id, int32_t priority); ~Downstream(); void reset_upstream(Upstream *upstream); Upstream *get_upstream() const; void set_stream_id(int32_t stream_id); int32_t get_stream_id() const; - void set_assoc_stream_id(int32_t stream_id); - int32_t get_assoc_stream_id() const; + void set_priority(int32_t pri); + int32_t get_priority() const; void pause_read(IOCtrlReason reason); int resume_read(IOCtrlReason reason, size_t consumed); void force_resume_read(); @@ -228,18 +68,21 @@ int attach_downstream_connection(std::unique_ptr dconn); void detach_downstream_connection(); + // Releases dconn_, without freeing it. + void release_downstream_connection(); DownstreamConnection *get_downstream_connection(); // Returns dconn_ and nullifies dconn_. std::unique_ptr pop_downstream_connection(); // Returns true if output buffer is full. If underlying dconn_ is // NULL, this function always returns false. - bool request_buf_full(); + bool get_output_buffer_full(); // Returns true if upgrade (HTTP Upgrade or CONNECT) is succeeded. - // This should not depend on inspect_http1_response(). void check_upgrade_fulfilled(); + // Returns true if the request is upgrade. + bool get_upgrade_request() const; // Returns true if the upgrade is succeded as a result of the call - // check_upgrade_fulfilled(). HTTP/2 Upgrade is excluded. + // check_upgrade_fulfilled(). bool get_upgraded() const; // Inspects HTTP/2 request. void inspect_http2_request(); @@ -249,36 +92,77 @@ // Returns true if the request is HTTP Upgrade for HTTP/2 bool get_http2_upgrade_request() const; // Returns the value of HTTP2-Settings request header field. - StringRef get_http2_settings() const; - + const std::string &get_http2_settings() const; // downstream request API - const Request &request() const { return req_; } - Request &request() { return req_; } - - // Count number of crumbled cookies - size_t count_crumble_request_cookie(); - // Crumbles (split cookie by ";") in request_headers_ and adds them - // in |nva|. Headers::no_index is inherited. - void crumble_request_cookie(std::vector &nva); - // Assembles request cookies. The opposite operation against - // crumble_request_cookie(). - StringRef assemble_request_cookie(); - + const Headers &get_request_headers() const; + void crumble_request_cookie(); + void assemble_request_cookie(); + const std::string &get_assembled_request_cookie() const; + // Makes key lowercase and sort headers by name using < + void normalize_request_headers(); + // Returns iterator pointing to the request header with the name + // |name|. If multiple header have |name| as name, return first + // occurrence from the beginning. If no such header is found, + // returns std::end(get_request_headers()). This function must be + // called after calling normalize_request_headers(). + Headers::const_iterator + get_norm_request_header(const std::string &name) const; + // Returns iterator pointing to the request header with the name + // |name|. This function acts like get_norm_request_header(), but + // if request_headers_ was not normalized, use linear search to find + // the header. Otherwise, get_norm_request_header() is used. + Headers::const_iterator get_request_header(const std::string &name) const; + bool get_request_headers_normalized() const; + void add_request_header(std::string name, std::string value); + void set_last_request_header_value(std::string value); + + void split_add_request_header(const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, + bool no_index); + + bool get_request_header_key_prev() const; + void append_last_request_header_key(const char *data, size_t len); + void append_last_request_header_value(const char *data, size_t len); + // Empties request headers. + void clear_request_headers(); + + size_t get_request_headers_sum() const; + + void set_request_method(std::string method); + const std::string &get_request_method() const; + void set_request_path(std::string path); void set_request_start_time(std::chrono::high_resolution_clock::time_point time); const std::chrono::high_resolution_clock::time_point & get_request_start_time() const; + void append_request_path(const char *data, size_t len); + // Returns request path. For HTTP/1.1, this is request-target. For + // HTTP/2, this is :path header field value. + const std::string &get_request_path() const; + // Returns HTTP/2 :scheme header field value. + const std::string &get_request_http2_scheme() const; + void set_request_http2_scheme(std::string scheme); + // Returns HTTP/2 :authority header field value. + const std::string &get_request_http2_authority() const; + void set_request_http2_authority(std::string authority); + void set_request_major(int major); + void set_request_minor(int minor); + int get_request_major() const; + int get_request_minor() const; int push_request_headers(); bool get_chunked_request() const; void set_chunked_request(bool f); + bool get_request_connection_close() const; + void set_request_connection_close(bool f); + bool get_request_http2_expect_body() const; + void set_request_http2_expect_body(bool f); int push_upload_data_chunk(const uint8_t *data, size_t datalen); int end_upload_data(); - // Validates that received request body length and content-length - // matches. - bool validate_request_recv_body_length() const; - void set_request_downstream_host(const StringRef &host); + size_t get_request_datalen() const; + void dec_request_datalen(size_t len); + void reset_request_datalen(); + bool request_pseudo_header_allowed() const; bool expect_response_body() const; - bool expect_response_trailer() const; enum { INITIAL, HEADER_COMPLETE, @@ -286,65 +170,100 @@ STREAM_CLOSED, CONNECT_FAIL, IDLE, - MSG_RESET, - // header contains invalid header field. We can safely send error - // response (502) to a client. - MSG_BAD_HEADER, - // header fields in HTTP/1 request exceed the configuration limit. - // This state is only transitioned from INITIAL state, and solely - // used to signal 431 status code to the client. - HTTP1_REQUEST_HEADER_TOO_LARGE, + MSG_RESET }; void set_request_state(int state); int get_request_state() const; - DefaultMemchunks *get_request_buf(); - void set_request_pending(bool f); - bool get_request_pending() const; - // Returns true if request is ready to be submitted to downstream. - bool request_submission_ready() const; - // downstream response API - const Response &response() const { return resp_; } - Response &response() { return resp_; } - - // Rewrites the location response header field. - void rewrite_location_response_header(const StringRef &upstream_scheme); - + const Headers &get_response_headers() const; + // Makes key lowercase and sort headers by name using < + void normalize_response_headers(); + // Returns iterator pointing to the response header with the name + // |name|. If multiple header have |name| as name, return first + // occurrence from the beginning. If no such header is found, + // returns std::end(get_response_headers()). This function must be + // called after calling normalize_response_headers(). + Headers::const_iterator + get_norm_response_header(const std::string &name) const; + // Rewrites the location response header field. This function must + // be called after calling normalize_response_headers() and + // normalize_request_headers(). + void rewrite_norm_location_response_header(const std::string &upstream_scheme, + uint16_t upstream_port); + void add_response_header(std::string name, std::string value); + void set_last_response_header_value(std::string value); + + void split_add_response_header(const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, + bool no_index); + + bool get_response_header_key_prev() const; + void append_last_response_header_key(const char *data, size_t len); + void append_last_response_header_value(const char *data, size_t len); + // Empties response headers. + void clear_response_headers(); + + size_t get_response_headers_sum() const; + + unsigned int get_response_http_status() const; + void set_response_http_status(unsigned int status); + void set_response_major(int major); + void set_response_minor(int minor); + int get_response_major() const; + int get_response_minor() const; + int get_response_version() const; bool get_chunked_response() const; void set_chunked_response(bool f); - + bool get_response_connection_close() const; + void set_response_connection_close(bool f); void set_response_state(int state); int get_response_state() const; - DefaultMemchunks *get_response_buf(); - bool response_buf_full(); - // Validates that received response body length and content-length - // matches. - bool validate_response_recv_body_length() const; + int init_response_body_buf(); + evbuffer *get_response_body_buf(); + void add_response_bodylen(size_t amount); + int64_t get_response_bodylen() const; + void add_response_sent_bodylen(size_t amount); + int64_t get_response_sent_bodylen() const; uint32_t get_response_rst_stream_error_code() const; void set_response_rst_stream_error_code(uint32_t error_code); // Inspects HTTP/1 response. This checks tranfer-encoding etc. void inspect_http1_response(); // Clears some of member variables for response. void reset_response(); - // True if the response is non-final (1xx status code). Note that - // if connection was upgraded, 101 status code is treated as final. bool get_non_final_response() const; void set_expect_final_response(bool f); bool get_expect_final_response() const; + void add_response_datalen(size_t len); + void dec_response_datalen(size_t len); + size_t get_response_datalen() const; + void reset_response_datalen(); + bool response_pseudo_header_allowed() const; // Call this method when there is incoming data in downstream // connection. int on_read(); - // Resets upstream read timer. If it is active, timeout value is - // reset. If it is not active, timer will be started. + // Change the priority of downstream + int change_priority(int32_t pri); + + // Maximum buffer size for header name/value pairs. + static const size_t MAX_HEADERS_SUM = 32768; + + bool get_rst_stream_after_end_stream() const; + void set_rst_stream_after_end_stream(bool f); + + // Initializes upstream timers, but they are not pending. + void init_upstream_timer(); + // Makes upstream read timer pending. If it is already pending, + // timeout value is reset. This function also resets write timer if + // it is already pending. void reset_upstream_rtimer(); - // Resets upstream write timer. If it is active, timeout value is - // reset. If it is not active, timer will be started. This - // function also resets read timer if it has been started. + // Makes upstream write timer pending. If it is already pending, + // timeout value is reset. This function also resets read timer if + // it is already pending. void reset_upstream_wtimer(); - // Makes sure that upstream write timer is started. If it has been - // started, do nothing. Otherwise, write timer will be started. + // Makes upstream write timer pending. If it is already pending, do + // nothing. void ensure_upstream_wtimer(); // Disables upstream read timer. void disable_upstream_rtimer(); @@ -353,6 +272,7 @@ // Downstream timer functions. They works in a similar way just // like the upstream timer function. + void init_downstream_timer(); void reset_downstream_rtimer(); void reset_downstream_wtimer(); void ensure_downstream_wtimer(); @@ -362,103 +282,82 @@ // Returns true if accesslog can be written for this downstream. bool accesslog_ready() const; - // Increment retry count - void add_retry(); - // true if retry attempt should not be done. - bool no_more_retry() const; - - int get_dispatch_state() const; - void set_dispatch_state(int s); - - void attach_blocked_link(BlockedLink *l); - BlockedLink *detach_blocked_link(); - - // Returns true if downstream_connection can be detached and reused. - bool can_detach_downstream_connection() const; - - DefaultMemchunks pop_response_buf(); - - BlockAllocator &get_block_allocator(); - - void add_rcbuf(nghttp2_rcbuf *rcbuf); - - enum { - EVENT_ERROR = 0x1, - EVENT_TIMEOUT = 0x2, - }; - - enum { - DISPATCH_NONE, - DISPATCH_PENDING, - DISPATCH_BLOCKED, - DISPATCH_ACTIVE, - DISPATCH_FAILURE, - }; - - Downstream *dlnext, *dlprev; - - // the length of response body sent to upstream client - int64_t response_sent_body_length; - private: - BlockAllocator balloc_; - - std::vector rcbufs_; - - Request req_; - Response resp_; + Headers request_headers_; + Headers response_headers_; + std::string request_method_; + std::string request_path_; + std::string request_http2_scheme_; + std::string request_http2_authority_; std::chrono::high_resolution_clock::time_point request_start_time_; + std::string assembled_request_cookie_; + std::string http2_settings_; + + // the length of request body + int64_t request_bodylen_; + // the length of response body + int64_t response_bodylen_; + // the length of response body sent to upstream client + int64_t response_sent_bodylen_; - // host we requested to downstream. This is used to rewrite - // location header field to decide the location should be rewritten - // or not. - StringRef request_downstream_host_; + Upstream *upstream_; + std::unique_ptr dconn_; + // This buffer is used to temporarily store downstream response + // body. nghttp2 library reads data from this in the callback. + evbuffer *response_body_buf_; - DefaultMemchunks request_buf_; - DefaultMemchunks response_buf_; + event *upstream_rtimerev_; + event *upstream_wtimerev_; - ev_timer upstream_rtimer_; - ev_timer upstream_wtimer_; + event *downstream_rtimerev_; + event *downstream_wtimerev_; - ev_timer downstream_rtimer_; - ev_timer downstream_wtimer_; + size_t request_headers_sum_; + size_t response_headers_sum_; - Upstream *upstream_; - std::unique_ptr dconn_; + // The number of bytes not consumed by the application yet. + size_t request_datalen_; + size_t response_datalen_; - // only used by HTTP/2 or SPDY upstream - BlockedLink *blocked_link_; - // How many times we tried in backend connection - size_t num_retry_; - // The stream ID in frontend connection int32_t stream_id_; - // The associated stream ID in frontend connection if this is pushed - // stream. - int32_t assoc_stream_id_; + int32_t priority_; // stream ID in backend connection int32_t downstream_stream_id_; + // RST_STREAM error_code from downstream HTTP2 connection uint32_t response_rst_stream_error_code_; - // request state + int request_state_; - // response state + int request_major_; + int request_minor_; + int response_state_; - // only used by HTTP/2 or SPDY upstream - int dispatch_state_; - // true if the connection is upgraded (HTTP Upgrade or CONNECT), - // excluding upgrade to HTTP/2. + unsigned int response_http_status_; + int response_major_; + int response_minor_; + + // true if the request contains upgrade token (HTTP Upgrade or + // CONNECT) + bool upgrade_request_; + // true if the connection is upgraded (HTTP Upgrade or CONNECT) bool upgraded_; - // true if backend request uses chunked transfer-encoding + + bool http2_upgrade_seen_; + bool http2_settings_seen_; + bool chunked_request_; - // true if response to client uses chunked transfer-encoding + bool request_connection_close_; + bool request_header_key_prev_; + bool request_http2_expect_body_; + bool chunked_response_; - // true if we have not got final response code + bool response_connection_close_; + bool response_header_key_prev_; bool expect_final_response_; - // true if downstream request is pending because backend connection - // has not been established or should be checked before use; - // currently used only with HTTP/2 connection. - bool request_pending_; + + // true if request_headers_ is normalized + bool request_headers_normalized_; }; } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_downstream_queue.cc nghttp2-0.6.7/src/shrpx_downstream_queue.cc --- nghttp2-1.13.0/src/shrpx_downstream_queue.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_downstream_queue.cc 2014-11-30 14:15:07.000000000 +0000 @@ -25,145 +25,115 @@ #include "shrpx_downstream_queue.h" #include -#include #include "shrpx_downstream.h" namespace shrpx { -DownstreamQueue::HostEntry::HostEntry() : num_active(0) {} +DownstreamQueue::DownstreamQueue() {} -DownstreamQueue::DownstreamQueue(size_t conn_max_per_host, bool unified_host) - : conn_max_per_host_(conn_max_per_host == 0 - ? std::numeric_limits::max() - : conn_max_per_host), - unified_host_(unified_host) {} - -DownstreamQueue::~DownstreamQueue() { - dlist_delete_all(downstreams_); - for (auto &p : host_entries_) { - auto &ent = p.second; - dlist_delete_all(ent.blocked); - } -} +DownstreamQueue::~DownstreamQueue() {} void DownstreamQueue::add_pending(std::unique_ptr downstream) { - downstream->set_dispatch_state(Downstream::DISPATCH_PENDING); - downstreams_.append(downstream.release()); + auto stream_id = downstream->get_stream_id(); + pending_downstreams_[stream_id] = std::move(downstream); } -void DownstreamQueue::mark_failure(Downstream *downstream) { - downstream->set_dispatch_state(Downstream::DISPATCH_FAILURE); +void DownstreamQueue::add_failure(std::unique_ptr downstream) { + auto stream_id = downstream->get_stream_id(); + failure_downstreams_[stream_id] = std::move(downstream); } -DownstreamQueue::HostEntry & -DownstreamQueue::find_host_entry(const std::string &host) { - auto itr = host_entries_.find(host); - if (itr == std::end(host_entries_)) { -#ifdef HAVE_STD_MAP_EMPLACE - std::tie(itr, std::ignore) = host_entries_.emplace(host, HostEntry()); -#else // !HAVE_STD_MAP_EMPLACE - // for g++-4.7 - std::tie(itr, std::ignore) = - host_entries_.insert(std::make_pair(host, HostEntry())); -#endif // !HAVE_STD_MAP_EMPLACE - } - return (*itr).second; +void DownstreamQueue::add_active(std::unique_ptr downstream) { + auto stream_id = downstream->get_stream_id(); + active_downstreams_[stream_id] = std::move(downstream); } -std::string DownstreamQueue::make_host_key(const StringRef &host) const { - return unified_host_ ? "" : host.str(); -} +std::unique_ptr DownstreamQueue::remove(int32_t stream_id) { + auto kv = pending_downstreams_.find(stream_id); -std::string DownstreamQueue::make_host_key(Downstream *downstream) const { - return make_host_key(downstream->request().authority); -} + if (kv != std::end(pending_downstreams_)) { + auto downstream = std::move((*kv).second); + pending_downstreams_.erase(kv); + return downstream; + } -void DownstreamQueue::mark_active(Downstream *downstream) { - auto &ent = find_host_entry(make_host_key(downstream)); - ++ent.num_active; + kv = active_downstreams_.find(stream_id); - downstream->set_dispatch_state(Downstream::DISPATCH_ACTIVE); -} + if (kv != std::end(active_downstreams_)) { + auto downstream = std::move((*kv).second); + active_downstreams_.erase(kv); + return downstream; + } -void DownstreamQueue::mark_blocked(Downstream *downstream) { - auto &ent = find_host_entry(make_host_key(downstream)); + kv = failure_downstreams_.find(stream_id); - downstream->set_dispatch_state(Downstream::DISPATCH_BLOCKED); + if (kv != std::end(failure_downstreams_)) { + auto downstream = std::move((*kv).second); + failure_downstreams_.erase(kv); + return downstream; + } - auto link = new BlockedLink{}; - downstream->attach_blocked_link(link); - ent.blocked.append(link); + return nullptr; } -bool DownstreamQueue::can_activate(const StringRef &host) const { - auto itr = host_entries_.find(make_host_key(host)); - if (itr == std::end(host_entries_)) { - return true; - } - auto &ent = (*itr).second; - return ent.num_active < conn_max_per_host_; -} +Downstream *DownstreamQueue::find(int32_t stream_id) { + auto kv = pending_downstreams_.find(stream_id); -namespace { -bool remove_host_entry_if_empty(const DownstreamQueue::HostEntry &ent, - DownstreamQueue::HostEntryMap &host_entries, - const std::string &host) { - if (ent.blocked.empty() && ent.num_active == 0) { - host_entries.erase(host); - return true; + if (kv != std::end(pending_downstreams_)) { + return (*kv).second.get(); } - return false; -} -} // namespace -Downstream *DownstreamQueue::remove_and_get_blocked(Downstream *downstream, - bool next_blocked) { - // Delete downstream when this function returns. - auto delptr = std::unique_ptr(downstream); + kv = active_downstreams_.find(stream_id); - downstreams_.remove(downstream); + if (kv != std::end(active_downstreams_)) { + return (*kv).second.get(); + } - auto host = make_host_key(downstream); - auto &ent = find_host_entry(host); + kv = failure_downstreams_.find(stream_id); - if (downstream->get_dispatch_state() == Downstream::DISPATCH_ACTIVE) { - --ent.num_active; - } else { - // For those downstreams deleted while in blocked state - auto link = downstream->detach_blocked_link(); - if (link) { - ent.blocked.remove(link); - delete link; - } + if (kv != std::end(failure_downstreams_)) { + return (*kv).second.get(); } - if (remove_host_entry_if_empty(ent, host_entries_, host)) { - return nullptr; - } + return nullptr; +} + +std::unique_ptr DownstreamQueue::pop_pending() { + auto i = std::begin(pending_downstreams_); - if (!next_blocked || ent.num_active >= conn_max_per_host_) { + if (i == std::end(pending_downstreams_)) { return nullptr; } - auto link = ent.blocked.head; + auto downstream = std::move((*i).second); + + pending_downstreams_.erase(i); - if (!link) { + return downstream; +} + +Downstream *DownstreamQueue::pending_top() const { + auto i = std::begin(pending_downstreams_); + + if (i == std::end(pending_downstreams_)) { return nullptr; } - auto next_downstream = link->downstream; - auto link2 = next_downstream->detach_blocked_link(); - assert(link2 == link); - ent.blocked.remove(link); - delete link; - remove_host_entry_if_empty(ent, host_entries_, host); + return (*i).second.get(); +} + +size_t DownstreamQueue::num_active() const { + return active_downstreams_.size(); +} - return next_downstream; +bool DownstreamQueue::pending_empty() const { + return pending_downstreams_.empty(); } -Downstream *DownstreamQueue::get_downstreams() const { - return downstreams_.head; +const std::map> & +DownstreamQueue::get_active_downstreams() const { + return active_downstreams_; } } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_downstream_queue.h nghttp2-0.6.7/src/shrpx_downstream_queue.h --- nghttp2-1.13.0/src/shrpx_downstream_queue.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_downstream_queue.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,79 +27,50 @@ #include "shrpx.h" -#include +#include + #include -#include #include -#include "template.h" - -using namespace nghttp2; - namespace shrpx { class Downstream; -// Link entry in HostEntry.blocked and downstream because downstream -// could be deleted in anytime and we'd like to find Downstream in -// O(1). Downstream has field to link back to this object. -struct BlockedLink { - Downstream *downstream; - BlockedLink *dlnext, *dlprev; -}; - class DownstreamQueue { public: - struct HostEntry { - // Set of stream ID that blocked by conn_max_per_host_. - DList blocked; - // The number of connections currently made to this host. - size_t num_active; - HostEntry(); - }; - - using HostEntryMap = std::map; - - // conn_max_per_host == 0 means no limit for downstream connection. - DownstreamQueue(size_t conn_max_per_host = 0, bool unified_host = true); + DownstreamQueue(); ~DownstreamQueue(); - // Add |downstream| to this queue. This is entry point for - // Downstream object. void add_pending(std::unique_ptr downstream); - // Set |downstream| to failure state, which means that downstream - // failed to connect to backend. - void mark_failure(Downstream *downstream); - // Set |downstream| to active state, which means that downstream - // connection has started. - void mark_active(Downstream *downstream); - // Set |downstream| to blocked state, which means that download - // connection was blocked because conn_max_per_host_ limit. - void mark_blocked(Downstream *downstream); - // Returns true if we can make downstream connection to given - // |host|. - bool can_activate(const StringRef &host) const; - // Removes and frees |downstream| object. If |downstream| is in - // Downstream::DISPATCH_ACTIVE, and |next_blocked| is true, this - // function may return Downstream object with the same target host - // in Downstream::DISPATCH_BLOCKED if its connection is now not - // blocked by conn_max_per_host_ limit. - Downstream *remove_and_get_blocked(Downstream *downstream, - bool next_blocked = true); - Downstream *get_downstreams() const; - HostEntry &find_host_entry(const std::string &host); - std::string make_host_key(const StringRef &host) const; - std::string make_host_key(Downstream *downstream) const; + void add_failure(std::unique_ptr downstream); + void add_active(std::unique_ptr downstream); + // Removes |downstream| from either pending_downstreams_, + // active_downstreams_ or failure_downstreams_ and returns it + // wrapped in std::unique_ptr. + std::unique_ptr remove(int32_t stream_id); + // Finds Downstream object denoted by |stream_id| either in + // pending_downstreams_, active_downstreams_ or + // failure_downstreams_. + Downstream *find(int32_t stream_id); + // Returns the number of active Downstream objects. + size_t num_active() const; + // Returns true if pending_downstreams_ is empty. + bool pending_empty() const; + // Pops first Downstream object in pending_downstreams_ and returns + // it. + std::unique_ptr pop_pending(); + // Returns first Downstream object in pending_downstreams_. This + // does not pop the first one. If queue is empty, returns nullptr. + Downstream *pending_top() const; + const std::map> & + get_active_downstreams() const; private: - // Per target host structure to keep track of the number of - // connections to the same host. - std::map host_entries_; - DList downstreams_; - // Maximum number of concurrent connections to the same host. - size_t conn_max_per_host_; - // true if downstream host is treated as the same. Used for reverse - // proxying. - bool unified_host_; + // Downstream objects, not processed yet + std::map> pending_downstreams_; + // Downstream objects in use, consuming downstream concurrency limit + std::map> active_downstreams_; + // Downstream objects, failed to connect to downstream server + std::map> failure_downstreams_; }; } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_downstream_test.cc nghttp2-0.6.7/src/shrpx_downstream_test.cc --- nghttp2-1.13.0/src/shrpx_downstream_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_downstream_test.cc 2014-11-30 14:15:07.000000000 +0000 @@ -32,127 +32,129 @@ namespace shrpx { -void test_downstream_field_store_append_last_header(void) { - BlockAllocator balloc(4096, 4096); - FieldStore fs(balloc, 0); - fs.add_header_token(StringRef::from_lit("alpha"), StringRef{}, false, -1); - auto bravo = StringRef::from_lit("BRAVO"); - fs.append_last_header_key(bravo.c_str(), bravo.size()); - auto charlie = StringRef::from_lit("Charlie"); - fs.append_last_header_value(charlie.c_str(), charlie.size()); - auto delta = StringRef::from_lit("deltA"); - fs.append_last_header_value(delta.c_str(), delta.size()); - fs.add_header_token(StringRef::from_lit("echo"), - StringRef::from_lit("foxtrot"), false, -1); - - auto ans = HeaderRefs{ - {StringRef::from_lit("alphabravo"), StringRef::from_lit("CharliedeltA")}, - {StringRef::from_lit("echo"), StringRef::from_lit("foxtrot")}}; - CU_ASSERT(ans == fs.headers()); -} - -void test_downstream_field_store_header(void) { - BlockAllocator balloc(4096, 4096); - FieldStore fs(balloc, 0); - fs.add_header_token(StringRef::from_lit("alpha"), StringRef::from_lit("0"), - false, -1); - fs.add_header_token(StringRef::from_lit(":authority"), - StringRef::from_lit("1"), false, http2::HD__AUTHORITY); - fs.add_header_token(StringRef::from_lit("content-length"), - StringRef::from_lit("2"), false, - http2::HD_CONTENT_LENGTH); - - // By token - CU_ASSERT(HeaderRef(StringRef{":authority"}, StringRef{"1"}) == - *fs.header(http2::HD__AUTHORITY)); - CU_ASSERT(nullptr == fs.header(http2::HD__METHOD)); - - // By name - CU_ASSERT(HeaderRef(StringRef{"alpha"}, StringRef{"0"}) == - *fs.header(StringRef::from_lit("alpha"))); - CU_ASSERT(nullptr == fs.header(StringRef::from_lit("bravo"))); +void test_downstream_normalize_request_headers(void) { + Downstream d(nullptr, 0, 0); + d.add_request_header("1", "0"); + d.add_request_header("2", "1"); + d.add_request_header("Charlie", "2"); + d.add_request_header("Alpha", "3"); + d.add_request_header("Delta", "4"); + d.add_request_header("BravO", "5"); + d.add_request_header(":method", "6"); + d.add_request_header(":authority", "7"); + d.normalize_request_headers(); + + auto ans = Headers{{":authority", "7"}, + {":method", "6"}, + {"1", "0"}, + {"2", "1"}, + {"alpha", "3"}, + {"bravo", "5"}, + {"charlie", "2"}, + {"delta", "4"}}; + CU_ASSERT(ans == d.get_request_headers()); +} + +void test_downstream_normalize_response_headers(void) { + Downstream d(nullptr, 0, 0); + d.add_response_header("Charlie", "0"); + d.add_response_header("Alpha", "1"); + d.add_response_header("Delta", "2"); + d.add_response_header("BravO", "3"); + d.normalize_response_headers(); + + auto ans = + Headers{{"alpha", "1"}, {"bravo", "3"}, {"charlie", "0"}, {"delta", "2"}}; + CU_ASSERT(ans == d.get_response_headers()); +} + +void test_downstream_get_norm_request_header(void) { + Downstream d(nullptr, 0, 0); + d.add_request_header("alpha", "0"); + d.add_request_header("bravo", "1"); + d.add_request_header("bravo", "2"); + d.add_request_header("charlie", "3"); + d.add_request_header("delta", "4"); + d.add_request_header("echo", "5"); + auto i = d.get_norm_request_header("alpha"); + CU_ASSERT(Header("alpha", "0") == *i); + i = d.get_norm_request_header("bravo"); + CU_ASSERT(Header("bravo", "1") == *i); + i = d.get_norm_request_header("delta"); + CU_ASSERT(Header("delta", "4") == *i); + i = d.get_norm_request_header("echo"); + CU_ASSERT(Header("echo", "5") == *i); + i = d.get_norm_request_header("foxtrot"); + CU_ASSERT(i == std::end(d.get_request_headers())); +} + +void test_downstream_get_norm_response_header(void) { + Downstream d(nullptr, 0, 0); + d.add_response_header("alpha", "0"); + d.add_response_header("bravo", "1"); + d.add_response_header("bravo", "2"); + d.add_response_header("charlie", "3"); + d.add_response_header("delta", "4"); + d.add_response_header("echo", "5"); + auto i = d.get_norm_response_header("alpha"); + CU_ASSERT(Header("alpha", "0") == *i); + i = d.get_norm_response_header("bravo"); + CU_ASSERT(Header("bravo", "1") == *i); + i = d.get_norm_response_header("delta"); + CU_ASSERT(Header("delta", "4") == *i); + i = d.get_norm_response_header("echo"); + CU_ASSERT(Header("echo", "5") == *i); + i = d.get_norm_response_header("foxtrot"); + CU_ASSERT(i == std::end(d.get_response_headers())); } void test_downstream_crumble_request_cookie(void) { - Downstream d(nullptr, nullptr, 0); - auto &req = d.request(); - req.fs.add_header_token(StringRef::from_lit(":method"), - StringRef::from_lit("get"), false, -1); - req.fs.add_header_token(StringRef::from_lit(":path"), - StringRef::from_lit("/"), false, -1); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("alpha; bravo; ; ;; charlie;;"), - true, http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit(";delta"), false, - http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("echo"), false, http2::HD_COOKIE); - - std::vector nva; - d.crumble_request_cookie(nva); - - auto num_cookies = d.count_crumble_request_cookie(); - - CU_ASSERT(5 == nva.size()); - CU_ASSERT(5 == num_cookies); - - HeaderRefs cookies; - std::transform(std::begin(nva), std::end(nva), std::back_inserter(cookies), - [](const nghttp2_nv &nv) { - return HeaderRef(StringRef{nv.name, nv.namelen}, - StringRef{nv.value, nv.valuelen}, - nv.flags & NGHTTP2_NV_FLAG_NO_INDEX); - }); - - HeaderRefs ans = { - {StringRef::from_lit("cookie"), StringRef::from_lit("alpha")}, - {StringRef::from_lit("cookie"), StringRef::from_lit("bravo")}, - {StringRef::from_lit("cookie"), StringRef::from_lit("charlie")}, - {StringRef::from_lit("cookie"), StringRef::from_lit("delta")}, - {StringRef::from_lit("cookie"), StringRef::from_lit("echo")}}; - - CU_ASSERT(ans == cookies); - CU_ASSERT(cookies[0].no_index); - CU_ASSERT(cookies[1].no_index); - CU_ASSERT(cookies[2].no_index); + Downstream d(nullptr, 0, 0); + d.add_request_header(":method", "get"); + d.add_request_header(":path", "/"); + d.add_request_header("cookie", "alpha; bravo; ; ;; charlie;;"); + d.add_request_header("cookie", ";delta"); + d.add_request_header("cookie", "echo"); + d.crumble_request_cookie(); + Headers ans = {{":method", "get"}, + {":path", "/"}, + {"cookie", "alpha"}, + {"cookie", "delta"}, + {"cookie", "echo"}, + {"cookie", "bravo"}, + {"cookie", "charlie"}}; + CU_ASSERT(ans == d.get_request_headers()); } void test_downstream_assemble_request_cookie(void) { - Downstream d(nullptr, nullptr, 0); - auto &req = d.request(); + Downstream d(nullptr, 0, 0); + d.add_request_header(":method", "get"); + d.add_request_header(":path", "/"); + d.add_request_header("cookie", "alpha"); + d.add_request_header("cookie", "bravo;"); + d.add_request_header("cookie", "charlie; "); + d.add_request_header("cookie", "delta;;"); + d.assemble_request_cookie(); + CU_ASSERT("alpha; bravo; charlie; delta" == d.get_assembled_request_cookie()); +} - req.fs.add_header_token(StringRef::from_lit(":method"), - StringRef::from_lit("get"), false, -1); - req.fs.add_header_token(StringRef::from_lit(":path"), - StringRef::from_lit("/"), false, -1); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("alpha"), false, - http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("bravo;"), false, - http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("charlie; "), false, - http2::HD_COOKIE); - req.fs.add_header_token(StringRef::from_lit("cookie"), - StringRef::from_lit("delta;;"), false, - http2::HD_COOKIE); - CU_ASSERT("alpha; bravo; charlie; delta" == d.assemble_request_cookie()); -} - -void test_downstream_rewrite_location_response_header(void) { - Downstream d(nullptr, nullptr, 0); - auto &req = d.request(); - auto &resp = d.response(); - d.set_request_downstream_host(StringRef::from_lit("localhost2")); - req.authority = StringRef::from_lit("localhost:8443"); - resp.fs.add_header_token(StringRef::from_lit("location"), - StringRef::from_lit("http://localhost2:3000/"), - false, http2::HD_LOCATION); - d.rewrite_location_response_header(StringRef::from_lit("https")); - auto location = resp.fs.header(http2::HD_LOCATION); - CU_ASSERT("https://localhost:8443/" == (*location).value); +void test_downstream_rewrite_norm_location_response_header(void) { + { + Downstream d(nullptr, 0, 0); + d.add_request_header("host", "localhost:3000"); + d.add_response_header("location", "http://localhost:3000/"); + d.rewrite_norm_location_response_header("https", 443); + auto location = d.get_norm_response_header("location"); + CU_ASSERT("https://localhost/" == (*location).value); + } + { + Downstream d(nullptr, 0, 0); + d.set_request_http2_authority("localhost"); + d.add_response_header("location", "http://localhost/"); + d.rewrite_norm_location_response_header("https", 443); + auto location = d.get_norm_response_header("location"); + CU_ASSERT("https://localhost/" == (*location).value); + } } } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_downstream_test.h nghttp2-0.6.7/src/shrpx_downstream_test.h --- nghttp2-1.13.0/src/shrpx_downstream_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_downstream_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,17 +25,15 @@ #ifndef SHRPX_DOWNSTREAM_TEST_H #define SHRPX_DOWNSTREAM_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - namespace shrpx { -void test_downstream_field_store_append_last_header(void); -void test_downstream_field_store_header(void); +void test_downstream_normalize_request_headers(void); +void test_downstream_normalize_response_headers(void); +void test_downstream_get_norm_request_header(void); +void test_downstream_get_norm_response_header(void); void test_downstream_crumble_request_cookie(void); void test_downstream_assemble_request_cookie(void); -void test_downstream_rewrite_location_response_header(void); +void test_downstream_rewrite_norm_location_response_header(void); } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_error.h nghttp2-0.6.7/src/shrpx_error.h --- nghttp2-1.13.0/src/shrpx_error.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_error.h 2014-11-30 14:15:07.000000000 +0000 @@ -29,14 +29,11 @@ namespace shrpx { -// Deprecated, do not use. enum ErrorCode { SHRPX_ERR_SUCCESS = 0, - SHRPX_ERR_ERROR = -1, - SHRPX_ERR_NETWORK = -100, - SHRPX_ERR_EOF = -101, - SHRPX_ERR_INPROGRESS = -102, - SHRPX_ERR_DCONN_CANCELED = -103, + SHRPX_ERR_UNKNOWN = -1, + SHRPX_ERR_HTTP_PARSE = -2, + SHRPX_ERR_NETWORK = -3 }; } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx.h nghttp2-0.6.7/src/shrpx.h --- nghttp2-1.13.0/src/shrpx.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx.h 2014-11-30 14:15:07.000000000 +0000 @@ -30,22 +30,26 @@ #endif // HAVE_CONFIG_H #include -#ifdef HAVE_SYS_SOCKET_H #include -#endif // HAVE_SYS_SOCKET_H #include #include "shrpx_log.h" +#ifndef SOCK_NONBLOCK +#define SOCK_NONBLOCK 0 +#endif // !SOCK_NONBLOCK + +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif // !SOCK_CLOEXEC + #ifndef HAVE__EXIT #define _Exit(status) _exit(status) #endif // !HAVE__EXIT -#define DIE() _Exit(EXIT_FAILURE) +#define DIE() exit(EXIT_FAILURE) -#if defined(HAVE_DECL_INITGROUPS) && !HAVE_DECL_INITGROUPS -inline int initgroups(const char *user, gid_t group) { return 0; } -#endif // defined(HAVE_DECL_INITGROUPS) && !HAVE_DECL_INITGROUPS +#define SHRPX_READ_WATERMARK (16 * 1024) #endif // SHRPX_H diff -Nru nghttp2-1.13.0/src/shrpx_health_monitor_downstream_connection.cc nghttp2-0.6.7/src/shrpx_health_monitor_downstream_connection.cc --- nghttp2-1.13.0/src/shrpx_health_monitor_downstream_connection.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_health_monitor_downstream_connection.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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. - */ -#include "shrpx_health_monitor_downstream_connection.h" - -#include "shrpx_client_handler.h" -#include "shrpx_upstream.h" -#include "shrpx_downstream.h" -//#include "shrpx_connection_handler.h" - -namespace shrpx { - -HealthMonitorDownstreamConnection::HealthMonitorDownstreamConnection() {} - -HealthMonitorDownstreamConnection::~HealthMonitorDownstreamConnection() {} - -int HealthMonitorDownstreamConnection::attach_downstream( - Downstream *downstream) { - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream; - } - - downstream_ = downstream; - - return 0; -} - -void HealthMonitorDownstreamConnection::detach_downstream( - Downstream *downstream) { - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "Detaching from DOWNSTREAM:" << downstream; - } - downstream_ = nullptr; -} - -int HealthMonitorDownstreamConnection::push_request_headers() { return 0; } - -int HealthMonitorDownstreamConnection::push_upload_data_chunk( - const uint8_t *data, size_t datalen) { - return 0; -} - -int HealthMonitorDownstreamConnection::end_upload_data() { - auto upstream = downstream_->get_upstream(); - auto &resp = downstream_->response(); - - resp.http_status = 200; - - resp.fs.add_header_token(StringRef::from_lit("content-length"), - StringRef::from_lit("0"), false, - http2::HD_CONTENT_LENGTH); - - if (upstream->send_reply(downstream_, nullptr, 0) != 0) { - return -1; - } - - return 0; -} - -void HealthMonitorDownstreamConnection::pause_read(IOCtrlReason reason) {} - -int HealthMonitorDownstreamConnection::resume_read(IOCtrlReason reason, - size_t consumed) { - return 0; -} - -void HealthMonitorDownstreamConnection::force_resume_read() {} - -int HealthMonitorDownstreamConnection::on_read() { return 0; } - -int HealthMonitorDownstreamConnection::on_write() { return 0; } - -void HealthMonitorDownstreamConnection::on_upstream_change(Upstream *uptream) {} - -bool HealthMonitorDownstreamConnection::poolable() const { return false; } - -DownstreamAddrGroup * -HealthMonitorDownstreamConnection::get_downstream_addr_group() const { - return nullptr; -} - -DownstreamAddr *HealthMonitorDownstreamConnection::get_addr() const { - return nullptr; -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_health_monitor_downstream_connection.h nghttp2-0.6.7/src/shrpx_health_monitor_downstream_connection.h --- nghttp2-1.13.0/src/shrpx_health_monitor_downstream_connection.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_health_monitor_downstream_connection.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 SHRPX_HEALTH_MONITOR_DOWNSTREAM_CONNECTION_H -#define SHRPX_HEALTH_MONITOR_DOWNSTREAM_CONNECTION_H - -#include "shrpx_downstream_connection.h" - -namespace shrpx { - -class Worker; - -class HealthMonitorDownstreamConnection : public DownstreamConnection { -public: - HealthMonitorDownstreamConnection(); - virtual ~HealthMonitorDownstreamConnection(); - virtual int attach_downstream(Downstream *downstream); - virtual void detach_downstream(Downstream *downstream); - - virtual int push_request_headers(); - virtual int push_upload_data_chunk(const uint8_t *data, size_t datalen); - virtual int end_upload_data(); - - virtual void pause_read(IOCtrlReason reason); - virtual int resume_read(IOCtrlReason reason, size_t consumed); - virtual void force_resume_read(); - - virtual int on_read(); - virtual int on_write(); - - virtual void on_upstream_change(Upstream *uptream); - - // true if this object is poolable. - virtual bool poolable() const; - - virtual DownstreamAddrGroup *get_downstream_addr_group() const; - virtual DownstreamAddr *get_addr() const; -}; - -} // namespace shrpx - -#endif // SHRPX_HEALTH_MONITOR_DOWNSTREAM_CONNECTION_H diff -Nru nghttp2-1.13.0/src/shrpx_http2_downstream_connection.cc nghttp2-0.6.7/src/shrpx_http2_downstream_connection.cc --- nghttp2-1.13.0/src/shrpx_http2_downstream_connection.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http2_downstream_connection.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,9 +24,11 @@ */ #include "shrpx_http2_downstream_connection.h" -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H + +#include + +#include #include "http-parser/http_parser.h" @@ -37,7 +39,7 @@ #include "shrpx_error.h" #include "shrpx_http.h" #include "shrpx_http2_session.h" -#include "shrpx_worker.h" +#include "shrpx_worker_config.h" #include "http2.h" #include "util.h" @@ -45,16 +47,18 @@ namespace shrpx { -Http2DownstreamConnection::Http2DownstreamConnection(Http2Session *http2session) - : dlnext(nullptr), - dlprev(nullptr), - http2session_(http2session), - sd_(nullptr) {} +Http2DownstreamConnection::Http2DownstreamConnection( + DownstreamConnectionPool *dconn_pool, Http2Session *http2session) + : DownstreamConnection(dconn_pool), http2session_(http2session), + request_body_buf_(nullptr), sd_(nullptr) {} Http2DownstreamConnection::~Http2DownstreamConnection() { if (LOG_ENABLED(INFO)) { DCLOG(INFO, this) << "Deleting"; } + if (request_body_buf_) { + evbuffer_free(request_body_buf_); + } if (downstream_) { downstream_->disable_downstream_rtimer(); downstream_->disable_downstream_wtimer(); @@ -69,43 +73,69 @@ error_code = NGHTTP2_INTERNAL_ERROR; } - if (http2session_->get_state() == Http2Session::CONNECTED && - downstream_->get_downstream_stream_id() != -1) { - submit_rst_stream(downstream_, error_code); + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, this) << "Submit RST_STREAM for DOWNSTREAM:" << downstream_ + << ", stream_id=" + << downstream_->get_downstream_stream_id() + << ", error_code=" << error_code; + } - auto &resp = downstream_->response(); + if (submit_rst_stream(downstream_, error_code) == 0) { + http2session_->notify(); + } + if (downstream_->get_downstream_stream_id() != -1) { http2session_->consume(downstream_->get_downstream_stream_id(), - resp.unconsumed_body_length); + downstream_->get_response_datalen()); - resp.unconsumed_body_length = 0; + downstream_->reset_response_datalen(); - http2session_->signal_write(); + http2session_->notify(); } } http2session_->remove_downstream_connection(this); - + // Downstream and DownstreamConnection may be deleted + // asynchronously. + if (downstream_) { + downstream_->release_downstream_connection(); + } if (LOG_ENABLED(INFO)) { DCLOG(INFO, this) << "Deleted"; } } +int Http2DownstreamConnection::init_request_body_buf() { + int rv; + if (request_body_buf_) { + rv = evbuffer_drain(request_body_buf_, + evbuffer_get_length(request_body_buf_)); + if (rv != 0) { + return -1; + } + } else { + request_body_buf_ = evbuffer_new(); + if (request_body_buf_ == nullptr) { + return -1; + } + } + return 0; +} + int Http2DownstreamConnection::attach_downstream(Downstream *downstream) { if (LOG_ENABLED(INFO)) { DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream; } + if (init_request_body_buf() == -1) { + return -1; + } http2session_->add_downstream_connection(this); - http2session_->signal_write(); + if (http2session_->get_state() == Http2Session::DISCONNECTED) { + http2session_->notify(); + } downstream_ = downstream; - downstream_->reset_downstream_rtimer(); - - auto &req = downstream_->request(); - // HTTP/2 disables HTTP Upgrade. - if (req.method != HTTP_CONNECT) { - req.upgrade_request = false; - } + downstream_->init_downstream_timer(); return 0; } @@ -114,20 +144,17 @@ if (LOG_ENABLED(INFO)) { DCLOG(INFO, this) << "Detaching from DOWNSTREAM:" << downstream; } - - auto &resp = downstream_->response(); - if (submit_rst_stream(downstream) == 0) { - http2session_->signal_write(); + http2session_->notify(); } if (downstream_->get_downstream_stream_id() != -1) { http2session_->consume(downstream_->get_downstream_stream_id(), - resp.unconsumed_body_length); + downstream_->get_response_datalen()); - resp.unconsumed_body_length = 0; + downstream_->reset_response_datalen(); - http2session_->signal_write(); + http2session_->notify(); } downstream->disable_downstream_rtimer(); @@ -142,15 +169,13 @@ downstream->get_downstream_stream_id() != -1) { switch (downstream->get_response_state()) { case Downstream::MSG_RESET: - case Downstream::MSG_BAD_HEADER: case Downstream::MSG_COMPLETE: break; default: if (LOG_ENABLED(INFO)) { DCLOG(INFO, this) << "Submit RST_STREAM for DOWNSTREAM:" << downstream << ", stream_id=" - << downstream->get_downstream_stream_id() - << ", error_code=" << error_code; + << downstream->get_downstream_stream_id(); } rv = http2session_->submit_rst_stream( downstream->get_downstream_stream_id(), error_code); @@ -164,56 +189,58 @@ uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { - int rv; auto sd = static_cast( nghttp2_session_get_stream_user_data(session, stream_id)); if (!sd || !sd->dconn) { return NGHTTP2_ERR_DEFERRED; } - auto dconn = sd->dconn; + auto dconn = static_cast(source->ptr); auto downstream = dconn->get_downstream(); if (!downstream) { // In this case, RST_STREAM should have been issued. But depending // on the priority, DATA frame may come first. return NGHTTP2_ERR_DEFERRED; } - const auto &req = downstream->request(); - auto input = downstream->get_request_buf(); + auto body = dconn->get_request_body_buf(); + + auto nread = evbuffer_remove(body, buf, length); + if (nread == -1) { + DCLOG(FATAL, dconn) << "evbuffer_remove() failed"; + return NGHTTP2_ERR_CALLBACK_FAILURE; + } - auto nread = std::min(input->rleft(), length); - auto input_empty = input->rleft() == nread; + if (nread > 0) { + // This is important because it will handle flow control + // stuff. + if (downstream->get_upstream()->resume_read(SHRPX_NO_BUFFER, downstream, + nread) != 0) { + // In this case, downstream may be deleted. + return NGHTTP2_ERR_CALLBACK_FAILURE; + } - *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY; + // Check dconn is still alive because Upstream::resume_read() + // may delete downstream which will delete dconn. + if (sd->dconn == nullptr) { + return NGHTTP2_ERR_DEFERRED; + } + } - if (input_empty && + if (evbuffer_get_length(body) == 0 && downstream->get_request_state() == Downstream::MSG_COMPLETE && // If connection is upgraded, don't set EOF flag, since HTTP/1 // will set MSG_COMPLETE to request state after upgrade response // header is seen. - (!req.upgrade_request || + (!downstream->get_upgrade_request() || (downstream->get_response_state() == Downstream::HEADER_COMPLETE && !downstream->get_upgraded()))) { *data_flags |= NGHTTP2_DATA_FLAG_EOF; + } - const auto &trailers = req.fs.trailers(); - if (!trailers.empty()) { - std::vector nva; - nva.reserve(trailers.size()); - // We cannot use nocopy version, since nva may be touched after - // Downstream object is deleted. - http2::copy_headers_to_nva(nva, trailers); - if (!nva.empty()) { - rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size()); - if (rv != 0) { - if (nghttp2_is_fatal(rv)) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - } else { - *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM; - } - } - } + if (evbuffer_get_length(body) > 0) { + downstream->reset_downstream_wtimer(); + } else { + downstream->disable_downstream_wtimer(); } if (nread == 0 && (*data_flags & NGHTTP2_DATA_FLAG_EOF) == 0) { @@ -228,208 +255,203 @@ int Http2DownstreamConnection::push_request_headers() { int rv; - if (!downstream_) { + if (http2session_->get_state() != Http2Session::CONNECTED) { + // The HTTP2 session to the backend has not been established. + // This function will be called again just after it is + // established. return 0; } - if (!http2session_->can_push_request()) { - // The HTTP2 session to the backend has not been established or - // connection is now being checked. This function will be called - // again just after it is established. - downstream_->set_request_pending(true); - http2session_->start_checking_connection(); + if (!downstream_) { return 0; } - - downstream_->set_request_pending(false); - - const auto &req = downstream_->request(); - - auto &balloc = downstream_->get_block_allocator(); - - auto &httpconf = get_config()->http; - auto &http2conf = get_config()->http2; - - auto no_host_rewrite = httpconf.no_host_rewrite || - get_config()->http2_proxy || - req.method == HTTP_CONNECT; - - // http2session_ has already in CONNECTED state, so we can get - // addr_idx here. - const auto &downstream_hostport = http2session_->get_addr()->hostport; - - // For HTTP/1.0 request, there is no authority in request. In that - // case, we use backend server's host nonetheless. - auto authority = StringRef(downstream_hostport); - - if (no_host_rewrite && !req.authority.empty()) { - authority = req.authority; + size_t nheader = downstream_->get_request_headers().size(); + if (!get_config()->http2_no_cookie_crumbling) { + downstream_->crumble_request_cookie(); } - downstream_->set_request_downstream_host(authority); + assert(downstream_->get_request_headers_normalized()); - size_t num_cookies = 0; - if (!http2conf.no_cookie_crumbling) { - num_cookies = downstream_->count_crumble_request_cookie(); - } + auto end_headers = std::end(downstream_->get_request_headers()); - // 9 means: + // 7 means: // 1. :method // 2. :scheme // 3. :path - // 4. :authority (or host) + // 4. :authority (optional) // 5. via (optional) // 6. x-forwarded-for (optional) // 7. x-forwarded-proto (optional) - // 8. te (optional) - // 9. forwarded (optional) auto nva = std::vector(); - nva.reserve(req.fs.headers().size() + 9 + num_cookies + - httpconf.add_request_headers.size()); - - nva.push_back( - http2::make_nv_ls_nocopy(":method", http2::to_method_string(req.method))); - - if (req.method != HTTP_CONNECT) { - assert(!req.scheme.empty()); - - nva.push_back(http2::make_nv_ls_nocopy(":scheme", req.scheme)); - - if (req.method == HTTP_OPTIONS && req.path.empty()) { - nva.push_back(http2::make_nv_ll(":path", "*")); + nva.reserve(nheader + 7); + std::string via_value; + std::string xff_value; + std::string scheme, authority, path, query; + // To reconstruct HTTP/1 status line and headers, proxy should + // preserve host header field. See draft-09 section 8.1.3.1. + if (downstream_->get_request_method() == "CONNECT") { + // The upstream may be HTTP/2 or HTTP/1 + if (!downstream_->get_request_http2_authority().empty()) { + nva.push_back(http2::make_nv_ls( + ":authority", downstream_->get_request_http2_authority())); } else { - nva.push_back(http2::make_nv_ls_nocopy(":path", req.path)); + nva.push_back( + http2::make_nv_ls(":authority", downstream_->get_request_path())); } - - if (!req.no_authority) { - nva.push_back(http2::make_nv_ls_nocopy(":authority", authority)); - } else { - nva.push_back(http2::make_nv_ls_nocopy("host", authority)); + } else if (!downstream_->get_request_http2_scheme().empty()) { + // Here the upstream is HTTP/2 + nva.push_back( + http2::make_nv_ls(":scheme", downstream_->get_request_http2_scheme())); + nva.push_back(http2::make_nv_ls(":path", downstream_->get_request_path())); + if (!downstream_->get_request_http2_authority().empty()) { + nva.push_back(http2::make_nv_ls( + ":authority", downstream_->get_request_http2_authority())); + } else if (downstream_->get_norm_request_header("host") == end_headers) { + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, this) << "host header field missing"; + } + return -1; } } else { - nva.push_back(http2::make_nv_ls_nocopy(":authority", authority)); - } - - http2::copy_headers_to_nva_nocopy(nva, req.fs.headers()); - - if (!http2conf.no_cookie_crumbling) { - downstream_->crumble_request_cookie(nva); - } - - auto upstream = downstream_->get_upstream(); - auto handler = upstream->get_client_handler(); - - auto &fwdconf = httpconf.forwarded; - - auto fwd = - fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED); - - if (fwdconf.params) { - auto params = fwdconf.params; - - if (get_config()->http2_proxy || req.method == HTTP_CONNECT) { - params &= ~FORWARDED_PROTO; - } - - auto value = http::create_forwarded( - balloc, params, handler->get_forwarded_by(), - handler->get_forwarded_for(), req.authority, req.scheme); - - if (fwd || !value.empty()) { - if (fwd) { - if (value.empty()) { - value = fwd->value; + // The upstream is HTTP/1 + http_parser_url u; + const char *url = downstream_->get_request_path().c_str(); + memset(&u, 0, sizeof(u)); + rv = http_parser_parse_url(url, downstream_->get_request_path().size(), 0, + &u); + if (rv == 0) { + http2::copy_url_component(scheme, &u, UF_SCHEMA, url); + http2::copy_url_component(authority, &u, UF_HOST, url); + http2::copy_url_component(path, &u, UF_PATH, url); + http2::copy_url_component(query, &u, UF_QUERY, url); + if (path.empty()) { + if (!authority.empty() && + downstream_->get_request_method() == "OPTIONS") { + path = "*"; } else { - value = concat_string_ref(balloc, fwd->value, - StringRef::from_lit(", "), value); + path = "/"; } } - - nva.push_back(http2::make_nv_ls_nocopy("forwarded", value)); + if (!query.empty()) { + path += "?"; + path += query; + } } - } else if (fwd) { - nva.push_back(http2::make_nv_ls_nocopy("forwarded", fwd->value)); - } - - auto &xffconf = httpconf.xff; - - auto xff = xffconf.strip_incoming ? nullptr - : req.fs.header(http2::HD_X_FORWARDED_FOR); - - if (xffconf.add) { - StringRef xff_value; - auto addr = StringRef{upstream->get_client_handler()->get_ipaddr()}; - if (xff) { - xff_value = concat_string_ref(balloc, xff->value, - StringRef::from_lit(", "), addr); + if (scheme.empty()) { + if (client_handler_->get_ssl()) { + nva.push_back(http2::make_nv_ll(":scheme", "https")); + } else { + nva.push_back(http2::make_nv_ll(":scheme", "http")); + } } else { - xff_value = addr; + nva.push_back(http2::make_nv_ls(":scheme", scheme)); } - nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-for", xff_value)); - } else if (xff) { - nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-for", xff->value)); - } - - if (!get_config()->http2_proxy && req.method != HTTP_CONNECT) { - // We use same protocol with :scheme header field - nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-proto", req.scheme)); - } - - auto via = req.fs.header(http2::HD_VIA); - if (httpconf.no_via) { - if (via) { - nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value)); + if (path.empty()) { + nva.push_back( + http2::make_nv_ls(":path", downstream_->get_request_path())); + } else { + nva.push_back(http2::make_nv_ls(":path", path)); } - } else { - size_t vialen = 16; - if (via) { - vialen += via->value.size() + 2; + if (!authority.empty()) { + // TODO properly check IPv6 numeric address + if (authority.find(":") != std::string::npos) { + authority = "[" + authority; + authority += "]"; + } + if (u.field_set & (1 << UF_PORT)) { + authority += ":"; + authority += util::utos(u.port); + } + nva.push_back(http2::make_nv_ls(":authority", authority)); + } else if (downstream_->get_norm_request_header("host") == end_headers) { + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, this) << "host header field missing"; + } + return -1; } + } - auto iov = make_byte_ref(balloc, vialen + 1); - auto p = iov.base; + nva.push_back( + http2::make_nv_ls(":method", downstream_->get_request_method())); - if (via) { - p = std::copy(std::begin(via->value), std::end(via->value), p); - p = util::copy_lit(p, ", "); - } - p = http::create_via_header_value(p, req.http_major, req.http_minor); - *p = '\0'; + http2::copy_norm_headers_to_nva(nva, downstream_->get_request_headers()); - nva.push_back(http2::make_nv_ls_nocopy("via", StringRef{iov.base, p})); + bool chunked_encoding = false; + auto transfer_encoding = + downstream_->get_norm_request_header("transfer-encoding"); + if (transfer_encoding != end_headers && + util::strieq((*transfer_encoding).value.c_str(), "chunked")) { + chunked_encoding = true; + } + + auto xff = downstream_->get_norm_request_header("x-forwarded-for"); + if (get_config()->add_x_forwarded_for) { + if (xff != end_headers && !get_config()->strip_incoming_x_forwarded_for) { + xff_value = (*xff).value; + xff_value += ", "; + } + xff_value += + downstream_->get_upstream()->get_client_handler()->get_ipaddr(); + nva.push_back(http2::make_nv_ls("x-forwarded-for", xff_value)); + } else if (xff != end_headers && + !get_config()->strip_incoming_x_forwarded_for) { + nva.push_back(http2::make_nv_ls("x-forwarded-for", (*xff).value)); } - auto te = req.fs.header(http2::HD_TE); - // HTTP/1 upstream request can contain keyword other than - // "trailers". We just forward "trailers". - // TODO more strict handling required here. - if (te && util::strifind(te->value, StringRef::from_lit("trailers"))) { - nva.push_back(http2::make_nv_ll("te", "trailers")); + if (!get_config()->http2_proxy && !get_config()->client_proxy && + downstream_->get_request_method() != "CONNECT") { + // We use same protocol with :scheme header field + if (scheme.empty()) { + if (client_handler_->get_ssl()) { + nva.push_back(http2::make_nv_ll("x-forwarded-proto", "https")); + } else { + nva.push_back(http2::make_nv_ll("x-forwarded-proto", "http")); + } + } else { + nva.push_back(http2::make_nv_ls("x-forwarded-proto", scheme)); + } } - for (auto &p : httpconf.add_request_headers) { - nva.push_back(http2::make_nv_nocopy(p.name, p.value)); + auto via = downstream_->get_norm_request_header("via"); + if (get_config()->no_via) { + if (via != end_headers) { + nva.push_back(http2::make_nv_ls("via", (*via).value)); + } + } else { + if (via != end_headers) { + via_value = (*via).value; + via_value += ", "; + } + via_value += http::create_via_header_value( + downstream_->get_request_major(), downstream_->get_request_minor()); + nva.push_back(http2::make_nv_ls("via", via_value)); } if (LOG_ENABLED(INFO)) { std::stringstream ss; for (auto &nv : nva) { - ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST << ": " - << StringRef{nv.value, nv.valuelen} << "\n"; + ss << TTY_HTTP_HD; + ss.write(reinterpret_cast(nv.name), nv.namelen); + ss << TTY_RST << ": "; + ss.write(reinterpret_cast(nv.value), nv.valuelen); + ss << "\n"; } DCLOG(INFO, this) << "HTTP request headers\n" << ss.str(); } - auto transfer_encoding = req.fs.header(http2::HD_TRANSFER_ENCODING); + auto content_length = + downstream_->get_norm_request_header("content-length") != end_headers; - // Add body as long as transfer-encoding is given even if - // req.fs.content_length == 0 to forward trailer fields. - if (req.method == HTTP_CONNECT || transfer_encoding || - req.fs.content_length > 0 || req.http2_expect_body) { + if (downstream_->get_request_method() == "CONNECT" || chunked_encoding || + content_length || downstream_->get_request_http2_expect_body()) { // Request-body is expected. - nghttp2_data_provider data_prd{{}, http2_data_read_callback}; - rv = http2session_->submit_request(this, nva.data(), nva.size(), &data_prd); + nghttp2_data_provider data_prd; + data_prd.source.ptr = this; + data_prd.read_callback = http2_data_read_callback; + rv = http2session_->submit_request(this, downstream_->get_priority(), + nva.data(), nva.size(), &data_prd); } else { - rv = http2session_->submit_request(this, nva.data(), nva.size(), nullptr); + rv = http2session_->submit_request(this, downstream_->get_priority(), + nva.data(), nva.size(), nullptr); } if (rv != 0) { DCLOG(FATAL, this) << "nghttp2_submit_request() failed"; @@ -438,15 +460,17 @@ downstream_->reset_downstream_wtimer(); - http2session_->signal_write(); + http2session_->notify(); return 0; } int Http2DownstreamConnection::push_upload_data_chunk(const uint8_t *data, size_t datalen) { - int rv; - auto output = downstream_->get_request_buf(); - output->append(data, datalen); + int rv = evbuffer_add(request_body_buf_, data, datalen); + if (rv != 0) { + DCLOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } if (downstream_->get_downstream_stream_id() != -1) { rv = http2session_->resume_data(this); if (rv != 0) { @@ -455,7 +479,7 @@ downstream_->ensure_downstream_wtimer(); - http2session_->signal_write(); + http2session_->notify(); } return 0; } @@ -470,7 +494,7 @@ downstream_->ensure_downstream_wtimer(); - http2session_->signal_write(); + http2session_->notify(); } return 0; } @@ -479,7 +503,8 @@ size_t consumed) { int rv; - if (http2session_->get_state() != Http2Session::CONNECTED) { + if (http2session_->get_state() != Http2Session::CONNECTED || + !http2session_->get_flow_control()) { return 0; } @@ -488,6 +513,8 @@ } if (consumed > 0) { + assert(downstream_->get_response_datalen() >= consumed); + rv = http2session_->consume(downstream_->get_downstream_stream_id(), consumed); @@ -495,11 +522,9 @@ return -1; } - auto &resp = downstream_->response(); - - resp.unconsumed_body_length -= consumed; + downstream_->dec_response_datalen(consumed); - http2session_->signal_write(); + http2session_->notify(); } return 0; @@ -509,6 +534,10 @@ int Http2DownstreamConnection::on_write() { return 0; } +evbuffer *Http2DownstreamConnection::get_request_body_buf() const { + return request_body_buf_; +} + void Http2DownstreamConnection::attach_stream_data(StreamData *sd) { // It is possible sd->dconn is not NULL. sd is detached when // on_stream_close_callback. Before that, after MSG_COMPLETE is set @@ -526,8 +555,36 @@ sd_ = nullptr; sd->dconn = nullptr; return sd; + } else { + return nullptr; + } +} + +bool Http2DownstreamConnection::get_output_buffer_full() { + if (request_body_buf_) { + return evbuffer_get_length(request_body_buf_) >= + Http2Session::OUTBUF_MAX_THRES; + } else { + return false; + } +} + +int Http2DownstreamConnection::on_priority_change(int32_t pri) { + int rv; + if (downstream_->get_priority() == pri) { + return 0; + } + downstream_->set_priority(pri); + if (http2session_->get_state() != Http2Session::CONNECTED) { + return 0; + } + rv = http2session_->submit_priority(this, pri); + if (rv != 0) { + DLOG(FATAL, this) << "nghttp2_submit_priority() failed"; + return -1; } - return nullptr; + http2session_->notify(); + return 0; } int Http2DownstreamConnection::on_timeout() { @@ -538,11 +595,4 @@ return submit_rst_stream(downstream_, NGHTTP2_NO_ERROR); } -DownstreamAddrGroup * -Http2DownstreamConnection::get_downstream_addr_group() const { - return http2session_->get_downstream_addr_group(); -} - -DownstreamAddr *Http2DownstreamConnection::get_addr() const { return nullptr; } - } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_http2_downstream_connection.h nghttp2-0.6.7/src/shrpx_http2_downstream_connection.h --- nghttp2-1.13.0/src/shrpx_http2_downstream_connection.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http2_downstream_connection.h 2014-11-30 14:15:07.000000000 +0000 @@ -41,7 +41,8 @@ class Http2DownstreamConnection : public DownstreamConnection { public: - Http2DownstreamConnection(Http2Session *http2session); + Http2DownstreamConnection(DownstreamConnectionPool *dconn_pool, + Http2Session *http2session); virtual ~Http2DownstreamConnection(); virtual int attach_downstream(Downstream *downstream); virtual void detach_downstream(Downstream *downstream); @@ -54,31 +55,29 @@ virtual int resume_read(IOCtrlReason reason, size_t consumed); virtual void force_resume_read() {} + virtual bool get_output_buffer_full(); + virtual int on_read(); virtual int on_write(); virtual int on_timeout(); virtual void on_upstream_change(Upstream *upstream) {} - - // This object is not poolable because we dont' have facility to - // migrate to another Http2Session object. - virtual bool poolable() const { return false; } - - virtual DownstreamAddrGroup *get_downstream_addr_group() const; - virtual DownstreamAddr *get_addr() const; + virtual int on_priority_change(int32_t pri); int send(); + int init_request_body_buf(); + evbuffer *get_request_body_buf() const; + void attach_stream_data(StreamData *sd); StreamData *detach_stream_data(); int submit_rst_stream(Downstream *downstream, uint32_t error_code = NGHTTP2_INTERNAL_ERROR); - Http2DownstreamConnection *dlnext, *dlprev; - private: Http2Session *http2session_; + evbuffer *request_body_buf_; StreamData *sd_; }; diff -Nru nghttp2-1.13.0/src/shrpx_http2_session.cc nghttp2-0.6.7/src/shrpx_http2_session.cc --- nghttp2-1.13.0/src/shrpx_http2_session.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http2_session.cc 2014-11-30 14:15:07.000000000 +0000 @@ -25,14 +25,14 @@ #include "shrpx_http2_session.h" #include -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H #include #include +#include + #include "shrpx_upstream.h" #include "shrpx_downstream.h" #include "shrpx_config.h" @@ -41,319 +41,371 @@ #include "shrpx_client_handler.h" #include "shrpx_ssl.h" #include "shrpx_http.h" -#include "shrpx_worker.h" -#include "shrpx_connect_blocker.h" +#include "shrpx_worker_config.h" #include "http2.h" #include "util.h" +#include "libevent_util.h" #include "base64.h" -#include "ssl.h" using namespace nghttp2; namespace shrpx { -namespace { -const ev_tstamp CONNCHK_TIMEOUT = 5.; -const ev_tstamp CONNCHK_PING_TIMEOUT = 1.; -} // namespace +Http2Session::Http2Session(event_base *evbase, SSL_CTX *ssl_ctx) + : evbase_(evbase), ssl_ctx_(ssl_ctx), ssl_(nullptr), session_(nullptr), + bev_(nullptr), wrbev_(nullptr), rdbev_(nullptr), + settings_timerev_(nullptr), fd_(-1), state_(DISCONNECTED), + notified_(false), flow_control_(false) {} -namespace { -constexpr size_t MAX_BUFFER_SIZE = 32_k; -} // namespace +Http2Session::~Http2Session() { disconnect(); } -namespace { -void connchk_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto http2session = static_cast(w->data); +int Http2Session::disconnect() { + if (LOG_ENABLED(INFO)) { + SSLOG(INFO, this) << "Disconnecting"; + } + nghttp2_session_del(session_); + session_ = nullptr; - ev_timer_stop(loop, w); + if (settings_timerev_) { + event_free(settings_timerev_); + settings_timerev_ = nullptr; + } - switch (http2session->get_connection_check_state()) { - case Http2Session::CONNECTION_CHECK_STARTED: - // ping timeout; disconnect - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, http2session) << "ping timeout"; + if (ssl_) { + SSL_set_shutdown(ssl_, SSL_RECEIVED_SHUTDOWN); + SSL_shutdown(ssl_); + } + if (bev_) { + int fd = bufferevent_getfd(bev_); + util::bev_disable_unless(bev_, EV_READ | EV_WRITE); + bufferevent_free(bev_); + bev_ = nullptr; + if (fd != -1) { + if (fd_ == -1) { + fd_ = fd; + } else if (fd != fd_) { + SSLOG(WARN, this) << "fd in bev_ != fd_"; + shutdown(fd, SHUT_WR); + close(fd); + } } + } + if (ssl_) { + SSL_free(ssl_); + } + ssl_ = nullptr; - delete http2session; - - return; - default: + if (fd_ != -1) { if (LOG_ENABLED(INFO)) { - SSLOG(INFO, http2session) << "connection check required"; + SSLOG(INFO, this) << "Closing fd=" << fd_; } - http2session->set_connection_check_state( - Http2Session::CONNECTION_CHECK_REQUIRED); + shutdown(fd_, SHUT_WR); + close(fd_); + fd_ = -1; } -} -} // namespace -namespace { -void settings_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto http2session = static_cast(w->data); - SSLOG(INFO, http2session) << "SETTINGS timeout"; + if (proxy_htp_) { + proxy_htp_.reset(); + } - downstream_failure(http2session->get_addr()); + notified_ = false; + state_ = DISCONNECTED; - if (http2session->terminate_session(NGHTTP2_SETTINGS_TIMEOUT) != 0) { - delete http2session; + // Delete all client handler associated to Downstream. When deleting + // Http2DownstreamConnection, it calls this object's + // remove_downstream_connection(). The multiple + // Http2DownstreamConnection objects belong to the same ClientHandler + // object. So first dump ClientHandler objects and delete them once + // and for all. + std::vector vec(std::begin(dconns_), + std::end(dconns_)); + std::set handlers; + for (auto dc : vec) { + handlers.insert(dc->get_client_handler()); + } + for (auto &h : handlers) { + delete h; + } - return; + dconns_.clear(); + for (auto &s : streams_) { + delete s; } - http2session->signal_write(); + streams_.clear(); + return 0; } -} // namespace namespace { -void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - auto conn = static_cast(w->data); - auto http2session = static_cast(conn->data); - - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, http2session) << "Timeout"; +void notify_readcb(bufferevent *bev, void *arg) { + int rv; + auto http2session = static_cast(arg); + http2session->clear_notify(); + switch (http2session->get_state()) { + case Http2Session::DISCONNECTED: + rv = http2session->initiate_connection(); + if (rv != 0) { + SSLOG(FATAL, http2session) << "Could not initiate backend connection"; + http2session->disconnect(); + } + break; + case Http2Session::CONNECTED: + rv = http2session->send(); + if (rv != 0) { + http2session->disconnect(); + } + break; } - - http2session->on_timeout(); - - delete http2session; } } // namespace namespace { -void readcb(struct ev_loop *loop, ev_io *w, int revents) { - int rv; - auto conn = static_cast(w->data); - auto http2session = static_cast(conn->data); - rv = http2session->do_read(); - if (rv != 0) { - delete http2session; - - return; +void notify_eventcb(bufferevent *bev, short events, void *arg) { + auto http2session = static_cast(arg); + // TODO should DIE()? + if (events & BEV_EVENT_EOF) { + SSLOG(ERROR, http2session) << "Notification connection lost: EOF"; + } + if (events & BEV_EVENT_TIMEOUT) { + SSLOG(ERROR, http2session) << "Notification connection lost: timeout"; } - http2session->connection_alive(); + if (events & BEV_EVENT_ERROR) { + SSLOG(ERROR, http2session) << "Notification connection lost: network error"; + } +} +} // namespace - rv = http2session->do_write(); - if (rv != 0) { - delete http2session; +int Http2Session::init_notification() { + int rv; + int sockpair[2]; + rv = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, + sockpair); + if (rv == -1) { + auto error = errno; + SSLOG(FATAL, this) << "socketpair() failed: errno=" << error; + return -1; + } - return; + wrbev_ = bufferevent_socket_new( + evbase_, sockpair[0], BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); + if (!wrbev_) { + SSLOG(FATAL, this) << "bufferevent_socket_new() failed"; + for (int i = 0; i < 2; ++i) { + close(sockpair[i]); + } + return -1; + } + rdbev_ = bufferevent_socket_new( + evbase_, sockpair[1], BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); + if (!rdbev_) { + SSLOG(FATAL, this) << "bufferevent_socket_new() failed"; + close(sockpair[1]); + return -1; } + util::bev_enable_unless(rdbev_, EV_READ); + bufferevent_setcb(rdbev_, notify_readcb, nullptr, notify_eventcb, this); + return 0; } -} // namespace namespace { -void writecb(struct ev_loop *loop, ev_io *w, int revents) { +void readcb(bufferevent *bev, void *ptr) { int rv; - auto conn = static_cast(w->data); - auto http2session = static_cast(conn->data); - rv = http2session->do_write(); + auto http2session = static_cast(ptr); + http2session->reset_timeouts(); + rv = http2session->on_read(); if (rv != 0) { - delete http2session; - - return; + http2session->disconnect(); } - http2session->reset_connection_check_timer_if_not_checking(); } } // namespace namespace { -void initiate_connection_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto http2session = static_cast(w->data); - ev_timer_stop(loop, w); - if (http2session->initiate_connection() != 0) { - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, http2session) << "Could not initiate backend connection"; - } - - delete http2session; - +void writecb(bufferevent *bev, void *ptr) { + auto http2session = static_cast(ptr); + http2session->reset_timeouts(); + if (evbuffer_get_length(bufferevent_get_output(bev)) > 0) { return; } + int rv; + rv = http2session->on_write(); + if (rv != 0) { + http2session->disconnect(); + } } } // namespace namespace { -void prepare_cb(struct ev_loop *loop, ev_prepare *w, int revents) { - auto http2session = static_cast(w->data); - http2session->check_retire(); -} -} // namespace - -Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx, - Worker *worker, - const std::shared_ptr &group, - DownstreamAddr *addr) - : dlnext(nullptr), - dlprev(nullptr), - conn_(loop, -1, nullptr, worker->get_mcpool(), - worker->get_downstream_config()->timeout.write, - worker->get_downstream_config()->timeout.read, {}, {}, writecb, - readcb, timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold, - get_config()->tls.dyn_rec.idle_timeout, PROTO_HTTP2), - wb_(worker->get_mcpool()), - worker_(worker), - ssl_ctx_(ssl_ctx), - group_(group), - addr_(addr), - session_(nullptr), - state_(DISCONNECTED), - connection_check_state_(CONNECTION_CHECK_NONE), - freelist_zone_(FREELIST_ZONE_NONE) { - read_ = write_ = &Http2Session::noop; - - on_read_ = &Http2Session::read_noop; - on_write_ = &Http2Session::write_noop; - - // We will resuse this many times, so use repeat timeout value. The - // timeout value is set later. - ev_timer_init(&connchk_timer_, connchk_timeout_cb, 0., 0.); - - connchk_timer_.data = this; - - // SETTINGS ACK timeout is 10 seconds for now. We will resuse this - // many times, so use repeat timeout value. - ev_timer_init(&settings_timer_, settings_timeout_cb, 0., 0.); - - settings_timer_.data = this; - - ev_timer_init(&initiate_connection_timer_, initiate_connection_cb, 0., 0.); - initiate_connection_timer_.data = this; - - ev_prepare_init(&prep_, prepare_cb); - prep_.data = this; - ev_prepare_start(loop, &prep_); -} - -Http2Session::~Http2Session() { - exclude_from_scheduling(); - disconnect(should_hard_fail()); -} - -int Http2Session::disconnect(bool hard) { - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Disconnecting"; - } - nghttp2_session_del(session_); - session_ = nullptr; - - wb_.reset(); - - conn_.rlimit.stopw(); - conn_.wlimit.stopw(); - - ev_prepare_stop(conn_.loop, &prep_); - - ev_timer_stop(conn_.loop, &initiate_connection_timer_); - ev_timer_stop(conn_.loop, &settings_timer_); - ev_timer_stop(conn_.loop, &connchk_timer_); - - read_ = write_ = &Http2Session::noop; - - on_read_ = &Http2Session::read_noop; - on_write_ = &Http2Session::write_noop; - - conn_.disconnect(); +void eventcb(bufferevent *bev, short events, void *ptr) { + auto http2session = static_cast(ptr); + if (events & BEV_EVENT_CONNECTED) { + if (LOG_ENABLED(INFO)) { + SSLOG(INFO, http2session) << "Connection established"; + } + http2session->set_state(Http2Session::CONNECTED); + if (!get_config()->downstream_no_tls && !get_config()->insecure && + http2session->check_cert() != 0) { - if (proxy_htp_) { - proxy_htp_.reset(); - } + http2session->disconnect(); - connection_check_state_ = CONNECTION_CHECK_NONE; - state_ = DISCONNECTED; + return; + } - // When deleting Http2DownstreamConnection, it calls this object's - // remove_downstream_connection(). The multiple - // Http2DownstreamConnection objects belong to the same - // ClientHandler object. So first dump ClientHandler objects. - // - // We allow creating new pending Http2DownstreamConnection with this - // object. Upstream::on_downstream_reset() may add - // Http2DownstreamConnection. + if (http2session->on_connect() != 0) { + http2session->disconnect(); + return; + } - std::set handlers; - for (auto dc = dconns_.head; dc; dc = dc->dlnext) { - if (!dc->get_client_handler()) { - continue; + auto fd = bufferevent_getfd(bev); + int val = 1; + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&val), + sizeof(val)) == -1) { + auto error = errno; + SSLOG(WARN, http2session) + << "Setting option TCP_NODELAY failed: errno=" << error; } - handlers.insert(dc->get_client_handler()); + return; } - for (auto h : handlers) { - if (h->get_upstream()->on_downstream_reset(hard) != 0) { - delete h; + + if (events & BEV_EVENT_EOF) { + if (LOG_ENABLED(INFO)) { + SSLOG(INFO, http2session) << "EOF"; } + http2session->disconnect(); + return; } - auto streams = std::move(streams_); - for (auto s = streams.head; s;) { - auto next = s->dlnext; - delete s; - s = next; + if (events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { + if (LOG_ENABLED(INFO)) { + if (events & BEV_EVENT_ERROR) { + SSLOG(INFO, http2session) << "Network error"; + } else { + SSLOG(INFO, http2session) << "Timeout"; + } + } + http2session->disconnect(); + return; } - - return 0; } +} // namespace -int Http2Session::initiate_connection() { - int rv = 0; - - auto worker_blocker = worker_->get_connect_blocker(); - - if (state_ == DISCONNECTED) { - if (worker_blocker->blocked()) { - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) - << "Worker wide backend connection was blocked temporarily"; +namespace { +void proxy_readcb(bufferevent *bev, void *ptr) { + auto http2session = static_cast(ptr); + if (http2session->on_read_proxy() == 0) { + switch (http2session->get_state()) { + case Http2Session::PROXY_CONNECTED: + // The current bufferevent is no longer necessary, so delete it + // here. But we keep fd_ inside it. + http2session->unwrap_free_bev(); + // Initiate SSL/TLS handshake through established tunnel. + if (http2session->initiate_connection() != 0) { + http2session->disconnect(); } - return -1; + break; + case Http2Session::PROXY_FAILED: + http2session->disconnect(); + break; } + } else { + http2session->disconnect(); } +} +} // namespace - const auto &proxy = get_config()->downstream_http_proxy; - if (!proxy.host.empty() && state_ == DISCONNECTED) { +namespace { +void proxy_eventcb(bufferevent *bev, short events, void *ptr) { + auto http2session = static_cast(ptr); + if (events & BEV_EVENT_CONNECTED) { if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Connecting to the proxy " << proxy.host << ":" - << proxy.port; + SSLOG(INFO, http2session) << "Connected to the proxy"; } - - conn_.fd = util::create_nonblock_socket(proxy.addr.su.storage.ss_family); - - if (conn_.fd == -1) { - auto error = errno; - SSLOG(WARN, this) << "Backend proxy socket() failed; addr=" - << util::to_numeric_addr(&proxy.addr) - << ", errno=" << error; - - worker_blocker->on_failure(); - return -1; + std::string req = "CONNECT "; + req += get_config()->downstream_hostport.get(); + req += " HTTP/1.1\r\nHost: "; + req += get_config()->downstream_host.get(); + req += "\r\n"; + if (get_config()->downstream_http_proxy_userinfo) { + req += "Proxy-Authorization: Basic "; + size_t len = strlen(get_config()->downstream_http_proxy_userinfo.get()); + req += base64::encode(get_config()->downstream_http_proxy_userinfo.get(), + get_config()->downstream_http_proxy_userinfo.get() + + len); + req += "\r\n"; } - - rv = connect(conn_.fd, &proxy.addr.su.sa, proxy.addr.len); - if (rv != 0 && errno != EINPROGRESS) { - auto error = errno; - SSLOG(WARN, this) << "Backend proxy connect() failed; addr=" - << util::to_numeric_addr(&proxy.addr) - << ", errno=" << error; - - worker_blocker->on_failure(); - - return -1; + req += "\r\n"; + if (LOG_ENABLED(INFO)) { + SSLOG(INFO, http2session) << "HTTP proxy request headers\n" << req; } + if (bufferevent_write(bev, req.c_str(), req.size()) != 0) { + SSLOG(ERROR, http2session) << "bufferevent_write() failed"; + http2session->disconnect(); + } + return; + } - worker_blocker->on_success(); - - ev_io_set(&conn_.rev, conn_.fd, EV_READ); - ev_io_set(&conn_.wev, conn_.fd, EV_WRITE); - - conn_.wlimit.startw(); - - // TODO we should have timeout for connection establishment - ev_timer_again(conn_.loop, &conn_.wt); + if (events & BEV_EVENT_EOF) { + if (LOG_ENABLED(INFO)) { + SSLOG(INFO, http2session) << "Proxy EOF"; + } + http2session->disconnect(); + return; + } - write_ = &Http2Session::connected; + if (events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { + if (LOG_ENABLED(INFO)) { + if (events & BEV_EVENT_ERROR) { + SSLOG(INFO, http2session) << "Network error"; + } else { + SSLOG(INFO, http2session) << "Timeout"; + } + } + http2session->disconnect(); + return; + } +} +} // namespace - on_read_ = &Http2Session::downstream_read_proxy; - on_write_ = &Http2Session::downstream_connect_proxy; +int Http2Session::check_cert() { return ssl::check_cert(ssl_); } - proxy_htp_ = make_unique(); +int Http2Session::initiate_connection() { + int rv = 0; + if (get_config()->downstream_http_proxy_host && state_ == DISCONNECTED) { + if (LOG_ENABLED(INFO)) { + SSLOG(INFO, this) << "Connecting to the proxy " + << get_config()->downstream_http_proxy_host.get() << ":" + << get_config()->downstream_http_proxy_port; + } + + auto fd = socket(get_config()->downstream_http_proxy_addr.storage.ss_family, + SOCK_STREAM | SOCK_CLOEXEC, 0); + + if (fd == -1) { + return SHRPX_ERR_NETWORK; + } + + bev_ = bufferevent_socket_new(evbase_, fd, BEV_OPT_DEFER_CALLBACKS); + if (!bev_) { + SSLOG(ERROR, this) << "bufferevent_socket_new() failed"; + close(fd); + return SHRPX_ERR_NETWORK; + } + util::bev_enable_unless(bev_, EV_READ); + bufferevent_set_timeouts(bev_, &get_config()->downstream_read_timeout, + &get_config()->downstream_write_timeout); + + // No need to set writecb because we write the request when + // connected at once. + bufferevent_setcb(bev_, proxy_readcb, nullptr, proxy_eventcb, this); + rv = bufferevent_socket_connect( + bev_, + const_cast(&get_config()->downstream_http_proxy_addr.sa), + get_config()->downstream_http_proxy_addrlen); + if (rv != 0) { + SSLOG(ERROR, this) << "Failed to connect to the proxy " + << get_config()->downstream_http_proxy_host.get() + << ":" << get_config()->downstream_http_proxy_port; + return SHRPX_ERR_NETWORK; + } + proxy_htp_ = util::make_unique(); http_parser_init(proxy_htp_.get(), HTTP_RESPONSE); proxy_htp_->data = this; @@ -366,126 +418,98 @@ if (LOG_ENABLED(INFO)) { SSLOG(INFO, this) << "Connecting to downstream server"; } - if (addr_->tls) { - assert(ssl_ctx_); - - auto ssl = ssl::create_ssl(ssl_ctx_); - if (!ssl) { + if (ssl_ctx_) { + // We are establishing TLS connection. + ssl_ = SSL_new(ssl_ctx_); + if (!ssl_) { + SSLOG(ERROR, this) << "SSL_new() failed: " + << ERR_error_string(ERR_get_error(), NULL); return -1; } - ssl::setup_downstream_http2_alpn(ssl); - - conn_.set_ssl(ssl); - - auto sni_name = - addr_->sni.empty() ? StringRef{addr_->host} : StringRef{addr_->sni}; + const char *sni_name = nullptr; + if (get_config()->backend_tls_sni_name) { + sni_name = get_config()->backend_tls_sni_name.get(); + } else { + sni_name = get_config()->downstream_host.get(); + } - if (!util::numeric_host(sni_name.c_str())) { + if (sni_name && !util::numeric_host(sni_name)) { // TLS extensions: SNI. There is no documentation about the return // code for this function (actually this is macro wrapping SSL_ctrl // at the time of this writing). - SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.c_str()); - } - - auto tls_session = ssl::reuse_tls_session(addr_->tls_session_cache); - if (tls_session) { - SSL_set_session(conn_.tls.ssl, tls_session); - SSL_SESSION_free(tls_session); + SSL_set_tlsext_host_name(ssl_, sni_name); } - // If state_ == PROXY_CONNECTED, we has connected to the proxy - // using conn_.fd and tunnel has been established. + // using fd_ and tunnel has been established. if (state_ == DISCONNECTED) { - assert(conn_.fd == -1); - - conn_.fd = - util::create_nonblock_socket(addr_->addr.su.storage.ss_family); - if (conn_.fd == -1) { - auto error = errno; - SSLOG(WARN, this) - << "socket() failed; addr=" << util::to_numeric_addr(&addr_->addr) - << ", errno=" << error; - - worker_blocker->on_failure(); - return -1; - } - - worker_blocker->on_success(); - - rv = connect(conn_.fd, - // TODO maybe not thread-safe? - const_cast(&addr_->addr.su.sa), - addr_->addr.len); - if (rv != 0 && errno != EINPROGRESS) { - auto error = errno; - SSLOG(WARN, this) << "connect() failed; addr=" - << util::to_numeric_addr(&addr_->addr) - << ", errno=" << error; - - downstream_failure(addr_); - return -1; - } + assert(fd_ == -1); - ev_io_set(&conn_.rev, conn_.fd, EV_READ); - ev_io_set(&conn_.wev, conn_.fd, EV_WRITE); + fd_ = socket(get_config()->downstream_addr.storage.ss_family, + SOCK_STREAM | SOCK_CLOEXEC, 0); } - conn_.prepare_client_handshake(); + bev_ = bufferevent_openssl_socket_new(evbase_, fd_, ssl_, + BUFFEREVENT_SSL_CONNECTING, + BEV_OPT_DEFER_CALLBACKS); + if (!bev_) { + SSLOG(ERROR, this) << "bufferevent_socket_new() failed"; + return SHRPX_ERR_NETWORK; + } + rv = bufferevent_socket_connect( + bev_, + // TODO maybe not thread-safe? + const_cast(&get_config()->downstream_addr.sa), + get_config()->downstream_addrlen); } else { if (state_ == DISCONNECTED) { // Without TLS and proxy. - assert(conn_.fd == -1); + assert(fd_ == -1); - conn_.fd = - util::create_nonblock_socket(addr_->addr.su.storage.ss_family); + fd_ = socket(get_config()->downstream_addr.storage.ss_family, + SOCK_STREAM | SOCK_CLOEXEC, 0); - if (conn_.fd == -1) { - auto error = errno; - SSLOG(WARN, this) - << "socket() failed; addr=" << util::to_numeric_addr(&addr_->addr) - << ", errno=" << error; - - worker_blocker->on_failure(); - return -1; + if (fd_ == -1) { + return SHRPX_ERR_NETWORK; } + } - worker_blocker->on_success(); + bev_ = bufferevent_socket_new(evbase_, fd_, BEV_OPT_DEFER_CALLBACKS); + if (!bev_) { + SSLOG(ERROR, this) << "bufferevent_socket_new() failed"; + return SHRPX_ERR_NETWORK; + } - rv = connect(conn_.fd, const_cast(&addr_->addr.su.sa), - addr_->addr.len); - if (rv != 0 && errno != EINPROGRESS) { - auto error = errno; - SSLOG(WARN, this) << "connect() failed; addr=" - << util::to_numeric_addr(&addr_->addr) - << ", errno=" << error; + if (state_ == DISCONNECTED) { + rv = bufferevent_socket_connect( + bev_, const_cast(&get_config()->downstream_addr.sa), + get_config()->downstream_addrlen); + } else { + // Without TLS but with proxy. - downstream_failure(addr_); + // Connection already established. + eventcb(bev_, BEV_EVENT_CONNECTED, this); + // eventcb() has no return value. Check state_ to whether it was + // failed or not. + if (state_ == DISCONNECTED) { return -1; } - - ev_io_set(&conn_.rev, conn_.fd, EV_READ); - ev_io_set(&conn_.wev, conn_.fd, EV_WRITE); } } - write_ = &Http2Session::connected; + if (rv != 0) { + return SHRPX_ERR_NETWORK; + } - on_write_ = &Http2Session::downstream_write; - on_read_ = &Http2Session::downstream_read; + bufferevent_setwatermark(bev_, EV_READ, 0, SHRPX_READ_WATERMARK); + util::bev_enable_unless(bev_, EV_READ); + bufferevent_setcb(bev_, readcb, writecb, eventcb, this); + // Set timeout for HTTP2 session + reset_timeouts(); // We have been already connected when no TLS and proxy is used. if (state_ != CONNECTED) { state_ = CONNECTING; - conn_.wlimit.startw(); - // TODO we should have timeout for connection establishment - ev_timer_again(conn_.loop, &conn_.wt); - } else { - conn_.rlimit.startw(); - - if (addr_->num_dconn == 0) { - ev_timer_again(conn_.loop, &conn_.rt); - } } return 0; @@ -496,21 +520,16 @@ return 0; } +void Http2Session::unwrap_free_bev() { + assert(fd_ == -1); + fd_ = bufferevent_getfd(bev_); + bufferevent_free(bev_); + bev_ = nullptr; +} + namespace { int htp_hdrs_completecb(http_parser *htp) { auto http2session = static_cast(htp->data); - - // We only read HTTP header part. If tunneling succeeds, response - // body is a different protocol (HTTP/2 in this case), we don't read - // them here. - // - // Here is a caveat: http-parser returns 1 less bytes if we pause - // here. The reason why they do this is probably they want to eat - // last 1 byte in s_headers_done state, on the other hand, this - // callback is called its previous state s_headers_almost_done. We - // will do "+ 1" to the return value to workaround this. - http_parser_pause(htp, 1); - // We just check status code here if (htp->status_code == 200) { if (LOG_ENABLED(INFO)) { @@ -521,7 +540,7 @@ return 0; } - SSLOG(WARN, http2session) << "Tunneling failed: " << htp->status_code; + SSLOG(WARN, http2session) << "Tunneling failed"; http2session->set_state(Http2Session::PROXY_FAILED); return 0; @@ -541,114 +560,60 @@ }; } // namespace -int Http2Session::downstream_read_proxy(const uint8_t *data, size_t datalen) { - auto nread = - http_parser_execute(proxy_htp_.get(), &htp_hooks, - reinterpret_cast(data), datalen); - (void)nread; +int Http2Session::on_read_proxy() { + auto input = bufferevent_get_input(bev_); - auto htperr = HTTP_PARSER_ERRNO(proxy_htp_.get()); + for (;;) { + auto inputlen = evbuffer_get_contiguous_space(input); + + if (inputlen == 0) { + assert(evbuffer_get_length(input) == 0); - if (htperr == HPE_PAUSED) { - switch (state_) { - case Http2Session::PROXY_CONNECTED: - // Initiate SSL/TLS handshake through established tunnel. - if (initiate_connection() != 0) { - return -1; - } return 0; - case Http2Session::PROXY_FAILED: - return -1; } - // should not be here - assert(0); - } - - if (htperr != HPE_OK) { - return -1; - } - return 0; -} + auto mem = evbuffer_pullup(input, inputlen); -int Http2Session::downstream_connect_proxy() { - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Connected to the proxy"; - } + size_t nread = + http_parser_execute(proxy_htp_.get(), &htp_hooks, + reinterpret_cast(mem), inputlen); - std::string req = "CONNECT "; - req.append(addr_->hostport.c_str(), addr_->hostport.size()); - if (addr_->port == 80 || addr_->port == 443) { - req += ':'; - req += util::utos(addr_->port); - } - req += " HTTP/1.1\r\nHost: "; - req += addr_->host; - req += "\r\n"; - const auto &proxy = get_config()->downstream_http_proxy; - if (!proxy.userinfo.empty()) { - req += "Proxy-Authorization: Basic "; - req += base64::encode(std::begin(proxy.userinfo), std::end(proxy.userinfo)); - req += "\r\n"; - } - req += "\r\n"; - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "HTTP proxy request headers\n" << req; - } - wb_.append(req); + if (evbuffer_drain(input, nread) != 0) { + SSLOG(FATAL, this) << "evbuffer_drain() failed"; + return -1; + } - on_write_ = &Http2Session::write_noop; + auto htperr = HTTP_PARSER_ERRNO(proxy_htp_.get()); - signal_write(); - return 0; + if (htperr != HPE_OK) { + return -1; + } + } } void Http2Session::add_downstream_connection(Http2DownstreamConnection *dconn) { - dconns_.append(dconn); - ++addr_->num_dconn; - - stop_read_timer(); + dconns_.insert(dconn); } -void Http2Session::remove_downstream_connection( - Http2DownstreamConnection *dconn) { - --addr_->num_dconn; - dconns_.remove(dconn); +void +Http2Session::remove_downstream_connection(Http2DownstreamConnection *dconn) { + dconns_.erase(dconn); dconn->detach_stream_data(); - - if (addr_->num_dconn == 0) { - repeat_read_timer(); - } - - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Remove downstream"; - } - - if (freelist_zone_ == FREELIST_ZONE_NONE && !max_concurrency_reached()) { - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Append to http2_extra_freelist, addr=" << addr_ - << ", freelist.size=" - << addr_->http2_extra_freelist.size(); - } - - add_to_extra_freelist(); - } } void Http2Session::remove_stream_data(StreamData *sd) { - streams_.remove(sd); + streams_.erase(sd); if (sd->dconn) { sd->dconn->detach_stream_data(); } delete sd; } -int Http2Session::submit_request(Http2DownstreamConnection *dconn, +int Http2Session::submit_request(Http2DownstreamConnection *dconn, int32_t pri, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd) { assert(state_ == CONNECTED); - auto sd = make_unique(); - sd->dlnext = sd->dlprev = nullptr; + auto sd = util::make_unique(); // TODO Specify nullptr to pri_spec for now auto stream_id = nghttp2_submit_request(session_, nullptr, nva, nvlen, data_prd, sd.get()); @@ -660,7 +625,7 @@ dconn->attach_stream_data(sd.get()); dconn->get_downstream()->set_downstream_stream_id(stream_id); - streams_.append(sd.release()); + streams_.insert(sd.release()); return 0; } @@ -681,21 +646,47 @@ return 0; } -nghttp2_session *Http2Session::get_session() const { return session_; } - -int Http2Session::resume_data(Http2DownstreamConnection *dconn) { +int Http2Session::submit_priority(Http2DownstreamConnection *dconn, + int32_t pri) { assert(state_ == CONNECTED); - auto downstream = dconn->get_downstream(); - int rv = nghttp2_session_resume_data(session_, - downstream->get_downstream_stream_id()); - switch (rv) { - case 0: - case NGHTTP2_ERR_INVALID_ARGUMENT: + if (!dconn) { return 0; - default: - SSLOG(FATAL, this) << "nghttp2_resume_session() failed: " - << nghttp2_strerror(rv); - return -1; + } + int rv; + + // TODO Disabled temporarily + + // rv = nghttp2_submit_priority(session_, NGHTTP2_FLAG_NONE, + // dconn->get_downstream()-> + // get_downstream_stream_id(), pri); + + rv = 0; + + if (rv < NGHTTP2_ERR_FATAL) { + SSLOG(FATAL, this) << "nghttp2_submit_priority() failed: " + << nghttp2_strerror(rv); + return -1; + } + return 0; +} + +nghttp2_session *Http2Session::get_session() const { return session_; } + +bool Http2Session::get_flow_control() const { return flow_control_; } + +int Http2Session::resume_data(Http2DownstreamConnection *dconn) { + assert(state_ == CONNECTED); + auto downstream = dconn->get_downstream(); + int rv = nghttp2_session_resume_data(session_, + downstream->get_downstream_stream_id()); + switch (rv) { + case 0: + case NGHTTP2_ERR_INVALID_ARGUMENT: + return 0; + default: + SSLOG(FATAL, this) << "nghttp2_resume_session() failed: " + << nghttp2_strerror(rv); + return -1; } } @@ -703,11 +694,9 @@ void call_downstream_readcb(Http2Session *http2session, Downstream *downstream) { auto upstream = downstream->get_upstream(); - if (!upstream) { - return; - } - if (upstream->downstream_read(downstream->get_downstream_connection()) != 0) { - delete upstream->get_client_handler(); + if (upstream) { + (upstream->get_downstream_readcb())( + http2session->get_bev(), downstream->get_downstream_connection()); } } } // namespace @@ -718,8 +707,7 @@ auto http2session = static_cast(user_data); if (LOG_ENABLED(INFO)) { SSLOG(INFO, http2session) << "Stream stream_id=" << stream_id - << " is being closed with error code " - << error_code; + << " is being closed"; } auto sd = static_cast( nghttp2_session_get_stream_user_data(session, stream_id)); @@ -732,43 +720,22 @@ if (dconn) { auto downstream = dconn->get_downstream(); if (downstream && downstream->get_downstream_stream_id() == stream_id) { - auto upstream = downstream->get_upstream(); - - if (downstream->get_downstream_stream_id() % 2 == 0 && - downstream->get_request_state() == Downstream::INITIAL) { - // Downstream is canceled in backend before it is submitted in - // frontend session. - // This will avoid to send RST_STREAM to backend - downstream->set_response_state(Downstream::MSG_RESET); - upstream->cancel_premature_downstream(downstream); - } else { - if (downstream->get_upgraded() && - downstream->get_response_state() == Downstream::HEADER_COMPLETE) { - // For tunneled connection, we have to submit RST_STREAM to - // upstream *after* whole response body is sent. We just set - // MSG_COMPLETE here. Upstream will take care of that. - downstream->get_upstream()->on_downstream_body_complete(downstream); - downstream->set_response_state(Downstream::MSG_COMPLETE); - } else if (error_code == NGHTTP2_NO_ERROR) { - switch (downstream->get_response_state()) { - case Downstream::MSG_COMPLETE: - case Downstream::MSG_BAD_HEADER: - break; - default: - downstream->set_response_state(Downstream::MSG_RESET); - } - } else if (downstream->get_response_state() != - Downstream::MSG_BAD_HEADER) { + if (downstream->get_upgraded() && + downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + // For tunneled connection, we have to submit RST_STREAM to + // upstream *after* whole response body is sent. We just set + // MSG_COMPLETE here. Upstream will take care of that. + downstream->get_upstream()->on_downstream_body_complete(downstream); + downstream->set_response_state(Downstream::MSG_COMPLETE); + } else if (error_code == NGHTTP2_NO_ERROR) { + if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { downstream->set_response_state(Downstream::MSG_RESET); } - if (downstream->get_response_state() == Downstream::MSG_RESET && - downstream->get_response_rst_stream_error_code() == - NGHTTP2_NO_ERROR) { - downstream->set_response_rst_stream_error_code(error_code); - } - call_downstream_readcb(http2session, downstream); + } else { + downstream->set_response_state(Downstream::MSG_RESET); } + call_downstream_readcb(http2session, downstream); // dconn may be deleted } } @@ -778,21 +745,52 @@ } } // namespace -void Http2Session::start_settings_timer() { - auto &downstreamconf = get_config()->http2.downstream; +namespace { +void settings_timeout_cb(evutil_socket_t fd, short what, void *arg) { + auto http2session = static_cast(arg); + SSLOG(INFO, http2session) << "SETTINGS timeout"; + if (http2session->terminate_session(NGHTTP2_SETTINGS_TIMEOUT) != 0) { + http2session->disconnect(); + return; + } + if (http2session->send() != 0) { + http2session->disconnect(); + } +} +} // namespace - ev_timer_set(&settings_timer_, downstreamconf.timeout.settings, 0.); - ev_timer_start(conn_.loop, &settings_timer_); +int Http2Session::start_settings_timer() { + int rv; + // We submit SETTINGS only once + if (settings_timerev_) { + return 0; + } + settings_timerev_ = evtimer_new(evbase_, settings_timeout_cb, this); + if (settings_timerev_ == nullptr) { + return -1; + } + // SETTINGS ACK timeout is 10 seconds for now + timeval settings_timeout = {10, 0}; + rv = evtimer_add(settings_timerev_, &settings_timeout); + if (rv == -1) { + return -1; + } + return 0; } void Http2Session::stop_settings_timer() { - ev_timer_stop(conn_.loop, &settings_timer_); + if (settings_timerev_ == nullptr) { + return; + } + event_free(settings_timerev_); + settings_timerev_ = nullptr; } namespace { -int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame, - nghttp2_rcbuf *name, nghttp2_rcbuf *value, - uint8_t flags, void *user_data) { +int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, + const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, uint8_t flags, + void *user_data) { auto http2session = static_cast(user_data); auto sd = static_cast( nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); @@ -804,99 +802,35 @@ return 0; } - auto namebuf = nghttp2_rcbuf_get_buf(name); - auto valuebuf = nghttp2_rcbuf_get_buf(value); - - auto &resp = downstream->response(); - auto &httpconf = get_config()->http; - - switch (frame->hd.type) { - case NGHTTP2_HEADERS: { - auto trailer = frame->headers.cat == NGHTTP2_HCAT_HEADERS && - !downstream->get_expect_final_response(); - - if (resp.fs.buffer_size() + namebuf.len + valuebuf.len > - httpconf.response_header_field_buffer || - resp.fs.num_fields() >= httpconf.max_response_header_fields) { - if (LOG_ENABLED(INFO)) { - DLOG(INFO, downstream) - << "Too large or many header field size=" - << resp.fs.buffer_size() + namebuf.len + valuebuf.len - << ", num=" << resp.fs.num_fields() + 1; - } - - if (trailer) { - // We don't care trailer part exceeds header size limit; just - // discard it. - return 0; - } - - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - - auto token = http2::lookup_token(namebuf.base, namebuf.len); - auto no_index = flags & NGHTTP2_NV_FLAG_NO_INDEX; - - downstream->add_rcbuf(name); - downstream->add_rcbuf(value); + if (frame->hd.type != NGHTTP2_HEADERS || + (frame->headers.cat != NGHTTP2_HCAT_RESPONSE && + !downstream->get_expect_final_response())) { + return 0; + } - if (trailer) { - // just store header fields for trailer part - resp.fs.add_trailer_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, - no_index, token); - return 0; + if (downstream->get_response_headers_sum() > Downstream::MAX_HEADERS_SUM) { + if (LOG_ENABLED(INFO)) { + DLOG(INFO, downstream) << "Too large header block size=" + << downstream->get_response_headers_sum(); } - - resp.fs.add_header_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, no_index, - token); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + if (!http2::check_nv(name, namelen, value, valuelen)) { return 0; } - case NGHTTP2_PUSH_PROMISE: { - auto promised_stream_id = frame->push_promise.promised_stream_id; - auto promised_sd = static_cast( - nghttp2_session_get_stream_user_data(session, promised_stream_id)); - if (!promised_sd || !promised_sd->dconn) { - http2session->submit_rst_stream(promised_stream_id, NGHTTP2_CANCEL); - return 0; - } - - auto promised_downstream = promised_sd->dconn->get_downstream(); - - auto namebuf = nghttp2_rcbuf_get_buf(name); - auto valuebuf = nghttp2_rcbuf_get_buf(value); - assert(promised_downstream); - - auto &promised_req = promised_downstream->request(); - - // We use request header limit for PUSH_PROMISE - if (promised_req.fs.buffer_size() + namebuf.len + valuebuf.len > - httpconf.request_header_field_buffer || - promised_req.fs.num_fields() >= httpconf.max_request_header_fields) { - if (LOG_ENABLED(INFO)) { - DLOG(INFO, downstream) - << "Too large or many header field size=" - << promised_req.fs.buffer_size() + namebuf.len + valuebuf.len - << ", num=" << promised_req.fs.num_fields() + 1; - } + if (namelen > 0 && name[0] == ':') { + if (!downstream->response_pseudo_header_allowed() || + !http2::check_http2_response_pseudo_header(name, namelen)) { + http2session->submit_rst_stream(frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } - - promised_downstream->add_rcbuf(name); - promised_downstream->add_rcbuf(value); - - auto token = http2::lookup_token(namebuf.base, namebuf.len); - promised_req.fs.add_header_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, - flags & NGHTTP2_NV_FLAG_NO_INDEX, token); - - return 0; - } } + downstream->split_add_response_header(name, namelen, value, valuelen, + flags & NGHTTP2_NV_FLAG_NO_INDEX); return 0; } } // namespace @@ -905,52 +839,29 @@ int on_begin_headers_callback(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) { auto http2session = static_cast(user_data); - - switch (frame->hd.type) { - case NGHTTP2_HEADERS: { - if (frame->headers.cat != NGHTTP2_HCAT_RESPONSE && - frame->headers.cat != NGHTTP2_HCAT_PUSH_RESPONSE) { - return 0; - } - auto sd = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); - if (!sd || !sd->dconn) { - http2session->submit_rst_stream(frame->hd.stream_id, - NGHTTP2_INTERNAL_ERROR); - return 0; - } - auto downstream = sd->dconn->get_downstream(); - if (!downstream || - downstream->get_downstream_stream_id() != frame->hd.stream_id) { - http2session->submit_rst_stream(frame->hd.stream_id, - NGHTTP2_INTERNAL_ERROR); - return 0; - } + if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { + // server sends request HEADERS + http2session->submit_rst_stream(frame->hd.stream_id, + NGHTTP2_REFUSED_STREAM); return 0; } - case NGHTTP2_PUSH_PROMISE: { - auto promised_stream_id = frame->push_promise.promised_stream_id; - auto sd = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); - if (!sd || !sd->dconn) { - http2session->submit_rst_stream(promised_stream_id, NGHTTP2_CANCEL); - return 0; - } - - auto downstream = sd->dconn->get_downstream(); - - assert(downstream); - assert(downstream->get_downstream_stream_id() == frame->hd.stream_id); - - if (http2session->handle_downstream_push_promise(downstream, - promised_stream_id) != 0) { - http2session->submit_rst_stream(promised_stream_id, NGHTTP2_CANCEL); - } - + if (frame->headers.cat != NGHTTP2_HCAT_RESPONSE) { return 0; } + auto sd = static_cast( + nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); + if (!sd || !sd->dconn) { + http2session->submit_rst_stream(frame->hd.stream_id, + NGHTTP2_INTERNAL_ERROR); + return 0; + } + auto downstream = sd->dconn->get_downstream(); + if (!downstream || + downstream->get_downstream_stream_id() != frame->hd.stream_id) { + http2session->submit_rst_stream(frame->hd.stream_id, + NGHTTP2_INTERNAL_ERROR); + return 0; } - return 0; } } // namespace @@ -961,20 +872,37 @@ int rv; auto upstream = downstream->get_upstream(); - const auto &req = downstream->request(); - auto &resp = downstream->response(); - auto &nva = resp.fs.headers(); + downstream->normalize_response_headers(); + auto &nva = downstream->get_response_headers(); downstream->set_expect_final_response(false); - auto status = resp.fs.header(http2::HD__STATUS); - // libnghttp2 guarantees this exists and can be parsed - auto status_code = http2::parse_http_status_code(status->value); - - resp.http_status = status_code; - resp.http_major = 2; - resp.http_minor = 0; + if (!http2::check_http2_response_headers(nva)) { + http2session->submit_rst_stream(frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + downstream->set_response_state(Downstream::MSG_RESET); + call_downstream_readcb(http2session, downstream); + return 0; + } + + auto status = http2::get_unique_header(nva, ":status"); + int status_code; + + if (!status || http2::value_lws(status) || + (status_code = http2::parse_http_status_code(status->value)) == -1) { + + http2session->submit_rst_stream(frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + downstream->set_response_state(Downstream::MSG_RESET); + call_downstream_readcb(http2session, downstream); + + return 0; + } + + downstream->set_response_http_status(status_code); + downstream->set_response_major(2); + downstream->set_response_minor(0); if (LOG_ENABLED(INFO)) { std::stringstream ss; @@ -1006,13 +934,34 @@ return 0; } + auto content_length = http2::get_header(nva, "content-length"); + if (!content_length && downstream->get_request_method() != "HEAD" && + downstream->get_request_method() != "CONNECT") { + unsigned int status; + status = downstream->get_response_http_status(); + if (!((100 <= status && status <= 199) || status == 204 || status == 304)) { + // Here we have response body but Content-Length is not known + // in advance. + if (downstream->get_request_major() <= 0 || + downstream->get_request_minor() <= 0) { + // We simply close connection for pre-HTTP/1.1 in this case. + downstream->set_response_connection_close(true); + } else { + // Otherwise, use chunked encoding to keep upstream + // connection open. In HTTP2, we are supporsed not to + // receive transfer-encoding. + downstream->add_response_header("transfer-encoding", "chunked"); + downstream->set_chunked_response(true); + } + } + } + downstream->set_response_state(Downstream::HEADER_COMPLETE); downstream->check_upgrade_fulfilled(); - if (downstream->get_upgraded()) { - resp.connection_close = true; + downstream->set_response_connection_close(true); // On upgrade sucess, both ends can send data - if (upstream->resume_read(SHRPX_NO_BUFFER, downstream, 0) != 0) { + if (upstream->resume_read(SHRPX_MSG_BLOCK, downstream, 0) != 0) { // If resume_read fails, just drop connection. Not ideal. delete upstream->get_client_handler(); return -1; @@ -1022,46 +971,16 @@ SSLOG(INFO, http2session) << "HTTP upgrade success. stream_id=" << frame->hd.stream_id; } - } else { - auto content_length = resp.fs.header(http2::HD_CONTENT_LENGTH); - if (content_length) { - // libnghttp2 guarantees this can be parsed - resp.fs.content_length = util::parse_uint(content_length->value); - } - - if (resp.fs.content_length == -1 && downstream->expect_response_body()) { - // Here we have response body but Content-Length is not known in - // advance. - if (req.http_major <= 0 || (req.http_major == 1 && req.http_minor == 0)) { - // We simply close connection for pre-HTTP/1.1 in this case. - resp.connection_close = true; - } else { - // Otherwise, use chunked encoding to keep upstream connection - // open. In HTTP2, we are supporsed not to receive - // transfer-encoding. - resp.fs.add_header_token(StringRef::from_lit("transfer-encoding"), - StringRef::from_lit("chunked"), false, - http2::HD_TRANSFER_ENCODING); - downstream->set_chunked_response(true); - } - } - } - - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - resp.headers_only = true; + } else if (downstream->get_request_method() == "CONNECT") { + // If request is CONNECT, terminate request body to avoid for + // stream to stall. + downstream->end_upload_data(); } - rv = upstream->on_downstream_header_complete(downstream); if (rv != 0) { - // Handling early return (in other words, response was hijacked by - // mruby scripting). - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - http2session->submit_rst_stream(frame->hd.stream_id, NGHTTP2_CANCEL); - } else { - http2session->submit_rst_stream(frame->hd.stream_id, - NGHTTP2_INTERNAL_ERROR); - downstream->set_response_state(Downstream::MSG_RESET); - } + http2session->submit_rst_stream(frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + downstream->set_response_state(Downstream::MSG_RESET); } return 0; @@ -1079,12 +998,12 @@ auto sd = static_cast( nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); if (!sd || !sd->dconn) { - return 0; + break; } auto downstream = sd->dconn->get_downstream(); if (!downstream || downstream->get_downstream_stream_id() != frame->hd.stream_id) { - return 0; + break; } auto upstream = downstream->get_upstream(); @@ -1111,13 +1030,13 @@ } call_downstream_readcb(http2session, downstream); - return 0; + break; } case NGHTTP2_HEADERS: { auto sd = static_cast( nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); if (!sd || !sd->dconn) { - return 0; + break; } auto downstream = sd->dconn->get_downstream(); @@ -1125,24 +1044,30 @@ return 0; } - if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE || - frame->headers.cat == NGHTTP2_HCAT_PUSH_RESPONSE) { + if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) { rv = on_response_headers(http2session, downstream, session, frame); if (rv != 0) { return 0; } - } else if (frame->headers.cat == NGHTTP2_HCAT_HEADERS) { + } + + if (frame->headers.cat == NGHTTP2_HCAT_HEADERS) { if (downstream->get_expect_final_response()) { rv = on_response_headers(http2session, downstream, session, frame); if (rv != 0) { return 0; } + } else if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { + http2session->submit_rst_stream(frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + return 0; } } if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + downstream->disable_downstream_rtimer(); if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { @@ -1163,7 +1088,7 @@ // This may delete downstream call_downstream_readcb(http2session, downstream); - return 0; + break; } case NGHTTP2_RST_STREAM: { auto sd = static_cast( @@ -1178,85 +1103,29 @@ call_downstream_readcb(http2session, downstream); } } - return 0; + break; } - case NGHTTP2_SETTINGS: { + case NGHTTP2_SETTINGS: if ((frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) { - return 0; + break; } - http2session->stop_settings_timer(); - - auto addr = http2session->get_addr(); - auto &connect_blocker = addr->connect_blocker; - - connect_blocker->on_success(); - - return 0; - } - case NGHTTP2_PING: - if (frame->hd.flags & NGHTTP2_FLAG_ACK) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "PING ACK received"; - } - http2session->connection_alive(); - } - return 0; - case NGHTTP2_PUSH_PROMISE: { - auto promised_stream_id = frame->push_promise.promised_stream_id; - + break; + case NGHTTP2_PUSH_PROMISE: if (LOG_ENABLED(INFO)) { SSLOG(INFO, http2session) << "Received downstream PUSH_PROMISE stream_id=" << frame->hd.stream_id - << ", promised_stream_id=" << promised_stream_id; - } - - auto sd = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); - if (!sd || !sd->dconn) { - http2session->submit_rst_stream(promised_stream_id, NGHTTP2_CANCEL); - return 0; - } - - auto downstream = sd->dconn->get_downstream(); - - assert(downstream); - assert(downstream->get_downstream_stream_id() == frame->hd.stream_id); - - auto promised_sd = static_cast( - nghttp2_session_get_stream_user_data(session, promised_stream_id)); - if (!promised_sd || !promised_sd->dconn) { - http2session->submit_rst_stream(promised_stream_id, NGHTTP2_CANCEL); - return 0; - } - - auto promised_downstream = promised_sd->dconn->get_downstream(); - - assert(promised_downstream); - - if (http2session->handle_downstream_push_promise_complete( - downstream, promised_downstream) != 0) { - http2session->submit_rst_stream(promised_stream_id, NGHTTP2_CANCEL); - return 0; - } - - return 0; - } - case NGHTTP2_GOAWAY: - if (LOG_ENABLED(INFO)) { - auto debug_data = util::ascii_dump(frame->goaway.opaque_data, - frame->goaway.opaque_data_len); - - SSLOG(INFO, http2session) - << "GOAWAY received: last-stream-id=" << frame->goaway.last_stream_id - << ", error_code=" << frame->goaway.error_code - << ", debug_data=" << debug_data; + << ", promised_stream_id=" << frame->push_promise.promised_stream_id; } - return 0; + // We just respond with RST_STREAM. + http2session->submit_rst_stream(frame->push_promise.promised_stream_id, + NGHTTP2_REFUSED_STREAM); + break; default: - return 0; + break; } + return 0; } } // namespace @@ -1304,10 +1173,7 @@ downstream->reset_downstream_rtimer(); - auto &resp = downstream->response(); - - resp.recv_body_length += len; - resp.unconsumed_body_length += len; + downstream->add_response_bodylen(len); auto upstream = downstream->get_upstream(); rv = upstream->on_downstream_body(downstream, data, len, false); @@ -1321,6 +1187,8 @@ downstream->set_response_state(Downstream::MSG_RESET); } + downstream->add_response_datalen(len); + call_downstream_readcb(http2session, downstream); return 0; } @@ -1357,7 +1225,9 @@ if (frame->hd.type == NGHTTP2_SETTINGS && (frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) { - http2session->start_settings_timer(); + if (http2session->start_settings_timer() != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } } return 0; } @@ -1368,99 +1238,71 @@ const nghttp2_frame *frame, int lib_error_code, void *user_data) { auto http2session = static_cast(user_data); - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, http2session) << "Failed to send control frame type=" - << static_cast(frame->hd.type) - << "lib_error_code=" << lib_error_code << ":" - << nghttp2_strerror(lib_error_code); - } + SSLOG(WARN, http2session) << "Failed to send control frame type=" + << static_cast(frame->hd.type) + << "lib_error_code=" << lib_error_code << ":" + << nghttp2_strerror(lib_error_code); if (frame->hd.type == NGHTTP2_HEADERS && - lib_error_code != NGHTTP2_ERR_STREAM_CLOSED && - lib_error_code != NGHTTP2_ERR_STREAM_CLOSING) { - // To avoid stream hanging around, flag Downstream::MSG_RESET. + frame->headers.cat == NGHTTP2_HCAT_REQUEST) { + // To avoid stream hanging around, flag Downstream::MSG_RESET and + // terminate the upstream and downstream connections. auto sd = static_cast( nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); if (!sd) { return 0; } - if (!sd->dconn) { - return 0; - } - auto downstream = sd->dconn->get_downstream(); - if (!downstream || - downstream->get_downstream_stream_id() != frame->hd.stream_id) { - return 0; + if (sd->dconn) { + auto downstream = sd->dconn->get_downstream(); + if (!downstream || + downstream->get_downstream_stream_id() != frame->hd.stream_id) { + return 0; + } + downstream->set_response_state(Downstream::MSG_RESET); + call_downstream_readcb(http2session, downstream); } - downstream->set_response_state(Downstream::MSG_RESET); - call_downstream_readcb(http2session, downstream); + http2session->remove_stream_data(sd); } return 0; } } // namespace -namespace { -constexpr auto PADDING = std::array{}; -} // namespace - -namespace { -int send_data_callback(nghttp2_session *session, nghttp2_frame *frame, - const uint8_t *framehd, size_t length, - nghttp2_data_source *source, void *user_data) { - auto http2session = static_cast(user_data); - auto sd = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); - - if (sd == nullptr) { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - - auto dconn = sd->dconn; - auto downstream = dconn->get_downstream(); - auto input = downstream->get_request_buf(); - auto wb = http2session->get_request_buf(); - - size_t padlen = 0; - - wb->append(framehd, 9); - if (frame->data.padlen > 0) { - padlen = frame->data.padlen - 1; - wb->append(static_cast(padlen)); - } - - input->remove(*wb, length); - - wb->append(PADDING.data(), padlen); - - downstream->reset_downstream_wtimer(); - - if (length > 0) { - // This is important because it will handle flow control - // stuff. - if (downstream->get_upstream()->resume_read(SHRPX_NO_BUFFER, downstream, - length) != 0) { - // In this case, downstream may be deleted. - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; +int Http2Session::on_connect() { + int rv; + if (ssl_ctx_) { + const unsigned char *next_proto = nullptr; + unsigned int next_proto_len; + SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len); + for (int i = 0; i < 2; ++i) { + if (next_proto) { + if (LOG_ENABLED(INFO)) { + std::string proto(next_proto, next_proto + next_proto_len); + SSLOG(INFO, this) << "Negotiated next protocol: " << proto; + } + if (!util::check_h2_is_selected(next_proto, next_proto_len)) { + return -1; + } + break; + } +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + SSL_get0_alpn_selected(ssl_, &next_proto, &next_proto_len); +#else // OPENSSL_VERSION_NUMBER < 0x10002000L + break; +#endif // OPENSSL_VERSION_NUMBER < 0x10002000L + } + if (!next_proto) { + return -1; } - - // Here sd->dconn could be nullptr, because - // Upstream::resume_read() may delete downstream which will delete - // dconn. Is this still really true? } - - return 0; -} -} // namespace - -nghttp2_session_callbacks *create_http2_downstream_callbacks() { - int rv; nghttp2_session_callbacks *callbacks; - rv = nghttp2_session_callbacks_new(&callbacks); if (rv != 0) { - return nullptr; + return -1; } + auto callbacks_deleter = + util::defer(callbacks, nghttp2_session_callbacks_del); + nghttp2_session_callbacks_set_on_stream_close_callback( callbacks, on_stream_close_callback); @@ -1476,758 +1318,247 @@ nghttp2_session_callbacks_set_on_frame_not_send_callback( callbacks, on_frame_not_send_callback); - nghttp2_session_callbacks_set_on_header_callback2(callbacks, - on_header_callback2); + nghttp2_session_callbacks_set_on_header_callback(callbacks, + on_header_callback); nghttp2_session_callbacks_set_on_begin_headers_callback( callbacks, on_begin_headers_callback); - nghttp2_session_callbacks_set_send_data_callback(callbacks, - send_data_callback); - if (get_config()->padding) { nghttp2_session_callbacks_set_select_padding_callback( callbacks, http::select_padding_callback); } - return callbacks; -} - -int Http2Session::connection_made() { - int rv; - - state_ = Http2Session::CONNECTED; - - if (addr_->tls) { - const unsigned char *next_proto = nullptr; - unsigned int next_proto_len = 0; - - SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (!next_proto) { - SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - if (!next_proto) { - downstream_failure(addr_); - return -1; - } - - auto proto = StringRef{next_proto, next_proto_len}; - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Negotiated next protocol: " << proto; - } - if (!util::check_h2_is_selected(proto)) { - downstream_failure(addr_); - return -1; - } - } - - auto &http2conf = get_config()->http2; - - rv = nghttp2_session_client_new2(&session_, http2conf.downstream.callbacks, - this, http2conf.downstream.option); + rv = nghttp2_session_client_new2(&session_, callbacks, this, + get_config()->http2_option); if (rv != 0) { return -1; } - std::array entry; - size_t nentry = 2; - entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; - entry[0].value = http2conf.downstream.max_concurrent_streams; - - entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; - entry[1].value = (1 << http2conf.downstream.window_bits) - 1; - - if (http2conf.no_server_push || get_config()->http2_proxy) { - entry[nentry].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; - entry[nentry].value = 0; - ++nentry; - } + flow_control_ = true; + + nghttp2_settings_entry entry[3]; + entry[0].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; + entry[0].value = 0; + entry[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; + entry[1].value = get_config()->http2_max_concurrent_streams; - rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(), - nentry); + entry[2].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; + entry[2].value = (1 << get_config()->http2_downstream_window_bits) - 1; + + rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry, + util::array_size(entry)); if (rv != 0) { return -1; } - if (http2conf.downstream.connection_window_bits != 16) { - int32_t window_size = - (1 << http2conf.downstream.connection_window_bits) - 1; - rv = nghttp2_session_set_local_window_size(session_, NGHTTP2_FLAG_NONE, 0, - window_size); + if (get_config()->http2_downstream_connection_window_bits > 16) { + int32_t delta = + (1 << get_config()->http2_downstream_connection_window_bits) - 1 - + NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; + rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta); if (rv != 0) { return -1; } } - auto must_terminate = - addr_->tls && !nghttp2::ssl::check_http2_requirement(conn_.tls.ssl); + rv = bufferevent_write(bev_, NGHTTP2_CLIENT_CONNECTION_PREFACE, + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); + if (rv != 0) { + SSLOG(FATAL, this) << "bufferevent_write() failed"; + return -1; + } - reset_connection_check_timer(CONNCHK_TIMEOUT); + auto must_terminate = + !get_config()->downstream_no_tls && !ssl::check_http2_requirement(ssl_); if (must_terminate) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "TLSv1.2 was not negotiated. HTTP/2 must not be negotiated."; - } - rv = terminate_session(NGHTTP2_INADEQUATE_SECURITY); if (rv != 0) { return -1; } - } else { - submit_pending_requests(); } - signal_write(); - return 0; -} - -int Http2Session::do_read() { return read_(*this); } -int Http2Session::do_write() { return write_(*this); } - -int Http2Session::on_read(const uint8_t *data, size_t datalen) { - return on_read_(*this, data, datalen); -} - -int Http2Session::on_write() { return on_write_(*this); } - -int Http2Session::downstream_read(const uint8_t *data, size_t datalen) { - ssize_t rv; - - rv = nghttp2_session_mem_recv(session_, data, datalen); - if (rv < 0) { - SSLOG(ERROR, this) << "nghttp2_session_mem_recv() returned error: " - << nghttp2_strerror(rv); + rv = send(); + if (rv != 0) { return -1; } - if (nghttp2_session_want_read(session_) == 0 && - nghttp2_session_want_write(session_) == 0 && wb_.rleft() == 0) { - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "No more read/write for this HTTP2 session"; - } - return -1; + if (must_terminate) { + return 0; } - signal_write(); - return 0; -} - -int Http2Session::downstream_write() { - for (;;) { - const uint8_t *data; - auto datalen = nghttp2_session_mem_send(session_, &data); - - if (datalen < 0) { - SSLOG(ERROR, this) << "nghttp2_session_mem_send() returned error: " - << nghttp2_strerror(datalen); - return -1; - } - if (datalen == 0) { - break; + // submit pending request + for (auto dconn : dconns_) { + if (dconn->push_request_headers() == 0) { + auto downstream = dconn->get_downstream(); + auto upstream = downstream->get_upstream(); + upstream->resume_read(SHRPX_NO_BUFFER, downstream, 0); + continue; } - wb_.append(data, datalen); - if (wb_.rleft() >= MAX_BUFFER_SIZE) { - break; - } - } - - if (nghttp2_session_want_read(session_) == 0 && - nghttp2_session_want_write(session_) == 0 && wb_.rleft() == 0) { if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "No more read/write for this session"; + SSLOG(INFO, this) << "backend request failed"; } - return -1; - } - - return 0; -} - -void Http2Session::signal_write() { - switch (state_) { - case Http2Session::DISCONNECTED: - if (!ev_is_active(&initiate_connection_timer_)) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Start connecting to backend server"; - } - // Since the timer is set to 0., these will feed 2 events. We - // will stop the timer in the initiate_connection_timer_ to void - // 2nd event. - ev_timer_start(conn_.loop, &initiate_connection_timer_); - ev_feed_event(conn_.loop, &initiate_connection_timer_, 0); - } - break; - case Http2Session::CONNECTED: - conn_.wlimit.startw(); - break; - } -} - -struct ev_loop *Http2Session::get_loop() const { - return conn_.loop; -} - -ev_io *Http2Session::get_wev() { return &conn_.wev; } - -int Http2Session::get_state() const { return state_; } - -void Http2Session::set_state(int state) { state_ = state; } - -int Http2Session::terminate_session(uint32_t error_code) { - int rv; - rv = nghttp2_session_terminate_session(session_, error_code); - if (rv != 0) { - return -1; - } - return 0; -} - -SSL *Http2Session::get_ssl() const { return conn_.tls.ssl; } - -int Http2Session::consume(int32_t stream_id, size_t len) { - int rv; - - if (!session_) { - return 0; - } - - rv = nghttp2_session_consume(session_, stream_id, len); - - if (rv != 0) { - SSLOG(WARN, this) << "nghttp2_session_consume() returned error: " - << nghttp2_strerror(rv); - - return -1; - } - return 0; -} - -bool Http2Session::can_push_request() const { - return state_ == CONNECTED && - connection_check_state_ == CONNECTION_CHECK_NONE; -} - -void Http2Session::start_checking_connection() { - if (state_ != CONNECTED || - connection_check_state_ != CONNECTION_CHECK_REQUIRED) { - return; - } - connection_check_state_ = CONNECTION_CHECK_STARTED; - - SSLOG(INFO, this) << "Start checking connection"; - // If connection is down, we may get error when writing data. Issue - // ping frame to see whether connection is alive. - nghttp2_submit_ping(session_, NGHTTP2_FLAG_NONE, NULL); - - // set ping timeout and start timer again - reset_connection_check_timer(CONNCHK_PING_TIMEOUT); - - signal_write(); -} - -void Http2Session::reset_connection_check_timer(ev_tstamp t) { - connchk_timer_.repeat = t; - ev_timer_again(conn_.loop, &connchk_timer_); -} - -void Http2Session::reset_connection_check_timer_if_not_checking() { - if (connection_check_state_ != CONNECTION_CHECK_NONE) { - return; - } - - reset_connection_check_timer(CONNCHK_TIMEOUT); -} - -void Http2Session::connection_alive() { - reset_connection_check_timer(CONNCHK_TIMEOUT); - - if (connection_check_state_ == CONNECTION_CHECK_NONE) { - return; - } - - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Connection alive"; - } - - connection_check_state_ = CONNECTION_CHECK_NONE; - - submit_pending_requests(); -} - -void Http2Session::submit_pending_requests() { - for (auto dconn = dconns_.head; dconn; dconn = dconn->dlnext) { auto downstream = dconn->get_downstream(); - if (!downstream || !downstream->request_submission_ready()) { + if (!downstream) { continue; } auto upstream = downstream->get_upstream(); - if (dconn->push_request_headers() != 0) { - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "backend request failed"; - } - - upstream->on_downstream_abort_request(downstream, 400); - - continue; - } - - upstream->resume_read(SHRPX_NO_BUFFER, downstream, 0); + upstream->on_downstream_abort_request(downstream, 400); } -} - -void Http2Session::set_connection_check_state(int state) { - connection_check_state_ = state; -} - -int Http2Session::get_connection_check_state() const { - return connection_check_state_; -} - -int Http2Session::noop() { return 0; } - -int Http2Session::read_noop(const uint8_t *data, size_t datalen) { return 0; } - -int Http2Session::write_noop() { return 0; } - -int Http2Session::connected() { - if (!util::check_socket_connected(conn_.fd)) { - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Backend connect failed; addr=" - << util::to_numeric_addr(&addr_->addr); - } - - downstream_failure(addr_); - - return -1; - } - - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Connection established"; - } - - conn_.rlimit.startw(); - - read_ = &Http2Session::read_clear; - write_ = &Http2Session::write_clear; - - if (state_ == PROXY_CONNECTING) { - return do_write(); - } - - if (conn_.tls.ssl) { - read_ = &Http2Session::tls_handshake; - write_ = &Http2Session::tls_handshake; - - return do_write(); - } - - if (connection_made() != 0) { - state_ = CONNECT_FAILING; - return -1; - } - return 0; } -int Http2Session::read_clear() { - std::array buf; +int Http2Session::on_read() { + ssize_t rv = 0; + auto input = bufferevent_get_input(bev_); for (;;) { - auto nread = conn_.read_clear(buf.data(), buf.size()); - - if (nread == 0) { - return 0; - } + auto inputlen = evbuffer_get_contiguous_space(input); - if (nread < 0) { - return nread; - } + if (inputlen == 0) { + assert(evbuffer_get_length(input) == 0); - if (on_read(buf.data(), nread) != 0) { - return -1; + return send(); } - } -} -int Http2Session::write_clear() { - std::array iov; + auto mem = evbuffer_pullup(input, inputlen); - for (;;) { - if (wb_.rleft() > 0) { - auto iovcnt = wb_.riovec(iov.data(), iov.size()); - auto nwrite = conn_.writev_clear(iov.data(), iovcnt); + rv = nghttp2_session_mem_recv(session_, mem, inputlen); - if (nwrite == 0) { - return 0; - } - - if (nwrite < 0) { - return nwrite; - } - - wb_.drain(nwrite); - continue; - } - - if (on_write() != 0) { + if (rv < 0) { + SSLOG(ERROR, this) << "nghttp2_session_recv() returned error: " + << nghttp2_strerror(rv); return -1; } - if (wb_.rleft() == 0) { - break; - } - } - - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - return 0; -} - -int Http2Session::tls_handshake() { - ev_timer_again(conn_.loop, &conn_.rt); - - ERR_clear_error(); - - auto rv = conn_.tls_handshake(); - - if (rv == SHRPX_ERR_INPROGRESS) { - return 0; - } - - if (rv < 0) { - downstream_failure(addr_); - - return rv; - } - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "SSL/TLS handshake completed"; - } - - if (!get_config()->tls.insecure && - ssl::check_cert(conn_.tls.ssl, addr_) != 0) { - downstream_failure(addr_); - - return -1; - } - - if (!SSL_session_reused(conn_.tls.ssl)) { - auto tls_session = SSL_get0_session(conn_.tls.ssl); - if (tls_session) { - ssl::try_cache_tls_session(addr_->tls_session_cache, addr_->addr, - tls_session, ev_now(conn_.loop)); + if (evbuffer_drain(input, rv) != 0) { + SSLOG(FATAL, this) << "evbuffer_drain() faild"; + return -1; } } - - read_ = &Http2Session::read_tls; - write_ = &Http2Session::write_tls; - - if (connection_made() != 0) { - state_ = CONNECT_FAILING; - return -1; - } - - return 0; } -int Http2Session::read_tls() { - std::array buf; - - ERR_clear_error(); +int Http2Session::on_write() { return send(); } +int Http2Session::send() { + int rv; + uint8_t buf[16384]; + auto output = bufferevent_get_output(bev_); + util::EvbufferBuffer evbbuf(output, buf, sizeof(buf)); for (;;) { - auto nread = conn_.read_tls(buf.data(), buf.size()); - - if (nread == 0) { - return 0; + // Check buffer length and return WOULDBLOCK if it is large enough. + if (evbuffer_get_length(output) + evbbuf.get_buflen() > + Http2Session::OUTBUF_MAX_THRES) { + return NGHTTP2_ERR_WOULDBLOCK; } - if (nread < 0) { - return nread; - } + const uint8_t *data; + auto datalen = nghttp2_session_mem_send(session_, &data); - if (on_read(buf.data(), nread) != 0) { - return -1; + if (datalen < 0) { + SSLOG(ERROR, this) << "nghttp2_session_mem_send() returned error: " + << nghttp2_strerror(datalen); + break; } - } -} - -int Http2Session::write_tls() { - ERR_clear_error(); - - struct iovec iov; - - for (;;) { - if (wb_.rleft() > 0) { - auto iovcnt = wb_.riovec(&iov, 1); - assert(iovcnt == 1); - auto nwrite = conn_.write_tls(iov.iov_base, iov.iov_len); - - if (nwrite == 0) { - return 0; - } - - if (nwrite < 0) { - return nwrite; - } - - wb_.drain(nwrite); - - continue; + if (datalen == 0) { + break; } - - if (on_write() != 0) { + rv = evbbuf.add(data, datalen); + if (rv != 0) { + SSLOG(FATAL, this) << "evbuffer_add() failed"; return -1; } - if (wb_.rleft() == 0) { - conn_.start_tls_write_idle(); - break; - } - } - - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - return 0; -} - -bool Http2Session::should_hard_fail() const { - switch (state_) { - case PROXY_CONNECTING: - case PROXY_FAILED: - return true; - case DISCONNECTED: { - const auto &proxy = get_config()->downstream_http_proxy; - return !proxy.host.empty(); } - default: - return false; - } -} -DownstreamAddr *Http2Session::get_addr() const { return addr_; } - -int Http2Session::handle_downstream_push_promise(Downstream *downstream, - int32_t promised_stream_id) { - auto upstream = downstream->get_upstream(); - if (!upstream->push_enabled()) { - return -1; - } - - auto promised_downstream = - upstream->on_downstream_push_promise(downstream, promised_stream_id); - if (!promised_downstream) { + rv = evbbuf.flush(); + if (rv != 0) { + SSLOG(FATAL, this) << "evbuffer_add() failed"; return -1; } - // Now we have Downstream object for pushed stream. - // promised_downstream->get_stream() still returns 0. - - auto handler = upstream->get_client_handler(); - - auto promised_dconn = make_unique(this); - promised_dconn->set_client_handler(handler); - - auto ptr = promised_dconn.get(); - - if (promised_downstream->attach_downstream_connection( - std::move(promised_dconn)) != 0) { + if (nghttp2_session_want_read(session_) == 0 && + nghttp2_session_want_write(session_) == 0 && + evbuffer_get_length(output) == 0) { + if (LOG_ENABLED(INFO)) { + SSLOG(INFO, this) << "No more read/write for this session"; + } return -1; } - - auto promised_sd = make_unique(); - - nghttp2_session_set_stream_user_data(session_, promised_stream_id, - promised_sd.get()); - - ptr->attach_stream_data(promised_sd.get()); - streams_.append(promised_sd.release()); - return 0; } -int Http2Session::handle_downstream_push_promise_complete( - Downstream *downstream, Downstream *promised_downstream) { - auto &promised_req = promised_downstream->request(); - - auto &promised_balloc = promised_downstream->get_block_allocator(); - - auto authority = promised_req.fs.header(http2::HD__AUTHORITY); - auto path = promised_req.fs.header(http2::HD__PATH); - auto method = promised_req.fs.header(http2::HD__METHOD); - auto scheme = promised_req.fs.header(http2::HD__SCHEME); - - if (!authority) { - authority = promised_req.fs.header(http2::HD_HOST); +void Http2Session::clear_notify() { + auto input = bufferevent_get_output(rdbev_); + if (evbuffer_drain(input, evbuffer_get_length(input)) != 0) { + SSLOG(FATAL, this) << "evbuffer_drain() failed"; } + notified_ = false; +} - auto method_token = http2::lookup_method_token(method->value); - if (method_token == -1) { - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Unrecognized method: " << method->value; +void Http2Session::notify() { + if (!notified_) { + if (bufferevent_write(wrbev_, "1", 1) != 0) { + SSLOG(FATAL, this) << "bufferevent_write failed"; } - - return -1; - } - - // TODO Rewrite authority if we enabled rewrite host. But we - // really don't know how to rewrite host. Should we use the same - // host in associated stream? - if (authority) { - promised_req.authority = authority->value; - } - promised_req.method = method_token; - // libnghttp2 ensures that we don't have CONNECT method in - // PUSH_PROMISE, and guarantees that :scheme exists. - if (scheme) { - promised_req.scheme = scheme->value; - } - - // For server-wide OPTIONS request, path is empty. - if (method_token != HTTP_OPTIONS || path->value != "*") { - promised_req.path = http2::rewrite_clean_path(promised_balloc, path->value); + notified_ = true; } +} - promised_downstream->inspect_http2_request(); +bufferevent *Http2Session::get_bev() const { return bev_; } - auto upstream = promised_downstream->get_upstream(); +int Http2Session::get_state() const { return state_; } - promised_downstream->set_request_state(Downstream::MSG_COMPLETE); +void Http2Session::set_state(int state) { state_ = state; } - if (upstream->on_downstream_push_promise_complete(downstream, - promised_downstream) != 0) { +int Http2Session::terminate_session(uint32_t error_code) { + int rv; + rv = nghttp2_session_terminate_session(session_, error_code); + if (rv != 0) { return -1; } - return 0; } -size_t Http2Session::get_num_dconns() const { return dconns_.size(); } - -bool Http2Session::max_concurrency_reached(size_t extra) const { - if (!session_) { - return dconns_.size() + extra >= 100; - } - - // If session does not allow further requests, it effectively means - // that maximum concurrency is reached. - return !nghttp2_session_check_request_allowed(session_) || - dconns_.size() + extra >= - nghttp2_session_get_remote_settings( - session_, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); -} - -DownstreamAddrGroup *Http2Session::get_downstream_addr_group() const { - return group_.get(); -} - -void Http2Session::add_to_avail_freelist() { - if (freelist_zone_ != FREELIST_ZONE_NONE) { - return; - } - - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Append to http2_avail_freelist, group=" - << group_.get() << ", freelist.size=" - << group_->shared_addr->http2_avail_freelist.size(); +size_t Http2Session::get_outbuf_length() const { + if (bev_) { + return evbuffer_get_length(bufferevent_get_output(bev_)); + } else { + return OUTBUF_MAX_THRES; } - - freelist_zone_ = FREELIST_ZONE_AVAIL; - group_->shared_addr->http2_avail_freelist.append(this); - addr_->in_avail = true; } -void Http2Session::add_to_extra_freelist() { - if (freelist_zone_ != FREELIST_ZONE_NONE) { - return; - } - - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Append to http2_extra_freelist, addr=" << addr_ - << ", freelist.size=" - << addr_->http2_extra_freelist.size(); - } +SSL *Http2Session::get_ssl() const { return ssl_; } - freelist_zone_ = FREELIST_ZONE_EXTRA; - addr_->http2_extra_freelist.append(this); -} +int Http2Session::consume(int32_t stream_id, size_t len) { + int rv; -void Http2Session::remove_from_freelist() { - switch (freelist_zone_) { - case FREELIST_ZONE_NONE: - return; - case FREELIST_ZONE_AVAIL: - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Remove from http2_avail_freelist, group=" << group_ - << ", freelist.size=" - << group_->shared_addr->http2_avail_freelist.size(); - } - group_->shared_addr->http2_avail_freelist.remove(this); - addr_->in_avail = false; - break; - case FREELIST_ZONE_EXTRA: - if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Remove from http2_extra_freelist, addr=" << addr_ - << ", freelist.size=" - << addr_->http2_extra_freelist.size(); - } - addr_->http2_extra_freelist.remove(this); - break; - case FREELIST_ZONE_GONE: - return; + if (!session_) { + return 0; } - freelist_zone_ = FREELIST_ZONE_NONE; -} - -void Http2Session::exclude_from_scheduling() { - remove_from_freelist(); - freelist_zone_ = FREELIST_ZONE_GONE; -} - -DefaultMemchunks *Http2Session::get_request_buf() { return &wb_; } + rv = nghttp2_session_consume(session_, stream_id, len); -void Http2Session::on_timeout() { - switch (state_) { - case PROXY_CONNECTING: { - auto worker_blocker = worker_->get_connect_blocker(); - worker_blocker->on_failure(); - break; - } - case CONNECTING: { - downstream_failure(addr_); - break; - } - } -} + if (rv != 0) { + SSLOG(WARN, this) << "nghttp2_session_consume() returned error: " + << nghttp2_strerror(rv); -void Http2Session::check_retire() { - if (!group_->retired) { - return; + return -1; } - ev_prepare_stop(conn_.loop, &prep_); - - auto last_stream_id = nghttp2_session_get_last_proc_stream_id(session_); - nghttp2_submit_goaway(session_, NGHTTP2_FLAG_NONE, last_stream_id, - NGHTTP2_NO_ERROR, nullptr, 0); - - signal_write(); + return 0; } -void Http2Session::repeat_read_timer() { - ev_timer_again(conn_.loop, &conn_.rt); +void Http2Session::reset_timeouts() { + bufferevent_set_timeouts(bev_, &get_config()->downstream_read_timeout, + &get_config()->downstream_write_timeout); } -void Http2Session::stop_read_timer() { ev_timer_stop(conn_.loop, &conn_.rt); } - } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_http2_session.h nghttp2-0.6.7/src/shrpx_http2_session.h --- nghttp2-1.13.0/src/shrpx_http2_session.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http2_session.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,59 +27,36 @@ #include "shrpx.h" -#include +#include #include #include -#include +#include +#include #include #include "http-parser/http_parser.h" -#include "shrpx_connection.h" -#include "buffer.h" -#include "template.h" - -using namespace nghttp2; - namespace shrpx { class Http2DownstreamConnection; -class Worker; -struct DownstreamAddrGroup; -struct DownstreamAddr; struct StreamData { - StreamData *dlnext, *dlprev; Http2DownstreamConnection *dconn; }; -enum FreelistZone { - // Http2Session object is not linked in any freelist. - FREELIST_ZONE_NONE, - // Http2Session object is linked in group scope - // http2_avail_freelist. - FREELIST_ZONE_AVAIL, - // Http2Session object is linked in address scope - // http2_extra_freelist. - FREELIST_ZONE_EXTRA, - // Http2Session object is about to be deleted, and it does not - // belong to any linked list. - FREELIST_ZONE_GONE -}; - class Http2Session { public: - Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx, Worker *worker, - const std::shared_ptr &group, - DownstreamAddr *addr); + Http2Session(event_base *evbase, SSL_CTX *ssl_ctx); ~Http2Session(); - // If hard is true, all pending requests are abandoned and - // associated ClientHandlers will be deleted. - int disconnect(bool hard = false); + int init_notification(); + + int check_cert(); + + int disconnect(); int initiate_connection(); void add_downstream_connection(Http2DownstreamConnection *dconn); @@ -87,124 +64,49 @@ void remove_stream_data(StreamData *sd); - int submit_request(Http2DownstreamConnection *dconn, const nghttp2_nv *nva, - size_t nvlen, const nghttp2_data_provider *data_prd); + int submit_request(Http2DownstreamConnection *dconn, int32_t pri, + const nghttp2_nv *nva, size_t nvlen, + const nghttp2_data_provider *data_prd); int submit_rst_stream(int32_t stream_id, uint32_t error_code); + int submit_priority(Http2DownstreamConnection *dconn, int32_t pri); + int terminate_session(uint32_t error_code); nghttp2_session *get_session() const; - int resume_data(Http2DownstreamConnection *dconn); + bool get_flow_control() const; - int connection_made(); + int resume_data(Http2DownstreamConnection *dconn); - int do_read(); - int do_write(); + int on_connect(); - int on_read(const uint8_t *data, size_t datalen); + int on_read(); int on_write(); + int send(); - int connected(); - int read_clear(); - int write_clear(); - int tls_handshake(); - int read_tls(); - int write_tls(); - - int downstream_read_proxy(const uint8_t *data, size_t datalen); - int downstream_connect_proxy(); + int on_read_proxy(); - int downstream_read(const uint8_t *data, size_t datalen); - int downstream_write(); + void clear_notify(); + void notify(); - int noop(); - int read_noop(const uint8_t *data, size_t datalen); - int write_noop(); - - void signal_write(); - - struct ev_loop *get_loop() const; - - ev_io *get_wev(); + bufferevent *get_bev() const; + void unwrap_free_bev(); int get_state() const; void set_state(int state); - void start_settings_timer(); + int start_settings_timer(); void stop_settings_timer(); + size_t get_outbuf_length() const; + SSL *get_ssl() const; int consume(int32_t stream_id, size_t len); - // Returns true if request can be issued on downstream connection. - bool can_push_request() const; - // Initiates the connection checking if downstream connection has - // been established and connection checking is required. - void start_checking_connection(); - // Resets connection check timer to timeout |t|. After timeout, we - // require connection checking. If connection checking is already - // enabled, this timeout is for PING ACK timeout. - void reset_connection_check_timer(ev_tstamp t); - void reset_connection_check_timer_if_not_checking(); - // Signals that connection is alive. Internally - // reset_connection_check_timer() is called. - void connection_alive(); - // Change connection check state. - void set_connection_check_state(int state); - int get_connection_check_state() const; - - bool should_hard_fail() const; - - void submit_pending_requests(); - - DownstreamAddr *get_addr() const; - - DownstreamAddrGroup *get_downstream_addr_group() const; - - int handle_downstream_push_promise(Downstream *downstream, - int32_t promised_stream_id); - int handle_downstream_push_promise_complete(Downstream *downstream, - Downstream *promised_downstream); - - // Returns number of downstream connections, including pushed - // streams. - size_t get_num_dconns() const; - - // Adds to group scope http2_avail_freelist. - void add_to_avail_freelist(); - // Adds to address scope http2_extra_freelist. - void add_to_extra_freelist(); - - // Removes this object from any freelist. If this object is not - // linked from any freelist, this function does nothing. - void remove_from_freelist(); - - // Removes this object form any freelist, and marks this object as - // not schedulable. - void exclude_from_scheduling(); - - // Returns true if the maximum concurrency is reached. In other - // words, the number of currently participated streams in this - // session is equal or greater than the max concurrent streams limit - // advertised by server. If |extra| is nonzero, it is added to the - // number of current concurrent streams when comparing against - // server initiated concurrency limit. - bool max_concurrency_reached(size_t extra = 0) const; - - DefaultMemchunks *get_request_buf(); - - void on_timeout(); - - // This is called periodically using ev_prepare watcher, and if - // group_ is retired (backend has been replaced), send GOAWAY to - // shutdown the connection. - void check_retire(); - - void repeat_read_timer(); - void stop_read_timer(); + void reset_timeouts(); enum { // Disconnected @@ -218,57 +120,35 @@ // Connecting to downstream and/or performing SSL/TLS handshake CONNECTING, // Connected to downstream - CONNECTED, - // Connection is started to fail - CONNECT_FAILING, + CONNECTED }; - enum { - // Connection checking is not required - CONNECTION_CHECK_NONE, - // Connection checking is required - CONNECTION_CHECK_REQUIRED, - // Connection checking has been started - CONNECTION_CHECK_STARTED - }; - - using ReadBuf = Buffer<8_k>; - - Http2Session *dlnext, *dlprev; + static const size_t OUTBUF_MAX_THRES = 64 * 1024; private: - Connection conn_; - DefaultMemchunks wb_; - ev_timer settings_timer_; - // This timer has 2 purpose: when it first timeout, set - // connection_check_state_ = CONNECTION_CHECK_REQUIRED. After - // connection check has started, this timer is started again and - // traps PING ACK timeout. - ev_timer connchk_timer_; - // timer to initiate connection. usually, this fires immediately. - ev_timer initiate_connection_timer_; - ev_prepare prep_; - DList dconns_; - DList streams_; - std::function read_, write_; - std::function on_read_; - std::function on_write_; + std::set dconns_; + std::set streams_; // Used to parse the response from HTTP proxy std::unique_ptr proxy_htp_; - Worker *worker_; + event_base *evbase_; // NULL if no TLS is configured SSL_CTX *ssl_ctx_; - std::shared_ptr group_; - // Address of remote endpoint - DownstreamAddr *addr_; + SSL *ssl_; nghttp2_session *session_; + bufferevent *bev_; + bufferevent *wrbev_; + bufferevent *rdbev_; + event *settings_timerev_; + // fd_ is used for proxy connection and no TLS connection. For + // direct or TLS connection, it may be -1 even after connection is + // established. Use bufferevent_getfd(bev_) to get file descriptor + // in these cases. + int fd_; int state_; - int connection_check_state_; - int freelist_zone_; + bool notified_; + bool flow_control_; }; -nghttp2_session_callbacks *create_http2_downstream_callbacks(); - } // namespace shrpx #endif // SHRPX_HTTP2_SESSION_H diff -Nru nghttp2-1.13.0/src/shrpx_http2_upstream.cc nghttp2-0.6.7/src/shrpx_http2_upstream.cc --- nghttp2-1.13.0/src/shrpx_http2_upstream.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http2_upstream.cc 2014-11-30 14:15:07.000000000 +0000 @@ -35,23 +35,19 @@ #include "shrpx_downstream_connection.h" #include "shrpx_config.h" #include "shrpx_http.h" -#include "shrpx_worker.h" -#include "shrpx_http2_session.h" -#ifdef HAVE_MRUBY -#include "shrpx_mruby.h" -#endif // HAVE_MRUBY +#include "shrpx_worker_config.h" #include "http2.h" #include "util.h" #include "base64.h" #include "app_helper.h" -#include "template.h" using namespace nghttp2; namespace shrpx { namespace { -constexpr size_t MAX_BUFFER_SIZE = 32_k; +const size_t OUTBUF_MAX_THRES = 16 * 1024; +const size_t INBUF_MAX_THRES = 16 * 1024; } // namespace namespace { @@ -63,18 +59,15 @@ << " is being closed"; } - auto downstream = static_cast( - nghttp2_session_get_stream_user_data(session, stream_id)); + auto downstream = upstream->find_downstream(stream_id); if (!downstream) { return 0; } - auto &req = downstream->request(); + upstream->consume(stream_id, downstream->get_request_datalen()); - upstream->consume(stream_id, req.unconsumed_body_length); - - req.unconsumed_body_length = 0; + downstream->reset_request_datalen(); if (downstream->get_request_state() == Downstream::CONNECT_FAIL) { upstream->remove_downstream(downstream); @@ -83,13 +76,22 @@ return 0; } - if (downstream->can_detach_downstream_connection()) { - // Keep-alive - downstream->detach_downstream_connection(); - } - downstream->set_request_state(Downstream::STREAM_CLOSED); + if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { + // At this point, downstream response was read + if (!downstream->get_upgraded() && + !downstream->get_response_connection_close()) { + // Keep-alive + downstream->detach_downstream_connection(); + } + + upstream->remove_downstream(downstream); + // downstream was deleted + + return 0; + } + // At this point, downstream read may be paused. // If shrpx_downstream::push_request_headers() failed, the @@ -108,38 +110,31 @@ int Http2Upstream::upgrade_upstream(HttpsUpstream *http) { int rv; - auto http2_settings = http->get_downstream()->get_http2_settings().str(); + auto http2_settings = http->get_downstream()->get_http2_settings(); util::to_base64(http2_settings); auto settings_payload = base64::decode(std::begin(http2_settings), std::end(http2_settings)); - rv = nghttp2_session_upgrade2( + rv = nghttp2_session_upgrade( session_, reinterpret_cast(settings_payload.c_str()), - settings_payload.size(), - http->get_downstream()->request().method == HTTP_HEAD, nullptr); + settings_payload.size(), nullptr); if (rv != 0) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, this) << "nghttp2_session_upgrade() returned error: " - << nghttp2_strerror(rv); - } + ULOG(WARN, this) << "nghttp2_session_upgrade() returned error: " + << nghttp2_strerror(rv); return -1; } pre_upstream_.reset(http); auto downstream = http->pop_downstream(); downstream->reset_upstream(this); downstream->set_stream_id(1); + downstream->init_upstream_timer(); downstream->reset_upstream_rtimer(); + downstream->init_response_body_buf(); downstream->set_stream_id(1); + downstream->set_priority(0); - auto ptr = downstream.get(); - - nghttp2_session_set_stream_user_data(session_, 1, ptr); - downstream_queue_.add_pending(std::move(downstream)); - downstream_queue_.mark_active(ptr); - - // TODO This might not be necessary - handler_->stop_read_timer(); + downstream_queue_.add_active(std::move(downstream)); if (LOG_ENABLED(INFO)) { ULOG(INFO, this) << "Connection upgraded to HTTP/2"; @@ -148,55 +143,75 @@ return 0; } -void Http2Upstream::start_settings_timer() { - ev_timer_start(handler_->get_loop(), &settings_timer_); +namespace { +void settings_timeout_cb(evutil_socket_t fd, short what, void *arg) { + auto upstream = static_cast(arg); + ULOG(INFO, upstream) << "SETTINGS timeout"; + if (upstream->terminate_session(NGHTTP2_SETTINGS_TIMEOUT) != 0) { + delete upstream->get_client_handler(); + return; + } + if (upstream->send() != 0) { + delete upstream->get_client_handler(); + } +} +} // namespace + +int Http2Upstream::start_settings_timer() { + int rv; + // We submit SETTINGS only once + if (settings_timerev_) { + return 0; + } + settings_timerev_ = + evtimer_new(handler_->get_evbase(), settings_timeout_cb, this); + if (settings_timerev_ == nullptr) { + return -1; + } + // SETTINGS ACK timeout is 10 seconds for now + timeval settings_timeout = {10, 0}; + rv = evtimer_add(settings_timerev_, &settings_timeout); + if (rv == -1) { + return -1; + } + return 0; } void Http2Upstream::stop_settings_timer() { - ev_timer_stop(handler_->get_loop(), &settings_timer_); + if (settings_timerev_ == nullptr) { + return; + } + event_free(settings_timerev_); + settings_timerev_ = nullptr; } namespace { -int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame, - nghttp2_rcbuf *name, nghttp2_rcbuf *value, - uint8_t flags, void *user_data) { - auto namebuf = nghttp2_rcbuf_get_buf(name); - auto valuebuf = nghttp2_rcbuf_get_buf(value); - - if (get_config()->http2.upstream.debug.frame_debug) { - verbose_on_header_callback(session, frame, namebuf.base, namebuf.len, - valuebuf.base, valuebuf.len, flags, user_data); +int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, + const uint8_t *name, size_t namelen, + const uint8_t *value, size_t valuelen, uint8_t flags, + void *user_data) { + if (get_config()->upstream_frame_debug) { + verbose_on_header_callback(session, frame, name, namelen, value, valuelen, + flags, user_data); } - if (frame->hd.type != NGHTTP2_HEADERS) { + if (frame->hd.type != NGHTTP2_HEADERS || + frame->headers.cat != NGHTTP2_HCAT_REQUEST) { return 0; } auto upstream = static_cast(user_data); - auto downstream = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); + auto downstream = upstream->find_downstream(frame->hd.stream_id); if (!downstream) { return 0; } - auto &req = downstream->request(); - - auto &httpconf = get_config()->http; - - if (req.fs.buffer_size() + namebuf.len + valuebuf.len > - httpconf.request_header_field_buffer || - req.fs.num_fields() >= httpconf.max_request_header_fields) { + if (downstream->get_request_headers_sum() > Downstream::MAX_HEADERS_SUM) { if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { return 0; } if (LOG_ENABLED(INFO)) { - ULOG(INFO, upstream) << "Too large or many header field size=" - << req.fs.buffer_size() + namebuf.len + valuebuf.len - << ", num=" << req.fs.num_fields() + 1; - } - - // just ignore header fields if this is trailer part. - if (frame->headers.cat == NGHTTP2_HCAT_HEADERS) { - return 0; + ULOG(INFO, upstream) << "Too large header block size=" + << downstream->get_request_headers_sum(); } if (upstream->error_reply(downstream, 431) != 0) { @@ -205,24 +220,22 @@ return 0; } + if (!http2::check_nv(name, namelen, value, valuelen)) { + // Simply discard name/value, as if it never happen. + return 0; + } - auto token = http2::lookup_token(namebuf.base, namebuf.len); - auto no_index = flags & NGHTTP2_NV_FLAG_NO_INDEX; - - downstream->add_rcbuf(name); - downstream->add_rcbuf(value); + if (namelen > 0 && name[0] == ':') { + if (!downstream->request_pseudo_header_allowed() || + !http2::check_http2_request_pseudo_header(name, namelen)) { - if (frame->headers.cat == NGHTTP2_HCAT_HEADERS) { - // just store header fields for trailer part - req.fs.add_trailer_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, no_index, - token); - return 0; + upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } } - req.fs.add_header_token(StringRef{namebuf.base, namebuf.len}, - StringRef{valuebuf.base, valuebuf.len}, no_index, - token); + downstream->split_add_request_header(name, namelen, value, valuelen, + flags & NGHTTP2_NV_FLAG_NO_INDEX); return 0; } } // namespace @@ -240,21 +253,18 @@ << frame->hd.stream_id; } - auto handler = upstream->get_client_handler(); - - auto downstream = make_unique(upstream, handler->get_mcpool(), - frame->hd.stream_id); - nghttp2_session_set_stream_user_data(session, frame->hd.stream_id, - downstream.get()); + // TODO Use priority 0 for now + auto downstream = + util::make_unique(upstream, frame->hd.stream_id, 0); + downstream->init_upstream_timer(); downstream->reset_upstream_rtimer(); - - auto &req = downstream->request(); + downstream->init_response_body_buf(); // Although, we deprecated minor version from HTTP/2, we supply // minor version 0 to use via header field in a conventional way. - req.http_major = 2; - req.http_minor = 0; + downstream->set_request_major(2); + downstream->set_request_minor(0); upstream->add_pending_downstream(std::move(downstream)); @@ -262,167 +272,148 @@ } } // namespace -int Http2Upstream::on_request_headers(Downstream *downstream, - const nghttp2_frame *frame) { +namespace { +int on_request_headers(Http2Upstream *upstream, Downstream *downstream, + nghttp2_session *session, const nghttp2_frame *frame) { if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { return 0; } - auto &req = downstream->request(); - auto &nva = req.fs.headers(); + downstream->normalize_request_headers(); + auto &nva = downstream->get_request_headers(); if (LOG_ENABLED(INFO)) { std::stringstream ss; for (auto &nv : nva) { ss << TTY_HTTP_HD << nv.name << TTY_RST << ": " << nv.value << "\n"; } - ULOG(INFO, this) << "HTTP request headers. stream_id=" - << downstream->get_stream_id() << "\n" << ss.str(); - } - - auto &dump = get_config()->http2.upstream.debug.dump; - - if (dump.request_header) { - http2::dump_nv(dump.request_header, nva); + ULOG(INFO, upstream) << "HTTP request headers. stream_id=" + << downstream->get_stream_id() << "\n" << ss.str(); } - auto content_length = req.fs.header(http2::HD_CONTENT_LENGTH); - if (content_length) { - // libnghttp2 guarantees this can be parsed - req.fs.content_length = util::parse_uint(content_length->value); + if (get_config()->http2_upstream_dump_request_header) { + http2::dump_nv(get_config()->http2_upstream_dump_request_header, nva); } - // presence of mandatory header fields are guaranteed by libnghttp2. - auto authority = req.fs.header(http2::HD__AUTHORITY); - auto path = req.fs.header(http2::HD__PATH); - auto method = req.fs.header(http2::HD__METHOD); - auto scheme = req.fs.header(http2::HD__SCHEME); + if (!http2::check_http2_request_headers(nva)) { + upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR); - auto method_token = http2::lookup_method_token(method->value); - if (method_token == -1) { - if (error_reply(downstream, 501) != 0) { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } return 0; } - // For HTTP/2 proxy, we request :authority. - if (method_token != HTTP_CONNECT && get_config()->http2_proxy && !authority) { - rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR); - return 0; - } + auto host = http2::get_unique_header(nva, "host"); + auto authority = http2::get_unique_header(nva, ":authority"); + auto path = http2::get_unique_header(nva, ":path"); + auto method = http2::get_unique_header(nva, ":method"); + auto scheme = http2::get_unique_header(nva, ":scheme"); - req.method = method_token; - if (scheme) { - req.scheme = scheme->value; - } + bool is_connect = method && "CONNECT" == method->value; + bool having_host = http2::non_empty_value(host); + bool having_authority = http2::non_empty_value(authority); - // nghttp2 library guarantees either :authority or host exist - if (!authority) { - req.no_authority = true; - authority = req.fs.header(http2::HD_HOST); - } + if (is_connect) { + // Here we strictly require :authority header field. + if (scheme || path || !having_authority) { - if (authority) { - req.authority = authority->value; - } + upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR); - if (path) { - if (method_token == HTTP_OPTIONS && - path->value == StringRef::from_lit("*")) { - // Server-wide OPTIONS request. Path is empty. - } else if (get_config()->http2_proxy) { - req.path = path->value; - } else { - req.path = http2::rewrite_clean_path(downstream->get_block_allocator(), - path->value); + return 0; + } + } else { + // For proxy, :authority is required. Otherwise, we can accept + // :authority or host for methods. + if (!http2::non_empty_value(method) || !http2::non_empty_value(scheme) || + (get_config()->http2_proxy && !having_authority) || + (!get_config()->http2_proxy && !having_authority && !having_host) || + !http2::non_empty_value(path)) { + + upstream->rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR); + + return 0; } } + downstream->set_request_method(http2::value_to_str(method)); + downstream->set_request_http2_scheme(http2::value_to_str(scheme)); + downstream->set_request_http2_authority(http2::value_to_str(authority)); + downstream->set_request_path(http2::value_to_str(path)); + downstream->set_request_start_time(std::chrono::high_resolution_clock::now()); + if (!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) { - req.http2_expect_body = true; + downstream->set_request_http2_expect_body(true); } downstream->inspect_http2_request(); downstream->set_request_state(Downstream::HEADER_COMPLETE); - -#ifdef HAVE_MRUBY - auto upstream = downstream->get_upstream(); - auto handler = upstream->get_client_handler(); - auto worker = handler->get_worker(); - auto mruby_ctx = worker->get_mruby_context(); - - if (mruby_ctx->run_on_request_proc(downstream) != 0) { - if (error_reply(downstream, 500) != 0) { - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; - } - return 0; - } -#endif // HAVE_MRUBY - if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { downstream->disable_upstream_rtimer(); downstream->set_request_state(Downstream::MSG_COMPLETE); } - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - return 0; - } - - start_downstream(downstream); + upstream->maintain_downstream_concurrency(); return 0; } +} // namespace -void Http2Upstream::start_downstream(Downstream *downstream) { - if (downstream_queue_.can_activate(downstream->request().authority)) { - initiate_downstream(downstream); - return; - } +void Http2Upstream::maintain_downstream_concurrency() { + while (get_config()->max_downstream_connections > + downstream_queue_.num_active()) { + if (downstream_queue_.pending_empty()) { + break; + } + + { + auto downstream = downstream_queue_.pending_top(); + if (downstream->get_request_state() != Downstream::HEADER_COMPLETE && + downstream->get_request_state() != Downstream::MSG_COMPLETE) { + break; + } + } + + auto downstream = downstream_queue_.pop_pending(); + + if (!downstream) { + break; + } - downstream_queue_.mark_blocked(downstream); + initiate_downstream(std::move(downstream)); + } } -void Http2Upstream::initiate_downstream(Downstream *downstream) { +void +Http2Upstream::initiate_downstream(std::unique_ptr downstream) { int rv; - auto dconn = handler_->get_downstream_connection(downstream); - if (!dconn || - (rv = downstream->attach_downstream_connection(std::move(dconn))) != 0) { + rv = downstream->attach_downstream_connection( + handler_->get_downstream_connection()); + if (rv != 0) { // downstream connection fails, send error page - if (error_reply(downstream, 503) != 0) { - rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); + if (error_reply(downstream.get(), 503) != 0) { + rst_stream(downstream.get(), NGHTTP2_INTERNAL_ERROR); } downstream->set_request_state(Downstream::CONNECT_FAIL); - downstream_queue_.mark_failure(downstream); + downstream_queue_.add_failure(std::move(downstream)); return; } rv = downstream->push_request_headers(); if (rv != 0) { - if (error_reply(downstream, 503) != 0) { - rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); + if (error_reply(downstream.get(), 503) != 0) { + rst_stream(downstream.get(), NGHTTP2_INTERNAL_ERROR); } - downstream_queue_.mark_failure(downstream); + downstream_queue_.add_failure(std::move(downstream)); return; } - downstream_queue_.mark_active(downstream); - - auto &req = downstream->request(); - if (!req.http2_expect_body) { - rv = downstream->end_upload_data(); - if (rv != 0) { - rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); - } - } + downstream_queue_.add_active(std::move(downstream)); return; } @@ -430,15 +421,15 @@ namespace { int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) { - if (get_config()->http2.upstream.debug.frame_debug) { + int rv; + if (get_config()->upstream_frame_debug) { verbose_on_frame_recv_callback(session, frame, user_data); } auto upstream = static_cast(user_data); switch (frame->hd.type) { case NGHTTP2_DATA: { - auto downstream = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); + auto downstream = upstream->find_downstream(frame->hd.stream_id); if (!downstream) { return 0; } @@ -446,20 +437,14 @@ if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { downstream->disable_upstream_rtimer(); - if (downstream->end_upload_data() != 0) { - if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { - upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); - } - } - + downstream->end_upload_data(); downstream->set_request_state(Downstream::MSG_COMPLETE); } - return 0; + break; } case NGHTTP2_HEADERS: { - auto downstream = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); + auto downstream = upstream->find_downstream(frame->hd.stream_id); if (!downstream) { return 0; } @@ -467,29 +452,47 @@ if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { downstream->reset_upstream_rtimer(); - return upstream->on_request_headers(downstream, frame); + return on_request_headers(upstream, downstream, session, frame); } if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { downstream->disable_upstream_rtimer(); - if (downstream->end_upload_data() != 0) { - if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { - upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); - } - } - + downstream->end_upload_data(); downstream->set_request_state(Downstream::MSG_COMPLETE); + } else { + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->hd.stream_id, + NGHTTP2_PROTOCOL_ERROR); + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } } - return 0; + break; + } + case NGHTTP2_PRIORITY: { + // TODO comment out for now + // rv = downstream->change_priority(frame->priority.pri); + // if(rv != 0) { + // return NGHTTP2_ERR_CALLBACK_FAILURE; + // } + break; } case NGHTTP2_SETTINGS: if ((frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) { - return 0; + break; } upstream->stop_settings_timer(); - return 0; + break; + case NGHTTP2_PUSH_PROMISE: + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->push_promise.promised_stream_id, + NGHTTP2_REFUSED_STREAM); + if (rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + break; case NGHTTP2_GOAWAY: if (LOG_ENABLED(INFO)) { auto debug_data = util::ascii_dump(frame->goaway.opaque_data, @@ -500,10 +503,11 @@ << ", error_code=" << frame->goaway.error_code << ", debug_data=" << debug_data; } - return 0; + break; default: - return 0; + break; } + return 0; } } // namespace @@ -512,8 +516,7 @@ int32_t stream_id, const uint8_t *data, size_t len, void *user_data) { auto upstream = static_cast(user_data); - auto downstream = static_cast( - nghttp2_session_get_stream_user_data(session, stream_id)); + auto downstream = upstream->find_downstream(stream_id); if (!downstream || !downstream->get_downstream_connection()) { if (upstream->consume(stream_id, len) != 0) { @@ -526,9 +529,7 @@ downstream->reset_upstream_rtimer(); if (downstream->push_upload_data_chunk(data, len) != 0) { - if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { - upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); - } + upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); if (upstream->consume(stream_id, len) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -544,129 +545,19 @@ namespace { int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame, void *user_data) { - if (get_config()->http2.upstream.debug.frame_debug) { + if (get_config()->upstream_frame_debug) { verbose_on_frame_send_callback(session, frame, user_data); } auto upstream = static_cast(user_data); - auto handler = upstream->get_client_handler(); switch (frame->hd.type) { - case NGHTTP2_DATA: - case NGHTTP2_HEADERS: { - if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) { - return 0; - } - // RST_STREAM if request is still incomplete. - auto stream_id = frame->hd.stream_id; - auto downstream = static_cast( - nghttp2_session_get_stream_user_data(session, stream_id)); - - if (!downstream) { - return 0; - } - - // For tunneling, issue RST_STREAM to finish the stream. - if (downstream->get_upgraded() || - nghttp2_session_get_stream_remote_close(session, stream_id) == 0) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, upstream) - << "Send RST_STREAM to " - << (downstream->get_upgraded() ? "tunneled " : "") - << "stream stream_id=" << downstream->get_stream_id() - << " to finish off incomplete request"; - } - - upstream->rst_stream(downstream, NGHTTP2_NO_ERROR); - } - - return 0; - } case NGHTTP2_SETTINGS: - if ((frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) { - upstream->start_settings_timer(); - } - return 0; - case NGHTTP2_PUSH_PROMISE: { - auto promised_stream_id = frame->push_promise.promised_stream_id; - - if (nghttp2_session_get_stream_user_data(session, promised_stream_id)) { - // In case of push from backend, downstream object was already - // created. - return 0; - } - - auto promised_downstream = make_unique( - upstream, handler->get_mcpool(), promised_stream_id); - auto &req = promised_downstream->request(); - - // As long as we use nghttp2_session_mem_send(), setting stream - // user data here should not fail. This is because this callback - // is called just after frame was serialized. So no worries about - // hanging Downstream. - nghttp2_session_set_stream_user_data(session, promised_stream_id, - promised_downstream.get()); - - promised_downstream->set_assoc_stream_id(frame->hd.stream_id); - promised_downstream->disable_upstream_rtimer(); - - req.http_major = 2; - req.http_minor = 0; - - auto &promised_balloc = promised_downstream->get_block_allocator(); - - for (size_t i = 0; i < frame->push_promise.nvlen; ++i) { - auto &nv = frame->push_promise.nva[i]; - - auto name = - make_string_ref(promised_balloc, StringRef{nv.name, nv.namelen}); - auto value = - make_string_ref(promised_balloc, StringRef{nv.value, nv.valuelen}); - - auto token = http2::lookup_token(nv.name, nv.namelen); - switch (token) { - case http2::HD__METHOD: - req.method = http2::lookup_method_token(value); - break; - case http2::HD__SCHEME: - req.scheme = value; - break; - case http2::HD__AUTHORITY: - req.authority = value; - break; - case http2::HD__PATH: - req.path = http2::rewrite_clean_path(promised_balloc, value); - break; - } - req.fs.add_header_token(name, value, nv.flags & NGHTTP2_NV_FLAG_NO_INDEX, - token); - } - - promised_downstream->inspect_http2_request(); - - promised_downstream->set_request_state(Downstream::MSG_COMPLETE); - - // a bit weird but start_downstream() expects that given - // downstream is in pending queue. - auto ptr = promised_downstream.get(); - upstream->add_pending_downstream(std::move(promised_downstream)); + if ((frame->hd.flags & NGHTTP2_FLAG_ACK) == 0 && + upstream->start_settings_timer() != 0) { -#ifdef HAVE_MRUBY - auto worker = handler->get_worker(); - auto mruby_ctx = worker->get_mruby_context(); - - if (mruby_ctx->run_on_request_proc(ptr) != 0) { - if (upstream->error_reply(ptr, 500) != 0) { - upstream->rst_stream(ptr, NGHTTP2_INTERNAL_ERROR); - return 0; - } - return 0; + return NGHTTP2_ERR_CALLBACK_FAILURE; } -#endif // HAVE_MRUBY - - upstream->start_downstream(ptr); - - return 0; - } + break; case NGHTTP2_GOAWAY: if (LOG_ENABLED(INFO)) { auto debug_data = util::ascii_dump(frame->goaway.opaque_data, @@ -677,10 +568,9 @@ << ", error_code=" << frame->goaway.error_code << ", debug_data=" << debug_data; } - return 0; - default: - return 0; + break; } + return 0; } } // namespace @@ -689,18 +579,14 @@ const nghttp2_frame *frame, int lib_error_code, void *user_data) { auto upstream = static_cast(user_data); - if (LOG_ENABLED(INFO)) { - ULOG(INFO, upstream) << "Failed to send control frame type=" - << static_cast(frame->hd.type) - << ", lib_error_code=" << lib_error_code << ":" - << nghttp2_strerror(lib_error_code); - } + ULOG(WARN, upstream) << "Failed to send control frame type=" + << static_cast(frame->hd.type) + << ", lib_error_code=" << lib_error_code << ":" + << nghttp2_strerror(lib_error_code); if (frame->hd.type == NGHTTP2_HEADERS && - lib_error_code != NGHTTP2_ERR_STREAM_CLOSED && - lib_error_code != NGHTTP2_ERR_STREAM_CLOSING) { + frame->headers.cat == NGHTTP2_HCAT_RESPONSE) { // To avoid stream hanging around, issue RST_STREAM. - auto downstream = static_cast( - nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)); + auto downstream = upstream->find_downstream(frame->hd.stream_id); if (downstream) { upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); } @@ -710,46 +596,6 @@ } // namespace namespace { -constexpr auto PADDING = std::array{}; -} // namespace - -namespace { -int send_data_callback(nghttp2_session *session, nghttp2_frame *frame, - const uint8_t *framehd, size_t length, - nghttp2_data_source *source, void *user_data) { - auto downstream = static_cast(source->ptr); - auto upstream = static_cast(downstream->get_upstream()); - auto body = downstream->get_response_buf(); - - auto wb = upstream->get_response_buf(); - - size_t padlen = 0; - - wb->append(framehd, 9); - if (frame->data.padlen > 0) { - padlen = frame->data.padlen - 1; - wb->append(static_cast(padlen)); - } - - body->remove(*wb, length); - - wb->append(PADDING.data(), padlen); - - downstream->reset_upstream_wtimer(); - - if (length > 0 && downstream->resume_read(SHRPX_NO_BUFFER, length) != 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - - // We have to add length here, so that we can log this amount of - // data transferred. - downstream->response_sent_body_length += length; - - return wb->rleft() >= MAX_BUFFER_SIZE ? NGHTTP2_ERR_PAUSE : 0; -} -} // namespace - -namespace { uint32_t infer_upstream_rst_stream_error_code(uint32_t downstream_error_code) { // NGHTTP2_REFUSED_STREAM is important because it tells upstream // client to retry. @@ -763,73 +609,19 @@ } } // namespace -namespace { -void settings_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto upstream = static_cast(w->data); - auto handler = upstream->get_client_handler(); - ULOG(INFO, upstream) << "SETTINGS timeout"; - if (upstream->terminate_session(NGHTTP2_SETTINGS_TIMEOUT) != 0) { - delete handler; - return; - } - handler->signal_write(); -} -} // namespace - -namespace { -void shutdown_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto upstream = static_cast(w->data); - auto handler = upstream->get_client_handler(); - upstream->submit_goaway(); - handler->signal_write(); -} -} // namespace - -namespace { -void prepare_cb(struct ev_loop *loop, ev_prepare *w, int revents) { - auto upstream = static_cast(w->data); - upstream->check_shutdown(); -} -} // namespace - -void Http2Upstream::submit_goaway() { - auto last_stream_id = nghttp2_session_get_last_proc_stream_id(session_); - nghttp2_submit_goaway(session_, NGHTTP2_FLAG_NONE, last_stream_id, - NGHTTP2_NO_ERROR, nullptr, 0); -} +Http2Upstream::Http2Upstream(ClientHandler *handler) + : handler_(handler), session_(nullptr), settings_timerev_(nullptr) { + reset_timeouts(); -void Http2Upstream::check_shutdown() { int rv; - auto worker = handler_->get_worker(); - - if (!worker->get_graceful_shutdown()) { - return; - } - - ev_prepare_stop(handler_->get_loop(), &prep_); - - rv = nghttp2_submit_shutdown_notice(session_); - if (rv != 0) { - ULOG(FATAL, this) << "nghttp2_submit_shutdown_notice() failed: " - << nghttp2_strerror(rv); - return; - } - - handler_->signal_write(); - - ev_timer_start(handler_->get_loop(), &shutdown_timer_); -} - -nghttp2_session_callbacks *create_http2_upstream_callbacks() { - int rv; nghttp2_session_callbacks *callbacks; - rv = nghttp2_session_callbacks_new(&callbacks); - if (rv != 0) { - return nullptr; - } + assert(rv == 0); + + auto callbacks_deleter = + util::defer(callbacks, nghttp2_session_callbacks_del); nghttp2_session_callbacks_set_on_stream_close_callback( callbacks, on_stream_close_callback); @@ -846,87 +638,43 @@ nghttp2_session_callbacks_set_on_frame_not_send_callback( callbacks, on_frame_not_send_callback); - nghttp2_session_callbacks_set_on_header_callback2(callbacks, - on_header_callback2); + nghttp2_session_callbacks_set_on_header_callback(callbacks, + on_header_callback); nghttp2_session_callbacks_set_on_begin_headers_callback( callbacks, on_begin_headers_callback); - nghttp2_session_callbacks_set_send_data_callback(callbacks, - send_data_callback); - if (get_config()->padding) { nghttp2_session_callbacks_set_select_padding_callback( callbacks, http::select_padding_callback); } - if (get_config()->http2.upstream.debug.frame_debug) { - nghttp2_session_callbacks_set_error_callback(callbacks, - verbose_error_callback); - } - - return callbacks; -} - -namespace { -size_t downstream_queue_size(Worker *worker) { - auto &downstreamconf = *worker->get_downstream_config(); - - if (get_config()->http2_proxy) { - return downstreamconf.connections_per_host; - } - - return downstreamconf.connections_per_frontend; -} -} // namespace - -Http2Upstream::Http2Upstream(ClientHandler *handler) - : wb_(handler->get_worker()->get_mcpool()), - downstream_queue_(downstream_queue_size(handler->get_worker()), - !get_config()->http2_proxy), - handler_(handler), - session_(nullptr) { - int rv; - - auto &http2conf = get_config()->http2; - - auto faddr = handler_->get_upstream_addr(); - - rv = nghttp2_session_server_new2( - &session_, http2conf.upstream.callbacks, this, - faddr->alt_mode ? http2conf.upstream.alt_mode_option - : http2conf.upstream.option); + rv = nghttp2_session_server_new2(&session_, callbacks, this, + get_config()->http2_option); assert(rv == 0); flow_control_ = true; // TODO Maybe call from outside? - std::array entry; + nghttp2_settings_entry entry[2]; entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; - entry[0].value = http2conf.upstream.max_concurrent_streams; + entry[0].value = get_config()->http2_max_concurrent_streams; entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; - if (faddr->alt_mode) { - entry[1].value = (1u << 31) - 1; - } else { - entry[1].value = (1 << http2conf.upstream.window_bits) - 1; - } + entry[1].value = (1 << get_config()->http2_upstream_window_bits) - 1; - rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(), - entry.size()); + rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry, + util::array_size(entry)); if (rv != 0) { ULOG(ERROR, this) << "nghttp2_submit_settings() returned error: " << nghttp2_strerror(rv); } - int32_t window_bits = - faddr->alt_mode ? 31 : http2conf.upstream.connection_window_bits; - - if (window_bits != 16) { - int32_t window_size = (1u << window_bits) - 1; - rv = nghttp2_session_set_local_window_size(session_, NGHTTP2_FLAG_NONE, 0, - window_size); + if (get_config()->http2_upstream_connection_window_bits > 16) { + int32_t delta = (1 << get_config()->http2_upstream_connection_window_bits) - + 1 - NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; + rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta); if (rv != 0) { ULOG(ERROR, this) << "nghttp2_submit_window_update() returned error: " @@ -934,73 +682,77 @@ } } - // We wait for SETTINGS ACK at least 10 seconds. - ev_timer_init(&settings_timer_, settings_timeout_cb, - http2conf.upstream.timeout.settings, 0.); - - settings_timer_.data = this; - - // timer for 2nd GOAWAY. HTTP/2 spec recommend 1 RTT. We wait for - // 2 seconds. - ev_timer_init(&shutdown_timer_, shutdown_timeout_cb, 2., 0); - shutdown_timer_.data = this; + if (!get_config()->altsvcs.empty()) { + // Set max_age to 24hrs, which is default for alt-svc header + // field. + for (auto &altsvc : get_config()->altsvcs) { + rv = nghttp2_submit_altsvc( + session_, NGHTTP2_FLAG_NONE, 0, 86400, altsvc.port, + reinterpret_cast(altsvc.protocol_id), + altsvc.protocol_id_len, + reinterpret_cast(altsvc.host), altsvc.host_len, + reinterpret_cast(altsvc.origin), altsvc.origin_len); - ev_prepare_init(&prep_, prepare_cb); - prep_.data = this; - ev_prepare_start(handler_->get_loop(), &prep_); - - handler_->reset_upstream_read_timeout( - get_config()->conn.upstream.timeout.http2_read); - - handler_->signal_write(); + if (rv != 0) { + ULOG(ERROR, this) << "nghttp2_submit_altsvc() returned error: " + << nghttp2_strerror(rv); + } + } + } } Http2Upstream::~Http2Upstream() { nghttp2_session_del(session_); - ev_prepare_stop(handler_->get_loop(), &prep_); - ev_timer_stop(handler_->get_loop(), &shutdown_timer_); - ev_timer_stop(handler_->get_loop(), &settings_timer_); + if (settings_timerev_) { + event_free(settings_timerev_); + } } int Http2Upstream::on_read() { ssize_t rv = 0; - auto rb = handler_->get_rb(); - auto rlimit = handler_->get_rlimit(); + auto bev = handler_->get_bev(); + auto input = bufferevent_get_input(bev); + + for (;;) { + auto inputlen = evbuffer_get_contiguous_space(input); + + if (inputlen == 0) { + assert(evbuffer_get_length(input) == 0); + + return send(); + } - if (rb->rleft()) { - rv = nghttp2_session_mem_recv(session_, rb->pos, rb->rleft()); + auto mem = evbuffer_pullup(input, inputlen); + + rv = nghttp2_session_mem_recv(session_, mem, inputlen); if (rv < 0) { - if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) { - ULOG(ERROR, this) << "nghttp2_session_mem_recv() returned error: " - << nghttp2_strerror(rv); - } + ULOG(ERROR, this) << "nghttp2_session_recv() returned error: " + << nghttp2_strerror(rv); return -1; } - // nghttp2_session_mem_recv should consume all input bytes on - // success. - assert(static_cast(rv) == rb->rleft()); - rb->reset(); - rlimit->startw(); - } - - if (nghttp2_session_want_read(session_) == 0 && - nghttp2_session_want_write(session_) == 0 && wb_.rleft() == 0) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, this) << "No more read/write for this HTTP2 session"; + if (evbuffer_drain(input, rv) != 0) { + DCLOG(FATAL, this) << "evbuffer_drain() failed"; + return -1; } - return -1; } - - handler_->signal_write(); - return 0; } +int Http2Upstream::on_write() { return send(); } + // After this function call, downstream may be deleted. -int Http2Upstream::on_write() { +int Http2Upstream::send() { + int rv; + uint8_t buf[16384]; + auto bev = handler_->get_bev(); + auto output = bufferevent_get_output(bev); + + sendbuf.reset(output, buf, sizeof(buf), handler_->get_write_limit()); for (;;) { - if (wb_.rleft() >= MAX_BUFFER_SIZE) { - return 0; + // Check buffer length and break if it is large enough. + if (handler_->get_outbuf_length() + sendbuf.get_buflen() >= + OUTBUF_MAX_THRES) { + break; } const uint8_t *data; @@ -1014,175 +766,237 @@ if (datalen == 0) { break; } - wb_.append(data, datalen); + rv = sendbuf.add(data, datalen); + if (rv != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } + } + + rv = sendbuf.flush(); + if (rv != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; } + handler_->update_warmup_writelen(sendbuf.get_writelen()); + if (nghttp2_session_want_read(session_) == 0 && - nghttp2_session_want_write(session_) == 0 && wb_.rleft() == 0) { + nghttp2_session_want_write(session_) == 0 && + handler_->get_outbuf_length() == 0) { if (LOG_ENABLED(INFO)) { ULOG(INFO, this) << "No more read/write for this HTTP2 session"; } return -1; } - return 0; } +int Http2Upstream::on_event() { return 0; } + ClientHandler *Http2Upstream::get_client_handler() const { return handler_; } -int Http2Upstream::downstream_read(DownstreamConnection *dconn) { +namespace { +void downstream_readcb(bufferevent *bev, void *ptr) { + auto dconn = static_cast(ptr); auto downstream = dconn->get_downstream(); + auto upstream = static_cast(downstream->get_upstream()); + + if (downstream->get_request_state() == Downstream::STREAM_CLOSED) { + // If upstream HTTP2 stream was closed, we just close downstream, + // because there is no consumer now. Downstream connection is also + // closed in this case. + upstream->remove_downstream(downstream); + // downstream was deleted + + return; + } if (downstream->get_response_state() == Downstream::MSG_RESET) { // The downstream stream was reset (canceled). In this case, // RST_STREAM to the upstream and delete downstream connection // here. Deleting downstream will be taken place at // on_stream_close_callback. - rst_stream(downstream, - infer_upstream_rst_stream_error_code( - downstream->get_response_rst_stream_error_code())); - downstream->pop_downstream_connection(); - // dconn was deleted - dconn = nullptr; - } else if (downstream->get_response_state() == Downstream::MSG_BAD_HEADER) { - if (error_reply(downstream, 502) != 0) { - return -1; - } + upstream->rst_stream(downstream, + infer_upstream_rst_stream_error_code( + downstream->get_response_rst_stream_error_code())); downstream->pop_downstream_connection(); // dconn was deleted dconn = nullptr; } else { auto rv = downstream->on_read(); - if (rv == SHRPX_ERR_EOF) { - return downstream_eof(dconn); - } - if (rv == SHRPX_ERR_DCONN_CANCELED) { - downstream->pop_downstream_connection(); - handler_->signal_write(); - return 0; - } if (rv != 0) { - if (rv != SHRPX_ERR_NETWORK) { - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "HTTP parser failure"; + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "HTTP parser failure"; + } + if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); + } else if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { + // If response was completed, then don't issue RST_STREAM + if (upstream->error_reply(downstream, 502) != 0) { + delete upstream->get_client_handler(); + return; } } - return downstream_error(dconn, Downstream::EVENT_ERROR); - } - - if (downstream->can_detach_downstream_connection()) { - // Keep-alive - downstream->detach_downstream_connection(); + downstream->set_response_state(Downstream::MSG_COMPLETE); + // Clearly, we have to close downstream connection on http parser + // failure. + downstream->pop_downstream_connection(); + // dconn was deleted + dconn = nullptr; } } - - handler_->signal_write(); - + if (upstream->send() != 0) { + delete upstream->get_client_handler(); + return; + } // At this point, downstream may be deleted. - - return 0; } +} // namespace -int Http2Upstream::downstream_write(DownstreamConnection *dconn) { - int rv; - rv = dconn->on_write(); - if (rv == SHRPX_ERR_NETWORK) { - return downstream_error(dconn, Downstream::EVENT_ERROR); - } - if (rv != 0) { - return -1; +namespace { +void downstream_writecb(bufferevent *bev, void *ptr) { + if (evbuffer_get_length(bufferevent_get_output(bev)) > 0) { + return; } - return 0; + auto dconn = static_cast(ptr); + dconn->on_write(); } +} // namespace -int Http2Upstream::downstream_eof(DownstreamConnection *dconn) { +namespace { +void downstream_eventcb(bufferevent *bev, short events, void *ptr) { + auto dconn = static_cast(ptr); auto downstream = dconn->get_downstream(); + auto upstream = static_cast(downstream->get_upstream()); + if (events & BEV_EVENT_CONNECTED) { + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "Connection established. stream_id=" + << downstream->get_stream_id(); + } + auto fd = bufferevent_getfd(bev); + int val = 1; + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&val), + sizeof(val)) == -1) { + DCLOG(WARN, dconn) << "Setting option TCP_NODELAY failed: errno=" + << errno; + } - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id(); + return; } - // Delete downstream connection. If we don't delete it here, it will - // be pooled in on_stream_close_callback. - downstream->pop_downstream_connection(); - // dconn was deleted - dconn = nullptr; - // downstream wil be deleted in on_stream_close_callback. - if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { - // Server may indicate the end of the request by EOF + if (events & BEV_EVENT_EOF) { if (LOG_ENABLED(INFO)) { - ULOG(INFO, this) << "Downstream body was ended by EOF"; + DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id(); } - downstream->set_response_state(Downstream::MSG_COMPLETE); + if (downstream->get_request_state() == Downstream::STREAM_CLOSED) { + // If stream was closed already, we don't need to send reply at + // the first place. We can delete downstream. + upstream->remove_downstream(downstream); + // downstream was deleted - // For tunneled connection, MSG_COMPLETE signals - // downstream_data_read_callback to send RST_STREAM after pending - // response body is sent. This is needed to ensure that RST_STREAM - // is sent after all pending data are sent. - on_downstream_body_complete(downstream); - } else if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { - // If stream was not closed, then we set MSG_COMPLETE and let - // on_stream_close_callback delete downstream. - if (error_reply(downstream, 502) != 0) { - return -1; + return; } - } - handler_->signal_write(); - // At this point, downstream may be deleted. - return 0; -} -int Http2Upstream::downstream_error(DownstreamConnection *dconn, int events) { - auto downstream = dconn->get_downstream(); + // Delete downstream connection. If we don't delete it here, it + // will be pooled in on_stream_close_callback. + downstream->pop_downstream_connection(); + // dconn was deleted + dconn = nullptr; + // downstream wil be deleted in on_stream_close_callback. + if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + // Server may indicate the end of the request by EOF + if (LOG_ENABLED(INFO)) { + ULOG(INFO, upstream) << "Downstream body was ended by EOF"; + } + downstream->set_response_state(Downstream::MSG_COMPLETE); - if (LOG_ENABLED(INFO)) { - if (events & Downstream::EVENT_ERROR) { - DCLOG(INFO, dconn) << "Downstream network/general error"; - } else { - DCLOG(INFO, dconn) << "Timeout"; + // For tunneled connection, MSG_COMPLETE signals + // downstream_data_read_callback to send RST_STREAM after + // pending response body is sent. This is needed to ensure + // that RST_STREAM is sent after all pending data are sent. + upstream->on_downstream_body_complete(downstream); + } else if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { + // If stream was not closed, then we set MSG_COMPLETE and let + // on_stream_close_callback delete downstream. + if (upstream->error_reply(downstream, 502) != 0) { + delete upstream->get_client_handler(); + return; + } + downstream->set_response_state(Downstream::MSG_COMPLETE); } - if (downstream->get_upgraded()) { - DCLOG(INFO, dconn) << "Note: this is tunnel connection"; + if (upstream->send() != 0) { + delete upstream->get_client_handler(); + return; } + // At this point, downstream may be deleted. + return; } - // Delete downstream connection. If we don't delete it here, it will - // be pooled in on_stream_close_callback. - downstream->pop_downstream_connection(); - // dconn was deleted - dconn = nullptr; + if (events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { + if (LOG_ENABLED(INFO)) { + if (events & BEV_EVENT_ERROR) { + DCLOG(INFO, dconn) << "Downstream network error: " + << evutil_socket_error_to_string( + EVUTIL_SOCKET_ERROR()); + } else { + DCLOG(INFO, dconn) << "Timeout"; + } + if (downstream->get_upgraded()) { + DCLOG(INFO, dconn) << "Note: this is tunnel connection"; + } + } - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - // For SSL tunneling, we issue RST_STREAM. For other types of - // stream, we don't have to do anything since response was - // complete. - if (downstream->get_upgraded()) { - rst_stream(downstream, NGHTTP2_NO_ERROR); + if (downstream->get_request_state() == Downstream::STREAM_CLOSED) { + upstream->remove_downstream(downstream); + // downstream was deleted + + return; } - } else { - if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + + // Delete downstream connection. If we don't delete it here, it + // will be pooled in on_stream_close_callback. + downstream->pop_downstream_connection(); + // dconn was deleted + dconn = nullptr; + + if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { + // For SSL tunneling, we issue RST_STREAM. For other types of + // stream, we don't have to do anything since response was + // complete. if (downstream->get_upgraded()) { - on_downstream_body_complete(downstream); - } else { - rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); + upstream->rst_stream(downstream, NGHTTP2_NO_ERROR); } } else { - unsigned int status; - if (events & Downstream::EVENT_TIMEOUT) { - status = 504; + if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + if (downstream->get_upgraded()) { + upstream->on_downstream_body_complete(downstream); + } else { + upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); + } } else { - status = 502; - } - if (error_reply(downstream, status) != 0) { - return -1; + unsigned int status; + if (events & BEV_EVENT_TIMEOUT) { + status = 504; + } else { + status = 502; + } + if (upstream->error_reply(downstream, status) != 0) { + delete upstream->get_client_handler(); + return; + } } + downstream->set_response_state(Downstream::MSG_COMPLETE); } - downstream->set_response_state(Downstream::MSG_COMPLETE); + if (upstream->send() != 0) { + delete upstream->get_client_handler(); + return; + } + // At this point, downstream may be deleted. + return; } - handler_->signal_write(); - // At this point, downstream may be deleted. - return 0; } +} // namespace int Http2Upstream::rst_stream(Downstream *downstream, uint32_t error_code) { if (LOG_ENABLED(INFO)) { @@ -1215,17 +1029,29 @@ size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { - int rv; auto downstream = static_cast(source->ptr); - auto body = downstream->get_response_buf(); + auto upstream = static_cast(downstream->get_upstream()); + auto body = downstream->get_response_body_buf(); + auto handler = upstream->get_client_handler(); assert(body); - const auto &resp = downstream->response(); + auto limit = handler->get_write_limit(); + + if (limit != -1) { + // 9 is HTTP/2 frame header length. Make DATA frame also under + // certain limit, so that application layer can flush at DATA + // frame boundary, instead of buffering large frame. + assert(limit > 9); + length = std::min(length, static_cast(limit - 9)); + } - auto nread = std::min(body->rleft(), length); - auto body_empty = body->rleft() == nread; + int nread = evbuffer_remove(body, buf, length); + if (nread == -1) { + ULOG(FATAL, upstream) << "evbuffer_remove() failed"; + return NGHTTP2_ERR_CALLBACK_FAILURE; + } - *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY; + auto body_empty = evbuffer_get_length(body) == 0; if (body_empty && downstream->get_response_state() == Downstream::MSG_COMPLETE) { @@ -1233,149 +1059,94 @@ *data_flags |= NGHTTP2_DATA_FLAG_EOF; if (!downstream->get_upgraded()) { - const auto &trailers = resp.fs.trailers(); - if (!trailers.empty()) { - std::vector nva; - nva.reserve(trailers.size()); - http2::copy_headers_to_nva_nocopy(nva, trailers); - if (!nva.empty()) { - rv = nghttp2_submit_trailer(session, stream_id, nva.data(), - nva.size()); - if (rv != 0) { - if (nghttp2_is_fatal(rv)) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - } else { - *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM; - } - } + + if (nghttp2_session_get_stream_remote_close(session, stream_id) == 0) { + upstream->rst_stream(downstream, NGHTTP2_NO_ERROR); } + } else { + // For tunneling, issue RST_STREAM to finish the stream. + if (LOG_ENABLED(INFO)) { + ULOG(INFO, upstream) + << "RST_STREAM to tunneled stream stream_id=" << stream_id; + } + upstream->rst_stream(downstream, NGHTTP2_NO_ERROR); } } - if (nread == 0 && ((*data_flags) & NGHTTP2_DATA_FLAG_EOF) == 0) { - return NGHTTP2_ERR_DEFERRED; - } - - return nread; -} -} // namespace - -int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body, - size_t bodylen) { - int rv; - - nghttp2_data_provider data_prd, *data_prd_ptr = nullptr; - - if (bodylen) { - data_prd.source.ptr = downstream; - data_prd.read_callback = downstream_data_read_callback; - data_prd_ptr = &data_prd; - } - - const auto &resp = downstream->response(); - auto &httpconf = get_config()->http; - - auto &balloc = downstream->get_block_allocator(); - - const auto &headers = resp.fs.headers(); - auto nva = std::vector(); - // 2 for :status and server - nva.reserve(2 + headers.size() + httpconf.add_response_headers.size()); - - auto response_status = http2::stringify_status(balloc, resp.http_status); - - nva.push_back(http2::make_nv_ls_nocopy(":status", response_status)); - - for (auto &kv : headers) { - if (kv.name.empty() || kv.name[0] == ':') { - continue; - } - switch (kv.token) { - case http2::HD_CONNECTION: - case http2::HD_KEEP_ALIVE: - case http2::HD_PROXY_CONNECTION: - case http2::HD_TE: - case http2::HD_TRANSFER_ENCODING: - case http2::HD_UPGRADE: - continue; - } - nva.push_back(http2::make_nv_nocopy(kv.name, kv.value, kv.no_index)); + if (body_empty) { + downstream->disable_upstream_wtimer(); + } else { + downstream->reset_upstream_wtimer(); } - if (!resp.fs.header(http2::HD_SERVER)) { - nva.push_back( - http2::make_nv_ls_nocopy("server", get_config()->http.server_name)); + if (nread > 0 && downstream->resume_read(SHRPX_NO_BUFFER, nread) != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; } - for (auto &p : httpconf.add_response_headers) { - nva.push_back(http2::make_nv_nocopy(p.name, p.value)); + if (nread == 0 && ((*data_flags) & NGHTTP2_DATA_FLAG_EOF) == 0) { + return NGHTTP2_ERR_DEFERRED; } - rv = nghttp2_submit_response(session_, downstream->get_stream_id(), - nva.data(), nva.size(), data_prd_ptr); - if (nghttp2_is_fatal(rv)) { - ULOG(FATAL, this) << "nghttp2_submit_response() failed: " - << nghttp2_strerror(rv); - return -1; + if (nread > 0) { + downstream->add_response_sent_bodylen(nread); } - auto buf = downstream->get_response_buf(); - - buf->append(body, bodylen); - - downstream->set_response_state(Downstream::MSG_COMPLETE); - - return 0; + return nread; } +} // namespace int Http2Upstream::error_reply(Downstream *downstream, unsigned int status_code) { int rv; - auto &resp = downstream->response(); - - auto &balloc = downstream->get_block_allocator(); - - auto html = http::create_error_html(balloc, status_code); - resp.http_status = status_code; - auto body = downstream->get_response_buf(); - body->append(html); + auto html = http::create_error_html(status_code); + downstream->set_response_http_status(status_code); + downstream->init_response_body_buf(); + auto body = downstream->get_response_body_buf(); + rv = evbuffer_add(body, html.c_str(), html.size()); + if (rv == -1) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } downstream->set_response_state(Downstream::MSG_COMPLETE); nghttp2_data_provider data_prd; data_prd.source.ptr = downstream; data_prd.read_callback = downstream_data_read_callback; - auto lgconf = log_config(); - lgconf->update_tstamp(std::chrono::system_clock::now()); - - auto response_status = http2::stringify_status(balloc, status_code); - auto content_length = util::make_string_ref_uint(balloc, html.size()); - auto date = make_string_ref(balloc, StringRef{lgconf->time_http_str}); - - auto nva = std::array{ - {http2::make_nv_ls_nocopy(":status", response_status), - http2::make_nv_ll("content-type", "text/html; charset=UTF-8"), - http2::make_nv_ls_nocopy("server", get_config()->http.server_name), - http2::make_nv_ls_nocopy("content-length", content_length), - http2::make_nv_ls_nocopy("date", date)}}; + auto content_length = util::utos(html.size()); + auto status_code_str = util::utos(status_code); + auto nva = std::vector{ + http2::make_nv_ls(":status", status_code_str), + http2::make_nv_ll("content-type", "text/html; charset=UTF-8"), + http2::make_nv_lc("server", get_config()->server_name), + http2::make_nv_ls("content-length", content_length)}; rv = nghttp2_submit_response(session_, downstream->get_stream_id(), nva.data(), nva.size(), &data_prd); if (rv < NGHTTP2_ERR_FATAL) { ULOG(FATAL, this) << "nghttp2_submit_response() failed: " << nghttp2_strerror(rv); - return -1; + DIE(); } return 0; } -void Http2Upstream::add_pending_downstream( - std::unique_ptr downstream) { - downstream_queue_.add_pending(std::move(downstream)); +bufferevent_data_cb Http2Upstream::get_downstream_readcb() { + return downstream_readcb; +} - handler_->stop_read_timer(); +bufferevent_data_cb Http2Upstream::get_downstream_writecb() { + return downstream_writecb; +} + +bufferevent_event_cb Http2Upstream::get_downstream_eventcb() { + return downstream_eventcb; +} + +void +Http2Upstream::add_pending_downstream(std::unique_ptr downstream) { + downstream_queue_.add_pending(std::move(downstream)); } void Http2Upstream::remove_downstream(Downstream *downstream) { @@ -1383,31 +1154,22 @@ handler_->write_accesslog(downstream); } - nghttp2_session_set_stream_user_data(session_, downstream->get_stream_id(), - nullptr); - - auto next_downstream = downstream_queue_.remove_and_get_blocked(downstream); + downstream_queue_.remove(downstream->get_stream_id()); - if (next_downstream) { - initiate_downstream(next_downstream); - } + maintain_downstream_concurrency(); +} - if (downstream_queue_.get_downstreams() == nullptr) { - // There is no downstream at the moment. Start idle timer now. - handler_->repeat_read_timer(); - } +Downstream *Http2Upstream::find_downstream(int32_t stream_id) { + return downstream_queue_.find(stream_id); } +nghttp2_session *Http2Upstream::get_http2_session() { return session_; } + // WARNING: Never call directly or indirectly nghttp2_session_send or // nghttp2_session_recv. These calls may delete downstream. int Http2Upstream::on_downstream_header_complete(Downstream *downstream) { int rv; - const auto &req = downstream->request(); - auto &resp = downstream->response(); - - auto &balloc = downstream->get_block_allocator(); - if (LOG_ENABLED(INFO)) { if (downstream->get_non_final_response()) { DLOG(INFO, downstream) << "HTTP non-final response header"; @@ -1416,72 +1178,25 @@ } } - auto &httpconf = get_config()->http; - - if (!get_config()->http2_proxy && !httpconf.no_location_rewrite) { - downstream->rewrite_location_response_header(req.scheme); - } - -#ifdef HAVE_MRUBY - if (!downstream->get_non_final_response()) { - auto worker = handler_->get_worker(); - auto mruby_ctx = worker->get_mruby_context(); - - if (mruby_ctx->run_on_response_proc(downstream) != 0) { - if (error_reply(downstream, 500) != 0) { - return -1; - } - // Returning -1 will signal deletion of dconn. - return -1; - } - - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - return -1; - } - } -#endif // HAVE_MRUBY - - auto &http2conf = get_config()->http2; - - // We need some conditions that must be fulfilled to initiate server - // push. - // - // * Server push is disabled for http2 proxy or client proxy, since - // incoming headers are mixed origins. We don't know how to - // reliably determine the authority yet. - // - // * We need non-final response or 200 response code for associated - // resource. This is too restrictive, we will review this later. - // - // * We requires GET or POST for associated resource. Probably we - // don't want to push for HEAD request. Not sure other methods - // are also eligible for push. - if (!http2conf.no_server_push && - nghttp2_session_get_remote_settings(session_, - NGHTTP2_SETTINGS_ENABLE_PUSH) == 1 && - !get_config()->http2_proxy && (downstream->get_stream_id() % 2) && - resp.fs.header(http2::HD_LINK) && - (downstream->get_non_final_response() || resp.http_status == 200) && - (req.method == HTTP_GET || req.method == HTTP_POST)) { - - if (prepare_push_promise(downstream) != 0) { - // Continue to send response even if push was failed. - } + downstream->normalize_response_headers(); + if (!get_config()->http2_proxy && !get_config()->client_proxy && + !get_config()->no_location_rewrite) { + downstream->rewrite_norm_location_response_header( + get_client_handler()->get_upstream_scheme(), get_config()->port); } + auto end_headers = std::end(downstream->get_response_headers()); + size_t nheader = downstream->get_response_headers().size(); auto nva = std::vector(); - // 4 means :status and possible server, via and x-http2-push header - // field. - nva.reserve(resp.fs.headers().size() + 4 + - httpconf.add_response_headers.size()); + // 3 means :status and possible server and via header field. + nva.reserve(nheader + 3 + get_config()->add_response_headers.size()); + std::string via_value; + auto response_status = util::utos(downstream->get_response_http_status()); + nva.push_back(http2::make_nv_ls(":status", response_status)); - auto response_status = http2::stringify_status(balloc, resp.http_status); - - nva.push_back(http2::make_nv_ls_nocopy(":status", response_status)); + http2::copy_norm_headers_to_nva(nva, downstream->get_response_headers()); if (downstream->get_non_final_response()) { - http2::copy_headers_to_nva(nva, resp.fs.headers()); - if (LOG_ENABLED(INFO)) { log_response_headers(downstream, nva); } @@ -1490,7 +1205,7 @@ downstream->get_stream_id(), nullptr, nva.data(), nva.size(), nullptr); - resp.fs.clear_headers(); + downstream->clear_response_headers(); if (rv != 0) { ULOG(FATAL, this) << "nghttp2_submit_headers() failed"; @@ -1500,66 +1215,41 @@ return 0; } - if (downstream->get_assoc_stream_id() != -1) { - rv = adjust_pushed_stream_priority(downstream); - if (rv != 0) { - return -1; - } - } - - http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers()); - - if (!get_config()->http2_proxy) { - nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name)); + if (!get_config()->http2_proxy && !get_config()->client_proxy) { + nva.push_back(http2::make_nv_lc("server", get_config()->server_name)); } else { - auto server = resp.fs.header(http2::HD_SERVER); - if (server) { - nva.push_back(http2::make_nv_ls_nocopy("server", (*server).value)); + auto server = downstream->get_norm_response_header("server"); + if (server != end_headers) { + nva.push_back(http2::make_nv_ls("server", (*server).value)); } } - auto via = resp.fs.header(http2::HD_VIA); - if (httpconf.no_via) { - if (via) { - nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value)); + auto via = downstream->get_norm_response_header("via"); + if (get_config()->no_via) { + if (via != end_headers) { + nva.push_back(http2::make_nv_ls("via", (*via).value)); } } else { - // we don't create more than 16 bytes in - // http::create_via_header_value. - size_t len = 16; - if (via) { - len += via->value.size() + 2; + if (via != end_headers) { + via_value = (*via).value; + via_value += ", "; } - - auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; - if (via) { - p = std::copy(std::begin(via->value), std::end(via->value), p); - p = util::copy_lit(p, ", "); - } - p = http::create_via_header_value(p, resp.http_major, resp.http_minor); - *p = '\0'; - - nva.push_back(http2::make_nv_ls_nocopy("via", StringRef{iov.base, p})); + via_value += http::create_via_header_value( + downstream->get_response_major(), downstream->get_response_minor()); + nva.push_back(http2::make_nv_ls("via", via_value)); } - for (auto &p : httpconf.add_response_headers) { - nva.push_back(http2::make_nv_nocopy(p.name, p.value)); - } - - if (downstream->get_stream_id() % 2 == 0) { - // This header field is basically for human on client side to - // figure out that the resource is pushed. - nva.push_back(http2::make_nv_ll("x-http2-push", "1")); + for (auto &p : get_config()->add_response_headers) { + nva.push_back(http2::make_nv(p.first, p.second)); } if (LOG_ENABLED(INFO)) { log_response_headers(downstream, nva); } - if (http2conf.upstream.debug.dump.response_header) { - http2::dump_nv(http2conf.upstream.debug.dump.response_header, nva.data(), - nva.size()); + if (get_config()->http2_upstream_dump_response_header) { + http2::dump_nv(get_config()->http2_upstream_dump_response_header, + nva.data(), nva.size()); } nghttp2_data_provider data_prd; @@ -1568,8 +1258,7 @@ nghttp2_data_provider *data_prdptr; - if (downstream->expect_response_body() || - downstream->expect_response_trailer()) { + if (downstream->expect_response_body()) { data_prdptr = &data_prd; } else { data_prdptr = nullptr; @@ -1590,8 +1279,12 @@ int Http2Upstream::on_downstream_body(Downstream *downstream, const uint8_t *data, size_t len, bool flush) { - auto body = downstream->get_response_buf(); - body->append(data, len); + auto body = downstream->get_response_body_buf(); + int rv = evbuffer_add(body, data, len); + if (rv != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } if (flush) { nghttp2_session_resume_data(session_, downstream->get_stream_id()); @@ -1599,66 +1292,14 @@ downstream->ensure_upstream_wtimer(); } - return 0; -} - -int Http2Upstream::adjust_pushed_stream_priority(Downstream *downstream) { - int rv; - - // We only change pushed stream. The pushed stream has - // assoc_stream_id which is not -1. - auto assoc_stream_id = downstream->get_assoc_stream_id(); - auto stream_id = downstream->get_stream_id(); - - auto assoc_stream = nghttp2_session_find_stream(session_, assoc_stream_id); - auto stream = nghttp2_session_find_stream(session_, stream_id); - - // By default, downstream depends on assoc_stream. If its - // relationship is changed, then we don't change priority. - if (!assoc_stream || assoc_stream != nghttp2_stream_get_parent(stream)) { - return 0; - } - - // We are going to make stream depend on dep_stream which is the - // parent stream of assoc_stream, if the content-type of stream - // indicates javascript or css. - auto dep_stream = nghttp2_stream_get_parent(assoc_stream); - if (!dep_stream) { - return 0; - } + if (evbuffer_get_length(body) >= INBUF_MAX_THRES) { + if (!flush) { + nghttp2_session_resume_data(session_, downstream->get_stream_id()); - const auto &resp = downstream->response(); - auto ct = resp.fs.header(http2::HD_CONTENT_TYPE); - if (!ct) { - return 0; - } - - if (!util::istarts_with_l(ct->value, "application/javascript") && - !util::istarts_with_l(ct->value, "text/css") && - // for polymer... - !util::istarts_with_l(ct->value, "text/html")) { - return 0; - } - - auto dep_stream_id = nghttp2_stream_get_stream_id(dep_stream); - auto weight = nghttp2_stream_get_weight(assoc_stream); - - nghttp2_priority_spec pri_spec; - nghttp2_priority_spec_init(&pri_spec, dep_stream_id, weight, 0); - - rv = nghttp2_session_change_stream_priority(session_, stream_id, &pri_spec); - if (nghttp2_is_fatal(rv)) { - ULOG(FATAL, this) << "nghttp2_session_change_stream_priority() failed: " - << nghttp2_strerror(rv); - return -1; - } - - if (rv == 0) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, this) << "Changed pushed stream priority: pushed stream(" - << stream_id << ") now depends on stream(" - << dep_stream_id << ") with weight " << weight; + downstream->ensure_upstream_wtimer(); } + + downstream->pause_read(SHRPX_NO_BUFFER); } return 0; @@ -1670,15 +1311,6 @@ if (LOG_ENABLED(INFO)) { DLOG(INFO, downstream) << "HTTP response completed"; } - - auto &resp = downstream->response(); - - if (!downstream->validate_response_recv_body_length()) { - rst_stream(downstream, NGHTTP2_PROTOCOL_ERROR); - resp.connection_close = true; - return 0; - } - nghttp2_session_resume_data(session_, downstream->get_stream_id()); downstream->ensure_upstream_wtimer(); @@ -1692,17 +1324,16 @@ int Http2Upstream::resume_read(IOCtrlReason reason, Downstream *downstream, size_t consumed) { if (get_flow_control()) { + assert(downstream->get_request_datalen() >= consumed); + if (consume(downstream->get_stream_id(), consumed) != 0) { return -1; } - auto &req = downstream->request(); - - req.consume(consumed); + downstream->dec_request_datalen(consumed); } - handler_->signal_write(); - return 0; + return send(); } int Http2Upstream::on_downstream_abort_request(Downstream *downstream, @@ -1715,19 +1346,12 @@ return -1; } - handler_->signal_write(); - return 0; + return send(); } int Http2Upstream::consume(int32_t stream_id, size_t len) { int rv; - auto faddr = handler_->get_upstream_addr(); - - if (faddr->alt_mode) { - return 0; - } - rv = nghttp2_session_consume(session_, stream_id, len); if (rv != 0) { @@ -1739,12 +1363,16 @@ return 0; } -void Http2Upstream::log_response_headers( - Downstream *downstream, const std::vector &nva) const { +void +Http2Upstream::log_response_headers(Downstream *downstream, + const std::vector &nva) const { std::stringstream ss; for (auto &nv : nva) { - ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST << ": " - << StringRef{nv.value, nv.valuelen} << "\n"; + ss << TTY_HTTP_HD; + ss.write(reinterpret_cast(nv.name), nv.namelen); + ss << TTY_RST << ": "; + ss.write(reinterpret_cast(nv.value), nv.valuelen); + ss << "\n"; } ULOG(INFO, this) << "HTTP response headers. stream_id=" << downstream->get_stream_id() << "\n" << ss.str(); @@ -1761,303 +1389,17 @@ return 0; } -void Http2Upstream::on_handler_delete() { - for (auto d = downstream_queue_.get_downstreams(); d; d = d->dlnext) { - if (d->get_dispatch_state() == Downstream::DISPATCH_ACTIVE && - d->accesslog_ready()) { - handler_->write_accesslog(d); - } - } +void Http2Upstream::reset_timeouts() { + handler_->set_upstream_timeouts(&get_config()->http2_upstream_read_timeout, + &get_config()->upstream_write_timeout); } -int Http2Upstream::on_downstream_reset(bool no_retry) { - int rv; - - for (auto downstream = downstream_queue_.get_downstreams(); downstream; - downstream = downstream->dlnext) { - if (downstream->get_dispatch_state() != Downstream::DISPATCH_ACTIVE) { - // This is error condition when we failed push_request_headers() - // in initiate_downstream(). Otherwise, we have - // Downstream::DISPATCH_ACTIVE state, or we did not set - // DownstreamConnection. - downstream->pop_downstream_connection(); - continue; - } - - if (!downstream->request_submission_ready()) { - // pushed stream is handled here - rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); - downstream->pop_downstream_connection(); - continue; - } - - downstream->pop_downstream_connection(); - - downstream->add_retry(); - - std::unique_ptr dconn; - - if (no_retry || downstream->no_more_retry()) { - goto fail; - } - - // downstream connection is clean; we can retry with new - // downstream connection. - - dconn = handler_->get_downstream_connection(downstream); - if (!dconn) { - goto fail; - } - - rv = downstream->attach_downstream_connection(std::move(dconn)); - if (rv != 0) { - goto fail; - } - - rv = downstream->push_request_headers(); - if (rv != 0) { - goto fail; - } - - continue; - - fail: - if (on_downstream_abort_request(downstream, 503) != 0) { - return -1; - } - downstream->pop_downstream_connection(); - } - - handler_->signal_write(); - - return 0; -} - -int Http2Upstream::prepare_push_promise(Downstream *downstream) { - int rv; - - const auto &req = downstream->request(); - const auto &resp = downstream->response(); - - auto base = http2::get_pure_path_component(req.path); - if (base.empty()) { - return 0; - } - - auto &balloc = downstream->get_block_allocator(); - - for (auto &kv : resp.fs.headers()) { - if (kv.token != http2::HD_LINK) { - continue; - } - for (auto &link : http2::parse_link_header(kv.value)) { - StringRef scheme, authority, path; - - rv = http2::construct_push_component(balloc, scheme, authority, path, - base, link.uri); - if (rv != 0) { - continue; - } - - if (scheme.empty()) { - scheme = req.scheme; - } - - if (authority.empty()) { - authority = req.authority; - } - - rv = submit_push_promise(scheme, authority, path, downstream); - if (rv != 0) { - return -1; - } - } - } - return 0; -} - -int Http2Upstream::submit_push_promise(const StringRef &scheme, - const StringRef &authority, - const StringRef &path, - Downstream *downstream) { - const auto &req = downstream->request(); - - std::vector nva; - // 4 for :method, :scheme, :path and :authority - nva.reserve(4 + req.fs.headers().size()); - - // juse use "GET" for now - nva.push_back(http2::make_nv_ll(":method", "GET")); - nva.push_back(http2::make_nv_ls_nocopy(":scheme", scheme)); - nva.push_back(http2::make_nv_ls_nocopy(":path", path)); - nva.push_back(http2::make_nv_ls_nocopy(":authority", authority)); - - for (auto &kv : req.fs.headers()) { - switch (kv.token) { - // TODO generate referer - case http2::HD__AUTHORITY: - case http2::HD__SCHEME: - case http2::HD__METHOD: - case http2::HD__PATH: - continue; - case http2::HD_ACCEPT_ENCODING: - case http2::HD_ACCEPT_LANGUAGE: - case http2::HD_CACHE_CONTROL: - case http2::HD_HOST: - case http2::HD_USER_AGENT: - nva.push_back(http2::make_nv_nocopy(kv.name, kv.value, kv.no_index)); - break; - } - } - - auto promised_stream_id = nghttp2_submit_push_promise( - session_, NGHTTP2_FLAG_NONE, downstream->get_stream_id(), nva.data(), - nva.size(), nullptr); - - if (promised_stream_id < 0) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, this) << "nghttp2_submit_push_promise() failed: " - << nghttp2_strerror(promised_stream_id); - } - if (nghttp2_is_fatal(promised_stream_id)) { - return -1; - } - return 0; - } - - if (LOG_ENABLED(INFO)) { - std::stringstream ss; - for (auto &nv : nva) { - ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST << ": " - << StringRef{nv.value, nv.valuelen} << "\n"; +void Http2Upstream::on_handler_delete() { + for (auto &ent : downstream_queue_.get_active_downstreams()) { + if (ent.second->accesslog_ready()) { + handler_->write_accesslog(ent.second.get()); } - ULOG(INFO, this) << "HTTP push request headers. promised_stream_id=" - << promised_stream_id << "\n" << ss.str(); - } - - return 0; -} - -bool Http2Upstream::push_enabled() const { - return !(get_config()->http2.no_server_push || - nghttp2_session_get_remote_settings( - session_, NGHTTP2_SETTINGS_ENABLE_PUSH) == 0 || - get_config()->http2_proxy); -} - -int Http2Upstream::initiate_push(Downstream *downstream, const StringRef &uri) { - int rv; - - if (uri.empty() || !push_enabled() || - (downstream->get_stream_id() % 2) == 0) { - return 0; - } - - const auto &req = downstream->request(); - - auto base = http2::get_pure_path_component(req.path); - if (base.empty()) { - return -1; - } - - auto &balloc = downstream->get_block_allocator(); - - StringRef scheme, authority, path; - - rv = http2::construct_push_component(balloc, scheme, authority, path, base, - uri); - if (rv != 0) { - return -1; - } - - if (scheme.empty()) { - scheme = req.scheme; - } - - if (authority.empty()) { - authority = req.authority; - } - - rv = submit_push_promise(scheme, authority, path, downstream); - - if (rv != 0) { - return -1; - } - - return 0; -} - -int Http2Upstream::response_riovec(struct iovec *iov, int iovcnt) const { - if (iovcnt == 0 || wb_.rleft() == 0) { - return 0; - } - - return wb_.riovec(iov, iovcnt); -} - -void Http2Upstream::response_drain(size_t n) { wb_.drain(n); } - -bool Http2Upstream::response_empty() const { return wb_.rleft() == 0; } - -DefaultMemchunks *Http2Upstream::get_response_buf() { return &wb_; } - -Downstream * -Http2Upstream::on_downstream_push_promise(Downstream *downstream, - int32_t promised_stream_id) { - // promised_stream_id is for backend HTTP/2 session, not for - // frontend. - auto promised_downstream = - make_unique(this, handler_->get_mcpool(), 0); - auto &promised_req = promised_downstream->request(); - - promised_downstream->set_downstream_stream_id(promised_stream_id); - // Set associated stream in frontend - promised_downstream->set_assoc_stream_id(downstream->get_stream_id()); - - promised_downstream->disable_upstream_rtimer(); - - promised_req.http_major = 2; - promised_req.http_minor = 0; - - auto ptr = promised_downstream.get(); - add_pending_downstream(std::move(promised_downstream)); - downstream_queue_.mark_active(ptr); - - return ptr; -} - -int Http2Upstream::on_downstream_push_promise_complete( - Downstream *downstream, Downstream *promised_downstream) { - std::vector nva; - - const auto &promised_req = promised_downstream->request(); - const auto &headers = promised_req.fs.headers(); - - nva.reserve(headers.size()); - - for (auto &kv : headers) { - nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); - } - - auto promised_stream_id = nghttp2_submit_push_promise( - session_, NGHTTP2_FLAG_NONE, downstream->get_stream_id(), nva.data(), - nva.size(), promised_downstream); - if (promised_stream_id < 0) { - return -1; - } - - promised_downstream->set_stream_id(promised_stream_id); - - return 0; -} - -void Http2Upstream::cancel_premature_downstream( - Downstream *promised_downstream) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, this) << "Remove premature promised stream " - << promised_downstream; } - downstream_queue_.remove_and_get_blocked(promised_downstream, false); } } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_http2_upstream.h nghttp2-0.6.7/src/shrpx_http2_upstream.h --- nghttp2-1.13.0/src/shrpx_http2_upstream.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http2_upstream.h 2014-11-30 14:15:07.000000000 +0000 @@ -29,16 +29,11 @@ #include -#include - #include #include "shrpx_upstream.h" #include "shrpx_downstream_queue.h" -#include "memchunk.h" -#include "buffer.h" - -using namespace nghttp2; +#include "libevent_util.h" namespace shrpx { @@ -51,18 +46,20 @@ virtual ~Http2Upstream(); virtual int on_read(); virtual int on_write(); + virtual int on_event(); virtual int on_timeout(Downstream *downstream); virtual int on_downstream_abort_request(Downstream *downstream, unsigned int status_code); + int send(); virtual ClientHandler *get_client_handler() const; - - virtual int downstream_read(DownstreamConnection *dconn); - virtual int downstream_write(DownstreamConnection *dconn); - virtual int downstream_eof(DownstreamConnection *dconn); - virtual int downstream_error(DownstreamConnection *dconn, int events); - + virtual bufferevent_data_cb get_downstream_readcb(); + virtual bufferevent_data_cb get_downstream_writecb(); + virtual bufferevent_event_cb get_downstream_eventcb(); void add_pending_downstream(std::unique_ptr downstream); void remove_downstream(Downstream *downstream); + Downstream *find_downstream(int32_t stream_id); + + nghttp2_session *get_http2_session(); int rst_stream(Downstream *downstream, uint32_t error_code); int terminate_session(uint32_t error_code); @@ -78,64 +75,33 @@ virtual int on_downstream_body_complete(Downstream *downstream); virtual void on_handler_delete(); - virtual int on_downstream_reset(bool no_retry); - virtual int send_reply(Downstream *downstream, const uint8_t *body, - size_t bodylen); - virtual int initiate_push(Downstream *downstream, const StringRef &uri); - virtual int response_riovec(struct iovec *iov, int iovcnt) const; - virtual void response_drain(size_t n); - virtual bool response_empty() const; - - virtual Downstream *on_downstream_push_promise(Downstream *downstream, - int32_t promised_stream_id); - virtual int - on_downstream_push_promise_complete(Downstream *downstream, - Downstream *promised_downstream); - virtual bool push_enabled() const; - virtual void cancel_premature_downstream(Downstream *promised_downstream); + + virtual void reset_timeouts(); bool get_flow_control() const; // Perform HTTP/2 upgrade from |upstream|. On success, this object // takes ownership of the |upstream|. This function returns 0 if it // succeeds, or -1. int upgrade_upstream(HttpsUpstream *upstream); - void start_settings_timer(); + int start_settings_timer(); void stop_settings_timer(); int consume(int32_t stream_id, size_t len); void log_response_headers(Downstream *downstream, const std::vector &nva) const; - void start_downstream(Downstream *downstream); - void initiate_downstream(Downstream *downstream); - - void submit_goaway(); - void check_shutdown(); + void maintain_downstream_concurrency(); + void initiate_downstream(std::unique_ptr downstream); - int prepare_push_promise(Downstream *downstream); - int submit_push_promise(const StringRef &scheme, const StringRef &authority, - const StringRef &path, Downstream *downstream); - - int on_request_headers(Downstream *downstream, const nghttp2_frame *frame); - - DefaultMemchunks *get_response_buf(); - - // Changes stream priority of |downstream|, which is assumed to be a - // pushed stream. - int adjust_pushed_stream_priority(Downstream *downstream); + nghttp2::util::EvbufferBuffer sendbuf; private: - DefaultMemchunks wb_; - std::unique_ptr pre_upstream_; DownstreamQueue downstream_queue_; - ev_timer settings_timer_; - ev_timer shutdown_timer_; - ev_prepare prep_; + std::unique_ptr pre_upstream_; ClientHandler *handler_; nghttp2_session *session_; + event *settings_timerev_; bool flow_control_; }; -nghttp2_session_callbacks *create_http2_upstream_callbacks(); - } // namespace shrpx #endif // SHRPX_HTTP2_UPSTREAM_H diff -Nru nghttp2-1.13.0/src/shrpx_http.cc nghttp2-0.6.7/src/shrpx_http.cc --- nghttp2-1.13.0/src/shrpx_http.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http.cc 2014-11-30 14:15:07.000000000 +0000 @@ -26,6 +26,7 @@ #include "shrpx_config.h" #include "shrpx_log.h" +#include "shrpx_worker_config.h" #include "http2.h" #include "util.h" @@ -35,95 +36,30 @@ namespace http { -StringRef create_error_html(BlockAllocator &balloc, unsigned int http_status) { - auto &httpconf = get_config()->http; - - const auto &error_pages = httpconf.error_pages; - for (const auto &page : error_pages) { - if (page.http_status == 0 || page.http_status == http_status) { - return StringRef{std::begin(page.content), std::end(page.content)}; - } - } - - auto status_string = http2::get_status_string(balloc, http_status); - const auto &server_name = httpconf.server_name; - - return concat_string_ref( - balloc, StringRef::from_lit(R"()"), - status_string, StringRef::from_lit("

"), status_string, - StringRef::from_lit("

"), server_name, - StringRef::from_lit("
")); +std::string create_error_html(unsigned int status_code) { + std::string res; + res.reserve(512); + auto status = http2::get_status_string(status_code); + res += ""; + res += status; + res += "

"; + res += status; + res += "


"; + res += get_config()->server_name; + res += " at port "; + res += util::utos(get_config()->port); + res += "
"; + res += ""; + return res; } -StringRef create_forwarded(BlockAllocator &balloc, int params, - const StringRef &node_by, const StringRef &node_for, - const StringRef &host, const StringRef &proto) { - size_t len = 0; - if ((params & FORWARDED_BY) && !node_by.empty()) { - len += str_size("by=\"") + node_by.size() + str_size("\";"); - } - if ((params & FORWARDED_FOR) && !node_for.empty()) { - len += str_size("for=\"") + node_for.size() + str_size("\";"); - } - if ((params & FORWARDED_HOST) && !host.empty()) { - len += str_size("host=\"") + host.size() + str_size("\";"); - } - if ((params & FORWARDED_PROTO) && !proto.empty()) { - len += str_size("proto=") + proto.size() + str_size(";"); - } - - auto iov = make_byte_ref(balloc, len + 1); - auto p = iov.base; - - if ((params & FORWARDED_BY) && !node_by.empty()) { - // This must be quoted-string unless it is obfuscated version - // (which starts with "_") or some special value (e.g., - // "localhost" for UNIX domain socket), since ':' is not allowed - // in token. ':' is used to separate host and port. - if (node_by[0] == '_' || node_by[0] == 'l') { - p = util::copy_lit(p, "by="); - p = std::copy(std::begin(node_by), std::end(node_by), p); - p = util::copy_lit(p, ";"); - } else { - p = util::copy_lit(p, "by=\""); - p = std::copy(std::begin(node_by), std::end(node_by), p); - p = util::copy_lit(p, "\";"); - } - } - if ((params & FORWARDED_FOR) && !node_for.empty()) { - // We only quote IPv6 literal address only, which starts with '['. - if (node_for[0] == '[') { - p = util::copy_lit(p, "for=\""); - p = std::copy(std::begin(node_for), std::end(node_for), p); - p = util::copy_lit(p, "\";"); - } else { - p = util::copy_lit(p, "for="); - p = std::copy(std::begin(node_for), std::end(node_for), p); - p = util::copy_lit(p, ";"); - } - } - if ((params & FORWARDED_HOST) && !host.empty()) { - // Just be quoted to skip checking characters. - p = util::copy_lit(p, "host=\""); - p = std::copy(std::begin(host), std::end(host), p); - p = util::copy_lit(p, "\";"); - } - if ((params & FORWARDED_PROTO) && !proto.empty()) { - // Scheme production rule only allow characters which are all in - // token. - p = util::copy_lit(p, "proto="); - p = std::copy(std::begin(proto), std::end(proto), p); - *p++ = ';'; - } - - if (iov.base == p) { - return StringRef{}; - } - - --p; - *p = '\0'; - - return StringRef{iov.base, p}; +std::string create_via_header_value(int major, int minor) { + std::string hdrs; + hdrs += static_cast(major + '0'); + hdrs += "."; + hdrs += static_cast(minor + '0'); + hdrs += " nghttpx"; + return hdrs; } std::string colorizeHeaders(const char *hdrs) { diff -Nru nghttp2-1.13.0/src/shrpx_http_downstream_connection.cc nghttp2-0.6.7/src/shrpx_http_downstream_connection.cc --- nghttp2-1.13.0/src/shrpx_http_downstream_connection.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http_downstream_connection.cc 2014-11-30 14:15:07.000000000 +0000 @@ -30,146 +30,35 @@ #include "shrpx_config.h" #include "shrpx_error.h" #include "shrpx_http.h" -#include "shrpx_log_config.h" +#include "shrpx_worker_config.h" #include "shrpx_connect_blocker.h" #include "shrpx_downstream_connection_pool.h" -#include "shrpx_worker.h" -#include "shrpx_http2_session.h" -#include "shrpx_ssl.h" #include "http2.h" #include "util.h" +#include "libevent_util.h" using namespace nghttp2; namespace shrpx { namespace { -void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - auto conn = static_cast(w->data); - auto dconn = static_cast(conn->data); - - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "Time out"; - } - - auto downstream = dconn->get_downstream(); - auto upstream = downstream->get_upstream(); - auto handler = upstream->get_client_handler(); - auto &resp = downstream->response(); - - // Do this so that dconn is not pooled - resp.connection_close = true; - - if (upstream->downstream_error(dconn, Downstream::EVENT_TIMEOUT) != 0) { - delete handler; - } -} -} // namespace - -namespace { -void connect_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - auto conn = static_cast(w->data); - auto dconn = static_cast(conn->data); - - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "Connect time out"; - } - - downstream_failure(dconn->get_addr()); - - auto downstream = dconn->get_downstream(); - auto upstream = downstream->get_upstream(); - auto handler = upstream->get_client_handler(); - auto &resp = downstream->response(); - - // Do this so that dconn is not pooled - resp.connection_close = true; - - if (upstream->downstream_error(dconn, Downstream::EVENT_TIMEOUT) != 0) { - delete handler; - } -} -} // namespace - -namespace { -void readcb(struct ev_loop *loop, ev_io *w, int revents) { - auto conn = static_cast(w->data); - auto dconn = static_cast(conn->data); - auto downstream = dconn->get_downstream(); - auto upstream = downstream->get_upstream(); - auto handler = upstream->get_client_handler(); - - if (upstream->downstream_read(dconn) != 0) { - delete handler; - } -} -} // namespace - -namespace { -void writecb(struct ev_loop *loop, ev_io *w, int revents) { - auto conn = static_cast(w->data); - auto dconn = static_cast(conn->data); - auto downstream = dconn->get_downstream(); - auto upstream = downstream->get_upstream(); - auto handler = upstream->get_client_handler(); - - if (upstream->downstream_write(dconn) != 0) { - delete handler; - } -} -} // namespace - -namespace { -void connectcb(struct ev_loop *loop, ev_io *w, int revents) { - auto conn = static_cast(w->data); - auto dconn = static_cast(conn->data); - auto downstream = dconn->get_downstream(); - auto upstream = downstream->get_upstream(); - auto handler = upstream->get_client_handler(); - if (dconn->connected() != 0) { - downstream->pop_downstream_connection(); - - auto ndconn = handler->get_downstream_connection(downstream); - if (ndconn) { - if (downstream->attach_downstream_connection(std::move(ndconn)) == 0) { - return; - } - } - - downstream->set_request_state(Downstream::CONNECT_FAIL); - - if (upstream->on_downstream_abort_request(downstream, 503) != 0) { - delete handler; - } - return; - } - writecb(loop, w, revents); -} +const size_t OUTBUF_MAX_THRES = 64 * 1024; } // namespace HttpDownstreamConnection::HttpDownstreamConnection( - const std::shared_ptr &group, ssize_t initial_addr_idx, - struct ev_loop *loop, Worker *worker) - : conn_(loop, -1, nullptr, worker->get_mcpool(), - worker->get_downstream_config()->timeout.write, - worker->get_downstream_config()->timeout.read, {}, {}, connectcb, - readcb, connect_timeoutcb, this, - get_config()->tls.dyn_rec.warmup_threshold, - get_config()->tls.dyn_rec.idle_timeout, PROTO_HTTP1), - do_read_(&HttpDownstreamConnection::noop), - do_write_(&HttpDownstreamConnection::noop), - do_signal_write_(&HttpDownstreamConnection::noop), - worker_(worker), - ssl_ctx_(worker->get_cl_ssl_ctx()), - group_(group), - addr_(nullptr), - ioctrl_(&conn_.rlimit), - response_htp_{0}, - initial_addr_idx_(initial_addr_idx) {} + DownstreamConnectionPool *dconn_pool) + : DownstreamConnection(dconn_pool), bev_(nullptr), ioctrl_(nullptr), + response_htp_{0} {} HttpDownstreamConnection::~HttpDownstreamConnection() { - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "Deleted"; + if (bev_) { + util::bev_disable_unless(bev_, EV_READ | EV_WRITE); + bufferevent_free(bev_); + } + // Downstream and DownstreamConnection may be deleted + // asynchronously. + if (downstream_) { + downstream_->release_downstream_connection(); } } @@ -177,432 +66,299 @@ if (LOG_ENABLED(INFO)) { DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream; } + auto upstream = downstream->get_upstream(); + if (!bev_) { + auto connect_blocker = client_handler_->get_http1_connect_blocker(); - auto worker_blocker = worker_->get_connect_blocker(); - if (worker_blocker->blocked()) { - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) - << "Worker wide backend connection was blocked temporarily"; + if (connect_blocker->blocked()) { + return -1; } - return SHRPX_ERR_NETWORK; - } - - auto &downstreamconf = *worker_->get_downstream_config(); - - if (conn_.fd == -1) { - auto &shared_addr = group_->shared_addr; - auto &addrs = shared_addr->addrs; - - // If session affinity is enabled, we always start with address at - // initial_addr_idx_. - size_t temp_idx = initial_addr_idx_; - - auto &next_downstream = - shared_addr->affinity == AFFINITY_NONE ? shared_addr->next : temp_idx; - auto end = next_downstream; - for (;;) { - auto &addr = addrs[next_downstream]; - - if (++next_downstream >= addrs.size()) { - next_downstream = 0; - } - - if (addr.proto != PROTO_HTTP1) { - if (end == next_downstream) { - return SHRPX_ERR_NETWORK; - } - - continue; - } - - auto &connect_blocker = addr.connect_blocker; - - if (connect_blocker->blocked()) { - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "Backend server " - << util::to_numeric_addr(&addr.addr) - << " was not available temporarily"; - } - - if (end == next_downstream) { - return SHRPX_ERR_NETWORK; - } - - continue; - } - - conn_.fd = util::create_nonblock_socket(addr.addr.su.storage.ss_family); - - if (conn_.fd == -1) { - auto error = errno; - DCLOG(WARN, this) << "socket() failed; addr=" - << util::to_numeric_addr(&addr.addr) - << ", errno=" << error; - - worker_blocker->on_failure(); - - return SHRPX_ERR_NETWORK; - } - - worker_blocker->on_success(); - - int rv; - rv = connect(conn_.fd, &addr.addr.su.sa, addr.addr.len); - if (rv != 0 && errno != EINPROGRESS) { - auto error = errno; - DCLOG(WARN, this) << "connect() failed; addr=" - << util::to_numeric_addr(&addr.addr) - << ", errno=" << error; - - downstream_failure(&addr); - - close(conn_.fd); - conn_.fd = -1; - - if (end == next_downstream) { - return SHRPX_ERR_NETWORK; - } - - // Try again with the next downstream server - continue; - } - - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "Connecting to downstream server"; - } - addr_ = &addr; + auto evbase = client_handler_->get_evbase(); - if (addr_->tls) { - assert(ssl_ctx_); + auto fd = socket(get_config()->downstream_addr.storage.ss_family, + SOCK_STREAM | SOCK_CLOEXEC, 0); - auto ssl = ssl::create_ssl(ssl_ctx_); - if (!ssl) { - return -1; - } + if (fd == -1) { + connect_blocker->on_failure(); - ssl::setup_downstream_http1_alpn(ssl); - - conn_.set_ssl(ssl); - - auto sni_name = - addr_->sni.empty() ? StringRef{addr_->host} : StringRef{addr_->sni}; - if (!util::numeric_host(sni_name.c_str())) { - SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.c_str()); - } - - auto session = ssl::reuse_tls_session(addr_->tls_session_cache); - if (session) { - SSL_set_session(conn_.tls.ssl, session); - SSL_SESSION_free(session); - } + return SHRPX_ERR_NETWORK; + } - conn_.prepare_client_handshake(); - } + bev_ = bufferevent_socket_new(evbase, fd, BEV_OPT_CLOSE_ON_FREE | + BEV_OPT_DEFER_CALLBACKS); + if (!bev_) { + connect_blocker->on_failure(); - ev_io_set(&conn_.wev, conn_.fd, EV_WRITE); - ev_io_set(&conn_.rev, conn_.fd, EV_READ); + DCLOG(INFO, this) << "bufferevent_socket_new() failed"; + close(fd); - conn_.wlimit.startw(); + return SHRPX_ERR_NETWORK; + } + int rv = bufferevent_socket_connect( + bev_, + // TODO maybe not thread-safe? + const_cast(&get_config()->downstream_addr.sa), + get_config()->downstream_addrlen); + if (rv != 0) { + connect_blocker->on_failure(); - break; + bufferevent_free(bev_); + bev_ = nullptr; + return SHRPX_ERR_NETWORK; } - // TODO we should have timeout for connection establishment - ev_timer_again(conn_.loop, &conn_.wt); - } else { - // we may set read timer cb to idle_timeoutcb. Reset again. - conn_.rt.repeat = downstreamconf.timeout.read; - ev_set_cb(&conn_.rt, timeoutcb); - ev_timer_stop(conn_.loop, &conn_.rt); + connect_blocker->on_success(); - ev_set_cb(&conn_.rev, readcb); + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, this) << "Connecting to downstream server"; + } } downstream_ = downstream; + ioctrl_.set_bev(bev_); + http_parser_init(&response_htp_, HTTP_RESPONSE); response_htp_.data = downstream_; + bufferevent_setwatermark(bev_, EV_READ, 0, SHRPX_READ_WATERMARK); + util::bev_enable_unless(bev_, EV_READ); + bufferevent_setcb(bev_, upstream->get_downstream_readcb(), + upstream->get_downstream_writecb(), + upstream->get_downstream_eventcb(), this); + + reset_timeouts(); + return 0; } int HttpDownstreamConnection::push_request_headers() { - const auto &downstream_hostport = addr_->hostport; - const auto &req = downstream_->request(); - - auto &balloc = downstream_->get_block_allocator(); - - auto connect_method = req.method == HTTP_CONNECT; + assert(downstream_->get_request_headers_normalized()); - auto &httpconf = get_config()->http; - - // For HTTP/1.0 request, there is no authority in request. In that - // case, we use backend server's host nonetheless. - auto authority = StringRef(downstream_hostport); - auto no_host_rewrite = - httpconf.no_host_rewrite || get_config()->http2_proxy || connect_method; - - if (no_host_rewrite && !req.authority.empty()) { - authority = req.authority; - } - - downstream_->set_request_downstream_host(authority); - - auto buf = downstream_->get_request_buf(); + downstream_->assemble_request_cookie(); + auto end_headers = std::end(downstream_->get_request_headers()); // Assume that method and request path do not contain \r\n. - auto meth = http2::to_method_string(req.method); - buf->append(meth); - buf->append(" "); - - if (connect_method) { - buf->append(authority); - } else if (get_config()->http2_proxy) { + std::string hdrs = downstream_->get_request_method(); + hdrs += " "; + if (downstream_->get_request_method() == "CONNECT") { + if (!downstream_->get_request_http2_authority().empty()) { + hdrs += downstream_->get_request_http2_authority(); + } else { + hdrs += downstream_->get_request_path(); + } + } else if (get_config()->http2_proxy && + !downstream_->get_request_http2_scheme().empty() && + !downstream_->get_request_http2_authority().empty() && + (downstream_->get_request_path().c_str()[0] == '/' || + downstream_->get_request_path() == "*")) { // Construct absolute-form request target because we are going to // send a request to a HTTP/1 proxy. - assert(!req.scheme.empty()); - buf->append(req.scheme); - buf->append("://"); - buf->append(authority); - buf->append(req.path); - } else if (req.method == HTTP_OPTIONS && req.path.empty()) { - // Server-wide OPTIONS - buf->append("*"); + hdrs += downstream_->get_request_http2_scheme(); + hdrs += "://"; + hdrs += downstream_->get_request_http2_authority(); + + // Server-wide OPTIONS takes following form in proxy request: + // + // OPTIONS http://example.org HTTP/1.1 + // + // Notice that no slash after authority. See + // http://tools.ietf.org/html/rfc7230#section-5.3.4 + if (downstream_->get_request_path() != "*") { + hdrs += downstream_->get_request_path(); + } } else { - buf->append(req.path); - } - buf->append(" HTTP/1.1\r\nHost: "); - buf->append(authority); - buf->append("\r\n"); + // No proxy case. get_request_path() may be absolute-form but we + // don't care. + hdrs += downstream_->get_request_path(); + } + hdrs += " HTTP/1.1\r\n"; + if (downstream_->get_norm_request_header("host") == end_headers && + !downstream_->get_request_http2_authority().empty()) { + hdrs += "Host: "; + hdrs += downstream_->get_request_http2_authority(); + hdrs += "\r\n"; + } + http2::build_http1_headers_from_norm_headers( + hdrs, downstream_->get_request_headers()); + + if (!downstream_->get_assembled_request_cookie().empty()) { + hdrs += "Cookie: "; + hdrs += downstream_->get_assembled_request_cookie(); + hdrs += "\r\n"; + } + + if (downstream_->get_request_method() != "CONNECT" && + downstream_->get_request_http2_expect_body() && + downstream_->get_norm_request_header("content-length") == end_headers) { - http2::build_http1_headers_from_headers(buf, req.fs.headers()); - - auto cookie = downstream_->assemble_request_cookie(); - if (!cookie.empty()) { - buf->append("Cookie: "); - buf->append(cookie); - buf->append("\r\n"); - } - - // set transfer-encoding only when content-length is unknown and - // request body is expected. - if (!connect_method && req.http2_expect_body && req.fs.content_length == -1) { downstream_->set_chunked_request(true); - buf->append("Transfer-Encoding: chunked\r\n"); + hdrs += "Transfer-Encoding: chunked\r\n"; } - if (req.connection_close) { - buf->append("Connection: close\r\n"); + if (downstream_->get_request_connection_close()) { + hdrs += "Connection: close\r\n"; } - - if (!connect_method && req.upgrade_request) { - auto connection = req.fs.header(http2::HD_CONNECTION); - if (connection) { - buf->append("Connection: "); - buf->append((*connection).value); - buf->append("\r\n"); - } - - auto upgrade = req.fs.header(http2::HD_UPGRADE); - if (upgrade) { - buf->append("Upgrade: "); - buf->append((*upgrade).value); - buf->append("\r\n"); + auto xff = downstream_->get_norm_request_header("x-forwarded-for"); + if (get_config()->add_x_forwarded_for) { + hdrs += "X-Forwarded-For: "; + if (xff != end_headers && !get_config()->strip_incoming_x_forwarded_for) { + hdrs += (*xff).value; + http2::sanitize_header_value(hdrs, hdrs.size() - (*xff).value.size()); + hdrs += ", "; + } + hdrs += client_handler_->get_ipaddr(); + hdrs += "\r\n"; + } else if (xff != end_headers && + !get_config()->strip_incoming_x_forwarded_for) { + hdrs += "X-Forwarded-For: "; + hdrs += (*xff).value; + http2::sanitize_header_value(hdrs, hdrs.size() - (*xff).value.size()); + hdrs += "\r\n"; + } + if (!get_config()->http2_proxy && !get_config()->client_proxy && + downstream_->get_request_method() != "CONNECT") { + hdrs += "X-Forwarded-Proto: "; + if (!downstream_->get_request_http2_scheme().empty()) { + hdrs += downstream_->get_request_http2_scheme(); + hdrs += "\r\n"; + } else if (client_handler_->get_ssl()) { + hdrs += "https\r\n"; + } else { + hdrs += "http\r\n"; } } - - auto upstream = downstream_->get_upstream(); - auto handler = upstream->get_client_handler(); - - auto &fwdconf = httpconf.forwarded; - - auto fwd = - fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED); - - if (fwdconf.params) { - auto params = fwdconf.params; - - if (get_config()->http2_proxy || connect_method) { - params &= ~FORWARDED_PROTO; - } - - auto value = http::create_forwarded( - balloc, params, handler->get_forwarded_by(), - handler->get_forwarded_for(), req.authority, req.scheme); - - if (fwd || !value.empty()) { - buf->append("Forwarded: "); - if (fwd) { - buf->append(fwd->value); - - if (!value.empty()) { - buf->append(", "); - } - } - buf->append(value); - buf->append("\r\n"); - } - } else if (fwd) { - buf->append("Forwarded: "); - buf->append(fwd->value); - buf->append("\r\n"); - } - - auto &xffconf = httpconf.xff; - - auto xff = xffconf.strip_incoming ? nullptr - : req.fs.header(http2::HD_X_FORWARDED_FOR); - - if (xffconf.add) { - buf->append("X-Forwarded-For: "); - if (xff) { - buf->append((*xff).value); - buf->append(", "); - } - buf->append(client_handler_->get_ipaddr()); - buf->append("\r\n"); - } else if (xff) { - buf->append("X-Forwarded-For: "); - buf->append((*xff).value); - buf->append("\r\n"); - } - if (!get_config()->http2_proxy && !connect_method) { - buf->append("X-Forwarded-Proto: "); - assert(!req.scheme.empty()); - buf->append(req.scheme); - buf->append("\r\n"); - } - auto via = req.fs.header(http2::HD_VIA); - if (httpconf.no_via) { - if (via) { - buf->append("Via: "); - buf->append((*via).value); - buf->append("\r\n"); + auto expect = downstream_->get_norm_request_header("expect"); + if (expect != end_headers && + !util::strifind((*expect).value.c_str(), "100-continue")) { + hdrs += "Expect: "; + hdrs += (*expect).value; + http2::sanitize_header_value(hdrs, hdrs.size() - (*expect).value.size()); + hdrs += "\r\n"; + } + auto via = downstream_->get_norm_request_header("via"); + if (get_config()->no_via) { + if (via != end_headers) { + hdrs += "Via: "; + hdrs += (*via).value; + http2::sanitize_header_value(hdrs, hdrs.size() - (*via).value.size()); + hdrs += "\r\n"; } } else { - buf->append("Via: "); - if (via) { - buf->append((*via).value); - buf->append(", "); - } - std::array viabuf; - auto end = http::create_via_header_value(viabuf.data(), req.http_major, - req.http_minor); - buf->append(viabuf.data(), end - viabuf.data()); - buf->append("\r\n"); - } - - for (auto &p : httpconf.add_request_headers) { - buf->append(p.name); - buf->append(": "); - buf->append(p.value); - buf->append("\r\n"); + hdrs += "Via: "; + if (via != end_headers) { + hdrs += (*via).value; + http2::sanitize_header_value(hdrs, hdrs.size() - (*via).value.size()); + hdrs += ", "; + } + hdrs += http::create_via_header_value(downstream_->get_request_major(), + downstream_->get_request_minor()); + hdrs += "\r\n"; } - buf->append("\r\n"); - + hdrs += "\r\n"; if (LOG_ENABLED(INFO)) { + const char *hdrp; std::string nhdrs; - for (auto chunk = buf->head; chunk; chunk = chunk->next) { - nhdrs.append(chunk->pos, chunk->last); - } - if (log_config()->errorlog_tty) { - nhdrs = http::colorizeHeaders(nhdrs.c_str()); + if (worker_config->errorlog_tty) { + nhdrs = http::colorizeHeaders(hdrs.c_str()); + hdrp = nhdrs.c_str(); + } else { + hdrp = hdrs.c_str(); } DCLOG(INFO, this) << "HTTP request headers. stream_id=" - << downstream_->get_stream_id() << "\n" << nhdrs; + << downstream_->get_stream_id() << "\n" << hdrp; + } + auto output = bufferevent_get_output(bev_); + int rv; + rv = evbuffer_add(output, hdrs.c_str(), hdrs.size()); + if (rv != 0) { + return -1; } - - signal_write(); return 0; } int HttpDownstreamConnection::push_upload_data_chunk(const uint8_t *data, size_t datalen) { - auto chunked = downstream_->get_chunked_request(); - auto output = downstream_->get_request_buf(); + int rv; + int chunked = downstream_->get_chunked_request(); + auto output = bufferevent_get_output(bev_); if (chunked) { auto chunk_size_hex = util::utox(datalen); - output->append(chunk_size_hex); - output->append("\r\n"); + chunk_size_hex += "\r\n"; + + rv = evbuffer_add(output, chunk_size_hex.c_str(), chunk_size_hex.size()); + if (rv == -1) { + DCLOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } } - output->append(data, datalen); + rv = evbuffer_add(output, data, datalen); - if (chunked) { - output->append("\r\n"); + if (rv == -1) { + DCLOG(FATAL, this) << "evbuffer_add() failed"; + return -1; } - signal_write(); + if (chunked) { + rv = evbuffer_add(output, "\r\n", 2); + if (rv == -1) { + DCLOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } + } return 0; } int HttpDownstreamConnection::end_upload_data() { - if (!downstream_->get_chunked_request()) { - return 0; - } - - const auto &req = downstream_->request(); - - auto output = downstream_->get_request_buf(); - const auto &trailers = req.fs.trailers(); - if (trailers.empty()) { - output->append("0\r\n\r\n"); - } else { - output->append("0\r\n"); - http2::build_http1_headers_from_headers(output, trailers); - output->append("\r\n"); + if (downstream_->get_chunked_request()) { + auto output = bufferevent_get_output(bev_); + if (evbuffer_add(output, "0\r\n\r\n", 5) != 0) { + DCLOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } } - - signal_write(); - return 0; } namespace { -void remove_from_pool(HttpDownstreamConnection *dconn) { - auto group = dconn->get_downstream_addr_group(); - auto &shared_addr = group->shared_addr; - - if (shared_addr->affinity == AFFINITY_NONE) { - auto &dconn_pool = - dconn->get_downstream_addr_group()->shared_addr->dconn_pool; - dconn_pool.remove_downstream_connection(dconn); - return; - } - - auto addr = dconn->get_addr(); - auto &dconn_pool = addr->dconn_pool; +void idle_readcb(bufferevent *bev, void *arg) { + auto dconn = static_cast(arg); + auto dconn_pool = dconn->get_dconn_pool(); dconn_pool->remove_downstream_connection(dconn); -} -} // namespace - -namespace { -void idle_readcb(struct ev_loop *loop, ev_io *w, int revents) { - auto conn = static_cast(w->data); - auto dconn = static_cast(conn->data); - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "Idle connection EOF"; - } - - remove_from_pool(dconn); // dconn was deleted } } // namespace namespace { -void idle_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - auto conn = static_cast(w->data); - auto dconn = static_cast(conn->data); - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "Idle connection timeout"; +// Gets called when DownstreamConnection is pooled in ClientHandler. +void idle_eventcb(bufferevent *bev, short events, void *arg) { + auto dconn = static_cast(arg); + if (events & BEV_EVENT_CONNECTED) { + // Downstream was detached before connection established? + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "Idle connection connected?"; + } + } else if (events & BEV_EVENT_EOF) { + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "Idle connection EOF"; + } + } else if (events & BEV_EVENT_TIMEOUT) { + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "Idle connection timeout"; + } + } else if (events & BEV_EVENT_ERROR) { + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "Idle connection network error"; + } } - - remove_from_pool(dconn); + auto dconn_pool = dconn->get_dconn_pool(); + dconn_pool->remove_downstream_connection(dconn); // dconn was deleted } } // namespace @@ -612,33 +368,24 @@ DCLOG(INFO, this) << "Detaching from DOWNSTREAM:" << downstream; } downstream_ = nullptr; - - ev_set_cb(&conn_.rev, idle_readcb); ioctrl_.force_resume_read(); - - auto &downstreamconf = *worker_->get_downstream_config(); - - conn_.rt.repeat = downstreamconf.timeout.idle_read; - ev_set_cb(&conn_.rt, idle_timeoutcb); - ev_timer_again(conn_.loop, &conn_.rt); - - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); + util::bev_enable_unless(bev_, EV_READ); + bufferevent_setcb(bev_, idle_readcb, nullptr, idle_eventcb, this); + // On idle state, just enable read timeout. Normally idle downstream + // connection will get EOF from the downstream server and closed. + bufferevent_set_timeouts(bev_, &get_config()->downstream_idle_read_timeout, + &get_config()->downstream_write_timeout); } +bufferevent *HttpDownstreamConnection::get_bev() { return bev_; } + void HttpDownstreamConnection::pause_read(IOCtrlReason reason) { ioctrl_.pause_read(reason); } int HttpDownstreamConnection::resume_read(IOCtrlReason reason, size_t consumed) { - auto &downstreamconf = *worker_->get_downstream_config(); - - if (downstream_->get_response_buf()->rleft() <= - downstreamconf.request_buffer_size / 2) { - ioctrl_.resume_read(reason); - } - + ioctrl_.resume_read(reason); return 0; } @@ -646,6 +393,11 @@ ioctrl_.force_resume_read(); } +bool HttpDownstreamConnection::get_output_buffer_full() { + auto output = bufferevent_get_output(bev_); + return evbuffer_get_length(output) >= OUTBUF_MAX_THRES; +} + namespace { int htp_msg_begincb(http_parser *htp) { auto downstream = static_cast(htp->data); @@ -662,34 +414,13 @@ int htp_hdrs_completecb(http_parser *htp) { auto downstream = static_cast(htp->data); auto upstream = downstream->get_upstream(); - const auto &req = downstream->request(); - auto &resp = downstream->response(); int rv; - resp.http_status = htp->status_code; - resp.http_major = htp->http_major; - resp.http_minor = htp->http_minor; - - if (resp.http_major > 1) { - // Normalize HTTP version, since we use http_major == 2 specially - // in Downstream::expect_response_trailer(). - resp.http_major = 1; - resp.http_minor = 1; - } - - if (resp.fs.parse_content_length() != 0) { - downstream->set_response_state(Downstream::MSG_BAD_HEADER); - return -1; - } - - // Check upgrade before processing non-final response, since if - // upgrade succeeded, 101 response is treated as final in nghttpx. - downstream->check_upgrade_fulfilled(); + downstream->set_response_http_status(htp->status_code); + downstream->set_response_major(htp->http_major); + downstream->set_response_minor(htp->http_minor); if (downstream->get_non_final_response()) { - // Reset content-length because we reuse same Downstream for the - // next response. - resp.fs.content_length = -1; // For non-final response code, we just call // on_downstream_header_complete() without changing response // state. @@ -699,30 +430,23 @@ return -1; } - // Ignore response body for non-final response. - return 1; + return 0; } - resp.connection_close = !http_should_keep_alive(htp); + downstream->set_response_connection_close(!http_should_keep_alive(htp)); downstream->set_response_state(Downstream::HEADER_COMPLETE); downstream->inspect_http1_response(); + downstream->check_upgrade_fulfilled(); if (downstream->get_upgraded()) { - // content-length must be ignored for upgraded connection. - resp.fs.content_length = -1; - resp.connection_close = true; - // transfer-encoding not applied to upgraded connection - downstream->set_chunked_response(false); - } else if (!downstream->expect_response_body()) { - downstream->set_chunked_response(false); + downstream->set_response_connection_close(true); } - if (upstream->on_downstream_header_complete(downstream) != 0) { return -1; } if (downstream->get_upgraded()) { // Upgrade complete, read until EOF in both ends - if (upstream->resume_read(SHRPX_NO_BUFFER, downstream, 0) != 0) { + if (upstream->resume_read(SHRPX_MSG_BLOCK, downstream, 0) != 0) { return -1; } downstream->set_request_state(Downstream::HEADER_COMPLETE); @@ -732,109 +456,57 @@ } } + unsigned int status = downstream->get_response_http_status(); // Ignore the response body. HEAD response may contain // Content-Length or Transfer-Encoding: chunked. Some server send // 304 status code with nonzero Content-Length, but without response // body. See - // https://tools.ietf.org/html/rfc7230#section-3.3 + // http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-20#section-3.3 // TODO It seems that the cases other than HEAD are handled by // http-parser. Need test. - return !http2::expect_response_body(req.method, resp.http_status); + return downstream->get_request_method() == "HEAD" || + (100 <= status && status <= 199) || status == 204 || + status == 304 + ? 1 + : 0; } } // namespace namespace { -int ensure_header_field_buffer(const Downstream *downstream, - const HttpConfig &httpconf, size_t len) { - auto &resp = downstream->response(); - - if (resp.fs.buffer_size() + len > httpconf.response_header_field_buffer) { - if (LOG_ENABLED(INFO)) { - DLOG(INFO, downstream) << "Too large header header field size=" - << resp.fs.buffer_size() + len; - } - return -1; +int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) { + auto downstream = static_cast(htp->data); + if (downstream->get_response_header_key_prev()) { + downstream->append_last_response_header_key(data, len); + } else { + downstream->add_response_header(std::string(data, len), ""); } - - return 0; -} -} // namespace - -namespace { -int ensure_max_header_fields(const Downstream *downstream, - const HttpConfig &httpconf) { - auto &resp = downstream->response(); - - if (resp.fs.num_fields() >= httpconf.max_response_header_fields) { + if (downstream->get_response_headers_sum() > Downstream::MAX_HEADERS_SUM) { if (LOG_ENABLED(INFO)) { - DLOG(INFO, downstream) - << "Too many header field num=" << resp.fs.num_fields() + 1; + DLOG(INFO, downstream) << "Too large header block size=" + << downstream->get_response_headers_sum(); } return -1; } - return 0; } } // namespace namespace { -int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) { +int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) { auto downstream = static_cast(htp->data); - auto &resp = downstream->response(); - auto &httpconf = get_config()->http; - auto &balloc = downstream->get_block_allocator(); - - if (ensure_header_field_buffer(downstream, httpconf, len) != 0) { - return -1; - } - - if (downstream->get_response_state() == Downstream::INITIAL) { - if (resp.fs.header_key_prev()) { - resp.fs.append_last_header_key(data, len); - } else { - if (ensure_max_header_fields(downstream, httpconf) != 0) { - return -1; - } - auto name = http2::copy_lower(balloc, StringRef{data, len}); - auto token = http2::lookup_token(name); - resp.fs.add_header_token(name, StringRef{}, false, token); - } + if (downstream->get_response_header_key_prev()) { + downstream->set_last_response_header_value(std::string(data, len)); } else { - // trailer part - if (resp.fs.trailer_key_prev()) { - resp.fs.append_last_trailer_key(data, len); - } else { - if (ensure_max_header_fields(downstream, httpconf) != 0) { - // Could not ignore this trailer field easily, since we may - // get its value in htp_hdr_valcb, and it will be added to - // wrong place or crash if trailer fields are currently empty. - return -1; - } - auto name = http2::copy_lower(balloc, StringRef{data, len}); - auto token = http2::lookup_token(name); - resp.fs.add_trailer_token(name, StringRef{}, false, token); - } + downstream->append_last_response_header_value(data, len); } - return 0; -} -} // namespace - -namespace { -int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) { - auto downstream = static_cast(htp->data); - auto &resp = downstream->response(); - auto &httpconf = get_config()->http; - - if (ensure_header_field_buffer(downstream, httpconf, len) != 0) { + if (downstream->get_response_headers_sum() > Downstream::MAX_HEADERS_SUM) { + if (LOG_ENABLED(INFO)) { + DLOG(INFO, downstream) << "Too large header block size=" + << downstream->get_response_headers_sum(); + } return -1; } - - if (downstream->get_response_state() == Downstream::INITIAL) { - resp.fs.append_last_header_value(data, len); - } else { - resp.fs.append_last_trailer_value(data, len); - } return 0; } } // namespace @@ -842,9 +514,8 @@ namespace { int htp_bodycb(http_parser *htp, const char *data, size_t len) { auto downstream = static_cast(htp->data); - auto &resp = downstream->response(); - resp.recv_body_length += len; + downstream->add_response_bodylen(len); return downstream->get_upstream()->on_downstream_body( downstream, reinterpret_cast(data), len, true); @@ -855,15 +526,6 @@ int htp_msg_completecb(http_parser *htp) { auto downstream = static_cast(htp->data); - // http-parser does not treat "200 connection established" response - // against CONNECT request, and in that case, this function is not - // called. But if HTTP Upgrade is made (e.g., WebSocket), this - // function is called, and http_parser_execute() returns just after - // that. - if (downstream->get_upgraded()) { - return 0; - } - if (downstream->get_non_final_response()) { downstream->reset_response(); @@ -892,313 +554,88 @@ }; } // namespace -int HttpDownstreamConnection::read_clear() { - std::array buf; - int rv; - - for (;;) { - auto nread = conn_.read_clear(buf.data(), buf.size()); - if (nread == 0) { - return 0; - } - - if (nread < 0) { - return nread; - } - - rv = process_input(buf.data(), nread); - if (rv != 0) { - return rv; - } - - if (!ev_is_active(&conn_.rev)) { - return 0; - } - } -} - -int HttpDownstreamConnection::write_clear() { - auto upstream = downstream_->get_upstream(); - auto input = downstream_->get_request_buf(); - - std::array iov; - - while (input->rleft() > 0) { - auto iovcnt = input->riovec(iov.data(), iov.size()); - - auto nwrite = conn_.writev_clear(iov.data(), iovcnt); - - if (nwrite == 0) { - return 0; - } - - if (nwrite < 0) { - return nwrite; - } - - input->drain(nwrite); - } - - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - if (input->rleft() == 0) { - auto &req = downstream_->request(); - - upstream->resume_read(SHRPX_NO_BUFFER, downstream_, - req.unconsumed_body_length); - } - - return 0; -} - -int HttpDownstreamConnection::tls_handshake() { - ERR_clear_error(); - - ev_timer_again(conn_.loop, &conn_.rt); - - auto rv = conn_.tls_handshake(); - if (rv == SHRPX_ERR_INPROGRESS) { - return 0; - } - - if (rv < 0) { - downstream_failure(addr_); - - return rv; - } - - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "SSL/TLS handshake completed"; - } - - if (!get_config()->tls.insecure && - ssl::check_cert(conn_.tls.ssl, addr_) != 0) { - downstream_failure(addr_); - - return -1; - } - - if (!SSL_session_reused(conn_.tls.ssl)) { - auto session = SSL_get0_session(conn_.tls.ssl); - if (session) { - ssl::try_cache_tls_session(addr_->tls_session_cache, addr_->addr, session, - ev_now(conn_.loop)); - } - } - - auto &connect_blocker = addr_->connect_blocker; - - connect_blocker->on_success(); - - ev_set_cb(&conn_.rt, timeoutcb); - ev_set_cb(&conn_.wt, timeoutcb); - - do_read_ = &HttpDownstreamConnection::read_tls; - do_write_ = &HttpDownstreamConnection::write_tls; +int HttpDownstreamConnection::on_read() { + reset_timeouts(); - // TODO Check negotiated ALPN - - return on_write(); -} - -int HttpDownstreamConnection::read_tls() { - ERR_clear_error(); - - std::array buf; - int rv; - - for (;;) { - auto nread = conn_.read_tls(buf.data(), buf.size()); - if (nread == 0) { - return 0; - } - - if (nread < 0) { - return nread; - } - - rv = process_input(buf.data(), nread); - if (rv != 0) { - return rv; - } - - if (!ev_is_active(&conn_.rev)) { - return 0; - } - } -} - -int HttpDownstreamConnection::write_tls() { - ERR_clear_error(); - - auto upstream = downstream_->get_upstream(); - auto input = downstream_->get_request_buf(); - - struct iovec iov; - - while (input->rleft() > 0) { - auto iovcnt = input->riovec(&iov, 1); - assert(iovcnt == 1); - auto nwrite = conn_.write_tls(iov.iov_base, iov.iov_len); - - if (nwrite == 0) { - return 0; - } - - if (nwrite < 0) { - return nwrite; - } - - input->drain(nwrite); - } - - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - if (input->rleft() == 0) { - auto &req = downstream_->request(); - - upstream->resume_read(SHRPX_NO_BUFFER, downstream_, - req.unconsumed_body_length); - } - - return 0; -} - -int HttpDownstreamConnection::process_input(const uint8_t *data, - size_t datalen) { - int rv; + auto input = bufferevent_get_input(bev_); if (downstream_->get_upgraded()) { // For upgraded connection, just pass data to the upstream. - rv = downstream_->get_upstream()->on_downstream_body(downstream_, data, - datalen, true); - if (rv != 0) { - return rv; - } - - if (downstream_->response_buf_full()) { - downstream_->pause_read(SHRPX_NO_BUFFER); - return 0; - } - - return 0; - } + for (;;) { + auto inputlen = evbuffer_get_contiguous_space(input); - auto nproc = - http_parser_execute(&response_htp_, &htp_hooks, - reinterpret_cast(data), datalen); - - auto htperr = HTTP_PARSER_ERRNO(&response_htp_); - - if (htperr != HPE_OK) { - // Handling early return (in other words, response was hijacked by - // mruby scripting). - if (downstream_->get_response_state() == Downstream::MSG_COMPLETE) { - return SHRPX_ERR_DCONN_CANCELED; - } + if (inputlen == 0) { + assert(evbuffer_get_length(input) == 0); - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "HTTP parser failure: " - << "(" << http_errno_name(htperr) << ") " - << http_errno_description(htperr); - } + return 0; + } - return -1; - } + auto mem = evbuffer_pullup(input, inputlen); - if (downstream_->get_upgraded()) { - if (nproc < datalen) { - // Data from data + nproc are for upgraded protocol. + int rv; rv = downstream_->get_upstream()->on_downstream_body( - downstream_, data + nproc, datalen - nproc, true); + downstream_, reinterpret_cast(mem), inputlen, true); if (rv != 0) { return rv; } - - if (downstream_->response_buf_full()) { - downstream_->pause_read(SHRPX_NO_BUFFER); - return 0; + if (evbuffer_drain(input, inputlen) != 0) { + DCLOG(FATAL, this) << "evbuffer_drain() failed"; + return -1; } } - return 0; - } - - if (downstream_->response_buf_full()) { - downstream_->pause_read(SHRPX_NO_BUFFER); - return 0; } - return 0; -} - -int HttpDownstreamConnection::connected() { - auto &connect_blocker = addr_->connect_blocker; - - if (!util::check_socket_connected(conn_.fd)) { - conn_.wlimit.stopw(); + for (;;) { + auto inputlen = evbuffer_get_contiguous_space(input); - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "Backend connect failed; addr=" - << util::to_numeric_addr(&addr_->addr); + if (inputlen == 0) { + assert(evbuffer_get_length(input) == 0); + return 0; } - downstream_failure(addr_); + auto mem = evbuffer_pullup(input, inputlen); - return -1; - } - - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, this) << "Connected to downstream host"; - } - - conn_.rlimit.startw(); + auto nread = + http_parser_execute(&response_htp_, &htp_hooks, + reinterpret_cast(mem), inputlen); - ev_set_cb(&conn_.wev, writecb); + if (evbuffer_drain(input, nread) != 0) { + DCLOG(FATAL, this) << "evbuffer_drain() failed"; + return -1; + } - do_signal_write_ = &HttpDownstreamConnection::actual_signal_write; + auto htperr = HTTP_PARSER_ERRNO(&response_htp_); - if (conn_.tls.ssl) { - do_read_ = &HttpDownstreamConnection::tls_handshake; - do_write_ = &HttpDownstreamConnection::tls_handshake; + if (htperr != HPE_OK) { + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, this) << "HTTP parser failure: " + << "(" << http_errno_name(htperr) << ") " + << http_errno_description(htperr); + } - return 0; + return SHRPX_ERR_HTTP_PARSE; + } } - - connect_blocker->on_success(); - - ev_set_cb(&conn_.rt, timeoutcb); - ev_set_cb(&conn_.wt, timeoutcb); - - do_read_ = &HttpDownstreamConnection::read_clear; - do_write_ = &HttpDownstreamConnection::write_clear; - - return 0; } -int HttpDownstreamConnection::on_read() { return do_read_(*this); } - -int HttpDownstreamConnection::on_write() { return do_write_(*this); } +int HttpDownstreamConnection::on_write() { + reset_timeouts(); -void HttpDownstreamConnection::on_upstream_change(Upstream *upstream) {} - -void HttpDownstreamConnection::signal_write() { do_signal_write_(*this); } - -int HttpDownstreamConnection::actual_signal_write() { - ev_feed_event(conn_.loop, &conn_.wev, EV_WRITE); + auto upstream = downstream_->get_upstream(); + upstream->resume_read(SHRPX_NO_BUFFER, downstream_, + downstream_->get_request_datalen()); return 0; } -int HttpDownstreamConnection::noop() { return 0; } - -DownstreamAddrGroup * -HttpDownstreamConnection::get_downstream_addr_group() const { - return group_.get(); +void HttpDownstreamConnection::on_upstream_change(Upstream *upstream) { + bufferevent_setcb(bev_, upstream->get_downstream_readcb(), + upstream->get_downstream_writecb(), + upstream->get_downstream_eventcb(), this); } -DownstreamAddr *HttpDownstreamConnection::get_addr() const { return addr_; } - -bool HttpDownstreamConnection::poolable() const { return !group_->retired; } +void HttpDownstreamConnection::reset_timeouts() { + bufferevent_set_timeouts(bev_, &get_config()->downstream_read_timeout, + &get_config()->downstream_write_timeout); +} } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_http_downstream_connection.h nghttp2-0.6.7/src/shrpx_http_downstream_connection.h --- nghttp2-1.13.0/src/shrpx_http_downstream_connection.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http_downstream_connection.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,24 +27,21 @@ #include "shrpx.h" +#include +#include + #include "http-parser/http_parser.h" #include "shrpx_downstream_connection.h" #include "shrpx_io_control.h" -#include "shrpx_connection.h" namespace shrpx { class DownstreamConnectionPool; -class Worker; -struct DownstreamAddrGroup; -struct DownstreamAddr; class HttpDownstreamConnection : public DownstreamConnection { public: - HttpDownstreamConnection(const std::shared_ptr &group, - ssize_t initial_addr_idx, struct ev_loop *loop, - Worker *worker); + HttpDownstreamConnection(DownstreamConnectionPool *dconn_pool); virtual ~HttpDownstreamConnection(); virtual int attach_downstream(Downstream *downstream); virtual void detach_downstream(Downstream *downstream); @@ -57,43 +54,22 @@ virtual int resume_read(IOCtrlReason reason, size_t consumed); virtual void force_resume_read(); + virtual bool get_output_buffer_full(); + virtual int on_read(); virtual int on_write(); virtual void on_upstream_change(Upstream *upstream); + virtual int on_priority_change(int32_t pri) { return 0; } - virtual bool poolable() const; - - virtual DownstreamAddrGroup *get_downstream_addr_group() const; - virtual DownstreamAddr *get_addr() const; - - int read_clear(); - int write_clear(); - int read_tls(); - int write_tls(); - - int process_input(const uint8_t *data, size_t datalen); - int tls_handshake(); - - int connected(); - void signal_write(); - int actual_signal_write(); + bufferevent *get_bev(); - int noop(); + void reset_timeouts(); private: - Connection conn_; - std::function do_read_, do_write_, - do_signal_write_; - Worker *worker_; - // nullptr if TLS is not used. - SSL_CTX *ssl_ctx_; - const std::shared_ptr &group_; - // Address of remote endpoint - DownstreamAddr *addr_; + bufferevent *bev_; IOControl ioctrl_; http_parser response_htp_; - ssize_t initial_addr_idx_; }; } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_http.h nghttp2-0.6.7/src/shrpx_http.h --- nghttp2-1.13.0/src/shrpx_http.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http.h 2014-11-30 14:15:07.000000000 +0000 @@ -31,31 +31,13 @@ #include -#include "util.h" -#include "allocator.h" - namespace shrpx { namespace http { -StringRef create_error_html(BlockAllocator &balloc, unsigned int status_code); +std::string create_error_html(unsigned int status_code); -template -OutputIt create_via_header_value(OutputIt dst, int major, int minor) { - *dst++ = static_cast(major + '0'); - if (major < 2) { - *dst++ = '.'; - *dst++ = static_cast(minor + '0'); - } - return util::copy_lit(dst, " nghttpx"); -} - -// Returns generated RFC 7239 Forwarded header field value. The -// |params| is bitwise-OR of zero or more of shrpx_forwarded_param -// defined in shrpx_config.h. -StringRef create_forwarded(BlockAllocator &balloc, int params, - const StringRef &node_by, const StringRef &node_for, - const StringRef &host, const StringRef &proto); +std::string create_via_header_value(int major, int minor); // Adds ANSI color codes to HTTP headers |hdrs|. std::string colorizeHeaders(const char *hdrs); diff -Nru nghttp2-1.13.0/src/shrpx_https_upstream.cc nghttp2-0.6.7/src/shrpx_https_upstream.cc --- nghttp2-1.13.0/src/shrpx_https_upstream.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_https_upstream.cc 2014-11-30 14:15:07.000000000 +0000 @@ -31,27 +31,25 @@ #include "shrpx_client_handler.h" #include "shrpx_downstream.h" #include "shrpx_downstream_connection.h" +#include "shrpx_http2_downstream_connection.h" #include "shrpx_http.h" #include "shrpx_config.h" #include "shrpx_error.h" -#include "shrpx_log_config.h" -#include "shrpx_worker.h" -#include "shrpx_http2_session.h" -#ifdef HAVE_MRUBY -#include "shrpx_mruby.h" -#endif // HAVE_MRUBY +#include "shrpx_worker_config.h" #include "http2.h" #include "util.h" -#include "template.h" using namespace nghttp2; namespace shrpx { +namespace { +const size_t OUTBUF_MAX_THRES = 16 * 1024; +} // namespace + HttpsUpstream::HttpsUpstream(ClientHandler *handler) - : handler_(handler), - current_header_length_(0), - ioctrl_(handler->get_rlimit()) { + : handler_(handler), current_header_length_(0), + ioctrl_(handler->get_bev()) { http_parser_init(&htp_, HTTP_REQUEST); htp_.data = this; } @@ -69,15 +67,8 @@ ULOG(INFO, upstream) << "HTTP request started"; } upstream->reset_current_header_length(); - - auto handler = upstream->get_client_handler(); - - auto downstream = make_unique(upstream, handler->get_mcpool(), 0); - - upstream->attach_downstream(std::move(downstream)); - - handler->stop_read_timer(); - + // TODO specify 0 as priority for now + upstream->attach_downstream(util::make_unique(upstream, 0, 0)); return 0; } } // namespace @@ -86,33 +77,7 @@ int htp_uricb(http_parser *htp, const char *data, size_t len) { auto upstream = static_cast(htp->data); auto downstream = upstream->get_downstream(); - auto &req = downstream->request(); - - auto &balloc = downstream->get_block_allocator(); - - // We happen to have the same value for method token. - req.method = htp->method; - - if (req.fs.buffer_size() + len > - get_config()->http.request_header_field_buffer) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, upstream) << "Too large URI size=" - << req.fs.buffer_size() + len; - } - assert(downstream->get_request_state() == Downstream::INITIAL); - downstream->set_request_state(Downstream::HTTP1_REQUEST_HEADER_TOO_LARGE); - return -1; - } - - req.fs.add_extra_buffer_size(len); - - if (req.method == HTTP_CONNECT) { - req.authority = - concat_string_ref(balloc, req.authority, StringRef{data, len}); - } else { - req.path = concat_string_ref(balloc, req.path, StringRef{data, len}); - } - + downstream->append_request_path(data, len); return 0; } } // namespace @@ -121,54 +86,18 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) { auto upstream = static_cast(htp->data); auto downstream = upstream->get_downstream(); - auto &req = downstream->request(); - auto &httpconf = get_config()->http; - auto &balloc = downstream->get_block_allocator(); - - if (req.fs.buffer_size() + len > httpconf.request_header_field_buffer) { + if (downstream->get_request_header_key_prev()) { + downstream->append_last_request_header_key(data, len); + } else { + downstream->add_request_header(std::string(data, len), ""); + } + if (downstream->get_request_headers_sum() > Downstream::MAX_HEADERS_SUM) { if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "Too large header block size=" - << req.fs.buffer_size() + len; - } - if (downstream->get_request_state() == Downstream::INITIAL) { - downstream->set_request_state(Downstream::HTTP1_REQUEST_HEADER_TOO_LARGE); + << downstream->get_request_headers_sum(); } return -1; } - if (downstream->get_request_state() == Downstream::INITIAL) { - if (req.fs.header_key_prev()) { - req.fs.append_last_header_key(data, len); - } else { - if (req.fs.num_fields() >= httpconf.max_request_header_fields) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, upstream) - << "Too many header field num=" << req.fs.num_fields() + 1; - } - downstream->set_request_state( - Downstream::HTTP1_REQUEST_HEADER_TOO_LARGE); - return -1; - } - auto name = http2::copy_lower(balloc, StringRef{data, len}); - auto token = http2::lookup_token(name); - req.fs.add_header_token(name, StringRef{}, false, token); - } - } else { - // trailer part - if (req.fs.trailer_key_prev()) { - req.fs.append_last_trailer_key(data, len); - } else { - if (req.fs.num_fields() >= httpconf.max_request_header_fields) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, upstream) - << "Too many header field num=" << req.fs.num_fields() + 1; - } - return -1; - } - auto name = http2::copy_lower(balloc, StringRef{data, len}); - auto token = http2::lookup_token(name); - req.fs.add_trailer_token(name, StringRef{}, false, token); - } - } return 0; } } // namespace @@ -177,229 +106,75 @@ int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) { auto upstream = static_cast(htp->data); auto downstream = upstream->get_downstream(); - auto &req = downstream->request(); - - if (req.fs.buffer_size() + len > - get_config()->http.request_header_field_buffer) { + if (downstream->get_request_header_key_prev()) { + downstream->set_last_request_header_value(std::string(data, len)); + } else { + downstream->append_last_request_header_value(data, len); + } + if (downstream->get_request_headers_sum() > Downstream::MAX_HEADERS_SUM) { if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "Too large header block size=" - << req.fs.buffer_size() + len; - } - if (downstream->get_request_state() == Downstream::INITIAL) { - downstream->set_request_state(Downstream::HTTP1_REQUEST_HEADER_TOO_LARGE); + << downstream->get_request_headers_sum(); } return -1; } - if (downstream->get_request_state() == Downstream::INITIAL) { - req.fs.append_last_header_value(data, len); - } else { - req.fs.append_last_trailer_value(data, len); - } return 0; } } // namespace namespace { -void rewrite_request_host_path_from_uri(BlockAllocator &balloc, Request &req, - const StringRef &uri, - http_parser_url &u) { - assert(u.field_set & (1 << UF_HOST)); - - // As per https://tools.ietf.org/html/rfc7230#section-5.4, we - // rewrite host header field with authority component. - auto authority = util::get_uri_field(uri.c_str(), u, UF_HOST); - // TODO properly check IPv6 numeric address - auto ipv6 = std::find(std::begin(authority), std::end(authority), ':') != - std::end(authority); - auto authoritylen = authority.size(); - if (ipv6) { - authoritylen += 2; - } - if (u.field_set & (1 << UF_PORT)) { - authoritylen += 1 + str_size("65535"); - } - if (authoritylen > authority.size()) { - auto iovec = make_byte_ref(balloc, authoritylen + 1); - auto p = iovec.base; - if (ipv6) { - *p++ = '['; - } - p = std::copy(std::begin(authority), std::end(authority), p); - if (ipv6) { - *p++ = ']'; - } - - if (u.field_set & (1 << UF_PORT)) { - *p++ = ':'; - p = util::utos(p, u.port); - } - *p = '\0'; - - req.authority = StringRef{iovec.base, p}; - } else { - req.authority = authority; - } - - req.scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA); - - StringRef path; - if (u.field_set & (1 << UF_PATH)) { - path = util::get_uri_field(uri.c_str(), u, UF_PATH); - } else if (req.method == HTTP_OPTIONS) { - // Server-wide OPTIONS takes following form in proxy request: - // - // OPTIONS http://example.org HTTP/1.1 - // - // Notice that no slash after authority. See - // http://tools.ietf.org/html/rfc7230#section-5.3.4 - req.path = StringRef::from_lit(""); - // we ignore query component here - return; - } else { - path = StringRef::from_lit("/"); - } - - if (u.field_set & (1 << UF_QUERY)) { - auto &fdata = u.field_data[UF_QUERY]; - - if (u.field_set & (1 << UF_PATH)) { - auto q = util::get_uri_field(uri.c_str(), u, UF_QUERY); - path = StringRef{std::begin(path), std::end(q)}; - } else { - path = concat_string_ref(balloc, path, StringRef::from_lit("?"), - StringRef{&uri[fdata.off], fdata.len}); - } - } - - if (get_config()->http2_proxy) { - req.path = path; - } else { - req.path = http2::rewrite_clean_path(balloc, path); - } -} -} // namespace - -namespace { int htp_hdrs_completecb(http_parser *htp) { int rv; auto upstream = static_cast(htp->data); if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "HTTP request headers completed"; } - - auto handler = upstream->get_client_handler(); - auto downstream = upstream->get_downstream(); - auto &req = downstream->request(); - - req.http_major = htp->http_major; - req.http_minor = htp->http_minor; - req.connection_close = !http_should_keep_alive(htp); + downstream->set_request_method( + http_method_str((enum http_method)htp->method)); + downstream->set_request_major(htp->http_major); + downstream->set_request_minor(htp->http_minor); + downstream->set_request_start_time(std::chrono::high_resolution_clock::now()); - auto method = req.method; + downstream->set_request_connection_close(!http_should_keep_alive(htp)); if (LOG_ENABLED(INFO)) { std::stringstream ss; - ss << http2::to_method_string(method) << " " - << (method == HTTP_CONNECT ? req.authority : req.path) << " " - << "HTTP/" << req.http_major << "." << req.http_minor << "\n"; - - for (const auto &kv : req.fs.headers()) { - ss << TTY_HTTP_HD << kv.name << TTY_RST << ": " << kv.value << "\n"; + ss << downstream->get_request_method() << " " + << downstream->get_request_path() << " " + << "HTTP/" << downstream->get_request_major() << "." + << downstream->get_request_minor() << "\n"; + const auto &headers = downstream->get_request_headers(); + for (size_t i = 0; i < headers.size(); ++i) { + ss << TTY_HTTP_HD << headers[i].name << TTY_RST << ": " + << headers[i].value << "\n"; } - ULOG(INFO, upstream) << "HTTP request headers\n" << ss.str(); } - // set content-length if no transfer-encoding is given. If - // transfer-encoding is given, leave req.fs.content_length to -1. - if (!req.fs.header(http2::HD_TRANSFER_ENCODING)) { - req.fs.content_length = htp->content_length; - } - - auto host = req.fs.header(http2::HD_HOST); - - if (req.http_major == 1 && req.http_minor == 1 && !host) { - return -1; - } - - if (host) { - const auto &value = host->value; - // Not allow at least '"' or '\' in host. They are illegal in - // authority component, also they cause headaches when we put them - // in quoted-string. - if (std::find_if(std::begin(value), std::end(value), [](char c) { - return c == '"' || c == '\\'; - }) != std::end(value)) { - return -1; - } - } + downstream->normalize_request_headers(); downstream->inspect_http1_request(); - auto &balloc = downstream->get_block_allocator(); - - if (method != HTTP_CONNECT) { - http_parser_url u{}; - rv = http_parser_parse_url(req.path.c_str(), req.path.size(), 0, &u); - if (rv != 0) { + if (get_config()->client_proxy && + downstream->get_request_method() != "CONNECT") { + // Make sure that request path is an absolute URI. + http_parser_url u; + auto url = downstream->get_request_path().c_str(); + memset(&u, 0, sizeof(u)); + rv = http_parser_parse_url(url, downstream->get_request_path().size(), 0, + &u); + if (rv != 0 || !(u.field_set & (1 << UF_SCHEMA))) { // Expect to respond with 400 bad request return -1; } - // checking UF_HOST could be redundant, but just in case ... - if (!(u.field_set & (1 << UF_SCHEMA)) || !(u.field_set & (1 << UF_HOST))) { - if (get_config()->http2_proxy) { - // Request URI should be absolute-form for client proxy mode - return -1; - } - - req.no_authority = true; - - if (method == HTTP_OPTIONS && req.path == StringRef::from_lit("*")) { - req.path = StringRef{}; - } else { - req.path = http2::rewrite_clean_path(balloc, req.path); - } - - if (host) { - req.authority = host->value; - } - - if (handler->get_ssl()) { - req.scheme = StringRef::from_lit("https"); - } else { - req.scheme = StringRef::from_lit("http"); - } - } else { - rewrite_request_host_path_from_uri(balloc, req, req.path, u); - } } - downstream->set_request_state(Downstream::HEADER_COMPLETE); - -#ifdef HAVE_MRUBY - auto worker = handler->get_worker(); - auto mruby_ctx = worker->get_mruby_context(); - - auto &resp = downstream->response(); - - if (mruby_ctx->run_on_request_proc(downstream) != 0) { - resp.http_status = 500; - return -1; - } -#endif // HAVE_MRUBY - - // mruby hook may change method value + rv = downstream->attach_downstream_connection( + upstream->get_client_handler()->get_downstream_connection()); - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - return 0; - } - - auto dconn = handler->get_downstream_connection(downstream); - - if (!dconn || - (rv = downstream->attach_downstream_connection(std::move(dconn))) != 0) { + if (rv != 0) { downstream->set_request_state(Downstream::CONNECT_FAIL); return -1; @@ -411,22 +186,7 @@ return -1; } - auto faddr = handler->get_upstream_addr(); - - if (faddr->alt_mode) { - // Normally, we forward expect: 100-continue to backend server, - // and let them decide whether responds with 100 Continue or not. - // For alternative mode, we have no backend, so just send 100 - // Continue here to make the client happy. - auto expect = req.fs.header(http2::HD_EXPECT); - if (expect && - util::strieq(expect->value, StringRef::from_lit("100-continue"))) { - auto output = downstream->get_response_buf(); - constexpr auto res = StringRef::from_lit("HTTP/1.1 100 Continue\r\n\r\n"); - output->append(res); - handler->signal_write(); - } - } + downstream->set_request_state(Downstream::HEADER_COMPLETE); return 0; } @@ -440,12 +200,6 @@ rv = downstream->push_upload_data_chunk( reinterpret_cast(data), len); if (rv != 0) { - // Ignore error if response has been completed. We will end up in - // htp_msg_completecb, and request will end gracefully. - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - return 0; - } - return -1; } return 0; @@ -459,33 +213,12 @@ if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "HTTP request completed"; } - auto handler = upstream->get_client_handler(); auto downstream = upstream->get_downstream(); downstream->set_request_state(Downstream::MSG_COMPLETE); rv = downstream->end_upload_data(); if (rv != 0) { - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - // Here both response and request were completed. One of the - // reason why end_upload_data() failed is when we sent response - // in request phase hook. We only delete and proceed to the - // next request handling (if we don't close the connection). We - // first pause parser here just as we normally do, and call - // signal_write() to run on_write(). - http_parser_pause(htp, 1); - - return 0; - } return -1; } - - if (handler->get_http2_upgrade_allowed() && - downstream->get_http2_upgrade_request() && - handler->perform_http2_upgrade(upstream) != 0) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, upstream) << "HTTP Upgrade to HTTP/2 failed"; - } - } - // Stop further processing to complete this request http_parser_pause(htp, 1); return 0; @@ -508,170 +241,177 @@ // on_read() does not consume all available data in input buffer if // one http request is fully received. int HttpsUpstream::on_read() { - auto rb = handler_->get_rb(); - auto rlimit = handler_->get_rlimit(); + auto bev = handler_->get_bev(); + auto input = bufferevent_get_input(bev); auto downstream = get_downstream(); - if (rb->rleft() == 0) { - return 0; - } - // downstream can be nullptr here, because it is initialized in the // callback chain called by http_parser_execute() if (downstream && downstream->get_upgraded()) { + for (;;) { + auto inputlen = evbuffer_get_contiguous_space(input); - auto rv = downstream->push_upload_data_chunk(rb->pos, rb->rleft()); + if (inputlen == 0) { + return 0; + } - if (rv != 0) { - return -1; - } + auto mem = evbuffer_pullup(input, inputlen); - rb->reset(); - rlimit->startw(); + auto rv = downstream->push_upload_data_chunk( + reinterpret_cast(mem), inputlen); - if (downstream->request_buf_full()) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, this) << "Downstream request buf is full"; + if (rv != 0) { + return -1; } - pause_read(SHRPX_NO_BUFFER); - return 0; - } + if (evbuffer_drain(input, inputlen) != 0) { + ULOG(FATAL, this) << "evbuffer_drain() failed"; + return -1; + } - return 0; - } + if (downstream->get_output_buffer_full()) { + if (LOG_ENABLED(INFO)) { + ULOG(INFO, this) << "Downstream output buffer is full"; + } + pause_read(SHRPX_NO_BUFFER); - if (downstream) { - // To avoid reading next pipelined request - switch (downstream->get_request_state()) { - case Downstream::INITIAL: - case Downstream::HEADER_COMPLETE: - break; - default: - return 0; + return 0; + } } } - // http_parser_execute() does nothing once it entered error state. - auto nread = http_parser_execute( - &htp_, &htp_hooks, reinterpret_cast(rb->pos), rb->rleft()); - - rb->drain(nread); - rlimit->startw(); - - // Well, actually header length + some body bytes - current_header_length_ += nread; - - // Get downstream again because it may be initialized in http parser - // execution - downstream = get_downstream(); - - auto htperr = HTTP_PARSER_ERRNO(&htp_); - - if (htperr == HPE_PAUSED) { - // We may pause parser in htp_msg_completecb when both side are - // completed. Signal write, so that we can run on_write(). - if (downstream && - downstream->get_request_state() == Downstream::MSG_COMPLETE && - downstream->get_response_state() == Downstream::MSG_COMPLETE) { - handler_->signal_write(); - } - return 0; - } + for (;;) { + auto inputlen = evbuffer_get_contiguous_space(input); - if (htperr != HPE_OK) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, this) << "HTTP parse failure: " - << "(" << http_errno_name(htperr) << ") " - << http_errno_description(htperr); + if (inputlen == 0) { + return 0; } - if (downstream && downstream->get_response_state() != Downstream::INITIAL) { - handler_->set_should_close_after_write(true); - handler_->signal_write(); - return 0; + auto mem = evbuffer_pullup(input, inputlen); + + auto nread = http_parser_execute( + &htp_, &htp_hooks, reinterpret_cast(mem), inputlen); + + if (evbuffer_drain(input, nread) != 0) { + ULOG(FATAL, this) << "evbuffer_drain() failed"; + return -1; } - unsigned int status_code; + // Well, actually header length + some body bytes + current_header_length_ += nread; + + // Get downstream again because it may be initialized in http parser + // execution + downstream = get_downstream(); + + auto handler = get_client_handler(); + auto htperr = HTTP_PARSER_ERRNO(&htp_); + + if (htperr == HPE_PAUSED) { - if (htperr == HPE_INVALID_METHOD) { - status_code = 501; - } else if (downstream) { - status_code = downstream->response().http_status; - if (status_code == 0) { - if (downstream->get_request_state() == Downstream::CONNECT_FAIL) { - status_code = 503; - } else if (downstream->get_request_state() == - Downstream::HTTP1_REQUEST_HEADER_TOO_LARGE) { - status_code = 431; - } else { - status_code = 400; + assert(downstream); + + if (downstream->get_request_state() == Downstream::CONNECT_FAIL) { + handler->set_should_close_after_write(true); + // Following paues_read is needed to avoid reading next data. + pause_read(SHRPX_MSG_BLOCK); + if (error_reply(503) != 0) { + return -1; } + // Downstream gets deleted after response body is read. + return 0; } - } else { - status_code = 400; - } - error_reply(status_code); + assert(downstream->get_request_state() == Downstream::MSG_COMPLETE); - handler_->signal_write(); + if (downstream->get_downstream_connection() == nullptr) { + // Error response has already be sent + assert(downstream->get_response_state() == Downstream::MSG_COMPLETE); + delete_downstream(); - return 0; - } + return 0; + } - // downstream can be NULL here. - if (downstream && downstream->request_buf_full()) { - if (LOG_ENABLED(INFO)) { - ULOG(INFO, this) << "Downstream request buffer is full"; - } + if (handler->get_http2_upgrade_allowed() && + downstream->get_http2_upgrade_request()) { - pause_read(SHRPX_NO_BUFFER); + if (handler->perform_http2_upgrade(this) != 0) { + return -1; + } - return 0; - } + return 0; + } - return 0; -} + pause_read(SHRPX_MSG_BLOCK); -int HttpsUpstream::on_write() { - auto downstream = get_downstream(); - if (!downstream) { - return 0; - } + return 0; + } - auto output = downstream->get_response_buf(); - const auto &resp = downstream->response(); + if (htperr != HPE_OK) { + if (LOG_ENABLED(INFO)) { + ULOG(INFO, this) << "HTTP parse failure: " + << "(" << http_errno_name(htperr) << ") " + << http_errno_description(htperr); + } - if (output->rleft() > 0) { - return 0; - } + handler->set_should_close_after_write(true); + pause_read(SHRPX_MSG_BLOCK); - // We need to postpone detachment until all data are sent so that - // we can notify nghttp2 library all data consumed. - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - if (downstream->can_detach_downstream_connection()) { - // Keep-alive - downstream->detach_downstream_connection(); - } else { - // Connection close - downstream->pop_downstream_connection(); - // dconn was deleted + unsigned int status_code; + + if (downstream && + downstream->get_request_state() == Downstream::CONNECT_FAIL) { + status_code = 503; + } else { + status_code = 400; + } + + if (error_reply(status_code) != 0) { + return -1; + } + + return 0; } - // We need this if response ends before request. - if (downstream->get_request_state() == Downstream::MSG_COMPLETE) { - delete_downstream(); - if (handler_->get_should_close_after_write()) { - return 0; + // downstream can be NULL here. + if (downstream && downstream->get_output_buffer_full()) { + if (LOG_ENABLED(INFO)) { + ULOG(INFO, this) << "Downstream output buffer is full"; } - handler_->repeat_read_timer(); + pause_read(SHRPX_NO_BUFFER); - return resume_read(SHRPX_NO_BUFFER, nullptr, 0); + return 0; } } +} - return downstream->resume_read(SHRPX_NO_BUFFER, resp.unconsumed_body_length); +int HttpsUpstream::on_write() { + int rv = 0; + auto downstream = get_downstream(); + if (downstream) { + // We need to postpone detachment until all data are sent so that + // we can notify nghttp2 library all data consumed. + if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { + if (downstream->get_response_connection_close()) { + // Connection close + downstream->pop_downstream_connection(); + // dconn was deleted + } else { + // Keep-alive + downstream->detach_downstream_connection(); + } + // We need this if response ends before request. + if (downstream->get_request_state() == Downstream::MSG_COMPLETE) { + delete_downstream(); + return resume_read(SHRPX_MSG_BLOCK, nullptr, 0); + } + } + + rv = downstream->resume_read(SHRPX_NO_BUFFER, + downstream->get_response_datalen()); + } + return rv; } int HttpsUpstream::on_event() { return 0; } @@ -684,10 +424,6 @@ int HttpsUpstream::resume_read(IOCtrlReason reason, Downstream *downstream, size_t consumed) { - // downstream could be nullptr - if (downstream && downstream->request_buf_full()) { - return 0; - } if (ioctrl_.resume_read(reason)) { // Process remaining data in input buffer here because these bytes // are not notified by readcb until new data arrive. @@ -698,241 +434,272 @@ return 0; } -int HttpsUpstream::downstream_read(DownstreamConnection *dconn) { +namespace { +void https_downstream_readcb(bufferevent *bev, void *ptr) { + auto dconn = static_cast(ptr); auto downstream = dconn->get_downstream(); + auto upstream = static_cast(downstream->get_upstream()); int rv; rv = downstream->on_read(); - if (rv == SHRPX_ERR_EOF) { - return downstream_eof(dconn); - } - - if (rv == SHRPX_ERR_DCONN_CANCELED) { - downstream->pop_downstream_connection(); - goto end; - } + if (downstream->get_response_state() == Downstream::MSG_RESET) { + delete upstream->get_client_handler(); - if (rv < 0) { - return downstream_error(dconn, Downstream::EVENT_ERROR); + return; } - if (downstream->get_response_state() == Downstream::MSG_RESET) { - return -1; - } + if (rv != 0) { + if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + // We already sent HTTP response headers to upstream + // client. Just close the upstream connection. + delete upstream->get_client_handler(); - if (downstream->get_response_state() == Downstream::MSG_BAD_HEADER) { - error_reply(502); - downstream->pop_downstream_connection(); - goto end; - } + return; + } - if (downstream->can_detach_downstream_connection()) { - // Keep-alive - downstream->detach_downstream_connection(); - } + // We did not sent any HTTP response, so sent error + // response. Cannot reuse downstream connection in this case. + if (upstream->error_reply(502) != 0) { + delete upstream->get_client_handler(); -end: - handler_->signal_write(); + return; + } - return 0; -} + if (downstream->get_request_state() == Downstream::MSG_COMPLETE) { + upstream->delete_downstream(); -int HttpsUpstream::downstream_write(DownstreamConnection *dconn) { - int rv; - rv = dconn->on_write(); - if (rv == SHRPX_ERR_NETWORK) { - return downstream_error(dconn, Downstream::EVENT_ERROR); - } + // Process next HTTP request + if (upstream->resume_read(SHRPX_MSG_BLOCK, nullptr, 0) == -1) { + return; + } + } - if (rv != 0) { - return -1; + return; } - return 0; -} + auto handler = upstream->get_client_handler(); -int HttpsUpstream::downstream_eof(DownstreamConnection *dconn) { - auto downstream = dconn->get_downstream(); + if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { + if (handler->get_outbuf_length() >= OUTBUF_MAX_THRES) { + downstream->pause_read(SHRPX_NO_BUFFER); + } - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "EOF"; + return; } - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - goto end; - } + // If pending data exist, we defer detachment to correctly notify + // the all consumed data to nghttp2 library. + if (handler->get_outbuf_length() == 0) { + if (downstream->get_response_connection_close()) { + // Connection close + downstream->pop_downstream_connection(); - if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { - // Server may indicate the end of the request by EOF - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "The end of the response body was indicated by " - << "EOF"; + dconn = nullptr; + } else { + // Keep-alive + downstream->detach_downstream_connection(); } - on_downstream_body_complete(downstream); - downstream->set_response_state(Downstream::MSG_COMPLETE); - downstream->pop_downstream_connection(); - goto end; } - if (downstream->get_response_state() == Downstream::INITIAL) { - // we did not send any response headers, so we can reply error - // message. - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "Return error reply"; + if (downstream->get_request_state() == Downstream::MSG_COMPLETE) { + if (handler->get_should_close_after_write() && + handler->get_outbuf_length() == 0) { + // If all upstream response body has already written out to + // the peer, we cannot use writecb for ClientHandler. In + // this case, we just delete handler here. + delete handler; + + return; + } + + upstream->delete_downstream(); + + // Process next HTTP request + if (upstream->resume_read(SHRPX_MSG_BLOCK, nullptr, 0) == -1) { + return; } - error_reply(502); - downstream->pop_downstream_connection(); - goto end; + + return; } - // Otherwise, we don't know how to recover from this situation. Just - // drop connection. - return -1; -end: - handler_->signal_write(); + if (downstream->get_upgraded()) { + // This path is effectively only taken for HTTP2 downstream + // because only HTTP2 downstream sets response_state to + // MSG_COMPLETE and this function. For HTTP downstream, EOF + // from tunnel connection is handled on + // https_downstream_eventcb. + // + // Tunneled connection always indicates connection close. + if (handler->get_outbuf_length() == 0) { + // For tunneled connection, if there is no pending data, + // delete handler because on_write will not be called. + delete handler; - return 0; -} + return; + } -int HttpsUpstream::downstream_error(DownstreamConnection *dconn, int events) { - auto downstream = dconn->get_downstream(); - if (LOG_ENABLED(INFO)) { - if (events & Downstream::EVENT_ERROR) { - DCLOG(INFO, dconn) << "Network error/general error"; - } else { - DCLOG(INFO, dconn) << "Timeout"; + if (LOG_ENABLED(INFO)) { + DLOG(INFO, downstream) << "Tunneled connection has pending data"; } - } - if (downstream->get_response_state() != Downstream::INITIAL) { - return -1; - } - unsigned int status; - if (events & Downstream::EVENT_TIMEOUT) { - status = 504; - } else { - status = 502; + return; } - error_reply(status); - downstream->pop_downstream_connection(); + // Delete handler here if we have no pending write. + if (handler->get_should_close_after_write() && + handler->get_outbuf_length() == 0) { + delete handler; + } +} +} // namespace - handler_->signal_write(); - return 0; +namespace { +void https_downstream_writecb(bufferevent *bev, void *ptr) { + if (evbuffer_get_length(bufferevent_get_output(bev)) > 0) { + return; + } + auto dconn = static_cast(ptr); + auto downstream = dconn->get_downstream(); + auto upstream = static_cast(downstream->get_upstream()); + // May return -1 + upstream->resume_read(SHRPX_NO_BUFFER, downstream, 0); } +} // namespace -int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body, - size_t bodylen) { - const auto &req = downstream->request(); - auto &resp = downstream->response(); - auto &balloc = downstream->get_block_allocator(); - - auto connection_close = false; - - auto worker = handler_->get_worker(); - - if (worker->get_graceful_shutdown()) { - resp.fs.add_header_token(StringRef::from_lit("connection"), - StringRef::from_lit("close"), false, - http2::HD_CONNECTION); - connection_close = true; - } else if (req.http_major <= 0 || - (req.http_major == 1 && req.http_minor == 0)) { - connection_close = true; - } else { - auto c = resp.fs.header(http2::HD_CONNECTION); - if (c && util::strieq_l("close", c->value)) { - connection_close = true; +namespace { +void https_downstream_eventcb(bufferevent *bev, short events, void *ptr) { + auto dconn = static_cast(ptr); + auto downstream = dconn->get_downstream(); + auto upstream = static_cast(downstream->get_upstream()); + if (events & BEV_EVENT_CONNECTED) { + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "Connection established"; } - } - if (connection_close) { - resp.connection_close = true; - handler_->set_should_close_after_write(true); + return; } - auto output = downstream->get_response_buf(); - - output->append("HTTP/1.1 "); - output->append(http2::get_status_string(balloc, resp.http_status)); - output->append("\r\n"); + if (events & BEV_EVENT_EOF) { + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "EOF"; + } + if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + // Server may indicate the end of the request by EOF + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "The end of the response body was indicated by " + << "EOF"; + } + upstream->on_downstream_body_complete(downstream); + downstream->set_response_state(Downstream::MSG_COMPLETE); - for (auto &kv : resp.fs.headers()) { - if (kv.name.empty() || kv.name[0] == ':') { - continue; + auto handler = upstream->get_client_handler(); + if (handler->get_should_close_after_write() && + handler->get_outbuf_length() == 0) { + // If all upstream response body has already written out to + // the peer, we cannot use writecb for ClientHandler. In this + // case, we just delete handler here. + delete handler; + return; + } + } else if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { + // error + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "Treated as error"; + } + if (upstream->error_reply(502) != 0) { + delete upstream->get_client_handler(); + return; + } } - http2::capitalize(output, kv.name); - output->append(": "); - output->append(kv.value); - output->append("\r\n"); + if (downstream->get_request_state() == Downstream::MSG_COMPLETE) { + upstream->delete_downstream(); + if (upstream->resume_read(SHRPX_MSG_BLOCK, nullptr, 0) == -1) { + return; + } + } + + return; } - if (!resp.fs.header(http2::HD_SERVER)) { - output->append("Server: "); - output->append(get_config()->http.server_name); - output->append("\r\n"); + if (events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { + if (LOG_ENABLED(INFO)) { + if (events & BEV_EVENT_ERROR) { + DCLOG(INFO, dconn) << "Network error"; + } else { + DCLOG(INFO, dconn) << "Timeout"; + } + } + if (downstream->get_response_state() == Downstream::INITIAL) { + unsigned int status; + if (events & BEV_EVENT_TIMEOUT) { + status = 504; + } else { + status = 502; + } + if (upstream->error_reply(status) != 0) { + delete upstream->get_client_handler(); + return; + } + } + if (downstream->get_request_state() == Downstream::MSG_COMPLETE) { + upstream->delete_downstream(); + if (upstream->resume_read(SHRPX_MSG_BLOCK, nullptr, 0) == -1) { + return; + } + } } +} +} // namespace - auto &httpconf = get_config()->http; +int HttpsUpstream::error_reply(unsigned int status_code) { + auto html = http::create_error_html(status_code); + auto downstream = get_downstream(); - for (auto &p : httpconf.add_response_headers) { - output->append(p.name); - output->append(": "); - output->append(p.value); - output->append("\r\n"); + if (downstream) { + downstream->set_response_http_status(status_code); } - output->append("\r\n"); - - output->append(body, bodylen); + std::string header; + header.reserve(512); + header += "HTTP/1.1 "; + header += http2::get_status_string(status_code); + header += "\r\nServer: "; + header += get_config()->server_name; + header += "\r\nContent-Length: "; + header += util::utos(html.size()); + header += "\r\nContent-Type: text/html; charset=UTF-8\r\n"; + if (get_client_handler()->get_should_close_after_write()) { + header += "Connection: close\r\n"; + } + header += "\r\n"; + auto output = bufferevent_get_output(handler_->get_bev()); + if (evbuffer_add(output, header.c_str(), header.size()) != 0 || + evbuffer_add(output, html.c_str(), html.size()) != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } - downstream->response_sent_body_length += bodylen; - downstream->set_response_state(Downstream::MSG_COMPLETE); + if (downstream) { + downstream->add_response_sent_bodylen(html.size()); + downstream->set_response_state(Downstream::MSG_COMPLETE); + } else { + handler_->write_accesslog(1, 1, status_code, html.size()); + } return 0; } -void HttpsUpstream::error_reply(unsigned int status_code) { - auto downstream = get_downstream(); - - if (!downstream) { - attach_downstream(make_unique(this, handler_->get_mcpool(), 1)); - downstream = get_downstream(); - } - - auto &resp = downstream->response(); - auto &balloc = downstream->get_block_allocator(); - - auto html = http::create_error_html(balloc, status_code); +bufferevent_data_cb HttpsUpstream::get_downstream_readcb() { + return https_downstream_readcb; +} - resp.http_status = status_code; - // we are going to close connection for both frontend and backend in - // error condition. This is safest option. - resp.connection_close = true; - handler_->set_should_close_after_write(true); - - auto output = downstream->get_response_buf(); - - output->append("HTTP/1.1 "); - auto status_str = http2::get_status_string(balloc, status_code); - output->append(status_str); - output->append("\r\nServer: "); - output->append(get_config()->http.server_name); - output->append("\r\nContent-Length: "); - auto cl = util::utos(html.size()); - output->append(cl); - output->append("\r\nDate: "); - auto lgconf = log_config(); - lgconf->update_tstamp(std::chrono::system_clock::now()); - auto &date = lgconf->time_http_str; - output->append(date); - output->append("\r\nContent-Type: text/html; " - "charset=UTF-8\r\nConnection: close\r\n\r\n"); - output->append(html); +bufferevent_data_cb HttpsUpstream::get_downstream_writecb() { + return https_downstream_writecb; +} - downstream->response_sent_body_length += html.size(); - downstream->set_response_state(Downstream::MSG_COMPLETE); +bufferevent_event_cb HttpsUpstream::get_downstream_eventcb() { + return https_downstream_eventcb; } void HttpsUpstream::attach_downstream(std::unique_ptr downstream) { @@ -954,17 +721,6 @@ return std::unique_ptr(downstream_.release()); } -namespace { -void write_altsvc(DefaultMemchunks *buf, const AltSvc &altsvc) { - buf->append(util::percent_encode_token(altsvc.protocol_id)); - buf->append("=\""); - buf->append(util::quote_string(altsvc.host)); - buf->append(":"); - buf->append(altsvc.service); - buf->append("\""); -} -} // namespace - int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) { if (LOG_ENABLED(INFO)) { if (downstream->get_non_final_response()) { @@ -974,153 +730,124 @@ } } - const auto &req = downstream->request(); - auto &resp = downstream->response(); - auto &balloc = downstream->get_block_allocator(); - -#ifdef HAVE_MRUBY - if (!downstream->get_non_final_response()) { - auto worker = handler_->get_worker(); - auto mruby_ctx = worker->get_mruby_context(); - - if (mruby_ctx->run_on_response_proc(downstream) != 0) { - error_reply(500); - return -1; - } - - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - return -1; - } - } -#endif // HAVE_MRUBY - - auto connect_method = req.method == HTTP_CONNECT; - - auto buf = downstream->get_response_buf(); - - buf->append("HTTP/"); - buf->append(util::utos(req.http_major)); - buf->append("."); - buf->append(util::utos(req.http_minor)); - buf->append(" "); - buf->append(http2::get_status_string(balloc, resp.http_status)); - buf->append("\r\n"); - - auto &httpconf = get_config()->http; - - if (!get_config()->http2_proxy && !httpconf.no_location_rewrite) { - downstream->rewrite_location_response_header( - get_client_handler()->get_upstream_scheme()); - } - - http2::build_http1_headers_from_headers(buf, resp.fs.headers()); + std::string hdrs = "HTTP/"; + hdrs += util::utos(downstream->get_request_major()); + hdrs += "."; + hdrs += util::utos(downstream->get_request_minor()); + hdrs += " "; + hdrs += http2::get_status_string(downstream->get_response_http_status()); + hdrs += "\r\n"; + downstream->normalize_response_headers(); + if (!get_config()->http2_proxy && !get_config()->client_proxy && + !get_config()->no_location_rewrite) { + downstream->rewrite_norm_location_response_header( + get_client_handler()->get_upstream_scheme(), get_config()->port); + } + auto end_headers = std::end(downstream->get_response_headers()); + http2::build_http1_headers_from_norm_headers( + hdrs, downstream->get_response_headers()); if (downstream->get_non_final_response()) { - buf->append("\r\n"); + hdrs += "\r\n"; if (LOG_ENABLED(INFO)) { - log_response_headers(buf); + log_response_headers(hdrs); } - resp.fs.clear_headers(); - - return 0; - } + auto output = bufferevent_get_output(handler_->get_bev()); + if (evbuffer_add(output, hdrs.c_str(), hdrs.size()) != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } - auto worker = handler_->get_worker(); + downstream->clear_response_headers(); - // after graceful shutdown commenced, add connection: close header - // field. - if (worker->get_graceful_shutdown()) { - resp.connection_close = true; + return 0; } // We check downstream->get_response_connection_close() in case when // the Content-Length is not available. - if (!req.connection_close && !resp.connection_close) { - if (req.http_major <= 0 || req.http_minor <= 0) { + if (!downstream->get_request_connection_close() && + !downstream->get_response_connection_close()) { + if (downstream->get_request_major() <= 0 || + downstream->get_request_minor() <= 0) { // We add this header for HTTP/1.0 or HTTP/0.9 clients - buf->append("Connection: Keep-Alive\r\n"); - } - } else if (!downstream->get_upgraded()) { - buf->append("Connection: close\r\n"); - } - - if (!connect_method && downstream->get_upgraded()) { - auto connection = resp.fs.header(http2::HD_CONNECTION); - if (connection) { - buf->append("Connection: "); - buf->append((*connection).value); - buf->append("\r\n"); + hdrs += "Connection: Keep-Alive\r\n"; } + } else if (!downstream->get_upgraded() || + downstream->get_request_method() != "CONNECT") { + hdrs += "Connection: close\r\n"; + } + + if (downstream->get_norm_response_header("alt-svc") == end_headers) { + // We won't change or alter alt-svc from backend at the moment. + if (!get_config()->altsvcs.empty()) { + hdrs += "Alt-Svc: "; + + for (auto &altsvc : get_config()->altsvcs) { + hdrs += util::percent_encode_token(altsvc.protocol_id); + hdrs += "=\""; + hdrs += util::quote_string(std::string(altsvc.host, altsvc.host_len)); + hdrs += ":"; + hdrs += util::utos(altsvc.port); + hdrs += "\", "; + } - auto upgrade = resp.fs.header(http2::HD_UPGRADE); - if (upgrade) { - buf->append("Upgrade: "); - buf->append((*upgrade).value); - buf->append("\r\n"); + hdrs[hdrs.size() - 2] = '\r'; + hdrs[hdrs.size() - 1] = '\n'; } } - if (!resp.fs.header(http2::HD_ALT_SVC)) { - // We won't change or alter alt-svc from backend for now - if (!httpconf.altsvcs.empty()) { - buf->append("Alt-Svc: "); - - auto &altsvcs = httpconf.altsvcs; - write_altsvc(buf, altsvcs[0]); - for (size_t i = 1; i < altsvcs.size(); ++i) { - buf->append(", "); - write_altsvc(buf, altsvcs[i]); - } - buf->append("\r\n"); + if (!get_config()->http2_proxy && !get_config()->client_proxy) { + hdrs += "Server: "; + hdrs += get_config()->server_name; + hdrs += "\r\n"; + } else { + auto server = downstream->get_norm_response_header("server"); + if (server != end_headers) { + hdrs += "Server: "; + hdrs += (*server).value; + hdrs += "\r\n"; } } - if (!get_config()->http2_proxy) { - buf->append("Server: "); - buf->append(httpconf.server_name); - buf->append("\r\n"); + auto via = downstream->get_norm_response_header("via"); + if (get_config()->no_via) { + if (via != end_headers) { + hdrs += "Via: "; + hdrs += (*via).value; + http2::sanitize_header_value(hdrs, hdrs.size() - (*via).value.size()); + hdrs += "\r\n"; + } } else { - auto server = resp.fs.header(http2::HD_SERVER); - if (server) { - buf->append("Server: "); - buf->append((*server).value); - buf->append("\r\n"); + hdrs += "Via: "; + if (via != end_headers) { + hdrs += (*via).value; + http2::sanitize_header_value(hdrs, hdrs.size() - (*via).value.size()); + hdrs += ", "; } + hdrs += http::create_via_header_value(downstream->get_response_major(), + downstream->get_response_minor()); + hdrs += "\r\n"; } - auto via = resp.fs.header(http2::HD_VIA); - if (httpconf.no_via) { - if (via) { - buf->append("Via: "); - buf->append((*via).value); - buf->append("\r\n"); - } - } else { - buf->append("Via: "); - if (via) { - buf->append((*via).value); - buf->append(", "); - } - std::array viabuf; - auto end = http::create_via_header_value(viabuf.data(), resp.http_major, - resp.http_minor); - buf->append(viabuf.data(), end - std::begin(viabuf)); - buf->append("\r\n"); - } - - for (auto &p : httpconf.add_response_headers) { - buf->append(p.name); - buf->append(": "); - buf->append(p.value); - buf->append("\r\n"); + for (auto &p : get_config()->add_response_headers) { + hdrs += p.first; + hdrs += ": "; + hdrs += p.second; + hdrs += "\r\n"; } - buf->append("\r\n"); + hdrs += "\r\n"; if (LOG_ENABLED(INFO)) { - log_response_headers(buf); + log_response_headers(hdrs); + } + + auto output = bufferevent_get_output(handler_->get_bev()); + if (evbuffer_add(output, hdrs.c_str(), hdrs.size()) != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; } return 0; @@ -1129,48 +856,52 @@ int HttpsUpstream::on_downstream_body(Downstream *downstream, const uint8_t *data, size_t len, bool flush) { + int rv; if (len == 0) { return 0; } - auto output = downstream->get_response_buf(); + auto output = bufferevent_get_output(handler_->get_bev()); if (downstream->get_chunked_response()) { - output->append(util::utox(len)); - output->append("\r\n"); + auto chunk_size_hex = util::utox(len); + chunk_size_hex += "\r\n"; + + rv = evbuffer_add(output, chunk_size_hex.c_str(), chunk_size_hex.size()); + + if (rv != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } + } + if (evbuffer_add(output, data, len) != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; } - output->append(data, len); - downstream->response_sent_body_length += len; + downstream->add_response_sent_bodylen(len); if (downstream->get_chunked_response()) { - output->append("\r\n"); + if (evbuffer_add(output, "\r\n", 2) != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } } return 0; } int HttpsUpstream::on_downstream_body_complete(Downstream *downstream) { - const auto &req = downstream->request(); - auto &resp = downstream->response(); - if (downstream->get_chunked_response()) { - auto output = downstream->get_response_buf(); - const auto &trailers = resp.fs.trailers(); - if (trailers.empty()) { - output->append("0\r\n\r\n"); - } else { - output->append("0\r\n"); - http2::build_http1_headers_from_headers(output, trailers); - output->append("\r\n"); + auto output = bufferevent_get_output(handler_->get_bev()); + if (evbuffer_add(output, "0\r\n\r\n", 5) != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; } } if (LOG_ENABLED(INFO)) { DLOG(INFO, downstream) << "HTTP response completed"; } - if (!downstream->validate_response_recv_body_length()) { - resp.connection_close = true; - } - - if (req.connection_close || resp.connection_close) { + if (downstream->get_request_connection_close() || + downstream->get_response_connection_close()) { auto handler = get_client_handler(); handler->set_should_close_after_write(true); } @@ -1179,20 +910,24 @@ int HttpsUpstream::on_downstream_abort_request(Downstream *downstream, unsigned int status_code) { - error_reply(status_code); - handler_->signal_write(); - return 0; + return error_reply(status_code); } -void HttpsUpstream::log_response_headers(DefaultMemchunks *buf) const { +void HttpsUpstream::log_response_headers(const std::string &hdrs) const { + const char *hdrp; std::string nhdrs; - for (auto chunk = buf->head; chunk; chunk = chunk->next) { - nhdrs.append(chunk->pos, chunk->last); - } - if (log_config()->errorlog_tty) { - nhdrs = http::colorizeHeaders(nhdrs.c_str()); + if (worker_config->errorlog_tty) { + nhdrs = http::colorizeHeaders(hdrs.c_str()); + hdrp = nhdrs.c_str(); + } else { + hdrp = hdrs.c_str(); } - ULOG(INFO, this) << "HTTP response headers\n" << nhdrs; + ULOG(INFO, this) << "HTTP response headers\n" << hdrp; +} + +void HttpsUpstream::reset_timeouts() { + handler_->set_upstream_timeouts(&get_config()->upstream_read_timeout, + &get_config()->upstream_write_timeout); } void HttpsUpstream::on_handler_delete() { @@ -1201,97 +936,4 @@ } } -int HttpsUpstream::on_downstream_reset(bool no_retry) { - int rv; - std::unique_ptr dconn; - - if (!downstream_->request_submission_ready()) { - // Return error so that caller can delete handler - return -1; - } - - downstream_->pop_downstream_connection(); - - downstream_->add_retry(); - - if (no_retry || downstream_->no_more_retry()) { - goto fail; - } - - dconn = handler_->get_downstream_connection(downstream_.get()); - if (!dconn) { - goto fail; - } - - rv = downstream_->attach_downstream_connection(std::move(dconn)); - if (rv != 0) { - goto fail; - } - - rv = downstream_->push_request_headers(); - if (rv != 0) { - goto fail; - } - - return 0; - -fail: - if (on_downstream_abort_request(downstream_.get(), 503) != 0) { - return -1; - } - downstream_->pop_downstream_connection(); - - return 0; -} - -int HttpsUpstream::initiate_push(Downstream *downstream, const StringRef &uri) { - return 0; -} - -int HttpsUpstream::response_riovec(struct iovec *iov, int iovcnt) const { - if (!downstream_) { - return 0; - } - - auto buf = downstream_->get_response_buf(); - - return buf->riovec(iov, iovcnt); -} - -void HttpsUpstream::response_drain(size_t n) { - if (!downstream_) { - return; - } - - auto buf = downstream_->get_response_buf(); - - buf->drain(n); -} - -bool HttpsUpstream::response_empty() const { - if (!downstream_) { - return true; - } - - auto buf = downstream_->get_response_buf(); - - return buf->rleft() == 0; -} - -Downstream * -HttpsUpstream::on_downstream_push_promise(Downstream *downstream, - int32_t promised_stream_id) { - return nullptr; -} - -int HttpsUpstream::on_downstream_push_promise_complete( - Downstream *downstream, Downstream *promised_downstream) { - return -1; -} - -bool HttpsUpstream::push_enabled() const { return false; } - -void HttpsUpstream::cancel_premature_downstream( - Downstream *promised_downstream) {} - } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_https_upstream.h nghttp2-0.6.7/src/shrpx_https_upstream.h --- nghttp2-1.13.0/src/shrpx_https_upstream.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_https_upstream.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,15 +27,13 @@ #include "shrpx.h" -#include +#include + #include #include "http-parser/http_parser.h" #include "shrpx_upstream.h" -#include "memchunk.h" - -using namespace nghttp2; namespace shrpx { @@ -51,17 +49,14 @@ virtual int on_downstream_abort_request(Downstream *downstream, unsigned int status_code); virtual ClientHandler *get_client_handler() const; - - virtual int downstream_read(DownstreamConnection *dconn); - virtual int downstream_write(DownstreamConnection *dconn); - virtual int downstream_eof(DownstreamConnection *dconn); - virtual int downstream_error(DownstreamConnection *dconn, int events); - + virtual bufferevent_data_cb get_downstream_readcb(); + virtual bufferevent_data_cb get_downstream_writecb(); + virtual bufferevent_event_cb get_downstream_eventcb(); void attach_downstream(std::unique_ptr downstream); void delete_downstream(); Downstream *get_downstream() const; std::unique_ptr pop_downstream(); - void error_reply(unsigned int status_code); + int error_reply(unsigned int status_code); virtual void pause_read(IOCtrlReason reason); virtual int resume_read(IOCtrlReason reason, Downstream *downstream, @@ -73,24 +68,11 @@ virtual int on_downstream_body_complete(Downstream *downstream); virtual void on_handler_delete(); - virtual int on_downstream_reset(bool no_retry); - virtual int send_reply(Downstream *downstream, const uint8_t *body, - size_t bodylen); - virtual int initiate_push(Downstream *downstream, const StringRef &uri); - virtual int response_riovec(struct iovec *iov, int iovcnt) const; - virtual void response_drain(size_t n); - virtual bool response_empty() const; - - virtual Downstream *on_downstream_push_promise(Downstream *downstream, - int32_t promised_stream_id); - virtual int - on_downstream_push_promise_complete(Downstream *downstream, - Downstream *promised_downstream); - virtual bool push_enabled() const; - virtual void cancel_premature_downstream(Downstream *promised_downstream); + + virtual void reset_timeouts(); void reset_current_header_length(); - void log_response_headers(DefaultMemchunks *buf) const; + void log_response_headers(const std::string &hdrs) const; private: ClientHandler *handler_; diff -Nru nghttp2-1.13.0/src/shrpx_http_test.cc nghttp2-0.6.7/src/shrpx_http_test.cc --- nghttp2-1.13.0/src/shrpx_http_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http_test.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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. - */ -#include "shrpx_http_test.h" - -#ifdef HAVE_UNISTD_H -#include -#endif // HAVE_UNISTD_H - -#include - -#include - -#include "shrpx_http.h" -#include "shrpx_config.h" - -namespace shrpx { - -void test_shrpx_http_create_forwarded(void) { - BlockAllocator balloc(1024, 1024); - - CU_ASSERT("by=\"example.com:3000\";for=\"[::1]\";host=\"www.example.com\";" - "proto=https" == - http::create_forwarded(balloc, FORWARDED_BY | FORWARDED_FOR | - FORWARDED_HOST | FORWARDED_PROTO, - StringRef::from_lit("example.com:3000"), - StringRef::from_lit("[::1]"), - StringRef::from_lit("www.example.com"), - StringRef::from_lit("https"))); - - CU_ASSERT("for=192.168.0.1" == - http::create_forwarded( - balloc, FORWARDED_FOR, StringRef::from_lit("alpha"), - StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("bravo"), StringRef::from_lit("charlie"))); - - CU_ASSERT("by=_hidden;for=\"[::1]\"" == - http::create_forwarded( - balloc, FORWARDED_BY | FORWARDED_FOR, - StringRef::from_lit("_hidden"), StringRef::from_lit("[::1]"), - StringRef::from_lit(""), StringRef::from_lit(""))); - - CU_ASSERT("by=\"[::1]\";for=_hidden" == - http::create_forwarded( - balloc, FORWARDED_BY | FORWARDED_FOR, - StringRef::from_lit("[::1]"), StringRef::from_lit("_hidden"), - StringRef::from_lit(""), StringRef::from_lit(""))); - - CU_ASSERT("" == http::create_forwarded( - balloc, FORWARDED_BY | FORWARDED_FOR | FORWARDED_HOST | - FORWARDED_PROTO, - StringRef::from_lit(""), StringRef::from_lit(""), - StringRef::from_lit(""), StringRef::from_lit(""))); -} - -void test_shrpx_http_create_via_header_value(void) { - std::array buf; - - auto end = http::create_via_header_value(std::begin(buf), 1, 1); - - CU_ASSERT(("1.1 nghttpx" == StringRef{std::begin(buf), end})); - - std::fill(std::begin(buf), std::end(buf), '\0'); - - end = http::create_via_header_value(std::begin(buf), 2, 0); - - CU_ASSERT(("2 nghttpx" == StringRef{std::begin(buf), end})); -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_http_test.h nghttp2-0.6.7/src/shrpx_http_test.h --- nghttp2-1.13.0/src/shrpx_http_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_http_test.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 SHRPX_HTTP_TEST_H -#define SHRPX_HTTP_TEST_H - -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - -namespace shrpx { - -void test_shrpx_http_create_forwarded(void); -void test_shrpx_http_create_via_header_value(void); - -} // namespace shrpx - -#endif // SHRPX_HTTP_TEST_H diff -Nru nghttp2-1.13.0/src/shrpx_io_control.cc nghttp2-0.6.7/src/shrpx_io_control.cc --- nghttp2-1.13.0/src/shrpx_io_control.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_io_control.cc 2014-11-30 14:15:07.000000000 +0000 @@ -26,40 +26,42 @@ #include -#include "shrpx_rate_limit.h" #include "util.h" +#include "libevent_util.h" using namespace nghttp2; namespace shrpx { -IOControl::IOControl(RateLimit *lim) : lim_(lim), rdbits_(0) {} +IOControl::IOControl(bufferevent *bev) : bev_(bev), rdbits_(0) {} IOControl::~IOControl() {} +void IOControl::set_bev(bufferevent *bev) { bev_ = bev; } + void IOControl::pause_read(IOCtrlReason reason) { rdbits_ |= reason; - if (lim_) { - lim_->stopw(); + if (bev_) { + util::bev_disable_unless(bev_, EV_READ); } } bool IOControl::resume_read(IOCtrlReason reason) { rdbits_ &= ~reason; if (rdbits_ == 0) { - if (lim_) { - lim_->startw(); + if (bev_) { + util::bev_enable_unless(bev_, EV_READ); } return true; + } else { + return false; } - - return false; } void IOControl::force_resume_read() { rdbits_ = 0; - if (lim_) { - lim_->startw(); + if (bev_) { + util::bev_enable_unless(bev_, EV_READ); } } diff -Nru nghttp2-1.13.0/src/shrpx_io_control.h nghttp2-0.6.7/src/shrpx_io_control.h --- nghttp2-1.13.0/src/shrpx_io_control.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_io_control.h 2014-11-30 14:15:07.000000000 +0000 @@ -29,9 +29,8 @@ #include -#include - -#include "shrpx_rate_limit.h" +#include +#include namespace shrpx { @@ -39,8 +38,9 @@ class IOControl { public: - IOControl(RateLimit *lim); + IOControl(bufferevent *bev); ~IOControl(); + void set_bev(bufferevent *bev); void pause_read(IOCtrlReason reason); // Returns true if read operation is enabled after this call bool resume_read(IOCtrlReason reason); @@ -48,7 +48,7 @@ void force_resume_read(); private: - RateLimit *lim_; + bufferevent *bev_; uint32_t rdbits_; }; diff -Nru nghttp2-1.13.0/src/shrpx_listen_handler.cc nghttp2-0.6.7/src/shrpx_listen_handler.cc --- nghttp2-1.13.0/src/shrpx_listen_handler.cc 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_listen_handler.cc 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,378 @@ +/* + * 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. + */ +#include "shrpx_listen_handler.h" + +#include + +#include +#include + +#include + +#include "shrpx_client_handler.h" +#include "shrpx_thread_event_receiver.h" +#include "shrpx_ssl.h" +#include "shrpx_worker.h" +#include "shrpx_worker_config.h" +#include "shrpx_config.h" +#include "shrpx_http2_session.h" +#include "shrpx_connect_blocker.h" +#include "shrpx_downstream_connection.h" +#include "util.h" +#include "libevent_util.h" + +using namespace nghttp2; + +namespace shrpx { + +namespace { +void evlistener_disable_cb(evutil_socket_t fd, short events, void *arg) { + auto listener_handler = static_cast(arg); + + // If we are in graceful shutdown period, we must not enable + // evlisteners again. + if (worker_config->graceful_shutdown) { + return; + } + + listener_handler->enable_evlistener(); +} +} // namespace + +ListenHandler::ListenHandler(event_base *evbase, SSL_CTX *sv_ssl_ctx, + SSL_CTX *cl_ssl_ctx) + : evbase_(evbase), sv_ssl_ctx_(sv_ssl_ctx), cl_ssl_ctx_(cl_ssl_ctx), + rate_limit_group_(bufferevent_rate_limit_group_new( + evbase, get_config()->worker_rate_limit_cfg)), + evlistener4_(nullptr), evlistener6_(nullptr), + evlistener_disable_timerev_( + evtimer_new(evbase, evlistener_disable_cb, this)), + worker_stat_(util::make_unique()), num_worker_shutdown_(0), + worker_round_robin_cnt_(0) {} + +ListenHandler::~ListenHandler() { + bufferevent_rate_limit_group_free(rate_limit_group_); +} + +void ListenHandler::worker_reopen_log_files() { + WorkerEvent wev; + + memset(&wev, 0, sizeof(wev)); + wev.type = REOPEN_LOG; + + for (auto &info : workers_) { + bufferevent_write(info->bev, &wev, sizeof(wev)); + } +} + +#ifndef NOTHREADS +namespace { +void worker_writecb(bufferevent *bev, void *ptr) { + auto listener_handler = static_cast(ptr); + auto output = bufferevent_get_output(bev); + + if (!worker_config->graceful_shutdown || evbuffer_get_length(output) != 0) { + return; + } + + // If graceful_shutdown is true and nothing left to send, we sent + // graceful shutdown event to worker successfully. The worker is + // now doing shutdown. + listener_handler->notify_worker_shutdown(); + + // Disable bev so that this won' be called accidentally in the + // future. + util::bev_disable_unless(bev, EV_READ | EV_WRITE); +} +} // namespace +#endif // NOTHREADS + +void ListenHandler::create_worker_thread(size_t num) { +#ifndef NOTHREADS + workers_.resize(0); + for (size_t i = 0; i < num; ++i) { + int rv; + auto info = util::make_unique(); + rv = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, + info->sv); + if (rv == -1) { + auto error = errno; + LLOG(ERROR, this) << "socketpair() failed: errno=" << error; + continue; + } + + info->sv_ssl_ctx = sv_ssl_ctx_; + info->cl_ssl_ctx = cl_ssl_ctx_; + + info->fut = + std::async(std::launch::async, start_threaded_worker, info.get()); + + auto bev = + bufferevent_socket_new(evbase_, info->sv[0], BEV_OPT_DEFER_CALLBACKS); + if (!bev) { + LLOG(ERROR, this) << "bufferevent_socket_new() failed"; + for (size_t j = 0; j < 2; ++j) { + close(info->sv[j]); + } + continue; + } + + bufferevent_setcb(bev, nullptr, worker_writecb, nullptr, this); + + info->bev = bev; + + workers_.push_back(std::move(info)); + + if (LOG_ENABLED(INFO)) { + LLOG(INFO, this) << "Created thread #" << workers_.size() - 1; + } + } +#endif // NOTHREADS +} + +void ListenHandler::join_worker() { +#ifndef NOTHREADS + int n = 0; + + if (LOG_ENABLED(INFO)) { + LLOG(INFO, this) << "Waiting for worker thread to join: n=" + << workers_.size(); + } + + for (auto &worker : workers_) { + worker->fut.get(); + if (LOG_ENABLED(INFO)) { + LLOG(INFO, this) << "Thread #" << n << " joined"; + } + ++n; + } +#endif // NOTHREADS +} + +void ListenHandler::graceful_shutdown_worker() { + if (get_config()->num_worker == 1) { + return; + } + + for (auto &worker : workers_) { + WorkerEvent wev; + memset(&wev, 0, sizeof(wev)); + wev.type = GRACEFUL_SHUTDOWN; + + if (LOG_ENABLED(INFO)) { + LLOG(INFO, this) << "Sending graceful shutdown signal to worker"; + } + + auto output = bufferevent_get_output(worker->bev); + + if (evbuffer_add(output, &wev, sizeof(wev)) != 0) { + LLOG(FATAL, this) << "evbuffer_add() failed"; + } + } +} + +int ListenHandler::accept_connection(evutil_socket_t fd, sockaddr *addr, + int addrlen) { + if (LOG_ENABLED(INFO)) { + LLOG(INFO, this) << "Accepted connection. fd=" << fd; + } + + evutil_make_socket_closeonexec(fd); + + if (get_config()->num_worker == 1) { + + if (worker_stat_->num_connections >= + get_config()->worker_frontend_connections) { + + if (LOG_ENABLED(INFO)) { + TLOG(INFO, this) << "Too many connections >=" + << get_config()->worker_frontend_connections; + } + + close(fd); + return -1; + } + + auto client = + ssl::accept_connection(evbase_, rate_limit_group_, sv_ssl_ctx_, fd, + addr, addrlen, worker_stat_.get(), &dconn_pool_); + if (!client) { + LLOG(ERROR, this) << "ClientHandler creation failed"; + + close(fd); + return -1; + } + + client->set_http2_session(http2session_.get()); + client->set_http1_connect_blocker(http1_connect_blocker_.get()); + + return 0; + } + size_t idx = worker_round_robin_cnt_ % workers_.size(); + ++worker_round_robin_cnt_; + WorkerEvent wev; + memset(&wev, 0, sizeof(wev)); + wev.type = NEW_CONNECTION; + wev.client_fd = fd; + memcpy(&wev.client_addr, addr, addrlen); + wev.client_addrlen = addrlen; + auto output = bufferevent_get_output(workers_[idx]->bev); + if (evbuffer_add(output, &wev, sizeof(wev)) != 0) { + LLOG(FATAL, this) << "evbuffer_add() failed"; + close(fd); + return -1; + } + + return 0; +} + +event_base *ListenHandler::get_evbase() const { return evbase_; } + +int ListenHandler::create_http2_session() { + int rv; + http2session_ = util::make_unique(evbase_, cl_ssl_ctx_); + rv = http2session_->init_notification(); + return rv; +} + +int ListenHandler::create_http1_connect_blocker() { + int rv; + http1_connect_blocker_ = util::make_unique(); + + rv = http1_connect_blocker_->init(evbase_); + + if (rv != 0) { + return -1; + } + + return 0; +} + +const WorkerStat *ListenHandler::get_worker_stat() const { + return worker_stat_.get(); +} + +void ListenHandler::set_evlistener4(evconnlistener *evlistener4) { + evlistener4_ = evlistener4; +} + +evconnlistener *ListenHandler::get_evlistener4() const { return evlistener4_; } + +void ListenHandler::set_evlistener6(evconnlistener *evlistener6) { + evlistener6_ = evlistener6; +} + +evconnlistener *ListenHandler::get_evlistener6() const { return evlistener6_; } + +void ListenHandler::enable_evlistener() { + if (evlistener4_) { + evconnlistener_enable(evlistener4_); + } + + if (evlistener6_) { + evconnlistener_enable(evlistener6_); + } +} + +void ListenHandler::disable_evlistener() { + if (evlistener4_) { + evconnlistener_disable(evlistener4_); + } + + if (evlistener6_) { + evconnlistener_disable(evlistener6_); + } +} + +void ListenHandler::disable_evlistener_temporary(const timeval *timeout) { + int rv; + + if (timeout->tv_sec == 0 || + evtimer_pending(evlistener_disable_timerev_, nullptr)) { + return; + } + + disable_evlistener(); + + rv = evtimer_add(evlistener_disable_timerev_, timeout); + + if (rv < 0) { + LOG(ERROR) << "evtimer_add for evlistener_disable_timerev_ failed"; + } +} + +namespace { +void perform_accept_pending_connection(ListenHandler *listener_handler, + evconnlistener *listener) { + if (!listener) { + return; + } + + auto server_fd = evconnlistener_get_fd(listener); + + for (;;) { + sockaddr_union sockaddr; + socklen_t addrlen = sizeof(sockaddr); + + auto fd = accept(server_fd, &sockaddr.sa, &addrlen); + + if (fd == -1) { + switch (errno) { + case EINTR: + case ENETDOWN: + case EPROTO: + case ENOPROTOOPT: + case EHOSTDOWN: +#ifdef ENONET + case ENONET: +#endif // ENONET + case EHOSTUNREACH: + case EOPNOTSUPP: + case ENETUNREACH: + continue; + } + + return; + } + + evutil_make_socket_nonblocking(fd); + + listener_handler->accept_connection(fd, &sockaddr.sa, addrlen); + } +} +} // namespace + +void ListenHandler::accept_pending_connection() { + perform_accept_pending_connection(this, evlistener4_); + perform_accept_pending_connection(this, evlistener6_); +} + +void ListenHandler::notify_worker_shutdown() { + if (++num_worker_shutdown_ == workers_.size()) { + event_base_loopbreak(evbase_); + } +} + +} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_listen_handler.h nghttp2-0.6.7/src/shrpx_listen_handler.h --- nghttp2-1.13.0/src/shrpx_listen_handler.h 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_listen_handler.h 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,109 @@ +/* + * 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 SHRPX_LISTEN_HANDLER_H +#define SHRPX_LISTEN_HANDLER_H + +#include "shrpx.h" + +#include +#include + +#include +#include +#ifndef NOTHREADS +#include +#endif // NOTHREADS + +#include + +#include +#include +#include + +#include "shrpx_downstream_connection_pool.h" + +namespace shrpx { + +struct WorkerInfo { +#ifndef NOTHREADS + std::future fut; +#endif // NOTHREADS + SSL_CTX *sv_ssl_ctx; + SSL_CTX *cl_ssl_ctx; + bufferevent *bev; + int sv[2]; +}; + +class Http2Session; +class ConnectBlocker; +struct WorkerStat; + +class ListenHandler { +public: + ListenHandler(event_base *evbase, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx); + ~ListenHandler(); + int accept_connection(evutil_socket_t fd, sockaddr *addr, int addrlen); + void create_worker_thread(size_t num); + void worker_reopen_log_files(); + event_base *get_evbase() const; + int create_http2_session(); + int create_http1_connect_blocker(); + const WorkerStat *get_worker_stat() const; + void set_evlistener4(evconnlistener *evlistener4); + evconnlistener *get_evlistener4() const; + void set_evlistener6(evconnlistener *evlistener6); + evconnlistener *get_evlistener6() const; + void enable_evlistener(); + void disable_evlistener(); + void disable_evlistener_temporary(const timeval *timeout); + void accept_pending_connection(); + void graceful_shutdown_worker(); + void join_worker(); + void notify_worker_shutdown(); + +private: + DownstreamConnectionPool dconn_pool_; + std::vector> workers_; + event_base *evbase_; + // The frontend server SSL_CTX + SSL_CTX *sv_ssl_ctx_; + // The backend server SSL_CTX + SSL_CTX *cl_ssl_ctx_; + // Shared backend HTTP2 session. NULL if multi-threaded. In + // multi-threaded case, see shrpx_worker.cc. + std::unique_ptr http2session_; + std::unique_ptr http1_connect_blocker_; + bufferevent_rate_limit_group *rate_limit_group_; + evconnlistener *evlistener4_; + evconnlistener *evlistener6_; + event *evlistener_disable_timerev_; + std::unique_ptr worker_stat_; + size_t num_worker_shutdown_; + unsigned int worker_round_robin_cnt_; +}; + +} // namespace shrpx + +#endif // SHRPX_LISTEN_HANDLER_H diff -Nru nghttp2-1.13.0/src/shrpx_live_check.cc nghttp2-0.6.7/src/shrpx_live_check.cc --- nghttp2-1.13.0/src/shrpx_live_check.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_live_check.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,718 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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. - */ -#include "shrpx_live_check.h" -#include "shrpx_worker.h" -#include "shrpx_connect_blocker.h" -#include "shrpx_ssl.h" - -namespace shrpx { - -namespace { -constexpr size_t MAX_BUFFER_SIZE = 4_k; -} // namespace - -namespace { -void readcb(struct ev_loop *loop, ev_io *w, int revents) { - int rv; - auto conn = static_cast(w->data); - auto live_check = static_cast(conn->data); - - rv = live_check->do_read(); - if (rv != 0) { - live_check->on_failure(); - return; - } -} -} // namespace - -namespace { -void writecb(struct ev_loop *loop, ev_io *w, int revents) { - int rv; - auto conn = static_cast(w->data); - auto live_check = static_cast(conn->data); - - rv = live_check->do_write(); - if (rv != 0) { - live_check->on_failure(); - return; - } -} -} // namespace - -namespace { -void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - auto conn = static_cast(w->data); - auto live_check = static_cast(conn->data); - - live_check->on_failure(); -} -} // namespace - -namespace { -void backoff_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - int rv; - auto live_check = static_cast(w->data); - - rv = live_check->initiate_connection(); - if (rv != 0) { - live_check->on_failure(); - return; - } -} -} // namespace - -namespace { -void settings_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto live_check = static_cast(w->data); - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "SETTINGS timeout"; - } - - live_check->on_failure(); -} -} // namespace - -LiveCheck::LiveCheck(struct ev_loop *loop, SSL_CTX *ssl_ctx, Worker *worker, - DownstreamAddr *addr, std::mt19937 &gen) - : conn_(loop, -1, nullptr, worker->get_mcpool(), - worker->get_downstream_config()->timeout.write, - worker->get_downstream_config()->timeout.read, {}, {}, writecb, - readcb, timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold, - get_config()->tls.dyn_rec.idle_timeout, PROTO_NONE), - wb_(worker->get_mcpool()), - gen_(gen), - read_(&LiveCheck::noop), - write_(&LiveCheck::noop), - worker_(worker), - ssl_ctx_(ssl_ctx), - addr_(addr), - session_(nullptr), - success_count_(0), - fail_count_(0), - settings_ack_received_(false), - session_closing_(false) { - ev_timer_init(&backoff_timer_, backoff_timeoutcb, 0., 0.); - backoff_timer_.data = this; - - // SETTINGS ACK must be received in a short timeout. Otherwise, we - // assume that connection is broken. - ev_timer_init(&settings_timer_, settings_timeout_cb, 0., 0.); - settings_timer_.data = this; -} - -LiveCheck::~LiveCheck() { - disconnect(); - - ev_timer_stop(conn_.loop, &backoff_timer_); -} - -void LiveCheck::disconnect() { - conn_.rlimit.stopw(); - conn_.wlimit.stopw(); - - ev_timer_stop(conn_.loop, &settings_timer_); - - read_ = write_ = &LiveCheck::noop; - - conn_.disconnect(); - - nghttp2_session_del(session_); - session_ = nullptr; - - settings_ack_received_ = false; - session_closing_ = false; - - wb_.reset(); -} - -// Use the similar backoff algorithm described in -// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md -namespace { -constexpr size_t MAX_BACKOFF_EXP = 10; -constexpr auto MULTIPLIER = 1.6; -constexpr auto JITTER = 0.2; -} // namespace - -void LiveCheck::schedule() { - auto base_backoff = - util::int_pow(MULTIPLIER, std::min(fail_count_, MAX_BACKOFF_EXP)); - auto dist = std::uniform_real_distribution<>(-JITTER * base_backoff, - JITTER * base_backoff); - - auto &downstreamconf = *get_config()->conn.downstream; - - auto backoff = - std::min(downstreamconf.timeout.max_backoff, base_backoff + dist(gen_)); - - ev_timer_set(&backoff_timer_, backoff, 0.); - ev_timer_start(conn_.loop, &backoff_timer_); -} - -int LiveCheck::do_read() { return read_(*this); } - -int LiveCheck::do_write() { return write_(*this); } - -int LiveCheck::initiate_connection() { - int rv; - - auto worker_blocker = worker_->get_connect_blocker(); - if (worker_blocker->blocked()) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Worker wide backend connection was blocked temporarily"; - } - return -1; - } - - if (addr_->tls) { - assert(ssl_ctx_); - - auto ssl = ssl::create_ssl(ssl_ctx_); - if (!ssl) { - return -1; - } - - switch (addr_->proto) { - case PROTO_HTTP1: - ssl::setup_downstream_http1_alpn(ssl); - break; - case PROTO_HTTP2: - ssl::setup_downstream_http2_alpn(ssl); - break; - default: - assert(0); - } - - conn_.set_ssl(ssl); - } - - conn_.fd = util::create_nonblock_socket(addr_->addr.su.storage.ss_family); - - if (conn_.fd == -1) { - auto error = errno; - LOG(WARN) << "socket() failed; addr=" << util::to_numeric_addr(&addr_->addr) - << ", errno=" << error; - return -1; - } - - rv = connect(conn_.fd, &addr_->addr.su.sa, addr_->addr.len); - if (rv != 0 && errno != EINPROGRESS) { - auto error = errno; - LOG(WARN) << "connect() failed; addr=" - << util::to_numeric_addr(&addr_->addr) << ", errno=" << error; - - close(conn_.fd); - conn_.fd = -1; - - return -1; - } - - if (addr_->tls) { - auto sni_name = - addr_->sni.empty() ? StringRef{addr_->host} : StringRef{addr_->sni}; - if (!util::numeric_host(sni_name.c_str())) { - SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name.c_str()); - } - - auto session = ssl::reuse_tls_session(addr_->tls_session_cache); - if (session) { - SSL_set_session(conn_.tls.ssl, session); - SSL_SESSION_free(session); - } - - conn_.prepare_client_handshake(); - } - - write_ = &LiveCheck::connected; - - ev_io_set(&conn_.wev, conn_.fd, EV_WRITE); - ev_io_set(&conn_.rev, conn_.fd, EV_READ); - - conn_.wlimit.startw(); - - // TODO we should have timeout for connection establishment - ev_timer_again(conn_.loop, &conn_.wt); - - return 0; -} - -int LiveCheck::connected() { - if (!util::check_socket_connected(conn_.fd)) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Backend connect failed; addr=" - << util::to_numeric_addr(&addr_->addr); - } - - return -1; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Connection established"; - } - - conn_.rlimit.startw(); - - if (conn_.tls.ssl) { - read_ = &LiveCheck::tls_handshake; - write_ = &LiveCheck::tls_handshake; - - return do_write(); - } - - if (addr_->proto == PROTO_HTTP2) { - // For HTTP/2, we try to read SETTINGS ACK from server to make - // sure it is really alive, and serving HTTP/2. - read_ = &LiveCheck::read_clear; - write_ = &LiveCheck::write_clear; - - if (connection_made() != 0) { - return -1; - } - - return 0; - } - - on_success(); - - return 0; -} - -int LiveCheck::tls_handshake() { - ev_timer_again(conn_.loop, &conn_.rt); - - ERR_clear_error(); - - auto rv = conn_.tls_handshake(); - - if (rv == SHRPX_ERR_INPROGRESS) { - return 0; - } - - if (rv < 0) { - return rv; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "SSL/TLS handshake completed"; - } - - if (!get_config()->tls.insecure && - ssl::check_cert(conn_.tls.ssl, addr_) != 0) { - return -1; - } - - if (!SSL_session_reused(conn_.tls.ssl)) { - auto tls_session = SSL_get0_session(conn_.tls.ssl); - if (tls_session) { - ssl::try_cache_tls_session(addr_->tls_session_cache, addr_->addr, - tls_session, ev_now(conn_.loop)); - } - } - - // Check negotiated ALPN - - const unsigned char *next_proto = nullptr; - unsigned int next_proto_len = 0; - - SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (next_proto == nullptr) { - SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - auto proto = StringRef{next_proto, next_proto_len}; - - switch (addr_->proto) { - case PROTO_HTTP1: - if (proto.empty() || proto == StringRef::from_lit("http/1.1")) { - break; - } - return -1; - case PROTO_HTTP2: - if (util::check_h2_is_selected(proto)) { - // For HTTP/2, we try to read SETTINGS ACK from server to make - // sure it is really alive, and serving HTTP/2. - read_ = &LiveCheck::read_tls; - write_ = &LiveCheck::write_tls; - - if (connection_made() != 0) { - return -1; - } - - return 0; - } - return -1; - default: - break; - } - - on_success(); - - return 0; -} - -int LiveCheck::read_tls() { - ev_timer_again(conn_.loop, &conn_.rt); - - std::array buf; - - ERR_clear_error(); - - for (;;) { - auto nread = conn_.read_tls(buf.data(), buf.size()); - - if (nread == 0) { - return 0; - } - - if (nread < 0) { - return nread; - } - - if (on_read(buf.data(), nread) != 0) { - return -1; - } - } -} - -int LiveCheck::write_tls() { - ERR_clear_error(); - - struct iovec iov; - - for (;;) { - if (wb_.rleft() > 0) { - auto iovcnt = wb_.riovec(&iov, 1); - assert(iovcnt == 1); - auto nwrite = conn_.write_tls(iov.iov_base, iov.iov_len); - - if (nwrite == 0) { - return 0; - } - - if (nwrite < 0) { - return nwrite; - } - - wb_.drain(nwrite); - - continue; - } - - if (on_write() != 0) { - return -1; - } - - if (wb_.rleft() == 0) { - conn_.start_tls_write_idle(); - break; - } - } - - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - if (settings_ack_received_) { - on_success(); - } - - return 0; -} - -int LiveCheck::read_clear() { - ev_timer_again(conn_.loop, &conn_.rt); - - std::array buf; - - for (;;) { - auto nread = conn_.read_clear(buf.data(), buf.size()); - - if (nread == 0) { - return 0; - } - - if (nread < 0) { - return nread; - } - - if (on_read(buf.data(), nread) != 0) { - return -1; - } - } -} - -int LiveCheck::write_clear() { - struct iovec iov; - - for (;;) { - if (wb_.rleft() > 0) { - auto iovcnt = wb_.riovec(&iov, 1); - assert(iovcnt == 1); - auto nwrite = conn_.write_clear(iov.iov_base, iov.iov_len); - - if (nwrite == 0) { - return 0; - } - - if (nwrite < 0) { - return nwrite; - } - - wb_.drain(nwrite); - - continue; - } - - if (on_write() != 0) { - return -1; - } - - if (wb_.rleft() == 0) { - break; - } - } - - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - if (settings_ack_received_) { - on_success(); - } - - return 0; -} - -int LiveCheck::on_read(const uint8_t *data, size_t len) { - ssize_t rv; - - rv = nghttp2_session_mem_recv(session_, data, len); - if (rv < 0) { - LOG(ERROR) << "nghttp2_session_mem_recv() returned error: " - << nghttp2_strerror(rv); - return -1; - } - - if (settings_ack_received_ && !session_closing_) { - session_closing_ = true; - rv = nghttp2_session_terminate_session(session_, NGHTTP2_NO_ERROR); - if (rv != 0) { - return -1; - } - } - - if (nghttp2_session_want_read(session_) == 0 && - nghttp2_session_want_write(session_) == 0 && wb_.rleft() == 0) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "No more read/write for this session"; - } - - // If we have SETTINGS ACK already, we treat this success. - if (settings_ack_received_) { - return 0; - } - - return -1; - } - - signal_write(); - - return 0; -} - -int LiveCheck::on_write() { - for (;;) { - const uint8_t *data; - auto datalen = nghttp2_session_mem_send(session_, &data); - - if (datalen < 0) { - LOG(ERROR) << "nghttp2_session_mem_send() returned error: " - << nghttp2_strerror(datalen); - return -1; - } - if (datalen == 0) { - break; - } - wb_.append(data, datalen); - - if (wb_.rleft() >= MAX_BUFFER_SIZE) { - break; - } - } - - if (nghttp2_session_want_read(session_) == 0 && - nghttp2_session_want_write(session_) == 0 && wb_.rleft() == 0) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "No more read/write for this session"; - } - - if (settings_ack_received_) { - return 0; - } - - return -1; - } - - return 0; -} - -void LiveCheck::on_failure() { - ++fail_count_; - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Liveness check for " << util::to_numeric_addr(&addr_->addr) - << " failed " << fail_count_ << " time(s) in a row"; - } - - disconnect(); - - schedule(); -} - -void LiveCheck::on_success() { - ++success_count_; - fail_count_ = 0; - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Liveness check for " << util::to_numeric_addr(&addr_->addr) - << " succeeded " << success_count_ << " time(s) in a row"; - } - - if (success_count_ < addr_->rise) { - disconnect(); - - schedule(); - - return; - } - - LOG(NOTICE) << util::to_numeric_addr(&addr_->addr) << " is considered online"; - - addr_->connect_blocker->online(); - - success_count_ = 0; - fail_count_ = 0; - - disconnect(); -} - -int LiveCheck::noop() { return 0; } - -void LiveCheck::start_settings_timer() { - auto &downstreamconf = get_config()->http2.downstream; - - ev_timer_set(&settings_timer_, downstreamconf.timeout.settings, 0.); - ev_timer_start(conn_.loop, &settings_timer_); -} - -void LiveCheck::stop_settings_timer() { - ev_timer_stop(conn_.loop, &settings_timer_); -} - -void LiveCheck::settings_ack_received() { settings_ack_received_ = true; } - -namespace { -int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame, - void *user_data) { - auto live_check = static_cast(user_data); - - if (frame->hd.type != NGHTTP2_SETTINGS || - (frame->hd.flags & NGHTTP2_FLAG_ACK)) { - return 0; - } - - live_check->start_settings_timer(); - - return 0; -} -} // namespace - -namespace { -int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, - void *user_data) { - auto live_check = static_cast(user_data); - - if (frame->hd.type != NGHTTP2_SETTINGS || - (frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) { - return 0; - } - - live_check->stop_settings_timer(); - live_check->settings_ack_received(); - - return 0; -} -} // namespace - -int LiveCheck::connection_made() { - int rv; - - nghttp2_session_callbacks *callbacks; - rv = nghttp2_session_callbacks_new(&callbacks); - if (rv != 0) { - return -1; - } - - nghttp2_session_callbacks_set_on_frame_send_callback(callbacks, - on_frame_send_callback); - nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, - on_frame_recv_callback); - - rv = nghttp2_session_client_new(&session_, callbacks, this); - - nghttp2_session_callbacks_del(callbacks); - - if (rv != 0) { - return -1; - } - - rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, nullptr, 0); - if (rv != 0) { - return -1; - } - - auto must_terminate = - addr_->tls && !nghttp2::ssl::check_http2_requirement(conn_.tls.ssl); - - if (must_terminate) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "TLSv1.2 was not negotiated. HTTP/2 must not be negotiated."; - } - - rv = nghttp2_session_terminate_session(session_, - NGHTTP2_INADEQUATE_SECURITY); - if (rv != 0) { - return -1; - } - } - - signal_write(); - - return 0; -} - -void LiveCheck::signal_write() { conn_.wlimit.startw(); } - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_live_check.h nghttp2-0.6.7/src/shrpx_live_check.h --- nghttp2-1.13.0/src/shrpx_live_check.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_live_check.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 SHRPX_LIVE_CHECK_H -#define SHRPX_LIVE_CHECK_H - -#include "shrpx.h" - -#include -#include - -#include - -#include - -#include - -#include "shrpx_connection.h" - -namespace shrpx { - -class Worker; -struct DownstreamAddr; - -class LiveCheck { -public: - LiveCheck(struct ev_loop *loop, SSL_CTX *ssl_ctx, Worker *worker, - DownstreamAddr *addr, std::mt19937 &gen); - ~LiveCheck(); - - void disconnect(); - - void on_success(); - void on_failure(); - - int initiate_connection(); - - // Schedules next connection attempt - void schedule(); - - // Low level I/O operation callback; they are called from do_read() - // or do_write(). - int noop(); - int connected(); - int tls_handshake(); - int read_tls(); - int write_tls(); - int read_clear(); - int write_clear(); - - int do_read(); - int do_write(); - - // These functions are used to feed / extract data to - // nghttp2_session object. - int on_read(const uint8_t *data, size_t len); - int on_write(); - - // Call this function when HTTP/2 connection was established. We - // don't call this function for HTTP/1 at the moment. - int connection_made(); - - void start_settings_timer(); - void stop_settings_timer(); - - // Call this function when SETTINGS ACK was received from server. - void settings_ack_received(); - - void signal_write(); - -private: - Connection conn_; - DefaultMemchunks wb_; - std::mt19937 &gen_; - ev_timer backoff_timer_; - ev_timer settings_timer_; - std::function read_, write_; - Worker *worker_; - // nullptr if no TLS is configured - SSL_CTX *ssl_ctx_; - // Address of remote endpoint - DownstreamAddr *addr_; - nghttp2_session *session_; - // The number of successful connect attempt in a row. - size_t success_count_; - // The number of unsuccessful connect attempt in a row. - size_t fail_count_; - // true when SETTINGS ACK has been received from server. - bool settings_ack_received_; - // true when GOAWAY has been queued. - bool session_closing_; -}; - -} // namespace shrpx - -#endif // SHRPX_LIVE_CHECK_H diff -Nru nghttp2-1.13.0/src/shrpx_log.cc nghttp2-0.6.7/src/shrpx_log.cc --- nghttp2-1.13.0/src/shrpx_log.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_log.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,17 +24,9 @@ */ #include "shrpx_log.h" -#ifdef HAVE_SYSLOG_H #include -#endif // HAVE_SYSLOG_H -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H -#ifdef HAVE_INTTYPES_H #include -#endif // HAVE_INTTYPES_H - -#include #include #include @@ -45,18 +37,15 @@ #include "shrpx_config.h" #include "shrpx_downstream.h" +#include "shrpx_worker_config.h" #include "util.h" -#include "template.h" using namespace nghttp2; namespace shrpx { namespace { -const StringRef SEVERITY_STR[] = { - StringRef::from_lit("INFO"), StringRef::from_lit("NOTICE"), - StringRef::from_lit("WARN"), StringRef::from_lit("ERROR"), - StringRef::from_lit("FATAL")}; +const char *SEVERITY_STR[] = {"INFO", "NOTICE", "WARN", "ERROR", "FATAL"}; } // namespace namespace { @@ -73,9 +62,9 @@ void Log::set_severity_level(int severity) { severity_thres_ = severity; } -int Log::set_severity_level_by_name(const StringRef &name) { - for (size_t i = 0, max = array_size(SEVERITY_STR); i < max; ++i) { - if (name == SEVERITY_STR[i]) { +int Log::set_severity_level_by_name(const char *name) { + for (size_t i = 0, max = util::array_size(SEVERITY_STR); i < max; ++i) { + if (strcmp(SEVERITY_STR[i], name) == 0) { severity_thres_ = i; return 0; } @@ -110,47 +99,42 @@ return; } - auto lgconf = log_config(); - - auto &errorconf = get_config()->logging.error; + auto wconf = worker_config; if (!log_enabled(severity_) || - (lgconf->errorlog_fd == -1 && !errorconf.syslog)) { + (wconf->errorlog_fd == -1 && !get_config()->errorlog_syslog)) { return; } - if (errorconf.syslog) { + if (get_config()->errorlog_syslog) { if (severity_ == NOTICE) { syslog(severity_to_syslog_level(severity_), "[%s] %s", - SEVERITY_STR[severity_].c_str(), stream_.str().c_str()); + SEVERITY_STR[severity_], stream_.str().c_str()); } else { syslog(severity_to_syslog_level(severity_), "[%s] %s (%s:%d)", - SEVERITY_STR[severity_].c_str(), stream_.str().c_str(), filename_, + SEVERITY_STR[severity_], stream_.str().c_str(), filename_, linenum_); } return; } - char buf[4_k]; - auto tty = lgconf->errorlog_tty; + char buf[4096]; + auto tty = wconf->errorlog_tty; - lgconf->update_tstamp(std::chrono::system_clock::now()); - auto &time_local = lgconf->time_local_str; + auto cached_time = get_config()->cached_time; if (severity_ == NOTICE) { - rv = - snprintf(buf, sizeof(buf), "%s PID%d [%s%s%s] %s\n", time_local.c_str(), - get_config()->pid, tty ? SEVERITY_COLOR[severity_] : "", - SEVERITY_STR[severity_].c_str(), tty ? "\033[0m" : "", - stream_.str().c_str()); + rv = snprintf(buf, sizeof(buf), "%s PID%d [%s%s%s] %s\n", + cached_time->c_str(), get_config()->pid, + tty ? SEVERITY_COLOR[severity_] : "", SEVERITY_STR[severity_], + tty ? "\033[0m" : "", stream_.str().c_str()); } else { rv = snprintf(buf, sizeof(buf), "%s PID%d [%s%s%s] %s%s:%d%s %s\n", - time_local.c_str(), get_config()->pid, - tty ? SEVERITY_COLOR[severity_] : "", - SEVERITY_STR[severity_].c_str(), tty ? "\033[0m" : "", - tty ? "\033[1;30m" : "", filename_, linenum_, - tty ? "\033[0m" : "", stream_.str().c_str()); + cached_time->c_str(), get_config()->pid, + tty ? SEVERITY_COLOR[severity_] : "", SEVERITY_STR[severity_], + tty ? "\033[0m" : "", tty ? "\033[1;30m" : "", filename_, + linenum_, tty ? "\033[0m" : "", stream_.str().c_str()); } if (rv < 0) { @@ -159,213 +143,104 @@ auto nwrite = std::min(static_cast(rv), sizeof(buf) - 1); - while (write(lgconf->errorlog_fd, buf, nwrite) == -1 && errno == EINTR) + while (write(wconf->errorlog_fd, buf, nwrite) == -1 && errno == EINTR) ; } namespace { template -std::pair copy(const char *src, size_t srclen, - size_t avail, OutputIterator oitr) { - auto nwrite = std::min(srclen, avail); - auto noitr = std::copy_n(src, nwrite, oitr); - return std::make_pair(noitr, avail - nwrite); -} -} // namespace - -namespace { -template std::pair copy(const char *src, size_t avail, OutputIterator oitr) { - return copy(src, strlen(src), avail, oitr); -} -} // namespace - -namespace { -template -std::pair copy(const std::string &src, size_t avail, - OutputIterator oitr) { - return copy(src.c_str(), src.size(), avail, oitr); -} -} // namespace - -namespace { -template -std::pair copy(const StringRef &src, size_t avail, - OutputIterator oitr) { - return copy(src.c_str(), src.size(), avail, oitr); -} -} // namespace - -namespace { -template -std::pair copy(const ImmutableString &src, size_t avail, - OutputIterator oitr) { - return copy(src.c_str(), src.size(), avail, oitr); -} -} // namespace - -namespace { -template -std::pair copy_l(const char(&src)[N], size_t avail, - OutputIterator oitr) { - return copy(src, N - 1, avail, oitr); -} -} // namespace - -namespace { -const char LOWER_XDIGITS[] = "0123456789abcdef"; -} // namespace - -namespace { -template -std::pair copy_hex_low(const uint8_t *src, - size_t srclen, size_t avail, - OutputIterator oitr) { - auto nwrite = std::min(srclen * 2, avail) / 2; - for (auto i = 0u; i < nwrite; ++i) { - *oitr++ = LOWER_XDIGITS[src[i] >> 4]; - *oitr++ = LOWER_XDIGITS[src[i] & 0xf]; - } - return std::make_pair(oitr, avail - nwrite); + auto nwrite = std::min(strlen(src), avail); + auto noitr = std::copy_n(src, nwrite, oitr); + return std::make_pair(noitr, avail - nwrite); } } // namespace -void upstream_accesslog(const std::vector &lfv, - const LogSpec &lgsp) { - auto lgconf = log_config(); - auto &accessconf = get_config()->logging.access; +void upstream_accesslog(const std::vector &lfv, LogSpec *lgsp) { + auto wconf = worker_config; - if (lgconf->accesslog_fd == -1 && !accessconf.syslog) { + if (wconf->accesslog_fd == -1 && !get_config()->accesslog_syslog) { return; } - char buf[4_k]; + char buf[4096]; - auto downstream = lgsp.downstream; - - const Request *req = nullptr; - if (downstream) { - req = &downstream->request(); - } + auto downstream = lgsp->downstream; auto p = buf; auto avail = sizeof(buf) - 2; - lgconf->update_tstamp(lgsp.time_now); - auto &time_local = lgconf->time_local_str; - auto &time_iso8601 = lgconf->time_iso8601_str; - for (auto &lf : lfv) { switch (lf.type) { case SHRPX_LOGF_LITERAL: - std::tie(p, avail) = copy(lf.value, avail, p); + std::tie(p, avail) = copy(lf.value.get(), avail, p); break; case SHRPX_LOGF_REMOTE_ADDR: - std::tie(p, avail) = copy(lgsp.remote_addr, avail, p); + std::tie(p, avail) = copy(lgsp->remote_addr, avail, p); break; case SHRPX_LOGF_TIME_LOCAL: - std::tie(p, avail) = copy(time_local, avail, p); + std::tie(p, avail) = + copy(util::format_common_log(lgsp->time_now).c_str(), avail, p); break; case SHRPX_LOGF_TIME_ISO8601: - std::tie(p, avail) = copy(time_iso8601, avail, p); + std::tie(p, avail) = + copy(util::format_iso8601(lgsp->time_now).c_str(), avail, p); break; case SHRPX_LOGF_REQUEST: - std::tie(p, avail) = copy(lgsp.method, avail, p); - std::tie(p, avail) = copy_l(" ", avail, p); - std::tie(p, avail) = copy(lgsp.path, avail, p); - std::tie(p, avail) = copy_l(" HTTP/", avail, p); - std::tie(p, avail) = copy(util::utos(lgsp.major), avail, p); - if (lgsp.major < 2) { - std::tie(p, avail) = copy_l(".", avail, p); - std::tie(p, avail) = copy(util::utos(lgsp.minor), avail, p); - } + std::tie(p, avail) = copy(lgsp->method, avail, p); + std::tie(p, avail) = copy(" ", avail, p); + std::tie(p, avail) = copy(lgsp->path, avail, p); + std::tie(p, avail) = copy(" HTTP/", avail, p); + std::tie(p, avail) = copy(util::utos(lgsp->major).c_str(), avail, p); + std::tie(p, avail) = copy(".", avail, p); + std::tie(p, avail) = copy(util::utos(lgsp->minor).c_str(), avail, p); break; case SHRPX_LOGF_STATUS: - std::tie(p, avail) = copy(util::utos(lgsp.status), avail, p); + std::tie(p, avail) = copy(util::utos(lgsp->status).c_str(), avail, p); break; case SHRPX_LOGF_BODY_BYTES_SENT: - std::tie(p, avail) = copy(util::utos(lgsp.body_bytes_sent), avail, p); + std::tie(p, avail) = + copy(util::utos(lgsp->body_bytes_sent).c_str(), avail, p); break; case SHRPX_LOGF_HTTP: - if (req) { - auto hd = req->fs.header(StringRef(lf.value)); - if (hd) { - std::tie(p, avail) = copy((*hd).value, avail, p); - break; - } - } - - std::tie(p, avail) = copy_l("-", avail, p); - - break; - case SHRPX_LOGF_AUTHORITY: - if (req) { - if (!req->authority.empty()) { - std::tie(p, avail) = copy(req->authority, avail, p); + if (downstream) { + auto hd = downstream->get_request_header(lf.value.get()); + if (hd != std::end(downstream->get_request_headers())) { + std::tie(p, avail) = copy((*hd).value.c_str(), avail, p); break; } } - std::tie(p, avail) = copy_l("-", avail, p); + std::tie(p, avail) = copy("-", avail, p); break; case SHRPX_LOGF_REMOTE_PORT: - std::tie(p, avail) = copy(lgsp.remote_port, avail, p); + std::tie(p, avail) = copy(lgsp->remote_port, avail, p); break; case SHRPX_LOGF_SERVER_PORT: - std::tie(p, avail) = copy(util::utos(lgsp.server_port), avail, p); + std::tie(p, avail) = + copy(util::utos(lgsp->server_port).c_str(), avail, p); break; case SHRPX_LOGF_REQUEST_TIME: { auto t = std::chrono::duration_cast( - lgsp.request_end_time - lgsp.request_start_time).count(); + lgsp->time_now - lgsp->request_start_time).count(); auto frac = util::utos(t % 1000); auto sec = util::utos(t / 1000); if (frac.size() < 3) { frac = std::string(3 - frac.size(), '0') + frac; } - sec += '.'; + sec += "."; sec += frac; - std::tie(p, avail) = copy(sec, avail, p); + std::tie(p, avail) = copy(sec.c_str(), avail, p); } break; case SHRPX_LOGF_PID: - std::tie(p, avail) = copy(util::utos(lgsp.pid), avail, p); + std::tie(p, avail) = copy(util::utos(lgsp->pid).c_str(), avail, p); break; case SHRPX_LOGF_ALPN: - std::tie(p, avail) = copy(lgsp.alpn, avail, p); - break; - case SHRPX_LOGF_SSL_CIPHER: - if (!lgsp.tls_info) { - std::tie(p, avail) = copy_l("-", avail, p); - break; - } - std::tie(p, avail) = copy(lgsp.tls_info->cipher, avail, p); - break; - case SHRPX_LOGF_SSL_PROTOCOL: - if (!lgsp.tls_info) { - std::tie(p, avail) = copy_l("-", avail, p); - break; - } - std::tie(p, avail) = copy(lgsp.tls_info->protocol, avail, p); - break; - case SHRPX_LOGF_SSL_SESSION_ID: - if (!lgsp.tls_info || lgsp.tls_info->session_id_length == 0) { - std::tie(p, avail) = copy_l("-", avail, p); - break; - } - std::tie(p, avail) = - copy_hex_low(lgsp.tls_info->session_id, - lgsp.tls_info->session_id_length, avail, p); - break; - case SHRPX_LOGF_SSL_SESSION_REUSED: - if (!lgsp.tls_info) { - std::tie(p, avail) = copy_l("-", avail, p); - break; - } - std::tie(p, avail) = - copy_l(lgsp.tls_info->session_reused ? "r" : ".", avail, p); + std::tie(p, avail) = copy(lgsp->alpn, avail, p); break; case SHRPX_LOGF_NONE: break; @@ -376,7 +251,7 @@ *p = '\0'; - if (accessconf.syslog) { + if (get_config()->accesslog_syslog) { syslog(LOG_INFO, "%s", buf); return; @@ -385,86 +260,63 @@ *p++ = '\n'; auto nwrite = p - buf; - while (write(lgconf->accesslog_fd, buf, nwrite) == -1 && errno == EINTR) + while (write(wconf->accesslog_fd, buf, nwrite) == -1 && errno == EINTR) ; } int reopen_log_files() { int res = 0; - int new_accesslog_fd = -1; - int new_errorlog_fd = -1; - auto lgconf = log_config(); - auto &accessconf = get_config()->logging.access; - auto &errorconf = get_config()->logging.error; + auto wconf = worker_config; + + if (wconf->accesslog_fd != -1) { + close(wconf->accesslog_fd); + wconf->accesslog_fd = -1; + } + + if (!get_config()->accesslog_syslog && get_config()->accesslog_file) { - if (!accessconf.syslog && !accessconf.file.empty()) { - new_accesslog_fd = util::open_log_file(accessconf.file.c_str()); + wconf->accesslog_fd = + util::reopen_log_file(get_config()->accesslog_file.get()); - if (new_accesslog_fd == -1) { - LOG(ERROR) << "Failed to open accesslog file " << accessconf.file; + if (wconf->accesslog_fd == -1) { + LOG(ERROR) << "Failed to open accesslog file " + << get_config()->accesslog_file.get(); res = -1; } } - if (!errorconf.syslog && !errorconf.file.empty()) { - new_errorlog_fd = util::open_log_file(errorconf.file.c_str()); + int new_errorlog_fd = -1; + + if (!get_config()->errorlog_syslog && get_config()->errorlog_file) { + + new_errorlog_fd = util::reopen_log_file(get_config()->errorlog_file.get()); if (new_errorlog_fd == -1) { - if (lgconf->errorlog_fd != -1) { - LOG(ERROR) << "Failed to open errorlog file " << errorconf.file; + if (wconf->errorlog_fd != -1) { + LOG(ERROR) << "Failed to open errorlog file " + << get_config()->errorlog_file.get(); } else { - std::cerr << "Failed to open errorlog file " << errorconf.file - << std::endl; + std::cerr << "Failed to open errorlog file " + << get_config()->errorlog_file.get() << std::endl; } res = -1; } } - util::close_log_file(lgconf->accesslog_fd); - util::close_log_file(lgconf->errorlog_fd); - - lgconf->accesslog_fd = new_accesslog_fd; - lgconf->errorlog_fd = new_errorlog_fd; - lgconf->errorlog_tty = - (new_errorlog_fd == -1) ? false : isatty(new_errorlog_fd); - - return res; -} - -void log_chld(pid_t pid, int rstatus, const char *msg) { - std::string signalstr; - if (WIFSIGNALED(rstatus)) { - signalstr += "; signal "; - auto sig = WTERMSIG(rstatus); - auto s = strsignal(sig); - if (s) { - signalstr += s; - signalstr += '('; - } else { - signalstr += "UNKNOWN("; - } - signalstr += util::utos(sig); - signalstr += ')'; + if (wconf->errorlog_fd != -1) { + close(wconf->errorlog_fd); + wconf->errorlog_fd = -1; + wconf->errorlog_tty = false; } - LOG(NOTICE) << msg << ": [" << pid << "] exited " - << (WIFEXITED(rstatus) ? "normally" : "abnormally") - << " with status " << std::hex << rstatus << std::oct - << "; exit status " << WEXITSTATUS(rstatus) - << (signalstr.empty() ? "" : signalstr.c_str()); -} - -void redirect_stderr_to_errorlog() { - auto lgconf = log_config(); - auto &errorconf = get_config()->logging.error; - - if (errorconf.syslog || lgconf->errorlog_fd == -1) { - return; + if (new_errorlog_fd != -1) { + wconf->errorlog_fd = new_errorlog_fd; + wconf->errorlog_tty = isatty(wconf->errorlog_fd); } - dup2(lgconf->errorlog_fd, STDERR_FILENO); + return res; } } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_log_config.cc nghttp2-0.6.7/src/shrpx_log_config.cc --- nghttp2-1.13.0/src/shrpx_log_config.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_log_config.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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. - */ -#include "shrpx_log_config.h" -#include "util.h" - -using namespace nghttp2; - -namespace shrpx { - -LogConfig::LogConfig() - : accesslog_fd(-1), errorlog_fd(-1), errorlog_tty(false) {} - -#ifndef NOTHREADS -static pthread_key_t lckey; -static pthread_once_t lckey_once = PTHREAD_ONCE_INIT; - -static void make_key(void) { pthread_key_create(&lckey, NULL); } - -LogConfig *log_config(void) { - pthread_once(&lckey_once, make_key); - LogConfig *config = (LogConfig *)pthread_getspecific(lckey); - if (!config) { - config = new LogConfig(); - pthread_setspecific(lckey, config); - } - return config; -} -#else -static LogConfig *config = new LogConfig(); -LogConfig *log_config(void) { return config; } -#endif // NOTHREADS - -void LogConfig::update_tstamp( - const std::chrono::system_clock::time_point &now) { - auto t0 = std::chrono::system_clock::to_time_t(time_str_updated_); - auto t1 = std::chrono::system_clock::to_time_t(now); - if (t0 == t1) { - return; - } - - time_str_updated_ = now; - - time_local_str = util::format_common_log(now); - time_iso8601_str = util::format_iso8601(now); - time_http_str = util::format_http_date(now); -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_log_config.h nghttp2-0.6.7/src/shrpx_log_config.h --- nghttp2-1.13.0/src/shrpx_log_config.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_log_config.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2014 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 SHRPX_LOG_CONFIG_H -#define SHRPX_LOG_CONFIG_H - -#include "shrpx.h" - -#include - -namespace shrpx { - -struct LogConfig { - std::chrono::system_clock::time_point time_str_updated_; - std::string time_local_str; - std::string time_iso8601_str; - std::string time_http_str; - int accesslog_fd; - int errorlog_fd; - // true if errorlog_fd is referring to a terminal. - bool errorlog_tty; - - LogConfig(); - void update_tstamp(const std::chrono::system_clock::time_point &now); -}; - -// We need LogConfig per thread to avoid data race around opening file -// descriptor for log files. -extern LogConfig *log_config(void); - -} // namespace shrpx - -#endif // SHRPX_LOG_CONFIG_H diff -Nru nghttp2-1.13.0/src/shrpx_log.h nghttp2-0.6.7/src/shrpx_log.h --- nghttp2-1.13.0/src/shrpx_log.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_log.h 2014-11-30 14:15:07.000000000 +0000 @@ -34,57 +34,45 @@ #include #include -#include "shrpx_log_config.h" -#include "ssl.h" -#include "template.h" +namespace shrpx { -using namespace nghttp2; +class Downstream; #define ENABLE_LOG 1 -#define LOG_ENABLED(SEVERITY) (ENABLE_LOG && shrpx::Log::log_enabled(SEVERITY)) +#define LOG_ENABLED(SEVERITY) (ENABLE_LOG && Log::log_enabled(SEVERITY)) -#define LOG(SEVERITY) shrpx::Log(SEVERITY, __FILE__, __LINE__) +#define LOG(SEVERITY) Log(SEVERITY, __FILE__, __LINE__) // Listener log #define LLOG(SEVERITY, LISTEN) \ - (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[LISTEN:" << LISTEN << "] ") + (Log(SEVERITY, __FILE__, __LINE__) << "[LISTEN:" << LISTEN << "] ") -// Worker log -#define WLOG(SEVERITY, WORKER) \ - (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[WORKER:" << WORKER << "] ") +// ThreadEventReceiver log +#define TLOG(SEVERITY, THREAD_RECV) \ + (Log(SEVERITY, __FILE__, __LINE__) << "[THREAD_RECV:" << THREAD_RECV << "]" \ + " ") // ClientHandler log #define CLOG(SEVERITY, CLIENT_HANDLER) \ - (shrpx::Log(SEVERITY, __FILE__, __LINE__) \ - << "[CLIENT_HANDLER:" << CLIENT_HANDLER << "] ") + (Log(SEVERITY, __FILE__, __LINE__) << "[CLIENT_HANDLER:" << CLIENT_HANDLER \ + << "] ") // Upstream log #define ULOG(SEVERITY, UPSTREAM) \ - (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[UPSTREAM:" << UPSTREAM \ - << "]" \ - " ") + (Log(SEVERITY, __FILE__, __LINE__) << "[UPSTREAM:" << UPSTREAM << "] ") // Downstream log #define DLOG(SEVERITY, DOWNSTREAM) \ - (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[DOWNSTREAM:" << DOWNSTREAM \ - << "] ") + (Log(SEVERITY, __FILE__, __LINE__) << "[DOWNSTREAM:" << DOWNSTREAM << "] ") // Downstream connection log #define DCLOG(SEVERITY, DCONN) \ - (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[DCONN:" << DCONN << "] ") + (Log(SEVERITY, __FILE__, __LINE__) << "[DCONN:" << DCONN << "] ") // Downstream HTTP2 session log #define SSLOG(SEVERITY, HTTP2) \ - (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[DHTTP2:" << HTTP2 << "] ") - -// Memcached connection log -#define MCLOG(SEVERITY, MCONN) \ - (shrpx::Log(SEVERITY, __FILE__, __LINE__) << "[MCONN:" << MCONN << "] ") - -namespace shrpx { - -class Downstream; + (Log(SEVERITY, __FILE__, __LINE__) << "[DHTTP2:" << HTTP2 << "] ") enum SeverityLevel { INFO, NOTICE, WARN, ERROR, FATAL }; @@ -97,7 +85,7 @@ return *this; } static void set_severity_level(int severity); - static int set_severity_level_by_name(const StringRef &name); + static int set_severity_level_by_name(const char *name); static bool log_enabled(int severity) { return severity >= severity_thres_; } private: @@ -108,8 +96,8 @@ static int severity_thres_; }; -#define TTY_HTTP_HD (log_config()->errorlog_tty ? "\033[1;34m" : "") -#define TTY_RST (log_config()->errorlog_tty ? "\033[0m" : "") +#define TTY_HTTP_HD (worker_config->errorlog_tty ? "\033[1;34m" : "") +#define TTY_RST (worker_config->errorlog_tty ? "\033[0m" : "") enum LogFragmentType { SHRPX_LOGF_NONE, @@ -121,54 +109,38 @@ SHRPX_LOGF_STATUS, SHRPX_LOGF_BODY_BYTES_SENT, SHRPX_LOGF_HTTP, - SHRPX_LOGF_AUTHORITY, SHRPX_LOGF_REMOTE_PORT, SHRPX_LOGF_SERVER_PORT, SHRPX_LOGF_REQUEST_TIME, SHRPX_LOGF_PID, SHRPX_LOGF_ALPN, - SHRPX_LOGF_SSL_CIPHER, - SHRPX_LOGF_SSL_PROTOCOL, - SHRPX_LOGF_SSL_SESSION_ID, - SHRPX_LOGF_SSL_SESSION_REUSED, }; struct LogFragment { - LogFragment(LogFragmentType type, ImmutableString value = ImmutableString()) - : type(type), value(std::move(value)) {} LogFragmentType type; - ImmutableString value; + std::unique_ptr value; }; struct LogSpec { Downstream *downstream; - StringRef remote_addr; - StringRef method; - StringRef path; - StringRef alpn; - const nghttp2::ssl::TLSSessionInfo *tls_info; - std::chrono::system_clock::time_point time_now; + const char *remote_addr; + const char *method; + const char *path; + const char *alpn; std::chrono::high_resolution_clock::time_point request_start_time; - std::chrono::high_resolution_clock::time_point request_end_time; + std::chrono::high_resolution_clock::time_point time_now; int major, minor; unsigned int status; int64_t body_bytes_sent; - StringRef remote_port; + const char *remote_port; uint16_t server_port; pid_t pid; }; -void upstream_accesslog(const std::vector &lf, - const LogSpec &lgsp); +void upstream_accesslog(const std::vector &lf, LogSpec *lgsp); int reopen_log_files(); -// Logs message when process whose pid is |pid| and exist status is -// |rstatus| exited. The |msg| is prepended to the log message. -void log_chld(pid_t pid, int rstatus, const char *msg); - -void redirect_stderr_to_errorlog(); - } // namespace shrpx #endif // SHRPX_LOG_H diff -Nru nghttp2-1.13.0/src/shrpx_memcached_connection.cc nghttp2-0.6.7/src/shrpx_memcached_connection.cc --- nghttp2-1.13.0/src/shrpx_memcached_connection.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_memcached_connection.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,785 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_memcached_connection.h" - -#include -#include - -#include - -#include "shrpx_memcached_request.h" -#include "shrpx_memcached_result.h" -#include "shrpx_config.h" -#include "shrpx_ssl.h" -#include "util.h" - -namespace shrpx { - -namespace { -void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) { - auto conn = static_cast(w->data); - auto mconn = static_cast(conn->data); - - if (LOG_ENABLED(INFO)) { - MCLOG(INFO, mconn) << "Time out"; - } - - mconn->disconnect(); -} -} // namespace - -namespace { -void readcb(struct ev_loop *loop, ev_io *w, int revents) { - auto conn = static_cast(w->data); - auto mconn = static_cast(conn->data); - - if (mconn->on_read() != 0) { - mconn->reconnect_or_fail(); - return; - } -} -} // namespace - -namespace { -void writecb(struct ev_loop *loop, ev_io *w, int revents) { - auto conn = static_cast(w->data); - auto mconn = static_cast(conn->data); - - if (mconn->on_write() != 0) { - mconn->reconnect_or_fail(); - return; - } -} -} // namespace - -namespace { -void connectcb(struct ev_loop *loop, ev_io *w, int revents) { - auto conn = static_cast(w->data); - auto mconn = static_cast(conn->data); - - if (mconn->connected() != 0) { - mconn->disconnect(); - return; - } - - writecb(loop, w, revents); -} -} // namespace - -constexpr auto write_timeout = 10_s; -constexpr auto read_timeout = 10_s; - -MemcachedConnection::MemcachedConnection(const Address *addr, - struct ev_loop *loop, SSL_CTX *ssl_ctx, - const StringRef &sni_name, - MemchunkPool *mcpool, - std::mt19937 &gen) - : conn_(loop, -1, nullptr, mcpool, write_timeout, read_timeout, {}, {}, - connectcb, readcb, timeoutcb, this, 0, 0., PROTO_MEMCACHED), - do_read_(&MemcachedConnection::noop), - do_write_(&MemcachedConnection::noop), - sni_name_(sni_name.str()), - connect_blocker_(gen, loop, [] {}, [] {}), - parse_state_{}, - addr_(addr), - ssl_ctx_(ssl_ctx), - sendsum_(0), - try_count_(0), - connected_(false) {} - -MemcachedConnection::~MemcachedConnection() { disconnect(); } - -namespace { -void clear_request(std::deque> &q) { - for (auto &req : q) { - if (req->cb) { - req->cb(req.get(), MemcachedResult(MEMCACHED_ERR_EXT_NETWORK_ERROR)); - } - } - q.clear(); -} -} // namespace - -void MemcachedConnection::disconnect() { - clear_request(recvq_); - clear_request(sendq_); - - sendbufv_.clear(); - sendsum_ = 0; - - parse_state_ = {}; - - connected_ = false; - - conn_.disconnect(); - - assert(recvbuf_.rleft() == 0); - recvbuf_.reset(); - - do_read_ = do_write_ = &MemcachedConnection::noop; -} - -int MemcachedConnection::initiate_connection() { - assert(conn_.fd == -1); - - if (ssl_ctx_) { - auto ssl = ssl::create_ssl(ssl_ctx_); - if (!ssl) { - return -1; - } - conn_.set_ssl(ssl); - } - - conn_.fd = util::create_nonblock_socket(addr_->su.storage.ss_family); - - if (conn_.fd == -1) { - auto error = errno; - MCLOG(WARN, this) << "socket() failed; errno=" << error; - - return -1; - } - - int rv; - rv = connect(conn_.fd, &addr_->su.sa, addr_->len); - if (rv != 0 && errno != EINPROGRESS) { - auto error = errno; - MCLOG(WARN, this) << "connect() failed; errno=" << error; - - close(conn_.fd); - conn_.fd = -1; - - return -1; - } - - if (ssl_ctx_) { - if (!util::numeric_host(sni_name_.c_str())) { - SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name_.c_str()); - } - - auto session = ssl::reuse_tls_session(tls_session_cache_); - if (session) { - SSL_set_session(conn_.tls.ssl, session); - SSL_SESSION_free(session); - } - - conn_.prepare_client_handshake(); - } - - if (LOG_ENABLED(INFO)) { - MCLOG(INFO, this) << "Connecting to memcached server"; - } - - ev_io_set(&conn_.wev, conn_.fd, EV_WRITE); - ev_io_set(&conn_.rev, conn_.fd, EV_READ); - - ev_set_cb(&conn_.wev, connectcb); - - conn_.wlimit.startw(); - ev_timer_again(conn_.loop, &conn_.wt); - - return 0; -} - -int MemcachedConnection::connected() { - if (!util::check_socket_connected(conn_.fd)) { - connect_blocker_.on_failure(); - - conn_.wlimit.stopw(); - - if (LOG_ENABLED(INFO)) { - MCLOG(INFO, this) << "memcached connect failed"; - } - - return -1; - } - - if (LOG_ENABLED(INFO)) { - MCLOG(INFO, this) << "connected to memcached server"; - } - - conn_.rlimit.startw(); - - ev_set_cb(&conn_.wev, writecb); - - if (conn_.tls.ssl) { - do_read_ = &MemcachedConnection::tls_handshake; - do_write_ = &MemcachedConnection::tls_handshake; - - return 0; - } - - ev_timer_stop(conn_.loop, &conn_.wt); - - connected_ = true; - - connect_blocker_.on_success(); - - do_read_ = &MemcachedConnection::read_clear; - do_write_ = &MemcachedConnection::write_clear; - - return 0; -} - -int MemcachedConnection::on_write() { return do_write_(*this); } -int MemcachedConnection::on_read() { return do_read_(*this); } - -int MemcachedConnection::tls_handshake() { - ERR_clear_error(); - - ev_timer_again(conn_.loop, &conn_.rt); - - auto rv = conn_.tls_handshake(); - if (rv == SHRPX_ERR_INPROGRESS) { - return 0; - } - - if (rv < 0) { - connect_blocker_.on_failure(); - return rv; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "SSL/TLS handshake completed"; - } - - auto &tlsconf = get_config()->tls; - - if (!tlsconf.insecure && - ssl::check_cert(conn_.tls.ssl, addr_, StringRef(sni_name_)) != 0) { - connect_blocker_.on_failure(); - return -1; - } - - if (!SSL_session_reused(conn_.tls.ssl)) { - auto tls_session = SSL_get0_session(conn_.tls.ssl); - if (tls_session) { - ssl::try_cache_tls_session(tls_session_cache_, *addr_, tls_session, - ev_now(conn_.loop)); - } - } - - ev_timer_stop(conn_.loop, &conn_.rt); - ev_timer_stop(conn_.loop, &conn_.wt); - - connected_ = true; - - connect_blocker_.on_success(); - - do_read_ = &MemcachedConnection::read_tls; - do_write_ = &MemcachedConnection::write_tls; - - return on_write(); -} - -int MemcachedConnection::write_tls() { - if (!connected_) { - return 0; - } - - if (sendq_.empty()) { - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - return 0; - } - - std::array iov; - std::array buf; - - for (; !sendq_.empty();) { - auto iovcnt = fill_request_buffer(iov.data(), iov.size()); - auto p = std::begin(buf); - for (size_t i = 0; i < iovcnt; ++i) { - auto &v = iov[i]; - auto n = std::min(static_cast(std::end(buf) - p), v.iov_len); - p = std::copy_n(static_cast(v.iov_base), n, p); - if (p == std::end(buf)) { - break; - } - } - - auto nwrite = conn_.write_tls(buf.data(), p - std::begin(buf)); - if (nwrite < 0) { - return -1; - } - if (nwrite == 0) { - return 0; - } - - drain_send_queue(nwrite); - } - - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - return 0; -} - -int MemcachedConnection::read_tls() { - if (!connected_) { - return 0; - } - - if (ev_is_active(&conn_.rt)) { - ev_timer_again(conn_.loop, &conn_.rt); - } - - for (;;) { - auto nread = conn_.read_tls(recvbuf_.last, recvbuf_.wleft()); - - if (nread == 0) { - return 0; - } - - if (nread < 0) { - return -1; - } - - recvbuf_.write(nread); - - if (parse_packet() != 0) { - return -1; - } - } - - return 0; -} - -int MemcachedConnection::write_clear() { - if (!connected_) { - return 0; - } - - if (sendq_.empty()) { - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - return 0; - } - - std::array iov; - - for (; !sendq_.empty();) { - auto iovcnt = fill_request_buffer(iov.data(), iov.size()); - auto nwrite = conn_.writev_clear(iov.data(), iovcnt); - if (nwrite < 0) { - return -1; - } - if (nwrite == 0) { - return 0; - } - - drain_send_queue(nwrite); - } - - conn_.wlimit.stopw(); - ev_timer_stop(conn_.loop, &conn_.wt); - - return 0; -} - -int MemcachedConnection::read_clear() { - if (!connected_) { - return 0; - } - - if (ev_is_active(&conn_.rt)) { - ev_timer_again(conn_.loop, &conn_.rt); - } - - for (;;) { - auto nread = conn_.read_clear(recvbuf_.last, recvbuf_.wleft()); - - if (nread == 0) { - return 0; - } - - if (nread < 0) { - return -1; - } - - recvbuf_.write(nread); - - if (parse_packet() != 0) { - return -1; - } - } - - return 0; -} - -int MemcachedConnection::parse_packet() { - auto in = recvbuf_.pos; - - for (;;) { - auto busy = false; - - switch (parse_state_.state) { - case MEMCACHED_PARSE_HEADER24: { - if (recvbuf_.last - in < 24) { - recvbuf_.drain_reset(in - recvbuf_.pos); - return 0; - } - - if (recvq_.empty()) { - MCLOG(WARN, this) - << "Response received, but there is no in-flight request."; - return -1; - } - - auto &req = recvq_.front(); - - if (*in != MEMCACHED_RES_MAGIC) { - MCLOG(WARN, this) << "Response has bad magic: " - << static_cast(*in); - return -1; - } - ++in; - - parse_state_.op = *in++; - parse_state_.keylen = util::get_uint16(in); - in += 2; - parse_state_.extralen = *in++; - // skip 1 byte reserved data type - ++in; - parse_state_.status_code = util::get_uint16(in); - in += 2; - parse_state_.totalbody = util::get_uint32(in); - in += 4; - // skip 4 bytes opaque - in += 4; - parse_state_.cas = util::get_uint64(in); - in += 8; - - if (req->op != parse_state_.op) { - MCLOG(WARN, this) - << "opcode in response does not match to the request: want " - << static_cast(req->op) << ", got " << parse_state_.op; - return -1; - } - - if (parse_state_.keylen != 0) { - MCLOG(WARN, this) << "zero length keylen expected: got " - << parse_state_.keylen; - return -1; - } - - if (parse_state_.totalbody > 16_k) { - MCLOG(WARN, this) << "totalbody is too large: got " - << parse_state_.totalbody; - return -1; - } - - if (parse_state_.op == MEMCACHED_OP_GET && - parse_state_.status_code == 0 && parse_state_.extralen == 0) { - MCLOG(WARN, this) << "response for GET does not have extra"; - return -1; - } - - if (parse_state_.totalbody < - parse_state_.keylen + parse_state_.extralen) { - MCLOG(WARN, this) << "totalbody is too short: totalbody " - << parse_state_.totalbody << ", want min " - << parse_state_.keylen + parse_state_.extralen; - return -1; - } - - if (parse_state_.extralen) { - parse_state_.state = MEMCACHED_PARSE_EXTRA; - parse_state_.read_left = parse_state_.extralen; - } else { - parse_state_.state = MEMCACHED_PARSE_VALUE; - parse_state_.read_left = parse_state_.totalbody - parse_state_.keylen - - parse_state_.extralen; - } - busy = true; - break; - } - case MEMCACHED_PARSE_EXTRA: { - // We don't use extra for now. Just read and forget. - auto n = std::min(static_cast(recvbuf_.last - in), - parse_state_.read_left); - - parse_state_.read_left -= n; - in += n; - if (parse_state_.read_left) { - recvbuf_.reset(); - return 0; - } - parse_state_.state = MEMCACHED_PARSE_VALUE; - // since we require keylen == 0, totalbody - extralen == - // valuelen - parse_state_.read_left = - parse_state_.totalbody - parse_state_.keylen - parse_state_.extralen; - busy = true; - break; - } - case MEMCACHED_PARSE_VALUE: { - auto n = std::min(static_cast(recvbuf_.last - in), - parse_state_.read_left); - - parse_state_.value.insert(std::end(parse_state_.value), in, in + n); - - parse_state_.read_left -= n; - in += n; - if (parse_state_.read_left) { - recvbuf_.reset(); - return 0; - } - - if (LOG_ENABLED(INFO)) { - if (parse_state_.status_code) { - MCLOG(INFO, this) - << "response returned error status: " << parse_state_.status_code; - } - } - - // We require at least one complete response to clear try count. - try_count_ = 0; - - auto req = std::move(recvq_.front()); - recvq_.pop_front(); - - if (sendq_.empty() && recvq_.empty()) { - ev_timer_stop(conn_.loop, &conn_.rt); - } - - if (!req->canceled && req->cb) { - req->cb(req.get(), MemcachedResult(parse_state_.status_code, - std::move(parse_state_.value))); - } - - parse_state_ = {}; - break; - } - } - - if (!busy && in == recvbuf_.last) { - break; - } - } - - assert(in == recvbuf_.last); - recvbuf_.reset(); - - return 0; -} - -#undef DEFAULT_WR_IOVCNT -#define DEFAULT_WR_IOVCNT 128 - -#if defined(IOV_MAX) && IOV_MAX < DEFAULT_WR_IOVCNT -#define MAX_WR_IOVCNT IOV_MAX -#else // !defined(IOV_MAX) || IOV_MAX >= DEFAULT_WR_IOVCNT -#define MAX_WR_IOVCNT DEFAULT_WR_IOVCNT -#endif // !defined(IOV_MAX) || IOV_MAX >= DEFAULT_WR_IOVCNT - -size_t MemcachedConnection::fill_request_buffer(struct iovec *iov, - size_t iovlen) { - if (sendsum_ == 0) { - for (auto &req : sendq_) { - if (req->canceled) { - continue; - } - if (serialized_size(req.get()) + sendsum_ > 1300) { - break; - } - sendbufv_.emplace_back(); - sendbufv_.back().req = req.get(); - make_request(&sendbufv_.back(), req.get()); - sendsum_ += sendbufv_.back().left(); - } - - if (sendsum_ == 0) { - sendq_.clear(); - return 0; - } - } - - size_t iovcnt = 0; - for (auto &buf : sendbufv_) { - if (iovcnt + 2 > iovlen) { - break; - } - - auto req = buf.req; - if (buf.headbuf.rleft()) { - iov[iovcnt++] = {buf.headbuf.pos, buf.headbuf.rleft()}; - } - if (buf.send_value_left) { - iov[iovcnt++] = {req->value.data() + req->value.size() - - buf.send_value_left, - buf.send_value_left}; - } - } - - return iovcnt; -} - -void MemcachedConnection::drain_send_queue(size_t nwrite) { - sendsum_ -= nwrite; - - while (nwrite > 0) { - auto &buf = sendbufv_.front(); - auto &req = sendq_.front(); - if (req->canceled) { - sendq_.pop_front(); - continue; - } - assert(buf.req == req.get()); - auto n = std::min(static_cast(nwrite), buf.headbuf.rleft()); - buf.headbuf.drain(n); - nwrite -= n; - n = std::min(static_cast(nwrite), buf.send_value_left); - buf.send_value_left -= n; - nwrite -= n; - - if (buf.headbuf.rleft() || buf.send_value_left) { - break; - } - sendbufv_.pop_front(); - recvq_.push_back(std::move(sendq_.front())); - sendq_.pop_front(); - } - - // start read timer only when we wait for responses. - if (recvq_.empty()) { - ev_timer_stop(conn_.loop, &conn_.rt); - } else if (!ev_is_active(&conn_.rt)) { - ev_timer_again(conn_.loop, &conn_.rt); - } -} - -size_t MemcachedConnection::serialized_size(MemcachedRequest *req) { - switch (req->op) { - case MEMCACHED_OP_GET: - return 24 + req->key.size(); - case MEMCACHED_OP_ADD: - default: - return 24 + 8 + req->key.size() + req->value.size(); - } -} - -void MemcachedConnection::make_request(MemcachedSendbuf *sendbuf, - MemcachedRequest *req) { - auto &headbuf = sendbuf->headbuf; - - std::fill(std::begin(headbuf.buf), std::end(headbuf.buf), 0); - - headbuf[0] = MEMCACHED_REQ_MAGIC; - headbuf[1] = req->op; - switch (req->op) { - case MEMCACHED_OP_GET: - util::put_uint16be(&headbuf[2], req->key.size()); - util::put_uint32be(&headbuf[8], req->key.size()); - headbuf.write(24); - break; - case MEMCACHED_OP_ADD: - util::put_uint16be(&headbuf[2], req->key.size()); - headbuf[4] = 8; - util::put_uint32be(&headbuf[8], 8 + req->key.size() + req->value.size()); - util::put_uint32be(&headbuf[28], req->expiry); - headbuf.write(32); - break; - } - - headbuf.write(req->key.c_str(), req->key.size()); - - sendbuf->send_value_left = req->value.size(); -} - -int MemcachedConnection::add_request(std::unique_ptr req) { - if (connect_blocker_.blocked()) { - return -1; - } - - sendq_.push_back(std::move(req)); - - if (connected_) { - signal_write(); - return 0; - } - - if (conn_.fd == -1 && initiate_connection() != 0) { - connect_blocker_.on_failure(); - disconnect(); - return -1; - } - - return 0; -} - -// TODO should we start write timer too? -void MemcachedConnection::signal_write() { conn_.wlimit.startw(); } - -int MemcachedConnection::noop() { return 0; } - -void MemcachedConnection::reconnect_or_fail() { - if (!connected_ || (recvq_.empty() && sendq_.empty())) { - disconnect(); - return; - } - - constexpr size_t MAX_TRY_COUNT = 3; - - if (++try_count_ >= MAX_TRY_COUNT) { - if (LOG_ENABLED(INFO)) { - MCLOG(INFO, this) << "Tried " << MAX_TRY_COUNT - << " times, and all failed. Aborting"; - } - try_count_ = 0; - disconnect(); - return; - } - - std::vector> q; - q.reserve(recvq_.size() + sendq_.size()); - - if (LOG_ENABLED(INFO)) { - MCLOG(INFO, this) << "Retry connection, enqueue " - << recvq_.size() + sendq_.size() << " request(s) again"; - } - - q.insert(std::end(q), std::make_move_iterator(std::begin(recvq_)), - std::make_move_iterator(std::end(recvq_))); - q.insert(std::end(q), std::make_move_iterator(std::begin(sendq_)), - std::make_move_iterator(std::end(sendq_))); - - recvq_.clear(); - sendq_.clear(); - - disconnect(); - - sendq_.insert(std::end(sendq_), std::make_move_iterator(std::begin(q)), - std::make_move_iterator(std::end(q))); - - if (initiate_connection() != 0) { - connect_blocker_.on_failure(); - disconnect(); - return; - } -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_memcached_connection.h nghttp2-0.6.7/src/shrpx_memcached_connection.h --- nghttp2-1.13.0/src/shrpx_memcached_connection.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_memcached_connection.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,153 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_MEMCACHED_CONNECTION_H -#define SHRPX_MEMCACHED_CONNECTION_H - -#include "shrpx.h" - -#include -#include - -#include - -#include "shrpx_connection.h" -#include "shrpx_ssl.h" -#include "shrpx_connect_blocker.h" -#include "buffer.h" -#include "network.h" - -using namespace nghttp2; - -namespace shrpx { - -struct MemcachedRequest; - -enum { - MEMCACHED_PARSE_HEADER24, - MEMCACHED_PARSE_EXTRA, - MEMCACHED_PARSE_VALUE, -}; - -// Stores state when parsing response from memcached server -struct MemcachedParseState { - // Buffer for value, dynamically allocated. - std::vector value; - // cas in response - uint64_t cas; - // keylen in response - size_t keylen; - // extralen in response - size_t extralen; - // totalbody in response. The length of value is totalbody - - // extralen - keylen. - size_t totalbody; - // Number of bytes left to read variable length field. - size_t read_left; - // Parser state; see enum above - int state; - // status_code in response - int status_code; - // op in response - int op; -}; - -struct MemcachedSendbuf { - // Buffer for header + extra + key - Buffer<512> headbuf; - // MemcachedRequest associated to this object - MemcachedRequest *req; - // Number of bytes left when sending value - size_t send_value_left; - // Returns the number of bytes this object transmits. - size_t left() const { return headbuf.rleft() + send_value_left; } -}; - -constexpr uint8_t MEMCACHED_REQ_MAGIC = 0x80; -constexpr uint8_t MEMCACHED_RES_MAGIC = 0x81; - -// MemcachedConnection implements part of memcached binary protocol. -// This is not full brown implementation. Just the part we need is -// implemented. We only use GET and ADD. -// -// https://github.com/memcached/memcached/blob/master/doc/protocol-binary.xml -// https://code.google.com/p/memcached/wiki/MemcacheBinaryProtocol -class MemcachedConnection { -public: - MemcachedConnection(const Address *addr, struct ev_loop *loop, - SSL_CTX *ssl_ctx, const StringRef &sni_name, - MemchunkPool *mcpool, std::mt19937 &gen); - ~MemcachedConnection(); - - void disconnect(); - - int add_request(std::unique_ptr req); - int initiate_connection(); - - int connected(); - int on_write(); - int on_read(); - - int write_clear(); - int read_clear(); - - int tls_handshake(); - int write_tls(); - int read_tls(); - - size_t fill_request_buffer(struct iovec *iov, size_t iovlen); - void drain_send_queue(size_t nwrite); - - void make_request(MemcachedSendbuf *sendbuf, MemcachedRequest *req); - int parse_packet(); - size_t serialized_size(MemcachedRequest *req); - - void signal_write(); - - int noop(); - - void reconnect_or_fail(); - -private: - Connection conn_; - std::deque> recvq_; - std::deque> sendq_; - std::deque sendbufv_; - std::function do_read_, do_write_; - std::string sni_name_; - ssl::TLSSessionCache tls_session_cache_; - ConnectBlocker connect_blocker_; - MemcachedParseState parse_state_; - const Address *addr_; - SSL_CTX *ssl_ctx_; - // Sum of the bytes to be transmitted in sendbufv_. - size_t sendsum_; - size_t try_count_; - bool connected_; - Buffer<8_k> recvbuf_; -}; - -} // namespace shrpx - -#endif // SHRPX_MEMCACHED_CONNECTION_H diff -Nru nghttp2-1.13.0/src/shrpx_memcached_dispatcher.cc nghttp2-0.6.7/src/shrpx_memcached_dispatcher.cc --- nghttp2-1.13.0/src/shrpx_memcached_dispatcher.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_memcached_dispatcher.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_memcached_dispatcher.h" - -#include "shrpx_memcached_request.h" -#include "shrpx_memcached_connection.h" -#include "shrpx_config.h" - -namespace shrpx { - -MemcachedDispatcher::MemcachedDispatcher(const Address *addr, - struct ev_loop *loop, SSL_CTX *ssl_ctx, - const StringRef &sni_name, - MemchunkPool *mcpool, - std::mt19937 &gen) - : loop_(loop), - mconn_(make_unique(addr, loop_, ssl_ctx, sni_name, - mcpool, gen)) {} - -MemcachedDispatcher::~MemcachedDispatcher() {} - -int MemcachedDispatcher::add_request(std::unique_ptr req) { - if (mconn_->add_request(std::move(req)) != 0) { - return -1; - } - - return 0; -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_memcached_dispatcher.h nghttp2-0.6.7/src/shrpx_memcached_dispatcher.h --- nghttp2-1.13.0/src/shrpx_memcached_dispatcher.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_memcached_dispatcher.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_MEMCACHED_DISPATCHER_H -#define SHRPX_MEMCACHED_DISPATCHER_H - -#include "shrpx.h" - -#include -#include - -#include - -#include - -#include "memchunk.h" -#include "network.h" - -namespace shrpx { - -struct MemcachedRequest; -class MemcachedConnection; - -class MemcachedDispatcher { -public: - MemcachedDispatcher(const Address *addr, struct ev_loop *loop, - SSL_CTX *ssl_ctx, const StringRef &sni_name, - MemchunkPool *mcpool, std::mt19937 &gen); - ~MemcachedDispatcher(); - - int add_request(std::unique_ptr req); - -private: - struct ev_loop *loop_; - std::unique_ptr mconn_; -}; - -} // namespace shrpx - -#endif // SHRPX_MEMCACHED_DISPATCHER_H diff -Nru nghttp2-1.13.0/src/shrpx_memcached_request.h nghttp2-0.6.7/src/shrpx_memcached_request.h --- nghttp2-1.13.0/src/shrpx_memcached_request.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_memcached_request.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_MEMCACHED_REQUEST_H -#define SHRPX_MEMCACHED_REQUEST_H - -#include "shrpx.h" - -#include -#include -#include - -#include "shrpx_memcached_result.h" - -namespace shrpx { - -enum { - MEMCACHED_OP_GET = 0x00, - MEMCACHED_OP_ADD = 0x02, -}; - -struct MemcachedRequest; - -using MemcachedResultCallback = - std::function; - -struct MemcachedRequest { - std::string key; - std::vector value; - MemcachedResultCallback cb; - uint32_t expiry; - int op; - bool canceled; -}; - -} // namespace shrpx - -#endif // SHRPX_MEMCACHED_REQUEST_H diff -Nru nghttp2-1.13.0/src/shrpx_memcached_result.h nghttp2-0.6.7/src/shrpx_memcached_result.h --- nghttp2-1.13.0/src/shrpx_memcached_result.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_memcached_result.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_MEMCACHED_RESULT_H -#define SHRPX_MEMCACHED_RESULT_H - -#include "shrpx.h" - -#include - -namespace shrpx { - -enum MemcachedStatusCode { - MEMCACHED_ERR_NO_ERROR, - MEMCACHED_ERR_EXT_NETWORK_ERROR = 0x1001, -}; - -struct MemcachedResult { - MemcachedResult(int status_code) : status_code(status_code) {} - MemcachedResult(int status_code, std::vector value) - : value(std::move(value)), status_code(status_code) {} - - std::vector value; - int status_code; -}; - -} // namespace shrpx - -#endif // SHRPX_MEMCACHED_RESULT_H diff -Nru nghttp2-1.13.0/src/shrpx_mruby.cc nghttp2-0.6.7/src/shrpx_mruby.cc --- nghttp2-1.13.0/src/shrpx_mruby.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_mruby.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,234 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_mruby.h" - -#include -#include - -#include "shrpx_downstream.h" -#include "shrpx_config.h" -#include "shrpx_mruby_module.h" -#include "shrpx_downstream_connection.h" - -namespace shrpx { - -namespace mruby { - -MRubyContext::MRubyContext(mrb_state *mrb, mrb_value app, mrb_value env) - : mrb_(mrb), app_(std::move(app)), env_(std::move(env)) {} - -MRubyContext::~MRubyContext() { - if (mrb_) { - mrb_close(mrb_); - } -} - -int MRubyContext::run_app(Downstream *downstream, int phase) { - if (!mrb_) { - return 0; - } - - MRubyAssocData data{downstream, phase}; - - mrb_->ud = &data; - - int rv = 0; - auto ai = mrb_gc_arena_save(mrb_); - auto ai_d = defer([ai, this]() { mrb_gc_arena_restore(mrb_, ai); }); - - const char *method; - switch (phase) { - case PHASE_REQUEST: - if (!mrb_respond_to(mrb_, app_, mrb_intern_lit(mrb_, "on_req"))) { - return 0; - } - method = "on_req"; - break; - case PHASE_RESPONSE: - if (!mrb_respond_to(mrb_, app_, mrb_intern_lit(mrb_, "on_resp"))) { - return 0; - } - method = "on_resp"; - break; - default: - assert(0); - } - - auto res = mrb_funcall(mrb_, app_, method, 1, env_); - (void)res; - - if (mrb_->exc) { - // If response has been committed, ignore error - if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { - rv = -1; - } - - auto exc = mrb_obj_value(mrb_->exc); - auto inspect = mrb_inspect(mrb_, exc); - - LOG(ERROR) << "Exception caught while executing mruby code: " - << mrb_str_to_cstr(mrb_, inspect); - } - - mrb_->ud = nullptr; - - return rv; -} - -int MRubyContext::run_on_request_proc(Downstream *downstream) { - return run_app(downstream, PHASE_REQUEST); -} - -int MRubyContext::run_on_response_proc(Downstream *downstream) { - return run_app(downstream, PHASE_RESPONSE); -} - -void MRubyContext::delete_downstream(Downstream *downstream) { - if (!mrb_) { - return; - } - delete_downstream_from_module(mrb_, downstream); -} - -namespace { -mrb_value instantiate_app(mrb_state *mrb, RProc *proc) { - mrb->ud = nullptr; - - auto res = mrb_run(mrb, proc, mrb_top_self(mrb)); - - if (mrb->exc) { - auto exc = mrb_obj_value(mrb->exc); - auto inspect = mrb_inspect(mrb, exc); - - LOG(ERROR) << "Exception caught while executing mruby code: " - << mrb_str_to_cstr(mrb, inspect); - - return mrb_nil_value(); - } - - return res; -} -} // namespace - -// Based on -// https://github.com/h2o/h2o/blob/master/lib/handler/mruby.c. It is -// very hard to write these kind of code because mruby has almost no -// documentation aobut compiling or generating code, at least at the -// time of this writing. -RProc *compile(mrb_state *mrb, const StringRef &filename) { - if (filename.empty()) { - return nullptr; - } - - auto infile = fopen(filename.c_str(), "rb"); - if (infile == nullptr) { - return nullptr; - } - auto infile_d = defer(fclose, infile); - - auto mrbc = mrbc_context_new(mrb); - if (mrbc == nullptr) { - LOG(ERROR) << "mrb_context_new failed"; - return nullptr; - } - auto mrbc_d = defer(mrbc_context_free, mrb, mrbc); - - auto parser = mrb_parse_file(mrb, infile, nullptr); - if (parser == nullptr) { - LOG(ERROR) << "mrb_parse_nstring failed"; - return nullptr; - } - auto parser_d = defer(mrb_parser_free, parser); - - if (parser->nerr != 0) { - LOG(ERROR) << "mruby parser detected parse error"; - return nullptr; - } - - auto proc = mrb_generate_code(mrb, parser); - if (proc == nullptr) { - LOG(ERROR) << "mrb_generate_code failed"; - return nullptr; - } - - return proc; -} - -std::unique_ptr create_mruby_context(const StringRef &filename) { - if (filename.empty()) { - return make_unique(nullptr, mrb_nil_value(), mrb_nil_value()); - } - - auto mrb = mrb_open(); - if (mrb == nullptr) { - LOG(ERROR) << "mrb_open failed"; - return nullptr; - } - - auto ai = mrb_gc_arena_save(mrb); - - auto req_proc = compile(mrb, filename); - - if (!req_proc) { - mrb_gc_arena_restore(mrb, ai); - LOG(ERROR) << "Could not compile mruby code " << filename; - mrb_close(mrb); - return nullptr; - } - - auto env = init_module(mrb); - - auto app = instantiate_app(mrb, req_proc); - if (mrb_nil_p(app)) { - mrb_gc_arena_restore(mrb, ai); - LOG(ERROR) << "Could not instantiate mruby app from " << filename; - mrb_close(mrb); - return nullptr; - } - - mrb_gc_arena_restore(mrb, ai); - - // TODO These are not necessary, because we retain app and env? - mrb_gc_protect(mrb, env); - mrb_gc_protect(mrb, app); - - return make_unique(mrb, std::move(app), std::move(env)); -} - -mrb_sym intern_ptr(mrb_state *mrb, void *ptr) { - auto p = reinterpret_cast(ptr); - - return mrb_intern(mrb, reinterpret_cast(&p), sizeof(p)); -} - -void check_phase(mrb_state *mrb, int phase, int phase_mask) { - if ((phase & phase_mask) == 0) { - mrb_raise(mrb, E_RUNTIME_ERROR, "operation was not allowed in this phase"); - } -} - -} // namespace mruby - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_mruby.h nghttp2-0.6.7/src/shrpx_mruby.h --- nghttp2-1.13.0/src/shrpx_mruby.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_mruby.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_MRUBY_H -#define SHRPX_MRUBY_H - -#include "shrpx.h" - -#include - -#include -#include - -#include "template.h" - -using namespace nghttp2; - -namespace shrpx { - -namespace mruby { - -class MRubyContext { -public: - MRubyContext(mrb_state *mrb, mrb_value app, mrb_value env); - ~MRubyContext(); - - int run_on_request_proc(Downstream *downstream); - int run_on_response_proc(Downstream *downstream); - - int run_app(Downstream *downstream, int phase); - - void delete_downstream(Downstream *downstream); - -private: - mrb_state *mrb_; - mrb_value app_; - mrb_value env_; -}; - -enum { - PHASE_NONE = 0, - PHASE_REQUEST = 1, - PHASE_RESPONSE = 1 << 1, -}; - -struct MRubyAssocData { - Downstream *downstream; - int phase; -}; - -RProc *compile(mrb_state *mrb, const StringRef &filename); - -std::unique_ptr create_mruby_context(const StringRef &filename); - -// Return interned |ptr|. -mrb_sym intern_ptr(mrb_state *mrb, void *ptr); - -// Checks that |phase| is set in |phase_mask|. If not set, raise -// exception. -void check_phase(mrb_state *mrb, int phase, int phase_mask); - -} // namespace mruby - -} // namespace shrpx - -#endif // SHRPX_MRUBY_H diff -Nru nghttp2-1.13.0/src/shrpx_mruby_module.cc nghttp2-0.6.7/src/shrpx_mruby_module.cc --- nghttp2-1.13.0/src/shrpx_mruby_module.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_mruby_module.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_mruby_module.h" - -#include - -#include -#include -#include -#include - -#include "shrpx_mruby.h" -#include "shrpx_mruby_module_env.h" -#include "shrpx_mruby_module_request.h" -#include "shrpx_mruby_module_response.h" - -namespace shrpx { - -namespace mruby { - -namespace { -mrb_value create_env(mrb_state *mrb) { - auto module = mrb_module_get(mrb, "Nghttpx"); - - auto env_class = mrb_class_get_under(mrb, module, "Env"); - auto request_class = mrb_class_get_under(mrb, module, "Request"); - auto response_class = mrb_class_get_under(mrb, module, "Response"); - - auto env = mrb_obj_new(mrb, env_class, 0, nullptr); - auto req = mrb_obj_new(mrb, request_class, 0, nullptr); - auto resp = mrb_obj_new(mrb, response_class, 0, nullptr); - - mrb_iv_set(mrb, env, mrb_intern_lit(mrb, "req"), req); - mrb_iv_set(mrb, env, mrb_intern_lit(mrb, "resp"), resp); - - return env; -} -} // namespace - -void delete_downstream_from_module(mrb_state *mrb, Downstream *downstream) { - auto module = mrb_module_get(mrb, "Nghttpx"); - auto env = mrb_obj_iv_get(mrb, reinterpret_cast(module), - mrb_intern_lit(mrb, "env")); - if (mrb_nil_p(env)) { - return; - } - - mrb_iv_remove(mrb, env, intern_ptr(mrb, downstream)); -} - -mrb_value init_module(mrb_state *mrb) { - auto module = mrb_define_module(mrb, "Nghttpx"); - - mrb_define_const(mrb, module, "REQUEST_PHASE", - mrb_fixnum_value(PHASE_REQUEST)); - mrb_define_const(mrb, module, "RESPONSE_PHASE", - mrb_fixnum_value(PHASE_RESPONSE)); - - init_env_class(mrb, module); - init_request_class(mrb, module); - init_response_class(mrb, module); - - return create_env(mrb); -} - -mrb_value create_headers_hash(mrb_state *mrb, const HeaderRefs &headers) { - auto hash = mrb_hash_new(mrb); - - for (auto &hd : headers) { - if (hd.name.empty() || hd.name[0] == ':') { - continue; - } - auto ai = mrb_gc_arena_save(mrb); - - auto key = mrb_str_new(mrb, hd.name.c_str(), hd.name.size()); - auto ary = mrb_hash_get(mrb, hash, key); - if (mrb_nil_p(ary)) { - ary = mrb_ary_new(mrb); - mrb_hash_set(mrb, hash, key, ary); - } - mrb_ary_push(mrb, ary, mrb_str_new(mrb, hd.value.c_str(), hd.value.size())); - - mrb_gc_arena_restore(mrb, ai); - } - - return hash; -} - -} // namespace mruby - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_mruby_module_env.cc nghttp2-0.6.7/src/shrpx_mruby_module_env.cc --- nghttp2-1.13.0/src/shrpx_mruby_module_env.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_mruby_module_env.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,151 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_mruby_module_env.h" - -#include -#include -#include - -#include "shrpx_downstream.h" -#include "shrpx_upstream.h" -#include "shrpx_client_handler.h" -#include "shrpx_mruby.h" -#include "shrpx_mruby_module.h" - -namespace shrpx { - -namespace mruby { - -namespace { -mrb_value env_init(mrb_state *mrb, mrb_value self) { return self; } -} // namespace - -namespace { -mrb_value env_get_req(mrb_state *mrb, mrb_value self) { - return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "req")); -} -} // namespace - -namespace { -mrb_value env_get_resp(mrb_state *mrb, mrb_value self) { - return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "resp")); -} -} // namespace - -namespace { -mrb_value env_get_ctx(mrb_state *mrb, mrb_value self) { - auto data = reinterpret_cast(mrb->ud); - auto downstream = data->downstream; - - auto dsym = intern_ptr(mrb, downstream); - - auto ctx = mrb_iv_get(mrb, self, dsym); - if (mrb_nil_p(ctx)) { - ctx = mrb_hash_new(mrb); - mrb_iv_set(mrb, self, dsym, ctx); - } - - return ctx; -} -} // namespace - -namespace { -mrb_value env_get_phase(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - - return mrb_fixnum_value(data->phase); -} -} // namespace - -namespace { -mrb_value env_get_remote_addr(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto upstream = downstream->get_upstream(); - auto handler = upstream->get_client_handler(); - - auto &ipaddr = handler->get_ipaddr(); - - return mrb_str_new(mrb, ipaddr.c_str(), ipaddr.size()); -} -} // namespace - -namespace { -mrb_value env_get_server_port(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto upstream = downstream->get_upstream(); - auto handler = upstream->get_client_handler(); - auto faddr = handler->get_upstream_addr(); - - return mrb_fixnum_value(faddr->port); -} -} // namespace - -namespace { -mrb_value env_get_server_addr(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto upstream = downstream->get_upstream(); - auto handler = upstream->get_client_handler(); - auto faddr = handler->get_upstream_addr(); - - return mrb_str_new(mrb, faddr->host.c_str(), faddr->host.size()); -} -} // namespace - -namespace { -mrb_value env_get_tls_used(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto upstream = downstream->get_upstream(); - auto handler = upstream->get_client_handler(); - - return handler->get_ssl() ? mrb_true_value() : mrb_false_value(); -} -} // namespace - -void init_env_class(mrb_state *mrb, RClass *module) { - auto env_class = - mrb_define_class_under(mrb, module, "Env", mrb->object_class); - - mrb_define_method(mrb, env_class, "initialize", env_init, MRB_ARGS_NONE()); - mrb_define_method(mrb, env_class, "req", env_get_req, MRB_ARGS_NONE()); - mrb_define_method(mrb, env_class, "resp", env_get_resp, MRB_ARGS_NONE()); - mrb_define_method(mrb, env_class, "ctx", env_get_ctx, MRB_ARGS_NONE()); - mrb_define_method(mrb, env_class, "phase", env_get_phase, MRB_ARGS_NONE()); - mrb_define_method(mrb, env_class, "remote_addr", env_get_remote_addr, - MRB_ARGS_NONE()); - mrb_define_method(mrb, env_class, "server_addr", env_get_server_addr, - MRB_ARGS_NONE()); - mrb_define_method(mrb, env_class, "server_port", env_get_server_port, - MRB_ARGS_NONE()); - mrb_define_method(mrb, env_class, "tls_used", env_get_tls_used, - MRB_ARGS_NONE()); -} - -} // namespace mruby - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_mruby_module_env.h nghttp2-0.6.7/src/shrpx_mruby_module_env.h --- nghttp2-1.13.0/src/shrpx_mruby_module_env.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_mruby_module_env.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_MRUBY_MODULE_ENV_H -#define SHRPX_MRUBY_MODULE_ENV_H - -#include "shrpx.h" - -#include - -using namespace nghttp2; - -namespace shrpx { - -namespace mruby { - -void init_env_class(mrb_state *mrb, RClass *module); - -} // namespace mruby - -} // namespace shrpx - -#endif // SHRPX_MRUBY_MODULE_ENV_H diff -Nru nghttp2-1.13.0/src/shrpx_mruby_module.h nghttp2-0.6.7/src/shrpx_mruby_module.h --- nghttp2-1.13.0/src/shrpx_mruby_module.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_mruby_module.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_MRUBY_MODULE_H -#define SHRPX_MRUBY_MODULE_H - -#include "shrpx.h" - -#include - -#include "http2.h" - -using namespace nghttp2; - -namespace shrpx { - -class Downstream; - -namespace mruby { - -mrb_value init_module(mrb_state *mrb); - -void delete_downstream_from_module(mrb_state *mrb, Downstream *downstream); - -mrb_value create_headers_hash(mrb_state *mrb, const HeaderRefs &headers); - -} // namespace mruby - -} // namespace shrpx - -#endif // SHRPX_MRUBY_MODULE_H diff -Nru nghttp2-1.13.0/src/shrpx_mruby_module_request.cc nghttp2-0.6.7/src/shrpx_mruby_module_request.cc --- nghttp2-1.13.0/src/shrpx_mruby_module_request.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_mruby_module_request.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,354 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_mruby_module_request.h" - -#include -#include -#include -#include - -#include "shrpx_downstream.h" -#include "shrpx_upstream.h" -#include "shrpx_client_handler.h" -#include "shrpx_mruby.h" -#include "shrpx_mruby_module.h" -#include "util.h" -#include "http2.h" - -namespace shrpx { - -namespace mruby { - -namespace { -mrb_value request_init(mrb_state *mrb, mrb_value self) { return self; } -} // namespace - -namespace { -mrb_value request_get_http_version_major(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &req = downstream->request(); - return mrb_fixnum_value(req.http_major); -} -} // namespace - -namespace { -mrb_value request_get_http_version_minor(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &req = downstream->request(); - return mrb_fixnum_value(req.http_minor); -} -} // namespace - -namespace { -mrb_value request_get_method(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &req = downstream->request(); - auto method = http2::to_method_string(req.method); - - return mrb_str_new(mrb, method.c_str(), method.size()); -} -} // namespace - -namespace { -mrb_value request_set_method(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto &req = downstream->request(); - - check_phase(mrb, data->phase, PHASE_REQUEST); - - const char *method; - mrb_int n; - mrb_get_args(mrb, "s", &method, &n); - if (n == 0) { - mrb_raise(mrb, E_RUNTIME_ERROR, "method must not be empty string"); - } - auto token = - http2::lookup_method_token(reinterpret_cast(method), n); - if (token == -1) { - mrb_raise(mrb, E_RUNTIME_ERROR, "method not supported"); - } - - req.method = token; - - return self; -} -} // namespace - -namespace { -mrb_value request_get_authority(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &req = downstream->request(); - - return mrb_str_new(mrb, req.authority.c_str(), req.authority.size()); -} -} // namespace - -namespace { -mrb_value request_set_authority(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto &req = downstream->request(); - - auto &balloc = downstream->get_block_allocator(); - - check_phase(mrb, data->phase, PHASE_REQUEST); - - const char *authority; - mrb_int n; - mrb_get_args(mrb, "s", &authority, &n); - if (n == 0) { - mrb_raise(mrb, E_RUNTIME_ERROR, "authority must not be empty string"); - } - - req.authority = - make_string_ref(balloc, StringRef{authority, static_cast(n)}); - - return self; -} -} // namespace - -namespace { -mrb_value request_get_scheme(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &req = downstream->request(); - - return mrb_str_new(mrb, req.scheme.c_str(), req.scheme.size()); -} -} // namespace - -namespace { -mrb_value request_set_scheme(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto &req = downstream->request(); - - auto &balloc = downstream->get_block_allocator(); - - check_phase(mrb, data->phase, PHASE_REQUEST); - - const char *scheme; - mrb_int n; - mrb_get_args(mrb, "s", &scheme, &n); - if (n == 0) { - mrb_raise(mrb, E_RUNTIME_ERROR, "scheme must not be empty string"); - } - - req.scheme = - make_string_ref(balloc, StringRef{scheme, static_cast(n)}); - - return self; -} -} // namespace - -namespace { -mrb_value request_get_path(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &req = downstream->request(); - - return mrb_str_new(mrb, req.path.c_str(), req.path.size()); -} -} // namespace - -namespace { -mrb_value request_set_path(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto &req = downstream->request(); - - auto &balloc = downstream->get_block_allocator(); - - check_phase(mrb, data->phase, PHASE_REQUEST); - - const char *path; - mrb_int pathlen; - mrb_get_args(mrb, "s", &path, &pathlen); - - req.path = - make_string_ref(balloc, StringRef{path, static_cast(pathlen)}); - - return self; -} -} // namespace - -namespace { -mrb_value request_get_headers(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &req = downstream->request(); - return create_headers_hash(mrb, req.fs.headers()); -} -} // namespace - -namespace { -mrb_value request_mod_header(mrb_state *mrb, mrb_value self, bool repl) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto &req = downstream->request(); - auto &balloc = downstream->get_block_allocator(); - - check_phase(mrb, data->phase, PHASE_REQUEST); - - mrb_value key, values; - mrb_get_args(mrb, "oo", &key, &values); - - if (RSTRING_LEN(key) == 0) { - mrb_raise(mrb, E_RUNTIME_ERROR, "empty key is not allowed"); - } - - key = mrb_funcall(mrb, key, "downcase", 0); - - auto keyref = - make_string_ref(balloc, StringRef{RSTRING_PTR(key), - static_cast(RSTRING_LEN(key))}); - auto token = http2::lookup_token(keyref.byte(), keyref.size()); - - if (repl) { - size_t p = 0; - auto &headers = req.fs.headers(); - for (size_t i = 0; i < headers.size(); ++i) { - auto &kv = headers[i]; - if (kv.name == keyref) { - continue; - } - if (i != p) { - headers[p++] = std::move(kv); - } - } - headers.resize(p); - } - - if (mrb_obj_is_instance_of(mrb, values, mrb->array_class)) { - auto n = mrb_ary_len(mrb, values); - for (int i = 0; i < n; ++i) { - auto value = mrb_ary_entry(values, i); - req.fs.add_header_token( - keyref, - make_string_ref(balloc, - StringRef{RSTRING_PTR(value), - static_cast(RSTRING_LEN(value))}), - false, token); - } - } else if (!mrb_nil_p(values)) { - req.fs.add_header_token( - keyref, - make_string_ref(balloc, - StringRef{RSTRING_PTR(values), - static_cast(RSTRING_LEN(values))}), - false, token); - } - - return mrb_nil_value(); -} -} // namespace - -namespace { -mrb_value request_set_header(mrb_state *mrb, mrb_value self) { - return request_mod_header(mrb, self, true); -} -} // namespace - -namespace { -mrb_value request_add_header(mrb_state *mrb, mrb_value self) { - return request_mod_header(mrb, self, false); -} -} // namespace - -namespace { -mrb_value request_clear_headers(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto &req = downstream->request(); - - check_phase(mrb, data->phase, PHASE_REQUEST); - - req.fs.clear_headers(); - - return mrb_nil_value(); -} -} // namespace - -namespace { -mrb_value request_push(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto upstream = downstream->get_upstream(); - - const char *uri; - mrb_int len; - mrb_get_args(mrb, "s", &uri, &len); - - upstream->initiate_push(downstream, StringRef{uri, static_cast(len)}); - - return mrb_nil_value(); -} -} // namespace - -void init_request_class(mrb_state *mrb, RClass *module) { - auto request_class = - mrb_define_class_under(mrb, module, "Request", mrb->object_class); - - mrb_define_method(mrb, request_class, "initialize", request_init, - MRB_ARGS_NONE()); - mrb_define_method(mrb, request_class, "http_version_major", - request_get_http_version_major, MRB_ARGS_NONE()); - mrb_define_method(mrb, request_class, "http_version_minor", - request_get_http_version_minor, MRB_ARGS_NONE()); - mrb_define_method(mrb, request_class, "method", request_get_method, - MRB_ARGS_NONE()); - mrb_define_method(mrb, request_class, "method=", request_set_method, - MRB_ARGS_REQ(1)); - mrb_define_method(mrb, request_class, "authority", request_get_authority, - MRB_ARGS_NONE()); - mrb_define_method(mrb, request_class, "authority=", request_set_authority, - MRB_ARGS_REQ(1)); - mrb_define_method(mrb, request_class, "scheme", request_get_scheme, - MRB_ARGS_NONE()); - mrb_define_method(mrb, request_class, "scheme=", request_set_scheme, - MRB_ARGS_REQ(1)); - mrb_define_method(mrb, request_class, "path", request_get_path, - MRB_ARGS_NONE()); - mrb_define_method(mrb, request_class, "path=", request_set_path, - MRB_ARGS_REQ(1)); - mrb_define_method(mrb, request_class, "headers", request_get_headers, - MRB_ARGS_NONE()); - mrb_define_method(mrb, request_class, "add_header", request_add_header, - MRB_ARGS_REQ(2)); - mrb_define_method(mrb, request_class, "set_header", request_set_header, - MRB_ARGS_REQ(2)); - mrb_define_method(mrb, request_class, "clear_headers", request_clear_headers, - MRB_ARGS_NONE()); - mrb_define_method(mrb, request_class, "push", request_push, MRB_ARGS_REQ(1)); -} - -} // namespace mruby - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_mruby_module_request.h nghttp2-0.6.7/src/shrpx_mruby_module_request.h --- nghttp2-1.13.0/src/shrpx_mruby_module_request.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_mruby_module_request.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_MRUBY_MODULE_REQUEST_H -#define SHRPX_MRUBY_MODULE_REQUEST_H - -#include "shrpx.h" - -#include - -using namespace nghttp2; - -namespace shrpx { - -namespace mruby { - -void init_request_class(mrb_state *mrb, RClass *module); - -} // namespace mruby - -} // namespace shrpx - -#endif // SHRPX_MRUBY_MODULE_REQUEST_H diff -Nru nghttp2-1.13.0/src/shrpx_mruby_module_response.cc nghttp2-0.6.7/src/shrpx_mruby_module_response.cc --- nghttp2-1.13.0/src/shrpx_mruby_module_response.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_mruby_module_response.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,282 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_mruby_module_response.h" - -#include -#include -#include -#include - -#include "shrpx_downstream.h" -#include "shrpx_upstream.h" -#include "shrpx_client_handler.h" -#include "shrpx_mruby.h" -#include "shrpx_mruby_module.h" -#include "util.h" -#include "http2.h" - -namespace shrpx { - -namespace mruby { - -namespace { -mrb_value response_init(mrb_state *mrb, mrb_value self) { return self; } -} // namespace - -namespace { -mrb_value response_get_http_version_major(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &resp = downstream->response(); - return mrb_fixnum_value(resp.http_major); -} -} // namespace - -namespace { -mrb_value response_get_http_version_minor(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &resp = downstream->response(); - return mrb_fixnum_value(resp.http_minor); -} -} // namespace - -namespace { -mrb_value response_get_status(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &resp = downstream->response(); - return mrb_fixnum_value(resp.http_status); -} -} // namespace - -namespace { -mrb_value response_set_status(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto &resp = downstream->response(); - - mrb_int status; - mrb_get_args(mrb, "i", &status); - // We don't support 1xx status code for mruby scripting yet. - if (status < 200 || status > 999) { - mrb_raise(mrb, E_RUNTIME_ERROR, - "invalid status; it should be [200, 999], inclusive"); - } - - resp.http_status = status; - - return self; -} -} // namespace - -namespace { -mrb_value response_get_headers(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - const auto &resp = downstream->response(); - - return create_headers_hash(mrb, resp.fs.headers()); -} -} // namespace - -namespace { -mrb_value response_mod_header(mrb_state *mrb, mrb_value self, bool repl) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto &resp = downstream->response(); - auto &balloc = downstream->get_block_allocator(); - - mrb_value key, values; - mrb_get_args(mrb, "oo", &key, &values); - - if (RSTRING_LEN(key) == 0) { - mrb_raise(mrb, E_RUNTIME_ERROR, "empty key is not allowed"); - } - - key = mrb_funcall(mrb, key, "downcase", 0); - - auto keyref = - make_string_ref(balloc, StringRef{RSTRING_PTR(key), - static_cast(RSTRING_LEN(key))}); - auto token = http2::lookup_token(keyref.byte(), keyref.size()); - - if (repl) { - size_t p = 0; - auto &headers = resp.fs.headers(); - for (size_t i = 0; i < headers.size(); ++i) { - auto &kv = headers[i]; - if (kv.name == keyref) { - continue; - } - if (i != p) { - headers[p++] = std::move(kv); - } - } - headers.resize(p); - } - - if (mrb_obj_is_instance_of(mrb, values, mrb->array_class)) { - auto n = mrb_ary_len(mrb, values); - for (int i = 0; i < n; ++i) { - auto value = mrb_ary_entry(values, i); - resp.fs.add_header_token( - keyref, - make_string_ref(balloc, - StringRef{RSTRING_PTR(value), - static_cast(RSTRING_LEN(value))}), - false, token); - } - } else if (!mrb_nil_p(values)) { - resp.fs.add_header_token( - keyref, - make_string_ref(balloc, - StringRef{RSTRING_PTR(values), - static_cast(RSTRING_LEN(values))}), - false, token); - } - - return mrb_nil_value(); -} -} // namespace - -namespace { -mrb_value response_set_header(mrb_state *mrb, mrb_value self) { - return response_mod_header(mrb, self, true); -} -} // namespace - -namespace { -mrb_value response_add_header(mrb_state *mrb, mrb_value self) { - return response_mod_header(mrb, self, false); -} -} // namespace - -namespace { -mrb_value response_clear_headers(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto &resp = downstream->response(); - - resp.fs.clear_headers(); - - return mrb_nil_value(); -} -} // namespace - -namespace { -mrb_value response_return(mrb_state *mrb, mrb_value self) { - auto data = static_cast(mrb->ud); - auto downstream = data->downstream; - auto &resp = downstream->response(); - int rv; - - auto &balloc = downstream->get_block_allocator(); - - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - mrb_raise(mrb, E_RUNTIME_ERROR, "response has already been committed"); - } - - const char *val; - mrb_int vallen; - mrb_get_args(mrb, "|s", &val, &vallen); - - const uint8_t *body = nullptr; - size_t bodylen = 0; - - if (resp.http_status == 0) { - resp.http_status = 200; - } - - if (downstream->expect_response_body() && vallen > 0) { - body = reinterpret_cast(val); - bodylen = vallen; - } - - auto content_length = util::make_string_ref_uint(balloc, bodylen); - - auto cl = resp.fs.header(http2::HD_CONTENT_LENGTH); - if (cl) { - cl->value = content_length; - } else { - resp.fs.add_header_token(StringRef::from_lit("content-length"), - content_length, false, http2::HD_CONTENT_LENGTH); - } - resp.fs.content_length = bodylen; - - auto date = resp.fs.header(http2::HD_DATE); - if (!date) { - auto lgconf = log_config(); - lgconf->update_tstamp(std::chrono::system_clock::now()); - resp.fs.add_header_token( - StringRef::from_lit("date"), - make_string_ref(balloc, StringRef{lgconf->time_http_str}), false, - http2::HD_DATE); - } - - auto upstream = downstream->get_upstream(); - - rv = upstream->send_reply(downstream, body, bodylen); - if (rv != 0) { - mrb_raise(mrb, E_RUNTIME_ERROR, "could not send response"); - } - - auto handler = upstream->get_client_handler(); - - handler->signal_write(); - - return self; -} -} // namespace - -void init_response_class(mrb_state *mrb, RClass *module) { - auto response_class = - mrb_define_class_under(mrb, module, "Response", mrb->object_class); - - mrb_define_method(mrb, response_class, "initialize", response_init, - MRB_ARGS_NONE()); - mrb_define_method(mrb, response_class, "http_version_major", - response_get_http_version_major, MRB_ARGS_NONE()); - mrb_define_method(mrb, response_class, "http_version_minor", - response_get_http_version_minor, MRB_ARGS_NONE()); - mrb_define_method(mrb, response_class, "status", response_get_status, - MRB_ARGS_NONE()); - mrb_define_method(mrb, response_class, "status=", response_set_status, - MRB_ARGS_REQ(1)); - mrb_define_method(mrb, response_class, "headers", response_get_headers, - MRB_ARGS_NONE()); - mrb_define_method(mrb, response_class, "add_header", response_add_header, - MRB_ARGS_REQ(2)); - mrb_define_method(mrb, response_class, "set_header", response_set_header, - MRB_ARGS_REQ(2)); - mrb_define_method(mrb, response_class, "clear_headers", - response_clear_headers, MRB_ARGS_NONE()); - mrb_define_method(mrb, response_class, "return", response_return, - MRB_ARGS_OPT(1)); -} - -} // namespace mruby - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_mruby_module_response.h nghttp2-0.6.7/src/shrpx_mruby_module_response.h --- nghttp2-1.13.0/src/shrpx_mruby_module_response.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_mruby_module_response.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_MRUBY_MODULE_RESPONSE_H -#define SHRPX_MRUBY_MODULE_RESPONSE_H - -#include "shrpx.h" - -#include - -using namespace nghttp2; - -namespace shrpx { - -namespace mruby { - -void init_response_class(mrb_state *mrb, RClass *module); - -} // namespace mruby - -} // namespace shrpx - -#endif // SHRPX_MRUBY_MODULE_RESPONSE_H diff -Nru nghttp2-1.13.0/src/shrpx_process.h nghttp2-0.6.7/src/shrpx_process.h --- nghttp2-1.13.0/src/shrpx_process.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_process.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_PROCESS_H -#define SHRPX_PROCESS_H - -#include "shrpx.h" - -namespace shrpx { - -constexpr uint8_t SHRPX_IPC_REOPEN_LOG = 1; -constexpr uint8_t SHRPX_IPC_GRACEFUL_SHUTDOWN = 2; - -} // namespace shrpx - -#endif // SHRPX_PROCESS_H diff -Nru nghttp2-1.13.0/src/shrpx_rate_limit.cc nghttp2-0.6.7/src/shrpx_rate_limit.cc --- nghttp2-1.13.0/src/shrpx_rate_limit.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_rate_limit.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_rate_limit.h" - -#include - -#include "shrpx_connection.h" - -namespace shrpx { - -namespace { -void regencb(struct ev_loop *loop, ev_timer *w, int revents) { - auto r = static_cast(w->data); - r->regen(); -} -} // namespace - -RateLimit::RateLimit(struct ev_loop *loop, ev_io *w, size_t rate, size_t burst, - Connection *conn) - : w_(w), - loop_(loop), - conn_(conn), - rate_(rate), - burst_(burst), - avail_(burst), - startw_req_(false) { - ev_timer_init(&t_, regencb, 0., 1.); - t_.data = this; - if (rate_ > 0) { - ev_timer_again(loop_, &t_); - } -} - -RateLimit::~RateLimit() { ev_timer_stop(loop_, &t_); } - -size_t RateLimit::avail() const { - if (rate_ == 0) { - return std::numeric_limits::max(); - } - return avail_; -} - -void RateLimit::drain(size_t n) { - if (rate_ == 0) { - return; - } - n = std::min(avail_, n); - avail_ -= n; - if (avail_ == 0) { - ev_io_stop(loop_, w_); - } -} - -void RateLimit::regen() { - if (rate_ == 0) { - return; - } - if (avail_ + rate_ > burst_) { - avail_ = burst_; - } else { - avail_ += rate_; - } - - if (avail_ > 0 && startw_req_) { - ev_io_start(loop_, w_); - handle_tls_pending_read(); - } -} - -void RateLimit::startw() { - startw_req_ = true; - if (rate_ == 0 || avail_ > 0) { - ev_io_start(loop_, w_); - handle_tls_pending_read(); - return; - } -} - -void RateLimit::stopw() { - startw_req_ = false; - ev_io_stop(loop_, w_); -} - -void RateLimit::handle_tls_pending_read() { - if (!conn_ || !conn_->tls.ssl || - (SSL_pending(conn_->tls.ssl) == 0 && conn_->tls.rbuf.rleft() == 0)) { - return; - } - - // Note that ev_feed_event works without starting watcher, but we - // only call this function if watcher is active. - ev_feed_event(loop_, w_, EV_READ); -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_rate_limit.h nghttp2-0.6.7/src/shrpx_rate_limit.h --- nghttp2-1.13.0/src/shrpx_rate_limit.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_rate_limit.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_RATE_LIMIT_H -#define SHRPX_RATE_LIMIT_H - -#include "shrpx.h" - -#include - -#include - -namespace shrpx { - -struct Connection; - -class RateLimit { -public: - // We need |conn| object to check that it has unread bytes for TLS - // connection. - RateLimit(struct ev_loop *loop, ev_io *w, size_t rate, size_t burst, - Connection *conn = nullptr); - ~RateLimit(); - size_t avail() const; - void drain(size_t n); - void regen(); - void startw(); - void stopw(); - // Feeds event if conn_->tls object has unread bytes. This is - // required since it is buffered in conn_->tls object, io event is - // not generated unless new incoming data is received. - void handle_tls_pending_read(); - -private: - ev_timer t_; - ev_io *w_; - struct ev_loop *loop_; - Connection *conn_; - size_t rate_; - size_t burst_; - size_t avail_; - bool startw_req_; -}; - -} // namespace shrpx - -#endif // SHRPX_RATE_LIMIT_H diff -Nru nghttp2-1.13.0/src/shrpx_router.cc nghttp2-0.6.7/src/shrpx_router.cc --- nghttp2-1.13.0/src/shrpx_router.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_router.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,369 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_router.h" - -#include - -#include "shrpx_config.h" - -namespace shrpx { - -RNode::RNode() : s(nullptr), len(0), index(-1) {} - -RNode::RNode(const char *s, size_t len, size_t index) - : s(s), len(len), index(index) {} - -Router::Router() : balloc_(1024, 1024), root_{} {} - -Router::~Router() {} - -namespace { -RNode *find_next_node(const RNode *node, char c) { - auto itr = std::lower_bound(std::begin(node->next), std::end(node->next), c, - [](const std::unique_ptr &lhs, - const char c) { return lhs->s[0] < c; }); - if (itr == std::end(node->next) || (*itr)->s[0] != c) { - return nullptr; - } - - return (*itr).get(); -} -} // namespace - -namespace { -void add_next_node(RNode *node, std::unique_ptr new_node) { - auto itr = std::lower_bound(std::begin(node->next), std::end(node->next), - new_node->s[0], - [](const std::unique_ptr &lhs, - const char c) { return lhs->s[0] < c; }); - node->next.insert(itr, std::move(new_node)); -} -} // namespace - -void Router::add_node(RNode *node, const char *pattern, size_t patlen, - size_t index) { - auto pat = make_string_ref(balloc_, StringRef{pattern, patlen}); - auto new_node = make_unique(pat.c_str(), pat.size(), index); - add_next_node(node, std::move(new_node)); -} - -bool Router::add_route(const StringRef &pattern, size_t index) { - auto node = &root_; - size_t i = 0; - - for (;;) { - auto next_node = find_next_node(node, pattern[i]); - if (next_node == nullptr) { - add_node(node, pattern.c_str() + i, pattern.size() - i, index); - return true; - } - - node = next_node; - - auto slen = pattern.size() - i; - auto s = pattern.c_str() + i; - auto n = std::min(node->len, slen); - size_t j; - for (j = 0; j < n && node->s[j] == s[j]; ++j) - ; - if (j == n) { - // The common prefix was matched - if (slen == node->len) { - // Complete match - if (node->index != -1) { - // Don't allow duplicate - return false; - } - node->index = index; - return true; - } - - if (slen > node->len) { - // We still have pattern to add - i += j; - - continue; - } - } - - if (node->len > j) { - // node must be split into 2 nodes. new_node is now the child - // of node. - auto new_node = - make_unique(&node->s[j], node->len - j, node->index); - std::swap(node->next, new_node->next); - - node->len = j; - node->index = -1; - - add_next_node(node, std::move(new_node)); - - if (slen == j) { - node->index = index; - return true; - } - } - - i += j; - - assert(pattern.size() > i); - add_node(node, pattern.c_str() + i, pattern.size() - i, index); - - return true; - } -} - -namespace { -const RNode *match_complete(size_t *offset, const RNode *node, - const char *first, const char *last) { - *offset = 0; - - if (first == last) { - return node; - } - - auto p = first; - - for (;;) { - auto next_node = find_next_node(node, *p); - if (next_node == nullptr) { - return nullptr; - } - - node = next_node; - - auto n = std::min(node->len, static_cast(last - p)); - if (memcmp(node->s, p, n) != 0) { - return nullptr; - } - p += n; - if (p == last) { - *offset = n; - return node; - } - } -} -} // namespace - -namespace { -const RNode *match_partial(const RNode *node, size_t offset, const char *first, - const char *last) { - if (first == last) { - if (node->len == offset) { - return node; - } - return nullptr; - } - - auto p = first; - - const RNode *found_node = nullptr; - - if (offset > 0) { - auto n = std::min(node->len - offset, static_cast(last - first)); - if (memcmp(node->s + offset, first, n) != 0) { - return nullptr; - } - - p += n; - - if (p == last) { - if (node->len == offset + n) { - if (node->index != -1) { - return node; - } - - return nullptr; - } - - if (node->index != -1 && offset + n + 1 == node->len && - node->s[node->len - 1] == '/') { - return node; - } - - return nullptr; - } - - if (node->index != -1 && node->s[node->len - 1] == '/') { - found_node = node; - } - - assert(node->len == offset + n); - } - - for (;;) { - auto next_node = find_next_node(node, *p); - if (next_node == nullptr) { - return found_node; - } - - node = next_node; - - auto n = std::min(node->len, static_cast(last - p)); - if (memcmp(node->s, p, n) != 0) { - return found_node; - } - - p += n; - - if (p == last) { - if (node->len == n) { - // Complete match with this node - if (node->index != -1) { - return node; - } - - return found_node; - } - - // We allow match without trailing "/" at the end of pattern. - // So, if pattern ends with '/', and pattern and path matches - // without that slash, we consider they match to deal with - // request to the directory without trailing slash. That is if - // pattern is "/foo/" and path is "/foo", we consider they - // match. - if (node->index != -1 && n + 1 == node->len && node->s[n] == '/') { - return node; - } - - return found_node; - } - - // This is the case when pattern which ends with "/" is included - // in query. - if (node->index != -1 && node->s[node->len - 1] == '/') { - found_node = node; - } - - assert(node->len == n); - } -} -} // namespace - -ssize_t Router::match(const StringRef &host, const StringRef &path) const { - const RNode *node; - size_t offset; - - node = match_complete(&offset, &root_, std::begin(host), std::end(host)); - if (node == nullptr) { - return -1; - } - - node = match_partial(node, offset, std::begin(path), std::end(path)); - if (node == nullptr || node == &root_) { - return -1; - } - - return node->index; -} - -ssize_t Router::match(const StringRef &s) const { - const RNode *node; - size_t offset; - - node = match_complete(&offset, &root_, std::begin(s), std::end(s)); - if (node == nullptr) { - return -1; - } - - if (node->len != offset) { - return -1; - } - - return node->index; -} - -namespace { -const RNode *match_prefix(size_t *nread, const RNode *node, const char *first, - const char *last) { - if (first == last) { - return nullptr; - } - - auto p = first; - - for (;;) { - auto next_node = find_next_node(node, *p); - if (next_node == nullptr) { - return nullptr; - } - - node = next_node; - - auto n = std::min(node->len, static_cast(last - p)); - if (memcmp(node->s, p, n) != 0) { - return nullptr; - } - - p += n; - - if (p != last) { - if (node->index != -1) { - *nread = p - first; - return node; - } - continue; - } - - if (node->len == n) { - *nread = p - first; - return node; - } - - return nullptr; - } -} -} // namespace - -ssize_t Router::match_prefix(size_t *nread, const RNode **last_node, - const StringRef &s) const { - if (*last_node == nullptr) { - *last_node = &root_; - } - - auto node = - ::shrpx::match_prefix(nread, *last_node, std::begin(s), std::end(s)); - if (node == nullptr) { - return -1; - } - - *last_node = node; - - return node->index; -} - -namespace { -void dump_node(const RNode *node, int depth) { - fprintf(stderr, "%*ss='%.*s', len=%zu, index=%zd\n", depth, "", - (int)node->len, node->s, node->len, node->index); - for (auto &nd : node->next) { - dump_node(nd.get(), depth + 4); - } -} -} // namespace - -void Router::dump() const { dump_node(&root_, 0); } - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_router.h nghttp2-0.6.7/src/shrpx_router.h --- nghttp2-1.13.0/src/shrpx_router.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_router.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_ROUTER_H -#define SHRPX_ROUTER_H - -#include "shrpx.h" - -#include -#include - -#include "allocator.h" - -namespace shrpx { - -struct RNode { - RNode(); - RNode(const char *s, size_t len, size_t index); - RNode(RNode &&) = default; - RNode(const RNode &) = delete; - RNode &operator=(RNode &&) = default; - RNode &operator=(const RNode &) = delete; - - // Next RNode, sorted by s[0]. - std::vector> next; - // Stores pointer to the string this node represents. Not - // NULL-terminated. - const char *s; - // Length of |s| - size_t len; - // Index of pattern if match ends in this node. Note that we don't - // store duplicated pattern. - ssize_t index; -}; - -class Router { -public: - Router(); - ~Router(); - Router(Router &&) = default; - Router(const Router &) = delete; - Router &operator=(Router &&) = default; - Router &operator=(const Router &) = delete; - - // Adds route |pattern| with its |index|. - bool add_route(const StringRef &pattern, size_t index); - // Returns the matched index of pattern. -1 if there is no match. - ssize_t match(const StringRef &host, const StringRef &path) const; - // Returns the matched index of pattern |s|. -1 if there is no - // match. - ssize_t match(const StringRef &s) const; - // Returns the matched index of pattern if a pattern is a suffix of - // |s|, otherwise -1. If |*last_node| is not nullptr, it specifies - // the first node to start matching. If it is nullptr, match will - // start from scratch. When the match was found (the return value - // is not -1), |*nread| has the number of bytes matched in |s|, and - // |*last_node| has the last matched node. One can continue to - // match the longer pattern using the returned |*last_node| to the - // another invocation of this function until it returns -1. - ssize_t match_prefix(size_t *nread, const RNode **last_node, - const StringRef &s) const; - - void add_node(RNode *node, const char *pattern, size_t patlen, size_t index); - - void dump() const; - -private: - BlockAllocator balloc_; - // The root node of Patricia tree. This is special node and its s - // field is nulptr, and len field is 0. - RNode root_; -}; - -} // namespace shrpx - -#endif // SHRPX_ROUTER_H diff -Nru nghttp2-1.13.0/src/shrpx_router_test.cc nghttp2-0.6.7/src/shrpx_router_test.cc --- nghttp2-1.13.0/src/shrpx_router_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_router_test.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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. - */ -#include "shrpx_router_test.h" - -#include - -#include "shrpx_router.h" - -namespace shrpx { - -struct Pattern { - StringRef pattern; - size_t idx; -}; - -void test_shrpx_router_match(void) { - auto patterns = std::vector{ - {StringRef::from_lit("nghttp2.org/"), 0}, - {StringRef::from_lit("nghttp2.org/alpha"), 1}, - {StringRef::from_lit("nghttp2.org/alpha/"), 2}, - {StringRef::from_lit("nghttp2.org/alpha/bravo/"), 3}, - {StringRef::from_lit("www.nghttp2.org/alpha/"), 4}, - {StringRef::from_lit("/alpha"), 5}, - {StringRef::from_lit("example.com/alpha/"), 6}, - }; - - Router router; - - for (auto &p : patterns) { - router.add_route(p.pattern, p.idx); - } - - ssize_t idx; - - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/")); - - CU_ASSERT(0 == idx); - - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha")); - - CU_ASSERT(1 == idx); - - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/")); - - CU_ASSERT(2 == idx); - - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/charlie")); - - CU_ASSERT(2 == idx); - - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/")); - - CU_ASSERT(3 == idx); - - // matches pattern when last '/' is missing in path - idx = router.match(StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo")); - - idx = router.match(StringRef{}, StringRef::from_lit("/alpha")); - - CU_ASSERT(5 == idx); -} - -void test_shrpx_router_match_prefix(void) { - auto patterns = std::vector{ - {StringRef::from_lit("gro.2ptthgn."), 0}, - {StringRef::from_lit("gro.2ptthgn.www."), 1}, - {StringRef::from_lit("gro.2ptthgn.gmi."), 2}, - {StringRef::from_lit("gro.2ptthgn.gmi.ahpla."), 3}, - }; - - Router router; - - for (auto &p : patterns) { - router.add_route(p.pattern, p.idx); - } - - ssize_t idx; - const RNode *node; - size_t nread; - - node = nullptr; - - idx = router.match_prefix(&nread, &node, - StringRef::from_lit("gro.2ptthgn.gmi.ahpla.ovarb")); - - CU_ASSERT(0 == idx); - CU_ASSERT(12 == nread); - - idx = router.match_prefix(&nread, &node, - StringRef::from_lit("gmi.ahpla.ovarb")); - - CU_ASSERT(2 == idx); - CU_ASSERT(4 == nread); - - idx = router.match_prefix(&nread, &node, StringRef::from_lit("ahpla.ovarb")); - - CU_ASSERT(3 == idx); - CU_ASSERT(6 == nread); -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_router_test.h nghttp2-0.6.7/src/shrpx_router_test.h --- nghttp2-1.13.0/src/shrpx_router_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_router_test.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 SHRPX_ROUTER_TEST_H -#define SHRPX_ROUTER_TEST_H - -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - -namespace shrpx { - -void test_shrpx_router_match(void); -void test_shrpx_router_match_prefix(void); - -} // namespace shrpx - -#endif // SHRPX_ROUTER_TEST_H diff -Nru nghttp2-1.13.0/src/shrpx_signal.cc nghttp2-0.6.7/src/shrpx_signal.cc --- nghttp2-1.13.0/src/shrpx_signal.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_signal.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,137 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_signal.h" - -#include - -#include "template.h" - -using namespace nghttp2; - -namespace shrpx { - -int shrpx_signal_block_all(sigset_t *oldset) { - sigset_t newset; - - sigfillset(&newset); - -#ifndef NOTHREADS - int rv; - - rv = pthread_sigmask(SIG_SETMASK, &newset, oldset); - - if (rv != 0) { - errno = rv; - return -1; - } - - return 0; -#else // NOTHREADS - return sigprocmask(SIG_SETMASK, &newset, oldset); -#endif // NOTHREADS -} - -int shrpx_signal_unblock_all() { - sigset_t newset; - - sigemptyset(&newset); - -#ifndef NOTHREADS - int rv; - - rv = pthread_sigmask(SIG_SETMASK, &newset, nullptr); - - if (rv != 0) { - errno = rv; - return -1; - } - - return 0; -#else // NOTHREADS - return sigprocmask(SIG_SETMASK, &newset, nullptr); -#endif // NOTHREADS -} - -int shrpx_signal_set(sigset_t *set) { -#ifndef NOTHREADS - int rv; - - rv = pthread_sigmask(SIG_SETMASK, set, nullptr); - - if (rv != 0) { - errno = rv; - return -1; - } - - return 0; -#else // NOTHREADS - return sigprocmask(SIG_SETMASK, set, nullptr); -#endif // NOTHREADS -} - -namespace { -template -void signal_set_handler(void (*handler)(int), Signals &&sigs) { - struct sigaction act {}; - act.sa_handler = handler; - sigemptyset(&act.sa_mask); - int rv; - for (auto sig : sigs) { - rv = sigaction(sig, &act, nullptr); - if (rv != 0) { - auto error = errno; - LOG(WARN) << "sigaction() with signal " << sig - << " failed: errno=" << error; - } - } -} -} // namespace - -namespace { -constexpr auto master_proc_ign_signals = std::array{{SIGPIPE}}; -} // namespace - -namespace { -constexpr auto worker_proc_ign_signals = std::array{ - {REOPEN_LOG_SIGNAL, EXEC_BINARY_SIGNAL, GRACEFUL_SHUTDOWN_SIGNAL, SIGPIPE}}; -} // namespace - -void shrpx_signal_set_master_proc_ign_handler() { - signal_set_handler(SIG_IGN, master_proc_ign_signals); -} - -void shrpx_signal_unset_master_proc_ign_handler() { - signal_set_handler(SIG_DFL, master_proc_ign_signals); -} - -void shrpx_signal_set_worker_proc_ign_handler() { - signal_set_handler(SIG_IGN, worker_proc_ign_signals); -} - -void shrpx_signal_unset_worker_proc_ign_handler() { - signal_set_handler(SIG_DFL, worker_proc_ign_signals); -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_signal.h nghttp2-0.6.7/src/shrpx_signal.h --- nghttp2-1.13.0/src/shrpx_signal.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_signal.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_SIGNAL_H -#define SHRPX_SIGNAL_H - -#include "shrpx.h" - -#include - -namespace shrpx { - -constexpr int REOPEN_LOG_SIGNAL = SIGUSR1; -constexpr int EXEC_BINARY_SIGNAL = SIGUSR2; -constexpr int GRACEFUL_SHUTDOWN_SIGNAL = SIGQUIT; - -// Blocks all signals. The previous signal mask is stored into -// |oldset| if it is not nullptr. This function returns 0 if it -// succeeds, or -1. The errno will indicate the error. -int shrpx_signal_block_all(sigset_t *oldset); - -// Unblocks all signals. This function returns 0 if it succeeds, or -// -1. The errno will indicate the error. -int shrpx_signal_unblock_all(); - -// Sets signal mask |set|. This function returns 0 if it succeeds, or -// -1. The errno will indicate the error. -int shrpx_signal_set(sigset_t *set); - -void shrpx_signal_set_master_proc_ign_handler(); -void shrpx_signal_unset_master_proc_ign_handler(); - -void shrpx_signal_set_worker_proc_ign_handler(); -void shrpx_signal_unset_worker_proc_ign_handler(); - -} // namespace shrpx - -#endif // SHRPX_SIGNAL_H diff -Nru nghttp2-1.13.0/src/shrpx_spdy_upstream.cc nghttp2-0.6.7/src/shrpx_spdy_upstream.cc --- nghttp2-1.13.0/src/shrpx_spdy_upstream.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_spdy_upstream.cc 2014-11-30 14:15:07.000000000 +0000 @@ -36,58 +36,56 @@ #include "shrpx_downstream_connection.h" #include "shrpx_config.h" #include "shrpx_http.h" -#ifdef HAVE_MRUBY -#include "shrpx_mruby.h" -#endif // HAVE_MRUBY -#include "shrpx_worker.h" -#include "shrpx_http2_session.h" +#include "shrpx_worker_config.h" #include "http2.h" #include "util.h" -#include "template.h" using namespace nghttp2; namespace shrpx { namespace { -constexpr size_t MAX_BUFFER_SIZE = 32_k; +const size_t OUTBUF_MAX_THRES = 16 * 1024; +const size_t INBUF_MAX_THRES = 16 * 1024; } // namespace namespace { ssize_t send_callback(spdylay_session *session, const uint8_t *data, size_t len, int flags, void *user_data) { + int rv; auto upstream = static_cast(user_data); - auto wb = upstream->get_response_buf(); + auto handler = upstream->get_client_handler(); - if (wb->rleft() >= MAX_BUFFER_SIZE) { + // Check buffer length and return WOULDBLOCK if it is large enough. + if (handler->get_outbuf_length() + upstream->sendbuf.get_buflen() >= + OUTBUF_MAX_THRES) { return SPDYLAY_ERR_WOULDBLOCK; } - wb->append(data, len); - + rv = upstream->sendbuf.add(data, len); + if (rv != 0) { + ULOG(FATAL, upstream) << "evbuffer_add() failed"; + return SPDYLAY_ERR_CALLBACK_FAILURE; + } return len; } } // namespace namespace { -ssize_t recv_callback(spdylay_session *session, uint8_t *buf, size_t len, +ssize_t recv_callback(spdylay_session *session, uint8_t *data, size_t len, int flags, void *user_data) { auto upstream = static_cast(user_data); auto handler = upstream->get_client_handler(); - auto rb = handler->get_rb(); - auto rlimit = handler->get_rlimit(); - - if (rb->rleft() == 0) { + auto bev = handler->get_bev(); + auto input = bufferevent_get_input(bev); + int nread = evbuffer_remove(input, data, len); + if (nread == -1) { + return SPDYLAY_ERR_CALLBACK_FAILURE; + } else if (nread == 0) { return SPDYLAY_ERR_WOULDBLOCK; + } else { + return nread; } - - auto nread = std::min(rb->rleft(), len); - - memcpy(buf, rb->pos, nread); - rb->drain(nread); - rlimit->startw(); - - return nread; } } // namespace @@ -100,17 +98,14 @@ ULOG(INFO, upstream) << "Stream stream_id=" << stream_id << " is being closed"; } - auto downstream = static_cast( - spdylay_session_get_stream_user_data(session, stream_id)); + auto downstream = upstream->find_downstream(stream_id); if (!downstream) { return; } - auto &req = downstream->request(); + upstream->consume(stream_id, downstream->get_request_datalen()); - upstream->consume(stream_id, req.unconsumed_body_length); - - req.unconsumed_body_length = 0; + downstream->reset_request_datalen(); if (downstream->get_request_state() == Downstream::CONNECT_FAIL) { upstream->remove_downstream(downstream); @@ -119,12 +114,19 @@ return; } - if (downstream->can_detach_downstream_connection()) { - // Keep-alive - downstream->detach_downstream_connection(); - } - downstream->set_request_state(Downstream::STREAM_CLOSED); + if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { + // At this point, downstream response was read + if (!downstream->get_upgraded() && + !downstream->get_response_connection_close()) { + // Keep-alive + downstream->detach_downstream_connection(); + } + upstream->remove_downstream(downstream); + // downstrea was deleted + + return; + } // At this point, downstream read may be paused. @@ -143,7 +145,6 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { auto upstream = static_cast(user_data); - switch (type) { case SPDYLAY_SYN_STREAM: { if (LOG_ENABLED(INFO)) { @@ -151,169 +152,87 @@ << frame->syn_stream.stream_id; } - auto downstream = - upstream->add_pending_downstream(frame->syn_stream.stream_id); - - auto &req = downstream->request(); - - auto &balloc = downstream->get_block_allocator(); + auto downstream = upstream->add_pending_downstream( + frame->syn_stream.stream_id, frame->syn_stream.pri); + downstream->init_upstream_timer(); downstream->reset_upstream_rtimer(); + downstream->init_response_body_buf(); auto nv = frame->syn_stream.nv; + const char *path = nullptr; + const char *scheme = nullptr; + const char *host = nullptr; + const char *method = nullptr; + const char *content_length = nullptr; - if (LOG_ENABLED(INFO)) { - std::stringstream ss; - for (size_t i = 0; nv[i]; i += 2) { - ss << TTY_HTTP_HD << nv[i] << TTY_RST << ": " << nv[i + 1] << "\n"; - } - ULOG(INFO, upstream) << "HTTP request headers. stream_id=" - << downstream->get_stream_id() << "\n" << ss.str(); - } - - size_t num_headers = 0; - size_t header_buffer = 0; for (size_t i = 0; nv[i]; i += 2) { - ++num_headers; - // shut up scan-build - assert(nv[i + 1]); - header_buffer += strlen(nv[i]) + strlen(nv[i + 1]); - } - - auto &httpconf = get_config()->http; - - // spdy does not define usage of trailer fields, and we ignores - // them. - if (header_buffer > httpconf.request_header_field_buffer || - num_headers > httpconf.max_request_header_fields) { - upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); - return; - } - - for (size_t i = 0; nv[i]; i += 2) { - auto name = StringRef{nv[i]}; - auto value = StringRef{nv[i + 1]}; - auto token = http2::lookup_token(name.byte(), name.size()); - req.fs.add_header_token(make_string_ref(balloc, StringRef{name}), - make_string_ref(balloc, StringRef{value}), false, - token); - } - - if (req.fs.parse_content_length() != 0) { - if (upstream->error_reply(downstream, 400) != 0) { - ULOG(FATAL, upstream) << "error_reply failed"; - } - return; - } - - auto path = req.fs.header(http2::HD__PATH); - auto scheme = req.fs.header(http2::HD__SCHEME); - auto host = req.fs.header(http2::HD__HOST); - auto method = req.fs.header(http2::HD__METHOD); - - if (!method) { - upstream->rst_stream(downstream, SPDYLAY_PROTOCOL_ERROR); - return; - } - - auto method_token = http2::lookup_method_token(method->value); - if (method_token == -1) { - if (upstream->error_reply(downstream, 501) != 0) { - ULOG(FATAL, upstream) << "error_reply failed"; + if (strcmp(nv[i], ":path") == 0) { + path = nv[i + 1]; + } else if (strcmp(nv[i], ":scheme") == 0) { + scheme = nv[i + 1]; + } else if (strcmp(nv[i], ":method") == 0) { + method = nv[i + 1]; + } else if (strcmp(nv[i], ":host") == 0) { + host = nv[i + 1]; + } else if (nv[i][0] != ':') { + if (strcmp(nv[i], "content-length") == 0) { + content_length = nv[i + 1]; + } + downstream->add_request_header(nv[i], nv[i + 1]); } - return; } - auto is_connect = method_token == HTTP_CONNECT; - if (!path || !host || !http2::non_empty_value(host) || - !http2::non_empty_value(path) || - (!is_connect && (!scheme || !http2::non_empty_value(scheme)))) { - upstream->rst_stream(downstream, SPDYLAY_PROTOCOL_ERROR); - return; - } + downstream->normalize_request_headers(); - if (std::find_if(std::begin(host->value), std::end(host->value), - [](char c) { return c == '"' || c == '\\'; }) != - std::end(host->value)) { - if (upstream->error_reply(downstream, 400) != 0) { - ULOG(FATAL, upstream) << "error_reply failed"; - } + bool is_connect = method && strcmp("CONNECT", method) == 0; + if (!path || !host || !method || http2::lws(host) || http2::lws(path) || + http2::lws(method) || + (!is_connect && (!scheme || http2::lws(scheme)))) { + upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); return; } - - if (scheme) { - for (auto c : scheme->value) { - if (!(util::is_alpha(c) || util::is_digit(c) || c == '+' || c == '-' || - c == '.')) { - if (upstream->error_reply(downstream, 400) != 0) { - ULOG(FATAL, upstream) << "error_reply failed"; - } - return; - } - } - } - - // For other than CONNECT method, path must start with "/", except - // for OPTIONS method, which can take "*" as path. - if (!is_connect && path->value[0] != '/' && - (method_token != HTTP_OPTIONS || path->value != "*")) { + // Require content-length if FIN flag is not set. + if (!is_connect && !content_length && + (frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN) == 0) { upstream->rst_stream(downstream, SPDYLAY_PROTOCOL_ERROR); return; } - req.method = method_token; + downstream->set_request_method(method); if (is_connect) { - req.authority = path->value; + downstream->set_request_http2_authority(path); } else { - req.scheme = scheme->value; - req.authority = host->value; - if (get_config()->http2_proxy) { - req.path = path->value; - } else if (method_token == HTTP_OPTIONS && - path->value == StringRef::from_lit("*")) { - // Server-wide OPTIONS request. Path is empty. - } else { - req.path = http2::rewrite_clean_path(balloc, path->value); - } + downstream->set_request_http2_scheme(scheme); + downstream->set_request_http2_authority(host); + downstream->set_request_path(path); } + downstream->set_request_start_time( + std::chrono::high_resolution_clock::now()); + if (!(frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN)) { - req.http2_expect_body = true; + downstream->set_request_http2_expect_body(true); } downstream->inspect_http2_request(); - downstream->set_request_state(Downstream::HEADER_COMPLETE); - -#ifdef HAVE_MRUBY - auto handler = upstream->get_client_handler(); - auto worker = handler->get_worker(); - auto mruby_ctx = worker->get_mruby_context(); - - if (mruby_ctx->run_on_request_proc(downstream) != 0) { - if (upstream->error_reply(downstream, 500) != 0) { - ULOG(FATAL, upstream) << "error_reply failed"; - return; + if (LOG_ENABLED(INFO)) { + std::stringstream ss; + for (size_t i = 0; nv[i]; i += 2) { + ss << TTY_HTTP_HD << nv[i] << TTY_RST << ": " << nv[i + 1] << "\n"; } - return; + ULOG(INFO, upstream) << "HTTP request headers. stream_id=" + << downstream->get_stream_id() << "\n" << ss.str(); } -#endif // HAVE_MRUBY + downstream->set_request_state(Downstream::HEADER_COMPLETE); if (frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN) { - if (!downstream->validate_request_recv_body_length()) { - upstream->rst_stream(downstream, SPDYLAY_PROTOCOL_ERROR); - return; - } - downstream->disable_upstream_rtimer(); downstream->set_request_state(Downstream::MSG_COMPLETE); } - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - return; - } - - upstream->start_downstream(downstream); + upstream->maintain_downstream_concurrency(); break; } @@ -323,49 +242,53 @@ } } // namespace -void SpdyUpstream::start_downstream(Downstream *downstream) { - if (downstream_queue_.can_activate(downstream->request().authority)) { - initiate_downstream(downstream); - return; - } +void SpdyUpstream::maintain_downstream_concurrency() { + while (get_config()->max_downstream_connections > + downstream_queue_.num_active()) { + if (downstream_queue_.pending_empty()) { + break; + } - downstream_queue_.mark_blocked(downstream); -} + { + auto downstream = downstream_queue_.pending_top(); + if (downstream->get_request_state() != Downstream::HEADER_COMPLETE && + downstream->get_request_state() != Downstream::MSG_COMPLETE) { + break; + } + } -void SpdyUpstream::initiate_downstream(Downstream *downstream) { - int rv; + auto downstream = downstream_queue_.pop_pending(); + + if (!downstream) { + break; + } - auto dconn = handler_->get_downstream_connection(downstream); + initiate_downstream(std::move(downstream)); + } +} - if (!dconn || - (rv = downstream->attach_downstream_connection(std::move(dconn))) != 0) { +void SpdyUpstream::initiate_downstream(std::unique_ptr downstream) { + int rv = downstream->attach_downstream_connection( + handler_->get_downstream_connection()); + if (rv != 0) { // If downstream connection fails, issue RST_STREAM. - rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); + rst_stream(downstream.get(), SPDYLAY_INTERNAL_ERROR); downstream->set_request_state(Downstream::CONNECT_FAIL); - downstream_queue_.mark_failure(downstream); + downstream_queue_.add_failure(std::move(downstream)); return; } rv = downstream->push_request_headers(); if (rv != 0) { - rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); + rst_stream(downstream.get(), SPDYLAY_INTERNAL_ERROR); - downstream_queue_.mark_failure(downstream); + downstream_queue_.add_failure(std::move(downstream)); return; } - downstream_queue_.mark_active(downstream); - - auto &req = downstream->request(); - if (!req.http2_expect_body) { - if (downstream->end_upload_data() != 0) { - if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { - rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); - } - } - } + downstream_queue_.add_active(std::move(downstream)); } namespace { @@ -373,8 +296,7 @@ int32_t stream_id, const uint8_t *data, size_t len, void *user_data) { auto upstream = static_cast(user_data); - auto downstream = static_cast( - spdylay_session_get_stream_user_data(session, stream_id)); + auto downstream = upstream->find_downstream(stream_id); if (!downstream) { upstream->consume(stream_id, len); @@ -385,9 +307,7 @@ downstream->reset_upstream_rtimer(); if (downstream->push_upload_data_chunk(data, len) != 0) { - if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { - upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); - } + upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); upstream->consume(stream_id, len); @@ -398,33 +318,31 @@ return; } - auto &http2conf = get_config()->http2; - // If connection-level window control is not enabled (e.g, // spdy/3), spdylay_session_get_recv_data_length() is always // returns 0. if (spdylay_session_get_recv_data_length(session) > std::max(SPDYLAY_INITIAL_WINDOW_SIZE, - 1 << http2conf.upstream.connection_window_bits)) { + 1 << get_config()->http2_upstream_connection_window_bits)) { if (LOG_ENABLED(INFO)) { - ULOG(INFO, upstream) << "Flow control error on connection: " - << "recv_window_size=" - << spdylay_session_get_recv_data_length(session) - << ", window_size=" - << (1 << http2conf.upstream.connection_window_bits); + ULOG(INFO, upstream) + << "Flow control error on connection: " + << "recv_window_size=" + << spdylay_session_get_recv_data_length(session) << ", window_size=" + << (1 << get_config()->http2_upstream_connection_window_bits); } spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR); return; } if (spdylay_session_get_stream_recv_data_length(session, stream_id) > std::max(SPDYLAY_INITIAL_WINDOW_SIZE, - 1 << http2conf.upstream.window_bits)) { + 1 << get_config()->http2_upstream_window_bits)) { if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "Flow control error: recv_window_size=" << spdylay_session_get_stream_recv_data_length( session, stream_id) << ", initial_window_size=" - << (1 << http2conf.upstream.window_bits); + << (1 << get_config()->http2_upstream_window_bits); } upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR); return; @@ -436,21 +354,10 @@ void on_data_recv_callback(spdylay_session *session, uint8_t flags, int32_t stream_id, int32_t length, void *user_data) { auto upstream = static_cast(user_data); - auto downstream = static_cast( - spdylay_session_get_stream_user_data(session, stream_id)); - + auto downstream = upstream->find_downstream(stream_id); if (downstream && (flags & SPDYLAY_DATA_FLAG_FIN)) { - if (!downstream->validate_request_recv_body_length()) { - upstream->rst_stream(downstream, SPDYLAY_PROTOCOL_ERROR); - return; - } - downstream->disable_upstream_rtimer(); - if (downstream->end_upload_data() != 0) { - if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { - upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); - } - } + downstream->end_upload_data(); downstream->set_request_state(Downstream::MSG_COMPLETE); } } @@ -461,18 +368,13 @@ spdylay_frame_type type, spdylay_frame *frame, int error_code, void *user_data) { auto upstream = static_cast(user_data); - if (LOG_ENABLED(INFO)) { - ULOG(INFO, upstream) << "Failed to send control frame type=" << type - << ", error_code=" << error_code << ":" - << spdylay_strerror(error_code); - } - if (type == SPDYLAY_SYN_REPLY && error_code != SPDYLAY_ERR_STREAM_CLOSED && - error_code != SPDYLAY_ERR_STREAM_CLOSING) { + ULOG(WARN, upstream) << "Failed to send control frame type=" << type + << ", error_code=" << error_code << ":" + << spdylay_strerror(error_code); + if (type == SPDYLAY_SYN_REPLY) { // To avoid stream hanging around, issue RST_STREAM. auto stream_id = frame->syn_reply.stream_id; - // TODO Could be always nullptr - auto downstream = static_cast( - spdylay_session_get_stream_user_data(session, stream_id)); + auto downstream = upstream->find_downstream(stream_id); if (downstream) { upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); } @@ -522,25 +424,13 @@ } } // namespace -namespace { -size_t downstream_queue_size(Worker *worker) { - auto &downstreamconf = *worker->get_downstream_config(); - - if (get_config()->http2_proxy) { - return downstreamconf.connections_per_host; - } - - return downstreamconf.connections_per_frontend; -} -} // namespace - SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler) - : wb_(handler->get_worker()->get_mcpool()), - downstream_queue_(downstream_queue_size(handler->get_worker()), - !get_config()->http2_proxy), - handler_(handler), - session_(nullptr) { - spdylay_session_callbacks callbacks{}; + : handler_(handler), session_(nullptr) { + // handler->set_bev_cb(spdy_readcb, 0, spdy_eventcb); + reset_timeouts(); + + spdylay_session_callbacks callbacks; + memset(&callbacks, 0, sizeof(callbacks)); callbacks.send_callback = send_callback; callbacks.recv_callback = recv_callback; callbacks.on_stream_close_callback = on_stream_close_callback; @@ -556,24 +446,10 @@ rv = spdylay_session_server_new(&session_, version, &callbacks, this); assert(rv == 0); - uint32_t max_buffer = 64_k; - rv = spdylay_session_set_option(session_, - SPDYLAY_OPT_MAX_RECV_CTRL_FRAME_BUFFER, - &max_buffer, sizeof(max_buffer)); - assert(rv == 0); - - auto &http2conf = get_config()->http2; - - auto faddr = handler_->get_upstream_addr(); - - // We use automatic WINDOW_UPDATE for API endpoints. Since SPDY is - // going to be deprecated in the future, and the default stream - // window is large enough for API request body (64KiB), we don't - // expand window size depending on the options. - if (version >= SPDYLAY_PROTO_SPDY3 && !faddr->alt_mode) { + if (version >= SPDYLAY_PROTO_SPDY3) { int val = 1; flow_control_ = true; - initial_window_size_ = 1 << http2conf.upstream.window_bits; + initial_window_size_ = 1 << get_config()->http2_upstream_window_bits; rv = spdylay_session_set_option( session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE2, &val, sizeof(val)); assert(rv == 0); @@ -582,35 +458,29 @@ initial_window_size_ = 0; } // TODO Maybe call from outside? - std::array entry; - size_t num_entry = 1; + spdylay_settings_entry entry[2]; entry[0].settings_id = SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS; - entry[0].value = http2conf.upstream.max_concurrent_streams; + entry[0].value = get_config()->http2_max_concurrent_streams; entry[0].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE; - if (flow_control_) { - ++num_entry; - entry[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE; - entry[1].value = initial_window_size_; - entry[1].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE; - } + entry[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE; + entry[1].value = initial_window_size_; + entry[1].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE; - rv = spdylay_submit_settings(session_, SPDYLAY_FLAG_SETTINGS_NONE, - entry.data(), num_entry); + rv = spdylay_submit_settings(session_, SPDYLAY_FLAG_SETTINGS_NONE, entry, + util::array_size(entry)); assert(rv == 0); - if (flow_control_ && version >= SPDYLAY_PROTO_SPDY3_1 && - http2conf.upstream.connection_window_bits > 16) { - int32_t delta = (1 << http2conf.upstream.connection_window_bits) - + if (version >= SPDYLAY_PROTO_SPDY3_1 && + get_config()->http2_upstream_connection_window_bits > 16) { + int32_t delta = (1 << get_config()->http2_upstream_connection_window_bits) - SPDYLAY_INITIAL_WINDOW_SIZE; rv = spdylay_submit_window_update(session_, 0, delta); assert(rv == 0); } - handler_->reset_upstream_read_timeout( - get_config()->conn.upstream.timeout.http2_read); - - handler_->signal_write(); + // TODO Maybe call from outside? + send(); } SpdyUpstream::~SpdyUpstream() { spdylay_session_del(session_); } @@ -626,19 +496,18 @@ } return rv; } - - handler_->signal_write(); - - return 0; + return send(); } +int SpdyUpstream::on_write() { return send(); } + // After this function call, downstream may be deleted. -int SpdyUpstream::on_write() { +int SpdyUpstream::send() { int rv = 0; + uint8_t buf[16384]; - if (wb_.rleft() >= MAX_BUFFER_SIZE) { - return 0; - } + sendbuf.reset(bufferevent_get_output(handler_->get_bev()), buf, sizeof(buf), + handler_->get_write_limit()); rv = spdylay_session_send(session_); if (rv != 0) { @@ -647,8 +516,17 @@ return rv; } + rv = sendbuf.flush(); + if (rv != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } + + handler_->update_warmup_writelen(sendbuf.get_writelen()); + if (spdylay_session_want_read(session_) == 0 && - spdylay_session_want_write(session_) == 0 && wb_.rleft() == 0) { + spdylay_session_want_write(session_) == 0 && + handler_->get_outbuf_length() == 0) { if (LOG_ENABLED(INFO)) { ULOG(INFO, this) << "No more read/write for this SPDY session"; } @@ -657,160 +535,202 @@ return 0; } +int SpdyUpstream::on_event() { return 0; } + ClientHandler *SpdyUpstream::get_client_handler() const { return handler_; } -int SpdyUpstream::downstream_read(DownstreamConnection *dconn) { +namespace { +void spdy_downstream_readcb(bufferevent *bev, void *ptr) { + auto dconn = static_cast(ptr); auto downstream = dconn->get_downstream(); + auto upstream = static_cast(downstream->get_upstream()); + if (downstream->get_request_state() == Downstream::STREAM_CLOSED) { + // If upstream SPDY stream was closed, we just close downstream, + // because there is no consumer now. Downstream connection is also + // closed in this case. + upstream->remove_downstream(downstream); + // downstrea was deleted + + return; + } if (downstream->get_response_state() == Downstream::MSG_RESET) { // The downstream stream was reset (canceled). In this case, // RST_STREAM to the upstream and delete downstream connection // here. Deleting downstream will be taken place at // on_stream_close_callback. - rst_stream(downstream, - infer_upstream_rst_stream_status_code( - downstream->get_response_rst_stream_error_code())); - downstream->pop_downstream_connection(); - dconn = nullptr; - } else if (downstream->get_response_state() == Downstream::MSG_BAD_HEADER) { - if (error_reply(downstream, 502) != 0) { - return -1; - } + upstream->rst_stream(downstream, + infer_upstream_rst_stream_status_code( + downstream->get_response_rst_stream_error_code())); downstream->pop_downstream_connection(); - // dconn was deleted dconn = nullptr; } else { auto rv = downstream->on_read(); - if (rv == SHRPX_ERR_EOF) { - return downstream_eof(dconn); - } - if (rv == SHRPX_ERR_DCONN_CANCELED) { - downstream->pop_downstream_connection(); - handler_->signal_write(); - return 0; - } if (rv != 0) { - if (rv != SHRPX_ERR_NETWORK) { - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "HTTP parser failure"; + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "HTTP parser failure"; + } + if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); + } else if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { + // If response was completed, then don't issue RST_STREAM + if (upstream->error_reply(downstream, 502) != 0) { + delete upstream->get_client_handler(); + return; } } - return downstream_error(dconn, Downstream::EVENT_ERROR); - } - if (downstream->can_detach_downstream_connection()) { - // Keep-alive - downstream->detach_downstream_connection(); + downstream->set_response_state(Downstream::MSG_COMPLETE); + // Clearly, we have to close downstream connection on http parser + // failure. + downstream->pop_downstream_connection(); + dconn = nullptr; } } - - handler_->signal_write(); + if (upstream->send() != 0) { + delete upstream->get_client_handler(); + return; + } // At this point, downstream may be deleted. - - return 0; } +} // namespace -int SpdyUpstream::downstream_write(DownstreamConnection *dconn) { - int rv; - rv = dconn->on_write(); - if (rv == SHRPX_ERR_NETWORK) { - return downstream_error(dconn, Downstream::EVENT_ERROR); - } - if (rv != 0) { - return -1; +namespace { +void spdy_downstream_writecb(bufferevent *bev, void *ptr) { + if (evbuffer_get_length(bufferevent_get_output(bev)) > 0) { + return; } - return 0; + auto dconn = static_cast(ptr); + dconn->on_write(); } +} // namespace -int SpdyUpstream::downstream_eof(DownstreamConnection *dconn) { +namespace { +void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr) { + auto dconn = static_cast(ptr); auto downstream = dconn->get_downstream(); + auto upstream = static_cast(downstream->get_upstream()); - if (LOG_ENABLED(INFO)) { - DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id(); + if (events & BEV_EVENT_CONNECTED) { + if (LOG_ENABLED(INFO)) { + DCLOG(INFO, dconn) << "Connection established. stream_id=" + << downstream->get_stream_id(); + } + int fd = bufferevent_getfd(bev); + int val = 1; + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&val), + sizeof(val)) == -1) { + DCLOG(WARN, dconn) << "Setting option TCP_NODELAY failed: errno=" + << errno; + } + return; } - // Delete downstream connection. If we don't delete it here, it will - // be pooled in on_stream_close_callback. - downstream->pop_downstream_connection(); - // dconn was deleted - dconn = nullptr; - // downstream wil be deleted in on_stream_close_callback. - if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { - // Server may indicate the end of the request by EOF + if (events & BEV_EVENT_EOF) { if (LOG_ENABLED(INFO)) { - ULOG(INFO, this) << "Downstream body was ended by EOF"; + DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id(); } - downstream->set_response_state(Downstream::MSG_COMPLETE); + if (downstream->get_request_state() == Downstream::STREAM_CLOSED) { + // If stream was closed already, we don't need to send reply at + // the first place. We can delete downstream. + upstream->remove_downstream(downstream); + // downstrea was deleted - // For tunneled connection, MSG_COMPLETE signals - // downstream_data_read_callback to send RST_STREAM after pending - // response body is sent. This is needed to ensure that RST_STREAM - // is sent after all pending data are sent. - on_downstream_body_complete(downstream); - } else if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { - // If stream was not closed, then we set MSG_COMPLETE and let - // on_stream_close_callback delete downstream. - if (error_reply(downstream, 502) != 0) { - return -1; + return; } - } - handler_->signal_write(); - // At this point, downstream may be deleted. - return 0; -} -int SpdyUpstream::downstream_error(DownstreamConnection *dconn, int events) { - auto downstream = dconn->get_downstream(); + // Delete downstream connection. If we don't delete it here, it + // will be pooled in on_stream_close_callback. + downstream->pop_downstream_connection(); + dconn = nullptr; + // downstream wil be deleted in on_stream_close_callback. + if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + // Server may indicate the end of the request by EOF + if (LOG_ENABLED(INFO)) { + ULOG(INFO, upstream) << "Downstream body was ended by EOF"; + } + downstream->set_response_state(Downstream::MSG_COMPLETE); - if (LOG_ENABLED(INFO)) { - if (events & Downstream::EVENT_ERROR) { - DCLOG(INFO, dconn) << "Downstream network/general error"; - } else { - DCLOG(INFO, dconn) << "Timeout"; + // For tunneled connection, MSG_COMPLETE signals + // spdy_data_read_callback to send RST_STREAM after pending + // response body is sent. This is needed to ensure that + // RST_STREAM is sent after all pending data are sent. + upstream->on_downstream_body_complete(downstream); + } else if (downstream->get_response_state() != Downstream::MSG_COMPLETE) { + // If stream was not closed, then we set MSG_COMPLETE and let + // on_stream_close_callback delete downstream. + if (upstream->error_reply(downstream, 502) != 0) { + delete upstream->get_client_handler(); + return; + } + downstream->set_response_state(Downstream::MSG_COMPLETE); } - if (downstream->get_upgraded()) { - DCLOG(INFO, dconn) << "Note: this is tunnel connection"; + if (upstream->send() != 0) { + delete upstream->get_client_handler(); + return; } + // At this point, downstream may be deleted. + + return; } - // Delete downstream connection. If we don't delete it here, it will - // be pooled in on_stream_close_callback. - downstream->pop_downstream_connection(); - // dconn was deleted - dconn = nullptr; + if (events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { + if (LOG_ENABLED(INFO)) { + if (events & BEV_EVENT_ERROR) { + DCLOG(INFO, dconn) << "Downstream network error: " + << evutil_socket_error_to_string( + EVUTIL_SOCKET_ERROR()); + } else { + DCLOG(INFO, dconn) << "Timeout"; + } + if (downstream->get_upgraded()) { + DCLOG(INFO, dconn) << "Note: this is tunnel connection"; + } + } + if (downstream->get_request_state() == Downstream::STREAM_CLOSED) { + upstream->remove_downstream(downstream); + // downstrea was deleted - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - // For SSL tunneling, we issue RST_STREAM. For other types of - // stream, we don't have to do anything since response was - // complete. - if (downstream->get_upgraded()) { - // We want "NO_ERROR" error code but SPDY does not have such - // code for RST_STREAM. - rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); + return; } - } else { - if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + + // Delete downstream connection. If we don't delete it here, it + // will be pooled in on_stream_close_callback. + downstream->pop_downstream_connection(); + dconn = nullptr; + + if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { + // For SSL tunneling, we issue RST_STREAM. For other types of + // stream, we don't have to do anything since response was + // complete. if (downstream->get_upgraded()) { - on_downstream_body_complete(downstream); - } else { - rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); + upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); } } else { - unsigned int status; - if (events & Downstream::EVENT_TIMEOUT) { - status = 504; + if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) { + upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); } else { - status = 502; - } - if (error_reply(downstream, status) != 0) { - return -1; + unsigned int status; + if (events & BEV_EVENT_TIMEOUT) { + status = 504; + } else { + status = 502; + } + if (upstream->error_reply(downstream, status) != 0) { + delete upstream->get_client_handler(); + return; + } } + downstream->set_response_state(Downstream::MSG_COMPLETE); } - downstream->set_response_state(Downstream::MSG_COMPLETE); + if (upstream->send() != 0) { + delete upstream->get_client_handler(); + return; + } + // At this point, downstream may be deleted. + return; } - handler_->signal_write(); - // At this point, downstream may be deleted. - return 0; } +} // namespace int SpdyUpstream::rst_stream(Downstream *downstream, int status_code) { if (LOG_ENABLED(INFO)) { @@ -833,12 +753,25 @@ spdylay_data_source *source, void *user_data) { auto downstream = static_cast(source->ptr); auto upstream = static_cast(downstream->get_upstream()); - auto body = downstream->get_response_buf(); + auto body = downstream->get_response_body_buf(); + auto handler = upstream->get_client_handler(); assert(body); - auto nread = body->remove(buf, length); - auto body_empty = body->rleft() == 0; + auto limit = handler->get_write_limit(); + + if (limit != -1) { + // 9 is HTTP/2 frame header length. Make DATA frame also under + // certain limit, so that application layer can flush at DATA + // frame boundary, instead of buffering large frame. + assert(limit > 9); + length = std::min(length, static_cast(limit - 9)); + } + int nread = evbuffer_remove(body, buf, length); + if (nread == -1) { + ULOG(FATAL, upstream) << "evbuffer_remove() failed"; + return SPDYLAY_ERR_CALLBACK_FAILURE; + } if (nread == 0 && downstream->get_response_state() == Downstream::MSG_COMPLETE) { if (!downstream->get_upgraded()) { @@ -855,10 +788,10 @@ } } - if (body_empty) { - downstream->disable_upstream_wtimer(); - } else { + if (evbuffer_get_length(body) > 0) { downstream->reset_upstream_wtimer(); + } else { + downstream->disable_upstream_wtimer(); } if (nread > 0 && downstream->resume_read(SHRPX_NO_BUFFER, nread) != 0) { @@ -870,136 +803,70 @@ } if (nread > 0) { - downstream->response_sent_body_length += nread; + downstream->add_response_sent_bodylen(nread); } return nread; } } // namespace -int SpdyUpstream::send_reply(Downstream *downstream, const uint8_t *body, - size_t bodylen) { - int rv; - - spdylay_data_provider data_prd, *data_prd_ptr = nullptr; - if (bodylen) { - data_prd.source.ptr = downstream; - data_prd.read_callback = spdy_data_read_callback; - data_prd_ptr = &data_prd; - } - - const auto &resp = downstream->response(); - auto &balloc = downstream->get_block_allocator(); - - auto status_string = http2::get_status_string(balloc, resp.http_status); - - const auto &headers = resp.fs.headers(); - - auto &httpconf = get_config()->http; - - auto nva = std::vector(); - // 6 for :status, :version and server. 1 for last terminal nullptr. - nva.reserve(6 + headers.size() * 2 + - httpconf.add_response_headers.size() * 2 + 1); - - nva.push_back(":status"); - nva.push_back(status_string.c_str()); - nva.push_back(":version"); - nva.push_back("HTTP/1.1"); - - for (auto &kv : headers) { - if (kv.name.empty() || kv.name[0] == ':') { - continue; - } - switch (kv.token) { - case http2::HD_CONNECTION: - case http2::HD_KEEP_ALIVE: - case http2::HD_PROXY_CONNECTION: - case http2::HD_TRANSFER_ENCODING: - continue; - } - nva.push_back(kv.name.c_str()); - nva.push_back(kv.value.c_str()); - } - - if (!resp.fs.header(http2::HD_SERVER)) { - nva.push_back("server"); - nva.push_back(get_config()->http.server_name.c_str()); - } - - for (auto &p : httpconf.add_response_headers) { - nva.push_back(p.name.c_str()); - nva.push_back(p.value.c_str()); - } - - nva.push_back(nullptr); - - rv = spdylay_submit_response(session_, downstream->get_stream_id(), - nva.data(), data_prd_ptr); - if (rv < SPDYLAY_ERR_FATAL) { - ULOG(FATAL, this) << "spdylay_submit_response() failed: " - << spdylay_strerror(rv); - return -1; - } - - auto buf = downstream->get_response_buf(); - - buf->append(body, bodylen); - - downstream->set_response_state(Downstream::MSG_COMPLETE); - - return 0; -} - int SpdyUpstream::error_reply(Downstream *downstream, unsigned int status_code) { int rv; - auto &resp = downstream->response(); - auto &balloc = downstream->get_block_allocator(); - - auto html = http::create_error_html(balloc, status_code); - resp.http_status = status_code; - auto body = downstream->get_response_buf(); - body->append(html); + auto html = http::create_error_html(status_code); + downstream->set_response_http_status(status_code); + downstream->init_response_body_buf(); + auto body = downstream->get_response_body_buf(); + rv = evbuffer_add(body, html.c_str(), html.size()); + if (rv == -1) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } downstream->set_response_state(Downstream::MSG_COMPLETE); spdylay_data_provider data_prd; data_prd.source.ptr = downstream; data_prd.read_callback = spdy_data_read_callback; - auto lgconf = log_config(); - lgconf->update_tstamp(std::chrono::system_clock::now()); - - auto content_length = util::make_string_ref_uint(balloc, html.size()); - auto status_string = http2::get_status_string(balloc, status_code); - - const char *nv[] = {":status", status_string.c_str(), ":version", "http/1.1", - "content-type", "text/html; charset=UTF-8", "server", - get_config()->http.server_name.c_str(), "content-length", - content_length.c_str(), "date", - lgconf->time_http_str.c_str(), nullptr}; + std::string content_length = util::utos(html.size()); + std::string status_string = http2::get_status_string(status_code); + const char *nv[] = {":status", status_string.c_str(), + ":version", "http/1.1", + "content-type", "text/html; charset=UTF-8", + "server", get_config()->server_name, + "content-length", content_length.c_str(), + nullptr}; rv = spdylay_submit_response(session_, downstream->get_stream_id(), nv, &data_prd); if (rv < SPDYLAY_ERR_FATAL) { ULOG(FATAL, this) << "spdylay_submit_response() failed: " << spdylay_strerror(rv); - return -1; + DIE(); } return 0; } -Downstream *SpdyUpstream::add_pending_downstream(int32_t stream_id) { - auto downstream = - make_unique(this, handler_->get_mcpool(), stream_id); - spdylay_session_set_stream_user_data(session_, stream_id, downstream.get()); +bufferevent_data_cb SpdyUpstream::get_downstream_readcb() { + return spdy_downstream_readcb; +} + +bufferevent_data_cb SpdyUpstream::get_downstream_writecb() { + return spdy_downstream_writecb; +} + +bufferevent_event_cb SpdyUpstream::get_downstream_eventcb() { + return spdy_downstream_eventcb; +} + +Downstream *SpdyUpstream::add_pending_downstream(int32_t stream_id, + int32_t priority) { + auto downstream = util::make_unique(this, stream_id, priority); auto res = downstream.get(); downstream_queue_.add_pending(std::move(downstream)); - handler_->stop_read_timer(); - return res; } @@ -1008,127 +875,87 @@ handler_->write_accesslog(downstream); } - spdylay_session_set_stream_user_data(session_, downstream->get_stream_id(), - nullptr); - - auto next_downstream = downstream_queue_.remove_and_get_blocked(downstream); + downstream_queue_.remove(downstream->get_stream_id()); - if (next_downstream) { - initiate_downstream(next_downstream); - } + maintain_downstream_concurrency(); +} - if (downstream_queue_.get_downstreams() == nullptr) { - handler_->repeat_read_timer(); - } +Downstream *SpdyUpstream::find_downstream(int32_t stream_id) { + return downstream_queue_.find(stream_id); } +spdylay_session *SpdyUpstream::get_http2_session() { return session_; } + // WARNING: Never call directly or indirectly spdylay_session_send or // spdylay_session_recv. These calls may delete downstream. int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) { - auto &resp = downstream->response(); - if (downstream->get_non_final_response()) { // SPDY does not support non-final response. We could send it // with HEADERS and final response in SYN_REPLY, but it is not // official way. - resp.fs.clear_headers(); + downstream->clear_response_headers(); return 0; } - const auto &req = downstream->request(); - auto &balloc = downstream->get_block_allocator(); - -#ifdef HAVE_MRUBY - auto worker = handler_->get_worker(); - auto mruby_ctx = worker->get_mruby_context(); - - if (mruby_ctx->run_on_response_proc(downstream) != 0) { - if (error_reply(downstream, 500) != 0) { - return -1; - } - // Returning -1 will signal deletion of dconn. - return -1; - } - - if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { - return -1; - } -#endif // HAVE_MRUBY - if (LOG_ENABLED(INFO)) { DLOG(INFO, downstream) << "HTTP response header completed"; } - - auto &httpconf = get_config()->http; - - if (!get_config()->http2_proxy && !httpconf.no_location_rewrite) { - downstream->rewrite_location_response_header(req.scheme); + downstream->normalize_response_headers(); + if (!get_config()->http2_proxy && !get_config()->client_proxy && + !get_config()->no_location_rewrite) { + downstream->rewrite_norm_location_response_header( + get_client_handler()->get_upstream_scheme(), get_config()->port); } - + size_t nheader = downstream->get_response_headers().size(); // 8 means server, :status, :version and possible via header field. - auto nv = - make_unique(resp.fs.headers().size() * 2 + 8 + - httpconf.add_response_headers.size() * 2 + 1); + auto nv = util::make_unique( + nheader * 2 + 8 + get_config()->add_response_headers.size() * 2 + 1); size_t hdidx = 0; std::string via_value; - auto status_string = http2::get_status_string(balloc, resp.http_status); + std::string status_string = + http2::get_status_string(downstream->get_response_http_status()); nv[hdidx++] = ":status"; nv[hdidx++] = status_string.c_str(); nv[hdidx++] = ":version"; nv[hdidx++] = "HTTP/1.1"; - for (auto &hd : resp.fs.headers()) { - if (hd.name.empty() || hd.name.c_str()[0] == ':') { - continue; - } - switch (hd.token) { - case http2::HD_CONNECTION: - case http2::HD_KEEP_ALIVE: - case http2::HD_PROXY_CONNECTION: - case http2::HD_TRANSFER_ENCODING: - case http2::HD_VIA: - case http2::HD_SERVER: - continue; + for (auto &hd : downstream->get_response_headers()) { + if (hd.name.empty() || hd.name.c_str()[0] == ':' || + util::strieq(hd.name.c_str(), "transfer-encoding") || + util::strieq(hd.name.c_str(), "keep-alive") || // HTTP/1.0? + util::strieq(hd.name.c_str(), "connection") || + util::strieq(hd.name.c_str(), "proxy-connection")) { + // These are ignored + } else if (!get_config()->no_via && util::strieq(hd.name.c_str(), "via")) { + via_value = hd.value; + } else if (!get_config()->http2_proxy && !get_config()->client_proxy && + util::strieq(hd.name.c_str(), "server")) { + // Rewrite server header field later + } else { + nv[hdidx++] = hd.name.c_str(); + nv[hdidx++] = hd.value.c_str(); } - - nv[hdidx++] = hd.name.c_str(); - nv[hdidx++] = hd.value.c_str(); } - if (!get_config()->http2_proxy) { + if (!get_config()->http2_proxy && !get_config()->client_proxy) { nv[hdidx++] = "server"; - nv[hdidx++] = httpconf.server_name.c_str(); - } else { - auto server = resp.fs.header(http2::HD_SERVER); - if (server) { - nv[hdidx++] = "server"; - nv[hdidx++] = server->value.c_str(); - } + nv[hdidx++] = get_config()->server_name; } - auto via = resp.fs.header(http2::HD_VIA); - if (httpconf.no_via) { - if (via) { - nv[hdidx++] = "via"; - nv[hdidx++] = via->value.c_str(); - } - } else { - if (via) { - via_value = via->value.str(); + if (!get_config()->no_via) { + if (!via_value.empty()) { via_value += ", "; } - std::array viabuf; - auto end = http::create_via_header_value(std::begin(viabuf), - resp.http_major, resp.http_minor); - via_value.append(std::begin(viabuf), end); + via_value += http::create_via_header_value( + downstream->get_response_major(), downstream->get_response_minor()); nv[hdidx++] = "via"; nv[hdidx++] = via_value.c_str(); } - for (auto &p : httpconf.add_response_headers) { - nv[hdidx++] = p.name.c_str(); - nv[hdidx++] = p.value.c_str(); + for (auto &p : get_config()->add_response_headers) { + nv[hdidx++] = p.first.c_str(); + nv[hdidx++] = p.second.c_str(); } nv[hdidx++] = 0; @@ -1160,8 +987,12 @@ int SpdyUpstream::on_downstream_body(Downstream *downstream, const uint8_t *data, size_t len, bool flush) { - auto body = downstream->get_response_buf(); - body->append(data, len); + auto body = downstream->get_response_body_buf(); + int rv = evbuffer_add(body, data, len); + if (rv != 0) { + ULOG(FATAL, this) << "evbuffer_add() failed"; + return -1; + } if (flush) { spdylay_session_resume_data(session_, downstream->get_stream_id()); @@ -1169,6 +1000,16 @@ downstream->ensure_upstream_wtimer(); } + if (evbuffer_get_length(body) >= INBUF_MAX_THRES) { + if (!flush) { + spdylay_session_resume_data(session_, downstream->get_stream_id()); + + downstream->ensure_upstream_wtimer(); + } + + downstream->pause_read(SHRPX_NO_BUFFER); + } + return 0; } @@ -1179,14 +1020,6 @@ DLOG(INFO, downstream) << "HTTP response completed"; } - auto &resp = downstream->response(); - - if (!downstream->validate_response_recv_body_length()) { - rst_stream(downstream, SPDYLAY_PROTOCOL_ERROR); - resp.connection_close = true; - return 0; - } - spdylay_session_resume_data(session_, downstream->get_stream_id()); downstream->ensure_upstream_wtimer(); @@ -1200,17 +1033,16 @@ int SpdyUpstream::resume_read(IOCtrlReason reason, Downstream *downstream, size_t consumed) { if (get_flow_control()) { + assert(downstream->get_request_datalen() >= consumed); + if (consume(downstream->get_stream_id(), consumed) != 0) { return -1; } - auto &req = downstream->request(); - - req.consume(consumed); + downstream->dec_request_datalen(consumed); } - handler_->signal_write(); - return 0; + return send(); } int SpdyUpstream::on_downstream_abort_request(Downstream *downstream, @@ -1223,17 +1055,12 @@ return -1; } - handler_->signal_write(); - return 0; + return send(); } int SpdyUpstream::consume(int32_t stream_id, size_t len) { int rv; - if (!get_flow_control()) { - return 0; - } - rv = spdylay_session_consume(session_, stream_id, len); if (rv != 0) { @@ -1256,109 +1083,17 @@ return 0; } -void SpdyUpstream::on_handler_delete() { - for (auto d = downstream_queue_.get_downstreams(); d; d = d->dlnext) { - if (d->get_dispatch_state() == Downstream::DISPATCH_ACTIVE && - d->accesslog_ready()) { - handler_->write_accesslog(d); - } - } +void SpdyUpstream::reset_timeouts() { + handler_->set_upstream_timeouts(&get_config()->http2_upstream_read_timeout, + &get_config()->upstream_write_timeout); } -int SpdyUpstream::on_downstream_reset(bool no_retry) { - int rv; - - for (auto downstream = downstream_queue_.get_downstreams(); downstream; - downstream = downstream->dlnext) { - if (downstream->get_dispatch_state() != Downstream::DISPATCH_ACTIVE) { - // This is error condition when we failed push_request_headers() - // in initiate_downstream(). Otherwise, we have - // Downstream::DISPATCH_ACTIVE state, or we did not set - // DownstreamConnection. - downstream->pop_downstream_connection(); - continue; - } - - if (!downstream->request_submission_ready()) { - rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); - downstream->pop_downstream_connection(); - continue; - } - - downstream->pop_downstream_connection(); - - downstream->add_retry(); - - std::unique_ptr dconn; - - if (no_retry || downstream->no_more_retry()) { - goto fail; - } - - // downstream connection is clean; we can retry with new - // downstream connection. - - dconn = handler_->get_downstream_connection(downstream); - if (!dconn) { - goto fail; - } - - rv = downstream->attach_downstream_connection(std::move(dconn)); - if (rv != 0) { - goto fail; - } - - rv = downstream->push_request_headers(); - if (rv != 0) { - goto fail; - } - - continue; - - fail: - if (on_downstream_abort_request(downstream, 503) != 0) { - return -1; +void SpdyUpstream::on_handler_delete() { + for (auto &ent : downstream_queue_.get_active_downstreams()) { + if (ent.second->accesslog_ready()) { + handler_->write_accesslog(ent.second.get()); } - downstream->pop_downstream_connection(); - } - - handler_->signal_write(); - - return 0; -} - -int SpdyUpstream::initiate_push(Downstream *downstream, const StringRef &uri) { - return 0; -} - -int SpdyUpstream::response_riovec(struct iovec *iov, int iovcnt) const { - if (iovcnt == 0 || wb_.rleft() == 0) { - return 0; } - - return wb_.riovec(iov, iovcnt); -} - -void SpdyUpstream::response_drain(size_t n) { wb_.drain(n); } - -bool SpdyUpstream::response_empty() const { return wb_.rleft() == 0; } - -DefaultMemchunks *SpdyUpstream::get_response_buf() { return &wb_; } - -Downstream * -SpdyUpstream::on_downstream_push_promise(Downstream *downstream, - int32_t promised_stream_id) { - return nullptr; -} - -int SpdyUpstream::on_downstream_push_promise_complete( - Downstream *downstream, Downstream *promised_downstream) { - return -1; } -bool SpdyUpstream::push_enabled() const { return false; } - -void SpdyUpstream::cancel_premature_downstream( - Downstream *promised_downstream) {} - } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_spdy_upstream.h nghttp2-0.6.7/src/shrpx_spdy_upstream.h --- nghttp2-1.13.0/src/shrpx_spdy_upstream.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_spdy_upstream.h 2014-11-30 14:15:07.000000000 +0000 @@ -29,14 +29,12 @@ #include -#include - #include #include "shrpx_upstream.h" #include "shrpx_downstream_queue.h" -#include "memchunk.h" -#include "buffer.h" +#include "util.h" +#include "libevent_util.h" namespace shrpx { @@ -48,16 +46,20 @@ virtual ~SpdyUpstream(); virtual int on_read(); virtual int on_write(); + virtual int on_event(); virtual int on_timeout(Downstream *downstream); virtual int on_downstream_abort_request(Downstream *downstream, unsigned int status_code); + int send(); virtual ClientHandler *get_client_handler() const; - virtual int downstream_read(DownstreamConnection *dconn); - virtual int downstream_write(DownstreamConnection *dconn); - virtual int downstream_eof(DownstreamConnection *dconn); - virtual int downstream_error(DownstreamConnection *dconn, int events); - Downstream *add_pending_downstream(int32_t stream_id); + virtual bufferevent_data_cb get_downstream_readcb(); + virtual bufferevent_data_cb get_downstream_writecb(); + virtual bufferevent_event_cb get_downstream_eventcb(); + Downstream *add_pending_downstream(int32_t stream_id, int32_t priority); void remove_downstream(Downstream *downstream); + Downstream *find_downstream(int32_t stream_id); + + spdylay_session *get_http2_session(); int rst_stream(Downstream *downstream, int status_code); int error_reply(Downstream *downstream, unsigned int status_code); @@ -72,34 +74,19 @@ virtual int on_downstream_body_complete(Downstream *downstream); virtual void on_handler_delete(); - virtual int on_downstream_reset(bool no_retry); - virtual int send_reply(Downstream *downstream, const uint8_t *body, - size_t bodylen); - virtual int initiate_push(Downstream *downstream, const StringRef &uri); - virtual int response_riovec(struct iovec *iov, int iovcnt) const; - virtual void response_drain(size_t n); - virtual bool response_empty() const; - - virtual Downstream *on_downstream_push_promise(Downstream *downstream, - int32_t promised_stream_id); - virtual int - on_downstream_push_promise_complete(Downstream *downstream, - Downstream *promised_downstream); - virtual bool push_enabled() const; - virtual void cancel_premature_downstream(Downstream *promised_downstream); + virtual void reset_timeouts(); bool get_flow_control() const; int consume(int32_t stream_id, size_t len); - void start_downstream(Downstream *downstream); - void initiate_downstream(Downstream *downstream); + void maintain_downstream_concurrency(); + void initiate_downstream(std::unique_ptr downstream); - DefaultMemchunks *get_response_buf(); + nghttp2::util::EvbufferBuffer sendbuf; private: - DefaultMemchunks wb_; DownstreamQueue downstream_queue_; ClientHandler *handler_; spdylay_session *session_; diff -Nru nghttp2-1.13.0/src/shrpx_ssl.cc nghttp2-0.6.7/src/shrpx_ssl.cc --- nghttp2-1.13.0/src/shrpx_ssl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_ssl.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,27 +24,20 @@ */ #include "shrpx_ssl.h" -#ifdef HAVE_SYS_SOCKET_H #include -#endif // HAVE_SYS_SOCKET_H -#ifdef HAVE_NETDB_H #include -#endif // HAVE_NETDB_H #include #include -#include #include #include -#include - -#include #include #include #include -#include -#include + +#include +#include #include @@ -57,14 +50,8 @@ #include "shrpx_config.h" #include "shrpx_worker.h" #include "shrpx_downstream_connection_pool.h" -#include "shrpx_http2_session.h" -#include "shrpx_memcached_request.h" -#include "shrpx_memcached_dispatcher.h" -#include "shrpx_connection_handler.h" #include "util.h" #include "ssl.h" -#include "template.h" -#include "ssl_compat.h" using namespace nghttp2; @@ -75,7 +62,7 @@ namespace { int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len, void *arg) { - auto &prefs = get_config()->tls.alpn_prefs; + auto &prefs = get_config()->alpn_prefs; *data = prefs.data(); *len = prefs.size(); return SSL_TLSEXT_ERR_OK; @@ -94,33 +81,34 @@ } } // namespace -// This function is meant be called from master process, hence the -// call exit(3). -std::vector -set_alpn_prefs(const std::vector &protos) { +std::vector set_alpn_prefs(const std::vector &protos) { size_t len = 0; - for (const auto &proto : protos) { - if (proto.size() > 255) { - LOG(FATAL) << "Too long ALPN identifier: " << proto.size(); - exit(EXIT_FAILURE); + for (auto proto : protos) { + auto n = strlen(proto); + + if (n > 255) { + LOG(FATAL) << "Too long ALPN identifier: " << n; + DIE(); } - len += 1 + proto.size(); + len += 1 + n; } if (len > (1 << 16) - 1) { LOG(FATAL) << "Too long ALPN identifier list: " << len; - exit(EXIT_FAILURE); + DIE(); } auto out = std::vector(len); auto ptr = out.data(); - for (const auto &proto : protos) { - *ptr++ = proto.size(); - memcpy(ptr, proto.c_str(), proto.size()); - ptr += proto.size(); + for (auto proto : protos) { + auto proto_len = strlen(proto); + + *ptr++ = proto_len; + memcpy(ptr, proto, proto_len); + ptr += proto_len; } return out; @@ -129,292 +117,31 @@ namespace { int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data) { auto config = static_cast(user_data); - auto len = static_cast(config->tls.private_key_passwd.size()); + int len = (int)strlen(config->private_key_passwd.get()); if (size < len + 1) { LOG(ERROR) << "ssl_pem_passwd_cb: buf is too small " << size; return 0; } // Copy string including last '\0'. - memcpy(buf, config->tls.private_key_passwd.c_str(), len + 1); + memcpy(buf, config->private_key_passwd.get(), len + 1); return len; } } // namespace namespace { int servername_callback(SSL *ssl, int *al, void *arg) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto worker = handler->get_worker(); - auto cert_tree = worker->get_cert_lookup_tree(); - if (!cert_tree) { - return SSL_TLSEXT_ERR_OK; - } - - std::array buf; - - auto rawhost = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); - if (rawhost == nullptr) { - return SSL_TLSEXT_ERR_OK; - } - - auto len = strlen(rawhost); - // NI_MAXHOST includes terminal NULL. - if (len == 0 || len + 1 > buf.size()) { - return SSL_TLSEXT_ERR_OK; - } - - auto end_buf = std::copy_n(rawhost, len, std::begin(buf)); - - util::inp_strlower(std::begin(buf), end_buf); - - auto hostname = StringRef{std::begin(buf), end_buf}; - - auto idx = cert_tree->lookup(hostname); - if (idx == -1) { - return SSL_TLSEXT_ERR_OK; - } - - auto conn_handler = worker->get_connection_handler(); - auto ssl_ctx = conn_handler->get_ssl_ctx(idx); - - SSL_set_SSL_CTX(ssl, ssl_ctx); - - return SSL_TLSEXT_ERR_OK; -} -} // namespace - -#ifndef OPENSSL_IS_BORINGSSL -namespace { -std::shared_ptr> -get_ocsp_data(TLSContextData *tls_ctx_data) { - std::lock_guard g(tls_ctx_data->mu); - return tls_ctx_data->ocsp_data; -} -} // namespace - -namespace { -int ocsp_resp_cb(SSL *ssl, void *arg) { - auto ssl_ctx = SSL_get_SSL_CTX(ssl); - auto tls_ctx_data = - static_cast(SSL_CTX_get_app_data(ssl_ctx)); - - auto data = get_ocsp_data(tls_ctx_data); - - if (!data) { - return SSL_TLSEXT_ERR_OK; - } - - auto buf = - static_cast(CRYPTO_malloc(data->size(), __FILE__, __LINE__)); - - if (!buf) { - return SSL_TLSEXT_ERR_OK; - } - - std::copy(std::begin(*data), std::end(*data), buf); - - SSL_set_tlsext_status_ocsp_resp(ssl, buf, data->size()); - - return SSL_TLSEXT_ERR_OK; -} -} // namespace -#endif // OPENSSL_IS_BORINGSSL - -constexpr auto MEMCACHED_SESSION_CACHE_KEY_PREFIX = - StringRef::from_lit("nghttpx:tls-session-cache:"); - -namespace { -int tls_session_new_cb(SSL *ssl, SSL_SESSION *session) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto worker = handler->get_worker(); - auto dispatcher = worker->get_session_cache_memcached_dispatcher(); - - const unsigned char *id; - unsigned int idlen; - - id = SSL_SESSION_get_id(session, &idlen); - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Memached: cache session, id=" << util::format_hex(id, idlen); - } - - auto req = make_unique(); - req->op = MEMCACHED_OP_ADD; - req->key = MEMCACHED_SESSION_CACHE_KEY_PREFIX.str(); - req->key += util::format_hex(id, idlen); - - auto sessionlen = i2d_SSL_SESSION(session, nullptr); - req->value.resize(sessionlen); - auto buf = &req->value[0]; - i2d_SSL_SESSION(session, &buf); - req->expiry = 12_h; - req->cb = [](MemcachedRequest *req, MemcachedResult res) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Memcached: session cache done. key=" << req->key - << ", status_code=" << res.status_code << ", value=" - << std::string(std::begin(res.value), std::end(res.value)); - } - if (res.status_code != 0) { - LOG(WARN) << "Memcached: failed to cache session key=" << req->key - << ", status_code=" << res.status_code << ", value=" - << std::string(std::begin(res.value), std::end(res.value)); - } - }; - assert(!req->canceled); - - dispatcher->add_request(std::move(req)); - - return 0; -} -} // namespace - -namespace { -SSL_SESSION *tls_session_get_cb(SSL *ssl, -#if OPENSSL_101_API - const unsigned char *id, -#else // !OPENSSL_101_API - unsigned char *id, -#endif // !OPENSSL_101_API - int idlen, int *copy) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto worker = handler->get_worker(); - auto dispatcher = worker->get_session_cache_memcached_dispatcher(); - - if (conn->tls.cached_session) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Memcached: found cached session, id=" - << util::format_hex(id, idlen); - } - - // This is required, without this, memory leak occurs. - *copy = 0; - - auto session = conn->tls.cached_session; - conn->tls.cached_session = nullptr; - return session; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Memcached: get cached session, id=" - << util::format_hex(id, idlen); - } - - auto req = make_unique(); - req->op = MEMCACHED_OP_GET; - req->key = MEMCACHED_SESSION_CACHE_KEY_PREFIX.str(); - req->key += util::format_hex(id, idlen); - req->cb = [conn](MemcachedRequest *, MemcachedResult res) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Memcached: returned status code " << res.status_code; - } - - // We might stop reading, so start it again - conn->rlimit.startw(); - ev_timer_again(conn->loop, &conn->rt); - - conn->wlimit.startw(); - ev_timer_again(conn->loop, &conn->wt); - - conn->tls.cached_session_lookup_req = nullptr; - if (res.status_code != 0) { - conn->tls.handshake_state = TLS_CONN_CANCEL_SESSION_CACHE; - return; - } - - const uint8_t *p = res.value.data(); - - auto session = d2i_SSL_SESSION(nullptr, &p, res.value.size()); - if (!session) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "cannot materialize session"; - } - conn->tls.handshake_state = TLS_CONN_CANCEL_SESSION_CACHE; - return; - } - - conn->tls.cached_session = session; - conn->tls.handshake_state = TLS_CONN_GOT_SESSION_CACHE; - }; - - conn->tls.handshake_state = TLS_CONN_WAIT_FOR_SESSION_CACHE; - conn->tls.cached_session_lookup_req = req.get(); - - dispatcher->add_request(std::move(req)); - - return nullptr; -} -} // namespace - -namespace { -int ticket_key_cb(SSL *ssl, unsigned char *key_name, unsigned char *iv, - EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc) { - auto conn = static_cast(SSL_get_app_data(ssl)); - auto handler = static_cast(conn->data); - auto worker = handler->get_worker(); - auto ticket_keys = worker->get_ticket_keys(); - - if (!ticket_keys) { - // No ticket keys available. - return -1; - } - - auto &keys = ticket_keys->keys; - assert(!keys.empty()); - - if (enc) { - if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) == 0) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, handler) << "session ticket key: RAND_bytes failed"; + if (get_config()->cert_tree) { + const char *hostname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (hostname) { + auto ssl_ctx = cert_lookup_tree_lookup(get_config()->cert_tree, hostname, + strlen(hostname)); + if (ssl_ctx) { + SSL_set_SSL_CTX(ssl, ssl_ctx); } - return -1; - } - - auto &key = keys[0]; - - if (LOG_ENABLED(INFO)) { - CLOG(INFO, handler) << "encrypt session ticket key: " - << util::format_hex(key.data.name); } - - std::copy(std::begin(key.data.name), std::end(key.data.name), key_name); - - EVP_EncryptInit_ex(ctx, get_config()->tls.ticket.cipher, nullptr, - key.data.enc_key.data(), iv); - HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac, - nullptr); - return 1; - } - - size_t i; - for (i = 0; i < keys.size(); ++i) { - auto &key = keys[i]; - if (std::equal(std::begin(key.data.name), std::end(key.data.name), - key_name)) { - break; - } - } - - if (i == keys.size()) { - if (LOG_ENABLED(INFO)) { - CLOG(INFO, handler) << "session ticket key " - << util::format_hex(key_name, 16) << " not found"; - } - return 0; } - if (LOG_ENABLED(INFO)) { - CLOG(INFO, handler) << "decrypt session ticket key: " - << util::format_hex(key_name, 16); - } - - auto &key = keys[i]; - HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac, - nullptr); - EVP_DecryptInit_ex(ctx, key.cipher, nullptr, key.data.enc_key.data(), iv); - - return i == 0 ? 1 : 2; + return SSL_TLSEXT_ERR_OK; } } // namespace @@ -425,13 +152,12 @@ // to disable it, we check that renegotiation is started in this // callback. if (where & SSL_CB_HANDSHAKE_START) { - auto conn = static_cast(SSL_get_app_data(ssl)); - if (conn && conn->tls.initial_handshake_done) { - auto handler = static_cast(conn->data); + auto handler = static_cast(SSL_get_app_data(ssl)); + if (handler && handler->get_tls_handshake()) { + handler->set_tls_renegotiation(true); if (LOG_ENABLED(INFO)) { CLOG(INFO, handler) << "TLS renegotiation started"; } - handler->start_immediate_shutdown(); } } } @@ -445,14 +171,16 @@ // We assume that get_config()->npn_list contains ALPN protocol // identifier sorted by preference order. So we just break when we // found the first overlap. - for (const auto &target_proto_id : get_config()->tls.npn_list) { + for (auto target_proto_id : get_config()->npn_list) { + auto target_proto_len = + strlen(reinterpret_cast(target_proto_id)); + for (auto p = in, end = in + inlen; p < end;) { auto proto_id = p + 1; auto proto_len = *p; - if (proto_id + proto_len <= end && - util::streq(StringRef{target_proto_id}, - StringRef{proto_id, proto_len})) { + if (proto_id + proto_len <= end && target_proto_len == proto_len && + memcmp(target_proto_id, proto_id, proto_len) == 0) { *out = reinterpret_cast(proto_id); *outlen = proto_len; @@ -469,74 +197,59 @@ } // namespace #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L -struct TLSProtocol { - StringRef name; - long int mask; -}; - -constexpr TLSProtocol TLS_PROTOS[] = { - TLSProtocol{StringRef::from_lit("TLSv1.2"), SSL_OP_NO_TLSv1_2}, - TLSProtocol{StringRef::from_lit("TLSv1.1"), SSL_OP_NO_TLSv1_1}, - TLSProtocol{StringRef::from_lit("TLSv1.0"), SSL_OP_NO_TLSv1}}; +namespace { +const char *tls_names[] = {"TLSv1.2", "TLSv1.1", "TLSv1.0"}; +const size_t tls_namelen = util::array_size(tls_names); +const long int tls_masks[] = {SSL_OP_NO_TLSv1_2, SSL_OP_NO_TLSv1_1, + SSL_OP_NO_TLSv1}; +} // namespace -long int create_tls_proto_mask(const std::vector &tls_proto_list) { +long int create_tls_proto_mask(const std::vector &tls_proto_list) { long int res = 0; - for (auto &supported : TLS_PROTOS) { - auto ok = false; - for (auto &name : tls_proto_list) { - if (util::strieq(supported.name, name)) { - ok = true; + for (size_t i = 0; i < tls_namelen; ++i) { + size_t j; + for (j = 0; j < tls_proto_list.size(); ++j) { + if (util::strieq(tls_names[i], tls_proto_list[j])) { break; } } - if (!ok) { - res |= supported.mask; + if (j == tls_proto_list.size()) { + res |= tls_masks[i]; } } return res; } -SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file -#ifdef HAVE_NEVERBLEED - , - neverbleed_t *nb -#endif // HAVE_NEVERBLEED - ) { - auto ssl_ctx = SSL_CTX_new(SSLv23_server_method()); +SSL_CTX *create_ssl_context(const char *private_key_file, + const char *cert_file) { + SSL_CTX *ssl_ctx; + ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (!ssl_ctx) { LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr); DIE(); } - constexpr auto ssl_opts = - (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | SSL_OP_NO_SSLv2 | - SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE | - SSL_OP_SINGLE_DH_USE | SSL_OP_CIPHER_SERVER_PREFERENCE; - - auto &tlsconf = get_config()->tls; - - SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask); + SSL_CTX_set_options(ssl_ctx, + SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | + SSL_OP_NO_COMPRESSION | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | + SSL_OP_SINGLE_ECDH_USE | SSL_OP_SINGLE_DH_USE | + SSL_OP_NO_TICKET | get_config()->tls_proto_mask); const unsigned char sid_ctx[] = "shrpx"; SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1); SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER); - if (!tlsconf.session_cache.memcached.host.empty()) { - SSL_CTX_sess_set_new_cb(ssl_ctx, tls_session_new_cb); - SSL_CTX_sess_set_get_cb(ssl_ctx, tls_session_get_cb); - } - - SSL_CTX_set_timeout(ssl_ctx, tlsconf.session_timeout.count()); - const char *ciphers; - if (!tlsconf.ciphers.empty()) { - ciphers = tlsconf.ciphers.c_str(); + if (get_config()->ciphers) { + ciphers = get_config()->ciphers.get(); } else { ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST; } + SSL_CTX_set_options(ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + if (SSL_CTX_set_cipher_list(ssl_ctx, ciphers) == 0) { LOG(FATAL) << "SSL_CTX_set_cipher_list " << ciphers << " failed: " << ERR_error_string(ERR_get_error(), nullptr); @@ -565,9 +278,9 @@ #endif // OPENSSL_NO_EC - if (!tlsconf.dh_param_file.empty()) { + if (get_config()->dh_param_file) { // Read DH parameters from file - auto bio = BIO_new_file(tlsconf.dh_param_file.c_str(), "r"); + auto bio = BIO_new_file(get_config()->dh_param_file.get(), "r"); if (bio == nullptr) { LOG(FATAL) << "BIO_new_file() failed: " << ERR_error_string(ERR_get_error(), nullptr); @@ -586,26 +299,16 @@ SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS); - if (!tlsconf.private_key_passwd.empty()) { + if (get_config()->private_key_passwd) { SSL_CTX_set_default_passwd_cb(ssl_ctx, ssl_pem_passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)get_config()); } - -#ifndef HAVE_NEVERBLEED if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file, SSL_FILETYPE_PEM) != 1) { LOG(FATAL) << "SSL_CTX_use_PrivateKey_file failed: " << ERR_error_string(ERR_get_error(), nullptr); - } -#else // HAVE_NEVERBLEED - std::array errbuf; - if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file, - errbuf.data()) != 1) { - LOG(FATAL) << "neverbleed_load_private_key_file failed: " << errbuf.data(); DIE(); } -#endif // HAVE_NEVERBLEED - if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) { LOG(FATAL) << "SSL_CTX_use_certificate_file failed: " << ERR_error_string(ERR_get_error(), nullptr); @@ -616,13 +319,14 @@ << ERR_error_string(ERR_get_error(), nullptr); DIE(); } - if (tlsconf.client_verify.enabled) { - if (!tlsconf.client_verify.cacert.empty()) { + if (get_config()->verify_client) { + if (get_config()->verify_client_cacert) { if (SSL_CTX_load_verify_locations( - ssl_ctx, tlsconf.client_verify.cacert.c_str(), nullptr) != 1) { + ssl_ctx, get_config()->verify_client_cacert.get(), nullptr) != + 1) { LOG(FATAL) << "Could not load trusted ca certificates from " - << tlsconf.client_verify.cacert << ": " + << get_config()->verify_client_cacert.get() << ": " << ERR_error_string(ERR_get_error(), nullptr); DIE(); } @@ -630,10 +334,11 @@ // error even though it returns success. See // http://forum.nginx.org/read.php?29,242540 ERR_clear_error(); - auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.c_str()); + auto list = + SSL_load_client_CA_file(get_config()->verify_client_cacert.get()); if (!list) { LOG(FATAL) << "Could not load ca certificates from " - << tlsconf.client_verify.cacert << ": " + << get_config()->verify_client_cacert.get() << ": " << ERR_error_string(ERR_get_error(), nullptr); DIE(); } @@ -644,10 +349,6 @@ verify_callback); } SSL_CTX_set_tlsext_servername_callback(ssl_ctx, servername_callback); - SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx, ticket_key_cb); -#ifndef OPENSSL_IS_BORINGSSL - SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb); -#endif // OPENSSL_IS_BORINGSSL SSL_CTX_set_info_callback(ssl_ctx, info_callback); // NPN advertisement @@ -656,91 +357,39 @@ // ALPN selection callback SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, nullptr); #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - - auto tls_ctx_data = new TLSContextData(); - tls_ctx_data->cert_file = cert_file; - - SSL_CTX_set_app_data(ssl_ctx, tls_ctx_data); - return ssl_ctx; } namespace { -int select_h2_next_proto_cb(SSL *ssl, unsigned char **out, - unsigned char *outlen, const unsigned char *in, - unsigned int inlen, void *arg) { - if (!util::select_h2(const_cast(out), outlen, in, - inlen)) { - return SSL_TLSEXT_ERR_NOACK; - } - - return SSL_TLSEXT_ERR_OK; -} -} // namespace - -namespace { -int select_h1_next_proto_cb(SSL *ssl, unsigned char **out, - unsigned char *outlen, const unsigned char *in, - unsigned int inlen, void *arg) { - auto end = in + inlen; - for (; in < end;) { - if (util::streq(NGHTTP2_H1_1_ALPN, StringRef{in, in + (in[0] + 1)})) { - *out = const_cast(in) + 1; - *outlen = in[0]; - return SSL_TLSEXT_ERR_OK; - } - in += in[0] + 1; - } - - return SSL_TLSEXT_ERR_NOACK; -} -} // namespace - -namespace { int select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { - auto conn = static_cast(SSL_get_app_data(ssl)); - switch (conn->proto) { - case PROTO_HTTP1: - return select_h1_next_proto_cb(ssl, out, outlen, in, inlen, arg); - case PROTO_HTTP2: - return select_h2_next_proto_cb(ssl, out, outlen, in, inlen, arg); - default: - return SSL_TLSEXT_ERR_NOACK; + if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) { + *out = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; + *outlen = NGHTTP2_PROTO_VERSION_ID_LEN; } + return SSL_TLSEXT_ERR_OK; } } // namespace -SSL_CTX *create_ssl_client_context( -#ifdef HAVE_NEVERBLEED - neverbleed_t *nb, -#endif // HAVE_NEVERBLEED - const StringRef &cacert, const StringRef &cert_file, - const StringRef &private_key_file, - int (*next_proto_select_cb)(SSL *s, unsigned char **out, - unsigned char *outlen, const unsigned char *in, - unsigned int inlen, void *arg)) { - auto ssl_ctx = SSL_CTX_new(SSLv23_client_method()); +SSL_CTX *create_ssl_client_context() { + SSL_CTX *ssl_ctx; + ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if (!ssl_ctx) { LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr); DIE(); } - - constexpr auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | - SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_NO_COMPRESSION | - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; - - auto &tlsconf = get_config()->tls; - - SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask); + SSL_CTX_set_options(ssl_ctx, + SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | + SSL_OP_NO_COMPRESSION | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | + get_config()->tls_proto_mask); const char *ciphers; - if (!tlsconf.ciphers.empty()) { - ciphers = tlsconf.ciphers.c_str(); + if (get_config()->ciphers) { + ciphers = get_config()->ciphers.get(); } else { - ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST; + ciphers = "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK"; } if (SSL_CTX_set_cipher_list(ssl_ctx, ciphers) == 0) { LOG(FATAL) << "SSL_CTX_set_cipher_list " << ciphers @@ -756,743 +405,490 @@ << ERR_error_string(ERR_get_error(), nullptr); } - if (!cacert.empty()) { - if (SSL_CTX_load_verify_locations(ssl_ctx, cacert.c_str(), nullptr) != 1) { + if (get_config()->cacert) { + if (SSL_CTX_load_verify_locations(ssl_ctx, get_config()->cacert.get(), + nullptr) != 1) { - LOG(FATAL) << "Could not load trusted ca certificates from " << cacert - << ": " << ERR_error_string(ERR_get_error(), nullptr); - DIE(); - } - } - - if (!cert_file.empty()) { - if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file.c_str()) != 1) { - - LOG(FATAL) << "Could not load client certificate from " << cert_file - << ": " << ERR_error_string(ERR_get_error(), nullptr); + LOG(FATAL) << "Could not load trusted ca certificates from " + << get_config()->cacert.get() << ": " + << ERR_error_string(ERR_get_error(), nullptr); DIE(); } } - if (!private_key_file.empty()) { -#ifndef HAVE_NEVERBLEED - if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file.c_str(), + if (get_config()->client_private_key_file) { + if (SSL_CTX_use_PrivateKey_file(ssl_ctx, + get_config()->client_private_key_file.get(), SSL_FILETYPE_PEM) != 1) { LOG(FATAL) << "Could not load client private key from " - << private_key_file << ": " + << get_config()->client_private_key_file.get() << ": " << ERR_error_string(ERR_get_error(), nullptr); DIE(); } -#else // HAVE_NEVERBLEED - std::array errbuf; - if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file.c_str(), - errbuf.data()) != 1) { - LOG(FATAL) << "neverbleed_load_private_key_file: could not load client " - "private key from " << private_key_file << ": " - << errbuf.data(); + } + if (get_config()->client_cert_file) { + if (SSL_CTX_use_certificate_chain_file( + ssl_ctx, get_config()->client_cert_file.get()) != 1) { + + LOG(FATAL) << "Could not load client certificate from " + << get_config()->client_cert_file.get() << ": " + << ERR_error_string(ERR_get_error(), nullptr); DIE(); } -#endif // HAVE_NEVERBLEED } + // NPN selection callback + SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, nullptr); - // NPN selection callback. This is required to set SSL_CTX because - // OpenSSL does not offer SSL_set_next_proto_select_cb. - SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_cb, nullptr); - - return ssl_ctx; -} +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + // ALPN advertisement; We only advertise HTTP/2 + auto proto_list = util::get_default_alpn(); -SSL *create_ssl(SSL_CTX *ssl_ctx) { - auto ssl = SSL_new(ssl_ctx); - if (!ssl) { - LOG(ERROR) << "SSL_new() failed: " << ERR_error_string(ERR_get_error(), - nullptr); - return nullptr; - } + SSL_CTX_set_alpn_protos(ssl_ctx, proto_list.data(), proto_list.size()); +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - return ssl; + return ssl_ctx; } -ClientHandler *accept_connection(Worker *worker, int fd, sockaddr *addr, - int addrlen, const UpstreamAddr *faddr) { +ClientHandler *accept_connection(event_base *evbase, + bufferevent_rate_limit_group *rate_limit_group, + SSL_CTX *ssl_ctx, evutil_socket_t fd, + sockaddr *addr, int addrlen, + WorkerStat *worker_stat, + DownstreamConnectionPool *dconn_pool) { char host[NI_MAXHOST]; char service[NI_MAXSERV]; int rv; + rv = getnameinfo(addr, addrlen, host, sizeof(host), service, sizeof(service), + NI_NUMERICHOST); + if (rv != 0) { + LOG(ERROR) << "getnameinfo() failed: " << gai_strerror(rv); - if (addr->sa_family == AF_UNIX) { - std::copy_n("localhost", sizeof("localhost"), host); - service[0] = '\0'; - } else { - rv = getnameinfo(addr, addrlen, host, sizeof(host), service, - sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV); - if (rv != 0) { - LOG(ERROR) << "getnameinfo() failed: " << gai_strerror(rv); - - return nullptr; - } + return nullptr; + } - rv = util::make_socket_nodelay(fd); - if (rv == -1) { - LOG(WARN) << "Setting option TCP_NODELAY failed: errno=" << errno; - } + int val = 1; + rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&val), + sizeof(val)); + if (rv == -1) { + LOG(WARN) << "Setting option TCP_NODELAY failed: errno=" << errno; } SSL *ssl = nullptr; - if (faddr->tls) { - auto ssl_ctx = worker->get_sv_ssl_ctx(); - - assert(ssl_ctx); - - ssl = create_ssl(ssl_ctx); + bufferevent *bev; + if (ssl_ctx) { + ssl = SSL_new(ssl_ctx); if (!ssl) { + LOG(ERROR) << "SSL_new() failed: " << ERR_error_string(ERR_get_error(), + nullptr); return nullptr; } - // Disable TLS session ticket if we don't have working ticket - // keys. - if (!worker->get_ticket_keys()) { - SSL_set_options(ssl, SSL_OP_NO_TICKET); + + if (SSL_set_fd(ssl, fd) == 0) { + LOG(ERROR) << "SSL_set_fd() failed: " << ERR_error_string(ERR_get_error(), + nullptr); + SSL_free(ssl); + return nullptr; } + + bev = bufferevent_openssl_socket_new( + evbase, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, BEV_OPT_DEFER_CALLBACKS); + } else { + bev = bufferevent_socket_new(evbase, fd, BEV_OPT_DEFER_CALLBACKS); + } + if (!bev) { + LOG(ERROR) << "bufferevent_socket_new() failed"; + if (ssl) { + SSL_free(ssl); + } + return nullptr; } - return new ClientHandler(worker, fd, ssl, host, service, addr->sa_family, - faddr); + return new ClientHandler(bev, rate_limit_group, fd, ssl, host, service, + worker_stat, dconn_pool); } -bool tls_hostname_match(const StringRef &pattern, const StringRef &hostname) { - auto ptWildcard = std::find(std::begin(pattern), std::end(pattern), '*'); - if (ptWildcard == std::end(pattern)) { +namespace { +bool tls_hostname_match(const char *pattern, const char *hostname) { + const char *ptWildcard = strchr(pattern, '*'); + if (ptWildcard == nullptr) { return util::strieq(pattern, hostname); } - - auto ptLeftLabelEnd = std::find(std::begin(pattern), std::end(pattern), '.'); - auto wildcardEnabled = true; + const char *ptLeftLabelEnd = strchr(pattern, '.'); + bool wildcardEnabled = true; // Do case-insensitive match. At least 2 dots are required to enable // wildcard match. Also wildcard must be in the left-most label. // Don't attempt to match a presented identifier where the wildcard // character is embedded within an A-label. - if (ptLeftLabelEnd == std::end(pattern) || - std::find(ptLeftLabelEnd + 1, std::end(pattern), '.') == - std::end(pattern) || - ptLeftLabelEnd < ptWildcard || util::istarts_with_l(pattern, "xn--")) { + if (ptLeftLabelEnd == 0 || strchr(ptLeftLabelEnd + 1, '.') == 0 || + ptLeftLabelEnd < ptWildcard || util::istartsWith(pattern, "xn--")) { wildcardEnabled = false; } - if (!wildcardEnabled) { return util::strieq(pattern, hostname); } - - auto hnLeftLabelEnd = - std::find(std::begin(hostname), std::end(hostname), '.'); - if (hnLeftLabelEnd == std::end(hostname) || - !util::strieq(StringRef{ptLeftLabelEnd, std::end(pattern)}, - StringRef{hnLeftLabelEnd, std::end(hostname)})) { + const char *hnLeftLabelEnd = strchr(hostname, '.'); + if (hnLeftLabelEnd == 0 || !util::strieq(ptLeftLabelEnd, hnLeftLabelEnd)) { return false; } // Perform wildcard match. Here '*' must match at least one // character. - if (hnLeftLabelEnd - std::begin(hostname) < - ptLeftLabelEnd - std::begin(pattern)) { + if (hnLeftLabelEnd - hostname < ptLeftLabelEnd - pattern) { return false; } - return util::istarts_with(StringRef{std::begin(hostname), hnLeftLabelEnd}, - StringRef{std::begin(pattern), ptWildcard}) && - util::iends_with(StringRef{std::begin(hostname), hnLeftLabelEnd}, - StringRef{ptWildcard + 1, ptLeftLabelEnd}); + return util::istartsWith(hostname, hnLeftLabelEnd, pattern, ptWildcard) && + util::iendsWith(hostname, hnLeftLabelEnd, ptWildcard + 1, + ptLeftLabelEnd); } +} // namespace namespace { -// if return value is not empty, StringRef.c_str() must be freed using -// OPENSSL_free(). -StringRef get_common_name(X509 *cert) { - auto subjectname = X509_get_subject_name(cert); - if (!subjectname) { - LOG(WARN) << "Could not get X509 name object from the certificate."; - return StringRef{}; - } - int lastpos = -1; - for (;;) { - lastpos = X509_NAME_get_index_by_NID(subjectname, NID_commonName, lastpos); - if (lastpos == -1) { - break; +int verify_hostname(const char *hostname, const sockaddr_union *su, + size_t salen, const std::vector &dns_names, + const std::vector &ip_addrs, + const std::string &common_name) { + if (util::numeric_host(hostname)) { + if (ip_addrs.empty()) { + return util::strieq(common_name.c_str(), hostname) ? 0 : -1; } - auto entry = X509_NAME_get_entry(subjectname, lastpos); - - unsigned char *p; - auto plen = ASN1_STRING_to_UTF8(&p, X509_NAME_ENTRY_get_data(entry)); - if (plen < 0) { - continue; + const void *saddr; + switch (su->storage.ss_family) { + case AF_INET: + saddr = &su->in.sin_addr; + break; + case AF_INET6: + saddr = &su->in6.sin6_addr; + break; + default: + return -1; } - if (std::find(p, p + plen, '\0') != p + plen) { - // Embedded NULL is not permitted. - continue; + for (size_t i = 0; i < ip_addrs.size(); ++i) { + if (salen == ip_addrs[i].size() && + memcmp(saddr, ip_addrs[i].c_str(), salen) == 0) { + return 0; + } } - if (plen == 0) { - LOG(WARN) << "X509 name is empty"; - OPENSSL_free(p); - continue; + } else { + if (dns_names.empty()) { + return tls_hostname_match(common_name.c_str(), hostname) ? 0 : -1; } - - return StringRef{p, static_cast(plen)}; - } - return StringRef{}; -} -} // namespace - -namespace { -int verify_numeric_hostname(X509 *cert, const StringRef &hostname, - const Address *addr) { - const void *saddr; - switch (addr->su.storage.ss_family) { - case AF_INET: - saddr = &addr->su.in.sin_addr; - break; - case AF_INET6: - saddr = &addr->su.in6.sin6_addr; - break; - default: - return -1; - } - - auto altnames = static_cast( - X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); - if (altnames) { - auto altnames_deleter = defer(GENERAL_NAMES_free, altnames); - size_t n = sk_GENERAL_NAME_num(altnames); - auto ip_found = false; - for (size_t i = 0; i < n; ++i) { - auto altname = sk_GENERAL_NAME_value(altnames, i); - if (altname->type != GEN_IPADD) { - continue; - } - - auto ip_addr = altname->d.iPAddress->data; - if (!ip_addr) { - continue; - } - size_t ip_addrlen = altname->d.iPAddress->length; - - ip_found = true; - if (addr->len == ip_addrlen && memcmp(saddr, ip_addr, ip_addrlen) == 0) { + for (size_t i = 0; i < dns_names.size(); ++i) { + if (tls_hostname_match(dns_names[i].c_str(), hostname)) { return 0; } } - - if (ip_found) { - return -1; - } } - - auto cn = get_common_name(cert); - if (cn.empty()) { - return -1; - } - - // cn is not NULL terminated - auto rv = util::streq(hostname, cn); - OPENSSL_free(const_cast(cn.c_str())); - - if (rv) { - return 0; - } - return -1; } } // namespace -namespace { -int verify_hostname(X509 *cert, const StringRef &hostname, - const Address *addr) { - if (util::numeric_host(hostname.c_str())) { - return verify_numeric_hostname(cert, hostname, addr); - } - - auto altnames = static_cast( +void get_altnames(X509 *cert, std::vector &dns_names, + std::vector &ip_addrs, + std::string &common_name) { + GENERAL_NAMES *altnames = static_cast( X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); if (altnames) { - auto dns_found = false; - auto altnames_deleter = defer(GENERAL_NAMES_free, altnames); + auto altnames_deleter = util::defer(altnames, GENERAL_NAMES_free); size_t n = sk_GENERAL_NAME_num(altnames); for (size_t i = 0; i < n; ++i) { - auto altname = sk_GENERAL_NAME_value(altnames, i); - if (altname->type != GEN_DNS) { - continue; - } - - auto name = reinterpret_cast(ASN1_STRING_data(altname->d.ia5)); - if (!name) { - continue; - } - - auto len = ASN1_STRING_length(altname->d.ia5); - if (len == 0) { - continue; - } - if (std::find(name, name + len, '\0') != name + len) { - // Embedded NULL is not permitted. - continue; - } - - if (name[len - 1] == '.') { - --len; - if (len == 0) { + const GENERAL_NAME *altname = sk_GENERAL_NAME_value(altnames, i); + if (altname->type == GEN_DNS) { + const char *name; + name = reinterpret_cast(ASN1_STRING_data(altname->d.ia5)); + if (!name) { continue; } - } - - dns_found = true; - - if (tls_hostname_match(StringRef{name, static_cast(len)}, - hostname)) { - return 0; + size_t len = ASN1_STRING_length(altname->d.ia5); + if (std::find(name, name + len, '\0') != name + len) { + // Embedded NULL is not permitted. + continue; + } + dns_names.push_back(std::string(name, len)); + } else if (altname->type == GEN_IPADD) { + const unsigned char *ip_addr = altname->d.iPAddress->data; + if (!ip_addr) { + continue; + } + size_t len = altname->d.iPAddress->length; + ip_addrs.push_back( + std::string(reinterpret_cast(ip_addr), len)); } } - - // RFC 6125, section 6.4.4. says that client MUST not seek a match - // for CN if a dns dNSName is found. - if (dns_found) { - return -1; - } } - - auto cn = get_common_name(cert); - if (cn.empty()) { - return -1; + X509_NAME *subjectname = X509_get_subject_name(cert); + if (!subjectname) { + LOG(WARN) << "Could not get X509 name object from the certificate."; + return; } - - if (cn[cn.size() - 1] == '.') { - if (cn.size() == 1) { - OPENSSL_free(const_cast(cn.c_str())); - - return -1; + int lastpos = -1; + while (1) { + lastpos = X509_NAME_get_index_by_NID(subjectname, NID_commonName, lastpos); + if (lastpos == -1) { + break; + } + X509_NAME_ENTRY *entry = X509_NAME_get_entry(subjectname, lastpos); + unsigned char *out; + int outlen = ASN1_STRING_to_UTF8(&out, X509_NAME_ENTRY_get_data(entry)); + if (outlen < 0) { + continue; } - cn = StringRef{cn.c_str(), cn.size() - 1}; + if (std::find(out, out + outlen, '\0') != out + outlen) { + // Embedded NULL is not permitted. + continue; + } + common_name.assign(&out[0], &out[outlen]); + OPENSSL_free(out); + break; } - - auto rv = tls_hostname_match(cn, hostname); - OPENSSL_free(const_cast(cn.c_str())); - - return rv ? 0 : -1; } -} // namespace -int check_cert(SSL *ssl, const Address *addr, const StringRef &host) { +int check_cert(SSL *ssl) { auto cert = SSL_get_peer_certificate(ssl); if (!cert) { LOG(ERROR) << "No certificate found"; return -1; } - auto cert_deleter = defer(X509_free, cert); - auto verify_res = SSL_get_verify_result(ssl); + auto cert_deleter = util::defer(cert, X509_free); + long verify_res = SSL_get_verify_result(ssl); if (verify_res != X509_V_OK) { LOG(ERROR) << "Certificate verification failed: " << X509_verify_cert_error_string(verify_res); return -1; } - - if (verify_hostname(cert, host, addr) != 0) { + std::string common_name; + std::vector dns_names; + std::vector ip_addrs; + get_altnames(cert, dns_names, ip_addrs, common_name); + if (verify_hostname(get_config()->downstream_host.get(), + &get_config()->downstream_addr, + get_config()->downstream_addrlen, dns_names, ip_addrs, + common_name) != 0) { LOG(ERROR) << "Certificate verification failed: hostname does not match"; return -1; } return 0; } -int check_cert(SSL *ssl, const DownstreamAddr *addr) { - auto hostname = - addr->sni.empty() ? StringRef{addr->host} : StringRef{addr->sni}; - return check_cert(ssl, &addr->addr, hostname); +CertLookupTree *cert_lookup_tree_new() { + auto tree = new CertLookupTree(); + auto root = new CertNode(); + root->ssl_ctx = 0; + root->str = 0; + root->first = root->last = 0; + tree->root = root; + return tree; } -CertLookupTree::CertLookupTree() {} - -void CertLookupTree::add_cert(const StringRef &hostname, size_t idx) { - std::array buf; - - // NI_MAXHOST includes terminal NULL byte - if (hostname.empty() || hostname.size() + 1 > buf.size()) { - return; - } - - auto wildcard_it = std::find(std::begin(hostname), std::end(hostname), '*'); - if (wildcard_it != std::end(hostname) && - wildcard_it + 1 != std::end(hostname)) { - auto wildcard_prefix = StringRef{std::begin(hostname), wildcard_it}; - auto wildcard_suffix = StringRef{wildcard_it + 1, std::end(hostname)}; - - auto rev_suffix = StringRef{std::begin(buf), - std::reverse_copy(std::begin(wildcard_suffix), - std::end(wildcard_suffix), - std::begin(buf))}; - - WildcardPattern *wpat; - - if (!rev_wildcard_router_.add_route(rev_suffix, - wildcard_patterns_.size())) { - auto wcidx = rev_wildcard_router_.match(rev_suffix); - - assert(wcidx != -1); - - wpat = &wildcard_patterns_[wcidx]; - } else { - wildcard_patterns_.emplace_back(); - wpat = &wildcard_patterns_.back(); - } - - auto rev_prefix = StringRef{std::begin(buf), - std::reverse_copy(std::begin(wildcard_prefix), - std::end(wildcard_prefix), - std::begin(buf))}; - - wpat->rev_prefix.emplace_back(rev_prefix, idx); - - return; +namespace { +void cert_node_del(CertNode *node) { + for (auto &a : node->next) { + cert_node_del(a); } - - router_.add_route(hostname, idx); + delete node; } +} // namespace -ssize_t CertLookupTree::lookup(const StringRef &hostname) { - std::array buf; - - // NI_MAXHOST includes terminal NULL byte - if (hostname.empty() || hostname.size() + 1 > buf.size()) { - return -1; - } - - // Always prefer exact match - auto idx = router_.match(hostname); - if (idx != -1) { - return idx; - } - - if (wildcard_patterns_.empty()) { - return -1; +void cert_lookup_tree_del(CertLookupTree *lt) { + cert_node_del(lt->root); + for (auto &s : lt->hosts) { + delete[] s; } + delete lt; +} - ssize_t best_idx = -1; - size_t best_prefixlen = 0; - const RNode *last_node = nullptr; - - auto rev_host = StringRef{ - std::begin(buf), std::reverse_copy(std::begin(hostname), - std::end(hostname), std::begin(buf))}; - - for (;;) { - size_t nread = 0; - - auto wcidx = - rev_wildcard_router_.match_prefix(&nread, &last_node, rev_host); - if (wcidx == -1) { - return best_idx; - } - - // '*' must match at least one byte - if (nread == rev_host.size()) { - return best_idx; - } - - rev_host = StringRef{std::begin(rev_host) + nread, std::end(rev_host)}; - - auto rev_prefix = StringRef{std::begin(rev_host) + 1, std::end(rev_host)}; - - auto &wpat = wildcard_patterns_[wcidx]; - for (auto &wprefix : wpat.rev_prefix) { - if (!util::ends_with(rev_prefix, wprefix.prefix)) { - continue; - } - - auto prefixlen = - wprefix.prefix.size() + - (reinterpret_cast(&rev_host[0]) - &buf[0]); - - // Breaking a tie with longer suffix - if (prefixlen < best_prefixlen) { - continue; - } - - best_idx = wprefix.idx; - best_prefixlen = prefixlen; +namespace { +// The |offset| is the index in the hostname we are examining. We are +// going to scan from |offset| in backwards. +void cert_lookup_tree_add_cert(CertLookupTree *lt, CertNode *node, + SSL_CTX *ssl_ctx, char *hostname, size_t len, + int offset) { + int i, next_len = node->next.size(); + char c = hostname[offset]; + CertNode *cn = nullptr; + for (i = 0; i < next_len; ++i) { + cn = node->next[i]; + if (cn->str[cn->first] == c) { + break; } } -} - -void CertLookupTree::dump() const { - std::cerr << "exact:" << std::endl; - router_.dump(); - std::cerr << "wildcard suffix (reversed):" << std::endl; - rev_wildcard_router_.dump(); -} - -int cert_lookup_tree_add_cert_from_x509(CertLookupTree *lt, size_t idx, - X509 *cert) { - std::array buf; - - auto altnames = static_cast( - X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); - if (altnames) { - auto altnames_deleter = defer(GENERAL_NAMES_free, altnames); - size_t n = sk_GENERAL_NAME_num(altnames); - auto dns_found = false; - for (size_t i = 0; i < n; ++i) { - auto altname = sk_GENERAL_NAME_value(altnames, i); - if (altname->type != GEN_DNS) { - continue; - } - - auto name = reinterpret_cast(ASN1_STRING_data(altname->d.ia5)); - if (!name) { - continue; - } - - auto len = ASN1_STRING_length(altname->d.ia5); - if (len == 0) { - continue; - } - if (std::find(name, name + len, '\0') != name + len) { - // Embedded NULL is not permitted. - continue; + if (i == next_len) { + if (c == '*') { + // We assume hostname as wildcard hostname when first '*' is + // encountered. Note that as per RFC 6125 (6.4.3), there are + // some restrictions for wildcard hostname. We just ignore + // these rules here but do the proper check when we do the + // match. + node->wildcard_certs.push_back(std::make_pair(hostname, ssl_ctx)); + } else { + int j; + auto new_node = new CertNode(); + new_node->str = hostname; + new_node->first = offset; + // If wildcard is found, set the region before it because we + // don't include it in [first, last). + for (j = offset; j >= 0 && hostname[j] != '*'; --j) + ; + new_node->last = j; + if (j == -1) { + new_node->ssl_ctx = ssl_ctx; + } else { + new_node->ssl_ctx = nullptr; + new_node->wildcard_certs.push_back(std::make_pair(hostname, ssl_ctx)); } - - if (name[len - 1] == '.') { - --len; - if (len == 0) { - continue; + node->next.push_back(new_node); + } + } else { + int j; + for (i = cn->first, j = offset; + i > cn->last && j >= 0 && cn->str[i] == hostname[j]; --i, --j) + ; + if (i == cn->last) { + if (j == -1) { + if (cn->ssl_ctx) { + // same hostname, we don't overwrite exiting ssl_ctx + } else { + cn->ssl_ctx = ssl_ctx; } + } else { + // The existing hostname is a suffix of this hostname. + // Continue matching at potion j. + cert_lookup_tree_add_cert(lt, cn, ssl_ctx, hostname, len, j); } + } else { + auto new_node = new CertNode(); + new_node->ssl_ctx = cn->ssl_ctx; + new_node->str = cn->str; + new_node->first = i; + new_node->last = cn->last; + new_node->wildcard_certs.swap(cn->wildcard_certs); + new_node->next.swap(cn->next); - dns_found = true; + cn->next.push_back(new_node); - if (static_cast(len) + 1 > buf.size()) { - continue; + cn->last = i; + if (j == -1) { + // This hostname is a suffix of the existing hostname. + cn->ssl_ctx = ssl_ctx; + } else { + // This hostname and existing one share suffix. + cn->ssl_ctx = nullptr; + cert_lookup_tree_add_cert(lt, cn, ssl_ctx, hostname, len, j); } - - auto end_buf = std::copy_n(name, len, std::begin(buf)); - util::inp_strlower(std::begin(buf), end_buf); - - lt->add_cert(StringRef{std::begin(buf), end_buf}, idx); - } - - // Don't bother CN if we have dNSName. - if (dns_found) { - return 0; } } +} +} // namespace - auto cn = get_common_name(cert); - if (cn.empty()) { - return 0; +void cert_lookup_tree_add_cert(CertLookupTree *lt, SSL_CTX *ssl_ctx, + const char *hostname, size_t len) { + if (len == 0) { + return; } + // Copy hostname including terminal NULL + char *host_copy = new char[len + 1]; + for (size_t i = 0; i < len; ++i) { + host_copy[i] = util::lowcase(hostname[i]); + } + host_copy[len] = '\0'; + lt->hosts.push_back(host_copy); + cert_lookup_tree_add_cert(lt, lt->root, ssl_ctx, host_copy, len, len - 1); +} - if (cn[cn.size() - 1] == '.') { - if (cn.size() == 1) { - OPENSSL_free(const_cast(cn.c_str())); - - return 0; +namespace { +SSL_CTX *cert_lookup_tree_lookup(CertLookupTree *lt, CertNode *node, + const char *hostname, size_t len, int offset) { + int i, j; + for (i = node->first, j = offset; + i > node->last && j >= 0 && node->str[i] == util::lowcase(hostname[j]); + --i, --j) + ; + if (i != node->last) { + return nullptr; + } + if (j == -1) { + if (node->ssl_ctx) { + // exact match + return node->ssl_ctx; + } else { + // Do not perform wildcard-match because '*' must match at least + // one character. + return nullptr; } - - cn = StringRef{cn.c_str(), cn.size() - 1}; } - - auto end_buf = std::copy(std::begin(cn), std::end(cn), std::begin(buf)); - - OPENSSL_free(const_cast(cn.c_str())); - - util::inp_strlower(std::begin(buf), end_buf); - - lt->add_cert(StringRef{std::begin(buf), end_buf}, idx); - - return 0; -} - -bool in_proto_list(const std::vector &protos, - const StringRef &needle) { - for (auto &proto : protos) { - if (util::streq(StringRef{proto}, needle)) { - return true; + for (auto &wildcert : node->wildcard_certs) { + if (tls_hostname_match(wildcert.first, hostname)) { + return wildcert.second; } } - return false; + char c = util::lowcase(hostname[j]); + for (auto &next_node : node->next) { + if (next_node->str[next_node->first] == c) { + return cert_lookup_tree_lookup(lt, next_node, hostname, len, j); + } + } + return nullptr; } +} // namespace -bool upstream_tls_enabled() { - const auto &faddrs = get_config()->conn.listener.addrs; - return std::any_of(std::begin(faddrs), std::end(faddrs), - [](const UpstreamAddr &faddr) { return faddr.tls; }); +SSL_CTX *cert_lookup_tree_lookup(CertLookupTree *lt, const char *hostname, + size_t len) { + return cert_lookup_tree_lookup(lt, lt->root, hostname, len, len - 1); } -X509 *load_certificate(const char *filename) { +int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx, + const char *certfile) { auto bio = BIO_new(BIO_s_file()); if (!bio) { - fprintf(stderr, "BIO_new() failed\n"); - return nullptr; + LOG(ERROR) << "BIO_new failed"; + return -1; } - auto bio_deleter = defer(BIO_vfree, bio); - if (!BIO_read_filename(bio, filename)) { - fprintf(stderr, "Could not read certificate file '%s'\n", filename); - return nullptr; + auto bio_deleter = util::defer(bio, BIO_vfree); + if (!BIO_read_filename(bio, certfile)) { + LOG(ERROR) << "Could not read certificate file '" << certfile << "'"; + return -1; } auto cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr); if (!cert) { - fprintf(stderr, "Could not read X509 structure from file '%s'\n", filename); - return nullptr; - } - - return cert; -} - -SSL_CTX *setup_server_ssl_context(std::vector &all_ssl_ctx, - CertLookupTree *cert_tree -#ifdef HAVE_NEVERBLEED - , - neverbleed_t *nb -#endif // HAVE_NEVERBLEED - ) { - if (!upstream_tls_enabled()) { - return nullptr; - } - - auto &tlsconf = get_config()->tls; - - auto ssl_ctx = ssl::create_ssl_context(tlsconf.private_key_file.c_str(), - tlsconf.cert_file.c_str() -#ifdef HAVE_NEVERBLEED - , - nb -#endif // HAVE_NEVERBLEED - ); - - all_ssl_ctx.push_back(ssl_ctx); - - if (tlsconf.subcerts.empty()) { - return ssl_ctx; - } - - if (!cert_tree) { - LOG(WARN) << "We have multiple additional certificates (--subcert), but " - "cert_tree is not given. SNI may not work."; - return ssl_ctx; - } - -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10002000L - auto cert = SSL_CTX_get0_certificate(ssl_ctx); -#else // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < - // 0x10002000L - auto cert = load_certificate(tlsconf.cert_file.c_str()); - auto cert_deleter = defer(X509_free, cert); -#endif // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < - // 0x10002000L - - if (ssl::cert_lookup_tree_add_cert_from_x509( - cert_tree, all_ssl_ctx.size() - 1, cert) == -1) { - LOG(FATAL) << "Failed to add default certificate."; - DIE(); + LOG(ERROR) << "Could not read X509 structure from file '" << certfile + << "'"; + return -1; } - - for (auto &keycert : tlsconf.subcerts) { - auto &priv_key_file = keycert.first; - auto &cert_file = keycert.second; - - auto ssl_ctx = - ssl::create_ssl_context(priv_key_file.c_str(), cert_file.c_str() -#ifdef HAVE_NEVERBLEED - , - nb -#endif // HAVE_NEVERBLEED - ); - all_ssl_ctx.push_back(ssl_ctx); - -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10002000L - auto cert = SSL_CTX_get0_certificate(ssl_ctx); -#else // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < - // 0x10002000L - auto cert = load_certificate(cert_file.c_str()); - auto cert_deleter = defer(X509_free, cert); -#endif // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < - // 0x10002000L - - if (ssl::cert_lookup_tree_add_cert_from_x509( - cert_tree, all_ssl_ctx.size() - 1, cert) == -1) { - LOG(FATAL) << "Failed to add sub certificate."; - DIE(); - } + auto cert_deleter = util::defer(cert, X509_free); + std::string common_name; + std::vector dns_names; + std::vector ip_addrs; + get_altnames(cert, dns_names, ip_addrs, common_name); + for (auto &dns_name : dns_names) { + cert_lookup_tree_add_cert(lt, ssl_ctx, dns_name.c_str(), dns_name.size()); } - - return ssl_ctx; -} - -SSL_CTX *setup_downstream_client_ssl_context( -#ifdef HAVE_NEVERBLEED - neverbleed_t *nb -#endif // HAVE_NEVERBLEED - ) { - auto &tlsconf = get_config()->tls; - - return ssl::create_ssl_client_context( -#ifdef HAVE_NEVERBLEED - nb, -#endif // HAVE_NEVERBLEED - StringRef{tlsconf.cacert}, StringRef{tlsconf.client.cert_file}, - StringRef{tlsconf.client.private_key_file}, select_next_proto_cb); -} - -void setup_downstream_http2_alpn(SSL *ssl) { -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - // ALPN advertisement - auto alpn = util::get_default_alpn(); - SSL_set_alpn_protos(ssl, alpn.data(), alpn.size()); -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L -} - -void setup_downstream_http1_alpn(SSL *ssl) { -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - // ALPN advertisement - SSL_set_alpn_protos(ssl, NGHTTP2_H1_1_ALPN.byte(), NGHTTP2_H1_1_ALPN.size()); -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L + cert_lookup_tree_add_cert(lt, ssl_ctx, common_name.c_str(), + common_name.size()); + return 0; } -std::unique_ptr create_cert_lookup_tree() { - if (!upstream_tls_enabled() || get_config()->tls.subcerts.empty()) { - return nullptr; +bool in_proto_list(const std::vector &protos, + const unsigned char *needle, size_t len) { + for (auto proto : protos) { + if (strlen(proto) == len && memcmp(proto, needle, len) == 0) { + return true; + } } - return make_unique(); + return false; } -namespace { -std::vector serialize_ssl_session(SSL_SESSION *session) { - auto len = i2d_SSL_SESSION(session, nullptr); - auto buf = std::vector(len); - auto p = buf.data(); - i2d_SSL_SESSION(session, &p); +bool check_http2_requirement(SSL *ssl) { + auto tls_ver = SSL_version(ssl); - return buf; -} -} // namespace - -void try_cache_tls_session(TLSSessionCache &cache, const Address &addr, - SSL_SESSION *session, ev_tstamp t) { - if (cache.last_updated + 1_min > t) { + switch (tls_ver) { + case TLS1_2_VERSION: + break; + default: if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Cache for addr=" << util::to_numeric_addr(&addr) - << " is still host. Not updating."; + LOG(INFO) << "TLSv1.2 was not negotiated. " + << "HTTP/2 must not be negotiated."; } - return; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Update cache entry for SSL_SESSION=" << session - << ", addr=" << util::to_numeric_addr(&addr) - << ", timestamp=" << std::fixed << std::setprecision(6) << t; - } - - cache.session_data = serialize_ssl_session(session); - cache.last_updated = t; -} - -SSL_SESSION *reuse_tls_session(const TLSSessionCache &cache) { - if (cache.session_data.empty()) { - return nullptr; + return false; } - auto p = cache.session_data.data(); - return d2i_SSL_SESSION(nullptr, &p, cache.session_data.size()); + return true; } } // namespace ssl diff -Nru nghttp2-1.13.0/src/shrpx_ssl.h nghttp2-0.6.7/src/shrpx_ssl.h --- nghttp2-1.13.0/src/shrpx_ssl.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_ssl.h 2014-11-30 14:15:07.000000000 +0000 @@ -28,150 +28,105 @@ #include "shrpx.h" #include -#include #include #include -#include - -#ifdef HAVE_NEVERBLEED -#include -#endif // HAVE_NEVERBLEED - -#include "network.h" -#include "shrpx_router.h" +#include namespace shrpx { class ClientHandler; -class Worker; +struct WorkerStat; class DownstreamConnectionPool; -struct DownstreamAddr; -struct UpstreamAddr; namespace ssl { -struct TLSSessionCache { - // ASN1 representation of SSL_SESSION object. See - // i2d_SSL_SESSION(3SSL). - std::vector session_data; - // The last time stamp when this cache entry is created or updated. - ev_tstamp last_updated; -}; +SSL_CTX *create_ssl_context(const char *private_key_file, + const char *cert_file); -// This struct stores the additional information per SSL_CTX. This is -// attached to SSL_CTX using SSL_CTX_set_app_data(). -struct TLSContextData { - // Protects ocsp_data; - std::mutex mu; - // OCSP response - std::shared_ptr> ocsp_data; +SSL_CTX *create_ssl_client_context(); - // Path to certificate file - const char *cert_file; -}; +ClientHandler *accept_connection(event_base *evbase, + bufferevent_rate_limit_group *rate_limit_group, + SSL_CTX *ssl_ctx, evutil_socket_t fd, + sockaddr *addr, int addrlen, + WorkerStat *worker_stat, + DownstreamConnectionPool *dconn_pool); -// Create server side SSL_CTX -SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file -#ifdef HAVE_NEVERBLEED - , - neverbleed_t *nb -#endif // HAVE_NEVERBLEED - ); - -// Create client side SSL_CTX. This does not configure ALPN settings. -// |next_proto_select_cb| is for NPN. -SSL_CTX *create_ssl_client_context( -#ifdef HAVE_NEVERBLEED - neverbleed_t *nb, -#endif // HAVE_NEVERBLEED - const StringRef &cacert, const StringRef &cert_file, - const StringRef &private_key_file, - int (*next_proto_select_cb)(SSL *s, unsigned char **out, - unsigned char *outlen, const unsigned char *in, - unsigned int inlen, void *arg)); - -ClientHandler *accept_connection(Worker *worker, int fd, sockaddr *addr, - int addrlen, const UpstreamAddr *faddr); - -// Check peer's certificate against given |address| and |host|. -int check_cert(SSL *ssl, const Address *addr, const StringRef &host); -int check_cert(SSL *ssl, const DownstreamAddr *addr); +int check_cert(SSL *ssl); // Retrieves DNS and IP address in subjectAltNames and commonName from // the |cert|. void get_altnames(X509 *cert, std::vector &dns_names, std::vector &ip_addrs, std::string &common_name); -struct WildcardRevPrefix { - WildcardRevPrefix(const StringRef &prefix, size_t idx) - : prefix(std::begin(prefix), std::end(prefix)), idx(idx) {} - - // "Prefix" of wildcard pattern. It is reversed from original form. - // For example, if the original wildcard is "test*.nghttp2.org", - // prefix would be "tset". - ImmutableString prefix; - // The index of SSL_CTX. See ConnectionHandler::get_ssl_ctx(). - size_t idx; +// CertLookupTree forms lookup tree to get SSL_CTX whose DNS or +// commonName matches hostname in query. The tree is patricia trie +// data structure formed from the tail of the hostname pattern. Each +// CertNode contains part of hostname str member in range [first, +// last) member and the next member contains the following CertNode +// pointers ('following' means character before the current one). The +// CertNode where a hostname pattern ends contains its SSL_CTX pointer +// in the ssl_ctx member. For wildcard hostname pattern, we store the +// its pattern and SSL_CTX in CertNode one before first "*" found from +// the tail. +// +// When querying SSL_CTX with particular hostname, we match from its +// tail in our lookup tree. If the query goes to the first character +// of the hostname and current CertNode has non-NULL ssl_ctx member, +// then it is the exact match. The ssl_ctx member is returned. Along +// the way, if CertNode which contains non-empty wildcard_certs member +// is encountered, wildcard hostname matching is performed against +// them. If there is a match, its SSL_CTX is returned. If none +// matches, query is continued to the next character. + +struct CertNode { + // SSL_CTX for exact match + SSL_CTX *ssl_ctx; + // list of wildcard domain name and its SSL_CTX pair, the wildcard + // '*' appears in this position. + std::vector> wildcard_certs; + // Next CertNode index of CertLookupTree::nodes + std::vector next; + char *str; + // [first, last) in the reverse direction in str, first >= + // last. This indices only work for str member. + int first, last; }; -struct WildcardPattern { - // Wildcard host sharing only suffix is probably rare, so we just do - // linear search. - std::vector rev_prefix; +struct CertLookupTree { + std::vector certs; + std::vector hosts; + CertNode *root; }; -class CertLookupTree { -public: - CertLookupTree(); - - // Adds hostname pattern |hostname| to the lookup tree, associating - // value |index|. When the queried host matches this pattern, - // |index| is returned. We support wildcard pattern. The left most - // '*' is considered as wildcard character, and it must match at - // least one character. If the same pattern has been already added, - // this function is noop. - // - // The caller should lower-case |hostname| since this function does - // do that, and lookup function performs case-sensitive match. - // - // TODO Treat wildcard pattern described as RFC 6125. - void add_cert(const StringRef &hostname, size_t index); - - // Looks up index using the given |hostname|. The exact match takes - // precedence over wildcard match. For wildcard match, longest - // match (sum of matched suffix and prefix length in bytes) is - // preferred, breaking a tie with longer suffix. - // - // The caller should lower-case |hostname| since this function - // performs case-sensitive match. - ssize_t lookup(const StringRef &hostname); - - // Dumps the contents of this lookup tree to stderr. - void dump() const; - -private: - // Exact match - Router router_; - // Wildcard reversed suffix match. The returned index is into - // wildcard_patterns_. - Router rev_wildcard_router_; - // Stores wildcard suffix patterns. - std::vector wildcard_patterns_; -}; +CertLookupTree *cert_lookup_tree_new(); +void cert_lookup_tree_del(CertLookupTree *lt); -// Adds hostnames in |cert| to lookup tree |lt|. The subjectAltNames -// and commonName are considered as eligible hostname. If there is at -// least one dNSName in subjectAltNames, commonName is not considered. -// This function returns 0 if it succeeds, or -1. -int cert_lookup_tree_add_cert_from_x509(CertLookupTree *lt, size_t idx, - X509 *cert); +// Adds |ssl_ctx| with hostname pattern |hostname| with length |len| +// to the lookup tree |lt|. The |hostname| must be NULL-terminated. +void cert_lookup_tree_add_cert(CertLookupTree *lt, SSL_CTX *ssl_ctx, + const char *hostname, size_t len); + +// Looks up SSL_CTX using the given |hostname| with length |len|. If +// more than one SSL_CTX which matches the query, it is undefined +// which one is returned. The |hostname| must be NULL-terminated. If +// no matching SSL_CTX found, returns NULL. +SSL_CTX *cert_lookup_tree_lookup(CertLookupTree *lt, const char *hostname, + size_t len); + +// Adds |ssl_ctx| to lookup tree |lt| using hostnames read from +// |certfile|. The subjectAltNames and commonName are considered as +// eligible hostname. This function returns 0 if it succeeds, or -1. +// Even if no ssl_ctx is added to tree, this function returns 0. +int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx, + const char *certfile); -// Returns true if |proto| is included in the +// Returns true if |needle| which has |len| bytes is included in the // protocol list |protos|. -bool in_proto_list(const std::vector &protos, - const StringRef &proto); +bool in_proto_list(const std::vector &protos, + const unsigned char *needle, size_t len); // Returns true if security requirement for HTTP/2 is fulfilled. bool check_http2_requirement(SSL *ssl); @@ -179,66 +134,9 @@ // Returns SSL/TLS option mask to disable SSL/TLS protocol version not // included in |tls_proto_list|. The returned mask can be directly // passed to SSL_CTX_set_options(). -long int create_tls_proto_mask(const std::vector &tls_proto_list); - -std::vector -set_alpn_prefs(const std::vector &protos); +long int create_tls_proto_mask(const std::vector &tls_proto_list); -// Setups server side SSL_CTX. This function inspects get_config() -// and if upstream_no_tls is true, returns nullptr. Otherwise -// construct default SSL_CTX. If subcerts are available -// (get_config()->subcerts), caller should provide CertLookupTree -// object as |cert_tree| parameter, otherwise SNI does not work. All -// the created SSL_CTX is stored into |all_ssl_ctx|. -SSL_CTX *setup_server_ssl_context(std::vector &all_ssl_ctx, - CertLookupTree *cert_tree -#ifdef HAVE_NEVERBLEED - , - neverbleed_t *nb -#endif // HAVE_NEVERBLEED - ); - -// Setups client side SSL_CTX. -SSL_CTX *setup_downstream_client_ssl_context( -#ifdef HAVE_NEVERBLEED - neverbleed_t *nb -#endif // HAVE_NEVERBLEED - ); - -// Sets ALPN settings in |SSL| suitable for HTTP/2 use. -void setup_downstream_http2_alpn(SSL *ssl); -// Sets ALPN settings in |SSL| suitable for HTTP/1.1 use. -void setup_downstream_http1_alpn(SSL *ssl); - -// Creates CertLookupTree. If frontend is configured not to use TLS, -// this function returns nullptr. -std::unique_ptr create_cert_lookup_tree(); - -SSL *create_ssl(SSL_CTX *ssl_ctx); - -// Returns true if SSL/TLS is enabled on upstream -bool upstream_tls_enabled(); - -// Performs TLS hostname match. |pattern| can contain wildcard -// character '*', which matches prefix of target hostname. There are -// several restrictions to make wildcard work. The matching algorithm -// is based on RFC 6125. -bool tls_hostname_match(const StringRef &pattern, const StringRef &hostname); - -// Caches |session| which is associated to remote address |addr|. -// |session| is serialized into ASN1 representation, and stored. |t| -// is used as a time stamp. Depending on the existing cache's time -// stamp, |session| might not be cached. -void try_cache_tls_session(TLSSessionCache &cache, const Address &addr, - SSL_SESSION *session, ev_tstamp t); - -// Returns cached session associated |addr|. If no cache entry is -// found associated to |addr|, nullptr will be returned. -SSL_SESSION *reuse_tls_session(const TLSSessionCache &addr); - -// Loads certificate form file |filename|. The caller should delete -// the returned object using X509_free(). -X509 *load_certificate(const char *filename); +std::vector set_alpn_prefs(const std::vector &protos); } // namespace ssl diff -Nru nghttp2-1.13.0/src/shrpx_ssl_test.cc nghttp2-0.6.7/src/shrpx_ssl_test.cc --- nghttp2-1.13.0/src/shrpx_ssl_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_ssl_test.cc 2014-11-30 14:15:07.000000000 +0000 @@ -28,152 +28,98 @@ #include "shrpx_ssl.h" #include "util.h" -#include "template.h" using namespace nghttp2; namespace shrpx { void test_shrpx_ssl_create_lookup_tree(void) { - auto tree = make_unique(); + ssl::CertLookupTree *tree = ssl::cert_lookup_tree_new(); + SSL_CTX *ctxs[] = { + SSL_CTX_new(SSLv23_method()), SSL_CTX_new(SSLv23_method()), + SSL_CTX_new(SSLv23_method()), SSL_CTX_new(SSLv23_method()), + SSL_CTX_new(SSLv23_method()), SSL_CTX_new(SSLv23_method()), + SSL_CTX_new(SSLv23_method()), SSL_CTX_new(SSLv23_method()), + SSL_CTX_new(SSLv23_method()), SSL_CTX_new(SSLv23_method())}; + + const char *hostnames[] = {"example.com", "www.example.org", + "*www.example.org", "x*.host.domain", + "*yy.host.domain", "nghttp2.sourceforge.net", + "sourceforge.net", + "sourceforge.net", // duplicate + "*.foo.bar", // oo.bar is suffix of *.foo.bar + "oo.bar"}; + int num = util::array_size(ctxs); + for (int i = 0; i < num; ++i) { + ssl::cert_lookup_tree_add_cert(tree, ctxs[i], hostnames[i], + strlen(hostnames[i])); + } - constexpr StringRef hostnames[] = { - StringRef::from_lit("example.com"), // 0 - StringRef::from_lit("www.example.org"), // 1 - StringRef::from_lit("*www.example.org"), // 2 - StringRef::from_lit("xy*.host.domain"), // 3 - StringRef::from_lit("*yy.host.domain"), // 4 - StringRef::from_lit("nghttp2.sourceforge.net"), // 5 - StringRef::from_lit("sourceforge.net"), // 6 - StringRef::from_lit("sourceforge.net"), // 7, duplicate - StringRef::from_lit("*.foo.bar"), // 8, oo.bar is suffix of *.foo.bar - StringRef::from_lit("oo.bar") // 9 - }; - auto num = array_size(hostnames); - - for (size_t idx = 0; idx < num; ++idx) { - tree->add_cert(hostnames[idx], idx); - } - - tree->dump(); - - CU_ASSERT(0 == tree->lookup(hostnames[0])); - CU_ASSERT(1 == tree->lookup(hostnames[1])); - CU_ASSERT(2 == tree->lookup(StringRef::from_lit("2www.example.org"))); - CU_ASSERT(-1 == tree->lookup(StringRef::from_lit("www2.example.org"))); - CU_ASSERT(3 == tree->lookup(StringRef::from_lit("xy1.host.domain"))); + CU_ASSERT(ctxs[0] == ssl::cert_lookup_tree_lookup(tree, hostnames[0], + strlen(hostnames[0]))); + CU_ASSERT(ctxs[1] == ssl::cert_lookup_tree_lookup(tree, hostnames[1], + strlen(hostnames[1]))); + const char h1[] = "2www.example.org"; + CU_ASSERT(ctxs[2] == ssl::cert_lookup_tree_lookup(tree, h1, strlen(h1))); + const char h2[] = "www2.example.org"; + CU_ASSERT(0 == ssl::cert_lookup_tree_lookup(tree, h2, strlen(h2))); + const char h3[] = "x1.host.domain"; + CU_ASSERT(ctxs[3] == ssl::cert_lookup_tree_lookup(tree, h3, strlen(h3))); // Does not match *yy.host.domain, because * must match at least 1 // character. - CU_ASSERT(-1 == tree->lookup(StringRef::from_lit("yy.host.domain"))); - CU_ASSERT(4 == tree->lookup(StringRef::from_lit("xyy.host.domain"))); - CU_ASSERT(-1 == tree->lookup(StringRef{})); - CU_ASSERT(5 == tree->lookup(hostnames[5])); - CU_ASSERT(6 == tree->lookup(hostnames[6])); - constexpr char h6[] = "pdylay.sourceforge.net"; + const char h4[] = "yy.Host.domain"; + CU_ASSERT(0 == ssl::cert_lookup_tree_lookup(tree, h4, strlen(h4))); + const char h5[] = "zyy.host.domain"; + CU_ASSERT(ctxs[4] == ssl::cert_lookup_tree_lookup(tree, h5, strlen(h5))); + CU_ASSERT(0 == ssl::cert_lookup_tree_lookup(tree, "", 0)); + CU_ASSERT(ctxs[5] == ssl::cert_lookup_tree_lookup(tree, hostnames[5], + strlen(hostnames[5]))); + CU_ASSERT(ctxs[6] == ssl::cert_lookup_tree_lookup(tree, hostnames[6], + strlen(hostnames[6]))); + const char h6[] = "pdylay.sourceforge.net"; for (int i = 0; i < 7; ++i) { - CU_ASSERT(-1 == tree->lookup(StringRef{h6 + i, str_size(h6) - i})); + CU_ASSERT(0 == ssl::cert_lookup_tree_lookup(tree, h6 + i, strlen(h6) - i)); + } + const char h7[] = "x.foo.bar"; + CU_ASSERT(ctxs[8] == ssl::cert_lookup_tree_lookup(tree, h7, strlen(h7))); + CU_ASSERT(ctxs[9] == ssl::cert_lookup_tree_lookup(tree, hostnames[9], + strlen(hostnames[9]))); + ssl::cert_lookup_tree_del(tree); + for (int i = 0; i < num; ++i) { + SSL_CTX_free(ctxs[i]); } - CU_ASSERT(8 == tree->lookup(StringRef::from_lit("x.foo.bar"))); - CU_ASSERT(9 == tree->lookup(hostnames[9])); - constexpr StringRef names[] = { - StringRef::from_lit("rab"), // 1 - StringRef::from_lit("zab"), // 2 - StringRef::from_lit("zzub"), // 3 - StringRef::from_lit("ab") // 4 - }; - num = array_size(names); - - tree = make_unique(); - for (size_t idx = 0; idx < num; ++idx) { - tree->add_cert(names[idx], idx); + SSL_CTX *ctxs2[] = { + SSL_CTX_new(SSLv23_method()), SSL_CTX_new(SSLv23_method()), + SSL_CTX_new(SSLv23_method()), SSL_CTX_new(SSLv23_method())}; + const char *names[] = {"rab", "zab", "zzub", "ab"}; + num = util::array_size(ctxs2); + tree = ssl::cert_lookup_tree_new(); + for (int i = 0; i < num; ++i) { + ssl::cert_lookup_tree_add_cert(tree, ctxs2[i], names[i], strlen(names[i])); } - for (size_t i = 0; i < num; ++i) { - CU_ASSERT((ssize_t)i == tree->lookup(names[i])); + for (int i = 0; i < num; ++i) { + CU_ASSERT(ctxs2[i] == + ssl::cert_lookup_tree_lookup(tree, names[i], strlen(names[i]))); + } + ssl::cert_lookup_tree_del(tree); + for (int i = 0; i < num; ++i) { + SSL_CTX_free(ctxs2[i]); } } -// We use cfssl to generate key pairs. -// -// CA self-signed key pairs generation: -// -// $ cfssl genkey -initca ca.nghttp2.org.csr.json | -// cfssljson -bare ca.nghttp2.org -// -// Create CSR: -// -// $ cfssl genkey test.nghttp2.org.csr.json | cfssljson -bare test.nghttp2.org -// $ cfssl genkey test.example.com.csr.json | cfssljson -bare test.example.com -// -// Sign CSR: -// -// $ cfssl sign -ca ca.nghttp2.org.pem -ca-key ca.nghttp2.org-key.pem -// -config=ca-config.json -profile=server test.nghttp2.org.csr | -// cfssljson -bare test.nghttp2.org -// -// $ cfssl sign -ca ca.nghttp2.org.pem -ca-key ca.nghttp2.org-key.pem -// -config=ca-config.json -profile=server test.example.com.csr | -// cfssljson -bare test.example.com -// -void test_shrpx_ssl_cert_lookup_tree_add_cert_from_x509(void) { +void test_shrpx_ssl_cert_lookup_tree_add_cert_from_file(void) { int rv; - - constexpr char nghttp2_certfile[] = NGHTTP2_SRC_DIR "/test.nghttp2.org.pem"; - auto nghttp2_cert = ssl::load_certificate(nghttp2_certfile); - auto nghttp2_cert_deleter = defer(X509_free, nghttp2_cert); - - constexpr char examples_certfile[] = NGHTTP2_SRC_DIR "/test.example.com.pem"; - auto examples_cert = ssl::load_certificate(examples_certfile); - auto examples_cert_deleter = defer(X509_free, examples_cert); - - ssl::CertLookupTree tree; - - rv = ssl::cert_lookup_tree_add_cert_from_x509(&tree, 0, nghttp2_cert); - + ssl::CertLookupTree *tree = ssl::cert_lookup_tree_new(); + SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv23_method()); + const char certfile[] = NGHTTP2_TESTS_DIR "/testdata/cacert.pem"; + rv = ssl::cert_lookup_tree_add_cert_from_file(tree, ssl_ctx, certfile); CU_ASSERT(0 == rv); - - rv = ssl::cert_lookup_tree_add_cert_from_x509(&tree, 1, examples_cert); - - CU_ASSERT(0 == rv); - - CU_ASSERT(-1 == tree.lookup(StringRef::from_lit("not-used.nghttp2.org"))); - CU_ASSERT(0 == tree.lookup(StringRef::from_lit("test.nghttp2.org"))); - CU_ASSERT(0 == tree.lookup(StringRef::from_lit("w.test.nghttp2.org"))); - CU_ASSERT(0 == tree.lookup(StringRef::from_lit("www.test.nghttp2.org"))); - CU_ASSERT(1 == tree.lookup(StringRef::from_lit("test.example.com"))); -} - -template -bool tls_hostname_match_wrapper(const char(&pattern)[N], - const char(&hostname)[M]) { - return ssl::tls_hostname_match(StringRef{pattern, N}, StringRef{hostname, M}); -} - -void test_shrpx_ssl_tls_hostname_match(void) { - CU_ASSERT(tls_hostname_match_wrapper("example.com", "example.com")); - CU_ASSERT(tls_hostname_match_wrapper("example.com", "EXAMPLE.com")); - - // check wildcard - CU_ASSERT(tls_hostname_match_wrapper("*.example.com", "www.example.com")); - CU_ASSERT(tls_hostname_match_wrapper("*w.example.com", "www.example.com")); - CU_ASSERT(tls_hostname_match_wrapper("www*.example.com", "www1.example.com")); - CU_ASSERT( - tls_hostname_match_wrapper("www*.example.com", "WWW12.EXAMPLE.com")); - // at least 2 dots are required after '*' - CU_ASSERT(!tls_hostname_match_wrapper("*.com", "example.com")); - CU_ASSERT(!tls_hostname_match_wrapper("*", "example.com")); - // '*' must be in left most label - CU_ASSERT( - !tls_hostname_match_wrapper("blog.*.example.com", "blog.my.example.com")); - // prefix is wrong - CU_ASSERT( - !tls_hostname_match_wrapper("client*.example.com", "server.example.com")); - // '*' must match at least one character - CU_ASSERT(!tls_hostname_match_wrapper("www*.example.com", "www.example.com")); - - CU_ASSERT(!tls_hostname_match_wrapper("example.com", "nghttp2.org")); - CU_ASSERT(!tls_hostname_match_wrapper("www.example.com", "example.com")); - CU_ASSERT(!tls_hostname_match_wrapper("example.com", "www.example.com")); + const char localhost[] = "localhost"; + CU_ASSERT(ssl_ctx == ssl::cert_lookup_tree_lookup(tree, localhost, + sizeof(localhost) - 1)); + ssl::cert_lookup_tree_del(tree); + SSL_CTX_free(ssl_ctx); } } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_ssl_test.h nghttp2-0.6.7/src/shrpx_ssl_test.h --- nghttp2-1.13.0/src/shrpx_ssl_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_ssl_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,15 +25,10 @@ #ifndef SHRPX_SSL_TEST_H #define SHRPX_SSL_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - namespace shrpx { void test_shrpx_ssl_create_lookup_tree(void); -void test_shrpx_ssl_cert_lookup_tree_add_cert_from_x509(void); -void test_shrpx_ssl_tls_hostname_match(void); +void test_shrpx_ssl_cert_lookup_tree_add_cert_from_file(void); } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_thread_event_receiver.cc nghttp2-0.6.7/src/shrpx_thread_event_receiver.cc --- nghttp2-1.13.0/src/shrpx_thread_event_receiver.cc 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_thread_event_receiver.cc 2014-11-30 14:15:07.000000000 +0000 @@ -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. + */ +#include "shrpx_thread_event_receiver.h" + +#include + +#include "shrpx_ssl.h" +#include "shrpx_log.h" +#include "shrpx_client_handler.h" +#include "shrpx_http2_session.h" +#include "shrpx_worker.h" +#include "shrpx_worker_config.h" +#include "util.h" + +using namespace nghttp2; + +namespace shrpx { + +ThreadEventReceiver::ThreadEventReceiver(event_base *evbase, SSL_CTX *ssl_ctx, + Http2Session *http2session, + ConnectBlocker *http1_connect_blocker) + : evbase_(evbase), ssl_ctx_(ssl_ctx), http2session_(http2session), + http1_connect_blocker_(http1_connect_blocker), + rate_limit_group_(bufferevent_rate_limit_group_new( + evbase_, get_config()->worker_rate_limit_cfg)), + worker_stat_(util::make_unique()) {} + +ThreadEventReceiver::~ThreadEventReceiver() { + bufferevent_rate_limit_group_free(rate_limit_group_); +} + +void ThreadEventReceiver::on_read(bufferevent *bev) { + auto input = bufferevent_get_input(bev); + while (evbuffer_get_length(input) >= sizeof(WorkerEvent)) { + WorkerEvent wev; + int nread = evbuffer_remove(input, &wev, sizeof(wev)); + if (nread == -1) { + TLOG(FATAL, this) << "evbuffer_remove() failed"; + continue; + } + if (nread != sizeof(wev)) { + TLOG(FATAL, this) << "evbuffer_remove() removed fewer bytes. Expected:" + << sizeof(wev) << " Actual:" << nread; + continue; + } + + if (wev.type == REOPEN_LOG) { + if (LOG_ENABLED(INFO)) { + LOG(INFO) << "Reopening log files: worker_info(" << worker_config + << ")"; + } + + reopen_log_files(); + + continue; + } + + if (wev.type == GRACEFUL_SHUTDOWN) { + LOG(NOTICE) << "Graceful shutdown commencing"; + + worker_config->graceful_shutdown = true; + + if (worker_stat_->num_connections == 0) { + event_base_loopbreak(evbase_); + + break; + } + + continue; + } + + if (LOG_ENABLED(INFO)) { + TLOG(INFO, this) << "WorkerEvent: client_fd=" << wev.client_fd + << ", addrlen=" << wev.client_addrlen; + } + + if (worker_stat_->num_connections >= + get_config()->worker_frontend_connections) { + + if (LOG_ENABLED(INFO)) { + TLOG(INFO, this) << "Too many connections >= " + << get_config()->worker_frontend_connections; + } + + close(wev.client_fd); + + continue; + } + + auto evbase = bufferevent_get_base(bev); + auto client_handler = ssl::accept_connection( + evbase, rate_limit_group_, ssl_ctx_, wev.client_fd, &wev.client_addr.sa, + wev.client_addrlen, worker_stat_.get(), &dconn_pool_); + if (client_handler) { + client_handler->set_http2_session(http2session_); + client_handler->set_http1_connect_blocker(http1_connect_blocker_); + + if (LOG_ENABLED(INFO)) { + TLOG(INFO, this) << "CLIENT_HANDLER:" << client_handler << " created"; + } + } else { + if (LOG_ENABLED(INFO)) { + TLOG(ERROR, this) << "ClientHandler creation failed"; + } + close(wev.client_fd); + } + } +} + +} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_thread_event_receiver.h nghttp2-0.6.7/src/shrpx_thread_event_receiver.h --- nghttp2-1.13.0/src/shrpx_thread_event_receiver.h 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_thread_event_receiver.h 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * 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 SHRPX_THREAD_EVENT_RECEIVER_H +#define SHRPX_THREAD_EVENT_RECEIVER_H + +#include "shrpx.h" + +#include + +#include + +#include + +#include "shrpx_config.h" +#include "shrpx_downstream_connection_pool.h" + +namespace shrpx { + +class Http2Session; +class ConnectBlocker; +struct WorkerStat; + +enum WorkerEventType { + NEW_CONNECTION = 0x01, + REOPEN_LOG = 0x02, + GRACEFUL_SHUTDOWN = 0x03, +}; + +struct WorkerEvent { + WorkerEventType type; + union { + struct { + sockaddr_union client_addr; + size_t client_addrlen; + evutil_socket_t client_fd; + }; + }; +}; + +class ThreadEventReceiver { +public: + ThreadEventReceiver(event_base *evbase, SSL_CTX *ssl_ctx, + Http2Session *http2session, + ConnectBlocker *http1_connect_blocker); + ~ThreadEventReceiver(); + void on_read(bufferevent *bev); + +private: + DownstreamConnectionPool dconn_pool_; + event_base *evbase_; + SSL_CTX *ssl_ctx_; + // Shared HTTP2 session for each thread. NULL if not client + // mode. Not deleted by this object. + Http2Session *http2session_; + ConnectBlocker *http1_connect_blocker_; + bufferevent_rate_limit_group *rate_limit_group_; + std::unique_ptr worker_stat_; +}; + +} // namespace shrpx + +#endif // SHRPX_THREAD_EVENT_RECEIVER_H diff -Nru nghttp2-1.13.0/src/shrpx-unittest.cc nghttp2-0.6.7/src/shrpx-unittest.cc --- nghttp2-1.13.0/src/shrpx-unittest.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx-unittest.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,27 +24,20 @@ */ #ifdef HAVE_CONFIG_H #include -#endif // HAVE_CONFIG_H +#endif /* HAVE_CONFIG_H */ #include #include #include +#include +#include // include test cases' include files here #include "shrpx_ssl_test.h" #include "shrpx_downstream_test.h" #include "shrpx_config_test.h" -#include "shrpx_worker_test.h" #include "http2_test.h" #include "util_test.h" #include "nghttp2_gzip_test.h" -#include "buffer_test.h" -#include "memchunk_test.h" -#include "template_test.h" -#include "shrpx_http_test.h" -#include "base64_test.h" -#include "shrpx_config.h" -#include "ssl.h" -#include "shrpx_router_test.h" static int init_suite1(void) { return 0; } @@ -54,9 +47,9 @@ CU_pSuite pSuite = NULL; unsigned int num_tests_failed; - nghttp2::ssl::libssl_init(); - - shrpx::create_config(); + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); + SSL_library_init(); // initialize the CUnit test registry if (CUE_SUCCESS != CU_initialize_registry()) @@ -72,133 +65,57 @@ // add the tests to the suite if (!CU_add_test(pSuite, "ssl_create_lookup_tree", shrpx::test_shrpx_ssl_create_lookup_tree) || - !CU_add_test(pSuite, "ssl_cert_lookup_tree_add_cert_from_x509", - shrpx::test_shrpx_ssl_cert_lookup_tree_add_cert_from_x509) || - !CU_add_test(pSuite, "ssl_tls_hostname_match", - shrpx::test_shrpx_ssl_tls_hostname_match) || + !CU_add_test(pSuite, "ssl_cert_lookup_tree_add_cert_from_file", + shrpx::test_shrpx_ssl_cert_lookup_tree_add_cert_from_file) || !CU_add_test(pSuite, "http2_add_header", shrpx::test_http2_add_header) || + !CU_add_test(pSuite, "http2_check_http2_headers", + shrpx::test_http2_check_http2_headers) || + !CU_add_test(pSuite, "http2_get_unique_header", + shrpx::test_http2_get_unique_header) || !CU_add_test(pSuite, "http2_get_header", shrpx::test_http2_get_header) || - !CU_add_test(pSuite, "http2_copy_headers_to_nva", - shrpx::test_http2_copy_headers_to_nva) || - !CU_add_test(pSuite, "http2_build_http1_headers_from_headers", - shrpx::test_http2_build_http1_headers_from_headers) || + !CU_add_test(pSuite, "http2_value_lws", shrpx::test_http2_value_lws) || + !CU_add_test(pSuite, "http2_copy_norm_headers_to_nva", + shrpx::test_http2_copy_norm_headers_to_nva) || + !CU_add_test(pSuite, "http2_build_http1_headers_from_norm_headers", + shrpx::test_http2_build_http1_headers_from_norm_headers) || !CU_add_test(pSuite, "http2_lws", shrpx::test_http2_lws) || !CU_add_test(pSuite, "http2_rewrite_location_uri", shrpx::test_http2_rewrite_location_uri) || !CU_add_test(pSuite, "http2_parse_http_status_code", shrpx::test_http2_parse_http_status_code) || - !CU_add_test(pSuite, "http2_index_header", - shrpx::test_http2_index_header) || - !CU_add_test(pSuite, "http2_lookup_token", - shrpx::test_http2_lookup_token) || - !CU_add_test(pSuite, "http2_parse_link_header", - shrpx::test_http2_parse_link_header) || - !CU_add_test(pSuite, "http2_path_join", shrpx::test_http2_path_join) || - !CU_add_test(pSuite, "http2_normalize_path", - shrpx::test_http2_normalize_path) || - !CU_add_test(pSuite, "http2_rewrite_clean_path", - shrpx::test_http2_rewrite_clean_path) || - !CU_add_test(pSuite, "http2_get_pure_path_component", - shrpx::test_http2_get_pure_path_component) || - !CU_add_test(pSuite, "http2_construct_push_component", - shrpx::test_http2_construct_push_component) || - !CU_add_test(pSuite, "downstream_field_store_append_last_header", - shrpx::test_downstream_field_store_append_last_header) || - !CU_add_test(pSuite, "downstream_field_store_header", - shrpx::test_downstream_field_store_header) || + !CU_add_test(pSuite, "downstream_normalize_request_headers", + shrpx::test_downstream_normalize_request_headers) || + !CU_add_test(pSuite, "downstream_normalize_response_headers", + shrpx::test_downstream_normalize_response_headers) || + !CU_add_test(pSuite, "downstream_get_norm_request_header", + shrpx::test_downstream_get_norm_request_header) || + !CU_add_test(pSuite, "downstream_get_norm_response_header", + shrpx::test_downstream_get_norm_response_header) || !CU_add_test(pSuite, "downstream_crumble_request_cookie", shrpx::test_downstream_crumble_request_cookie) || !CU_add_test(pSuite, "downstream_assemble_request_cookie", shrpx::test_downstream_assemble_request_cookie) || - !CU_add_test(pSuite, "downstream_rewrite_location_response_header", - shrpx::test_downstream_rewrite_location_response_header) || + !CU_add_test( + pSuite, "downstream_rewrite_norm_location_response_header", + shrpx::test_downstream_rewrite_norm_location_response_header) || + !CU_add_test(pSuite, "config_parse_config_str_list", + shrpx::test_shrpx_config_parse_config_str_list) || !CU_add_test(pSuite, "config_parse_header", shrpx::test_shrpx_config_parse_header) || !CU_add_test(pSuite, "config_parse_log_format", shrpx::test_shrpx_config_parse_log_format) || - !CU_add_test(pSuite, "config_read_tls_ticket_key_file", - shrpx::test_shrpx_config_read_tls_ticket_key_file) || - !CU_add_test(pSuite, "config_read_tls_ticket_key_file_aes_256", - shrpx::test_shrpx_config_read_tls_ticket_key_file_aes_256) || - !CU_add_test(pSuite, "worker_match_downstream_addr_group", - shrpx::test_shrpx_worker_match_downstream_addr_group) || - !CU_add_test(pSuite, "http_create_forwarded", - shrpx::test_shrpx_http_create_forwarded) || - !CU_add_test(pSuite, "http_create_via_header_value", - shrpx::test_shrpx_http_create_via_header_value) || - !CU_add_test(pSuite, "router_match", shrpx::test_shrpx_router_match) || - !CU_add_test(pSuite, "router_match_prefix", - shrpx::test_shrpx_router_match_prefix) || !CU_add_test(pSuite, "util_streq", shrpx::test_util_streq) || !CU_add_test(pSuite, "util_strieq", shrpx::test_util_strieq) || !CU_add_test(pSuite, "util_inp_strlower", shrpx::test_util_inp_strlower) || !CU_add_test(pSuite, "util_to_base64", shrpx::test_util_to_base64) || - !CU_add_test(pSuite, "util_to_token68", shrpx::test_util_to_token68) || !CU_add_test(pSuite, "util_percent_encode_token", shrpx::test_util_percent_encode_token) || - !CU_add_test(pSuite, "util_percent_encode_path", - shrpx::test_util_percent_encode_path) || - !CU_add_test(pSuite, "util_percent_decode", - shrpx::test_util_percent_decode) || !CU_add_test(pSuite, "util_quote_string", shrpx::test_util_quote_string) || !CU_add_test(pSuite, "util_utox", shrpx::test_util_utox) || !CU_add_test(pSuite, "util_http_date", shrpx::test_util_http_date) || - !CU_add_test(pSuite, "util_select_h2", shrpx::test_util_select_h2) || - !CU_add_test(pSuite, "util_ipv6_numeric_addr", - shrpx::test_util_ipv6_numeric_addr) || - !CU_add_test(pSuite, "util_utos", shrpx::test_util_utos) || - !CU_add_test(pSuite, "util_make_string_ref_uint", - shrpx::test_util_make_string_ref_uint) || - !CU_add_test(pSuite, "util_utos_unit", shrpx::test_util_utos_unit) || - !CU_add_test(pSuite, "util_utos_funit", shrpx::test_util_utos_funit) || - !CU_add_test(pSuite, "util_parse_uint_with_unit", - shrpx::test_util_parse_uint_with_unit) || - !CU_add_test(pSuite, "util_parse_uint", shrpx::test_util_parse_uint) || - !CU_add_test(pSuite, "util_parse_duration_with_unit", - shrpx::test_util_parse_duration_with_unit) || - !CU_add_test(pSuite, "util_duration_str", - shrpx::test_util_duration_str) || - !CU_add_test(pSuite, "util_format_duration", - shrpx::test_util_format_duration) || - !CU_add_test(pSuite, "util_starts_with", shrpx::test_util_starts_with) || - !CU_add_test(pSuite, "util_ends_with", shrpx::test_util_ends_with) || - !CU_add_test(pSuite, "util_parse_http_date", - shrpx::test_util_parse_http_date) || - !CU_add_test(pSuite, "util_localtime_date", - shrpx::test_util_localtime_date) || - !CU_add_test(pSuite, "util_get_uint64", shrpx::test_util_get_uint64) || - !CU_add_test(pSuite, "util_parse_config_str_list", - shrpx::test_util_parse_config_str_list) || - !CU_add_test(pSuite, "util_make_http_hostport", - shrpx::test_util_make_http_hostport) || - !CU_add_test(pSuite, "util_make_hostport", - shrpx::test_util_make_hostport) || - !CU_add_test(pSuite, "util_strifind", shrpx::test_util_strifind) || - !CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate) || - !CU_add_test(pSuite, "buffer_write", nghttp2::test_buffer_write) || - !CU_add_test(pSuite, "pool_recycle", nghttp2::test_pool_recycle) || - !CU_add_test(pSuite, "memchunk_append", nghttp2::test_memchunks_append) || - !CU_add_test(pSuite, "memchunk_drain", nghttp2::test_memchunks_drain) || - !CU_add_test(pSuite, "memchunk_riovec", nghttp2::test_memchunks_riovec) || - !CU_add_test(pSuite, "memchunk_recycle", - nghttp2::test_memchunks_recycle) || - !CU_add_test(pSuite, "memchunk_reset", nghttp2::test_memchunks_reset) || - !CU_add_test(pSuite, "peek_memchunk_append", - nghttp2::test_peek_memchunks_append) || - !CU_add_test(pSuite, "peek_memchunk_disable_peek_drain", - nghttp2::test_peek_memchunks_disable_peek_drain) || - !CU_add_test(pSuite, "peek_memchunk_disable_peek_no_drain", - nghttp2::test_peek_memchunks_disable_peek_no_drain) || - !CU_add_test(pSuite, "peek_memchunk_reset", - nghttp2::test_peek_memchunks_reset) || - !CU_add_test(pSuite, "template_immutable_string", - nghttp2::test_template_immutable_string) || - !CU_add_test(pSuite, "template_string_ref", - nghttp2::test_template_string_ref) || - !CU_add_test(pSuite, "base64_encode", nghttp2::test_base64_encode) || - !CU_add_test(pSuite, "base64_decode", nghttp2::test_base64_decode)) { + !CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate)) { CU_cleanup_registry(); return CU_get_error(); } diff -Nru nghttp2-1.13.0/src/shrpx_upstream.h nghttp2-0.6.7/src/shrpx_upstream.h --- nghttp2-1.13.0/src/shrpx_upstream.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_upstream.h 2014-11-30 14:15:07.000000000 +0000 @@ -26,29 +26,28 @@ #define SHRPX_UPSTREAM_H #include "shrpx.h" -#include "shrpx_io_control.h" -#include "memchunk.h" -using namespace nghttp2; +#include + +#include "shrpx_io_control.h" namespace shrpx { class ClientHandler; class Downstream; -class DownstreamConnection; class Upstream { public: virtual ~Upstream() {} virtual int on_read() = 0; virtual int on_write() = 0; + virtual int on_event() = 0; virtual int on_timeout(Downstream *downstream) { return 0; }; virtual int on_downstream_abort_request(Downstream *downstream, unsigned int status_code) = 0; - virtual int downstream_read(DownstreamConnection *dconn) = 0; - virtual int downstream_write(DownstreamConnection *dconn) = 0; - virtual int downstream_eof(DownstreamConnection *dconn) = 0; - virtual int downstream_error(DownstreamConnection *dconn, int events) = 0; + virtual bufferevent_data_cb get_downstream_readcb() = 0; + virtual bufferevent_data_cb get_downstream_writecb() = 0; + virtual bufferevent_event_cb get_downstream_eventcb() = 0; virtual ClientHandler *get_client_handler() const = 0; virtual int on_downstream_header_complete(Downstream *downstream) = 0; @@ -57,49 +56,12 @@ virtual int on_downstream_body_complete(Downstream *downstream) = 0; virtual void on_handler_delete() = 0; - // Called when downstream connection is reset. Currently this is - // only used by Http2Session. If |no_retry| is true, another - // connection attempt using new DownstreamConnection is not allowed. - virtual int on_downstream_reset(bool no_retry) = 0; virtual void pause_read(IOCtrlReason reason) = 0; virtual int resume_read(IOCtrlReason reason, Downstream *downstream, size_t consumed) = 0; - virtual int send_reply(Downstream *downstream, const uint8_t *body, - size_t bodylen) = 0; - // Starts server push. The |downstream| is an associated stream for - // the pushed resource. This function returns 0 if it succeeds, - // otherwise -1. - virtual int initiate_push(Downstream *downstream, const StringRef &uri) = 0; - - // Fills response data in |iov| whose capacity is |iovcnt|. Returns - // the number of iovs filled. - virtual int response_riovec(struct iovec *iov, int iovcnt) const = 0; - virtual void response_drain(size_t n) = 0; - virtual bool response_empty() const = 0; - - // Called when PUSH_PROMISE was started in downstream. The - // associated downstream is given as |downstream|. The promised - // stream ID is given as |promised_stream_id|. If upstream supports - // server push for the corresponding upstream connection, it should - // return Downstream object for pushed stream. Otherwise, returns - // nullptr. - virtual Downstream * - on_downstream_push_promise(Downstream *downstream, - int32_t promised_stream_id) = 0; - // Called when PUSH_PROMISE frame was completely received in - // downstream. The associated downstream is given as |downstream|. - // This function returns 0 if it succeeds, or -1. - virtual int - on_downstream_push_promise_complete(Downstream *downstream, - Downstream *promised_downstream) = 0; - // Returns true if server push is enabled in upstream connection. - virtual bool push_enabled() const = 0; - // Cancels promised downstream. This function is called when - // PUSH_PROMISE for |promised_downstream| is not submitted to - // upstream session. - virtual void cancel_premature_downstream(Downstream *promised_downstream) = 0; + virtual void reset_timeouts() = 0; }; } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_worker.cc nghttp2-0.6.7/src/shrpx_worker.cc --- nghttp2-1.13.0/src/shrpx_worker.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_worker.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,634 +24,97 @@ */ #include "shrpx_worker.h" -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H +#include #include +#include +#include + #include "shrpx_ssl.h" +#include "shrpx_thread_event_receiver.h" #include "shrpx_log.h" -#include "shrpx_client_handler.h" #include "shrpx_http2_session.h" -#include "shrpx_log_config.h" +#include "shrpx_worker_config.h" #include "shrpx_connect_blocker.h" -#include "shrpx_live_check.h" -#include "shrpx_memcached_dispatcher.h" -#ifdef HAVE_MRUBY -#include "shrpx_mruby.h" -#endif // HAVE_MRUBY #include "util.h" -#include "template.h" +#include "libevent_util.h" + +using namespace nghttp2; namespace shrpx { -namespace { -void eventcb(struct ev_loop *loop, ev_async *w, int revents) { - auto worker = static_cast(w->data); - worker->process_events(); -} -} // namespace +Worker::Worker(const WorkerInfo *info) + : sv_ssl_ctx_(info->sv_ssl_ctx), cl_ssl_ctx_(info->cl_ssl_ctx), + fd_(info->sv[1]) {} -namespace { -void mcpool_clear_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto worker = static_cast(w->data); - if (worker->get_worker_stat()->num_connections != 0) { - return; - } - worker->get_mcpool()->clear(); +Worker::~Worker() { + shutdown(fd_, SHUT_WR); + close(fd_); } -} // namespace namespace { -void proc_wev_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto worker = static_cast(w->data); - worker->process_events(); +void readcb(bufferevent *bev, void *arg) { + auto receiver = static_cast(arg); + receiver->on_read(bev); } } // namespace namespace { -bool match_shared_downstream_addr( - const std::shared_ptr &lhs, - const std::shared_ptr &rhs) { - if (lhs->addrs.size() != rhs->addrs.size()) { - return false; +void eventcb(bufferevent *bev, short events, void *arg) { + if (events & BEV_EVENT_EOF) { + LOG(ERROR) << "Connection to main thread lost: eof"; } - - if (lhs->affinity != rhs->affinity) { - return false; + if (events & BEV_EVENT_ERROR) { + LOG(ERROR) << "Connection to main thread lost: network error"; } - - auto used = std::vector(lhs->addrs.size()); - - for (auto &a : lhs->addrs) { - size_t i; - for (i = 0; i < rhs->addrs.size(); ++i) { - if (used[i]) { - continue; - } - - auto &b = rhs->addrs[i]; - if (a.host == b.host && a.port == b.port && a.host_unix == b.host_unix && - a.proto == b.proto && a.tls == b.tls && a.sni == b.sni && - a.fall == b.fall && a.rise == b.rise) { - break; - } - } - - if (i == rhs->addrs.size()) { - return false; - } - - used[i] = true; - } - - return true; } } // namespace -namespace { -std::random_device rd; -} // namespace - -Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx, - SSL_CTX *tls_session_cache_memcached_ssl_ctx, - ssl::CertLookupTree *cert_tree, - const std::shared_ptr &ticket_keys, - ConnectionHandler *conn_handler, - std::shared_ptr downstreamconf) - : randgen_(rd()), - worker_stat_{}, - loop_(loop), - sv_ssl_ctx_(sv_ssl_ctx), - cl_ssl_ctx_(cl_ssl_ctx), - cert_tree_(cert_tree), - conn_handler_(conn_handler), - ticket_keys_(ticket_keys), - connect_blocker_( - make_unique(randgen_, loop_, []() {}, []() {})), - graceful_shutdown_(false) { - ev_async_init(&w_, eventcb); - w_.data = this; - ev_async_start(loop_, &w_); - - ev_timer_init(&mcpool_clear_timer_, mcpool_clear_cb, 0., 0.); - mcpool_clear_timer_.data = this; - - ev_timer_init(&proc_wev_timer_, proc_wev_cb, 0., 0.); - proc_wev_timer_.data = this; - - auto &session_cacheconf = get_config()->tls.session_cache; - - if (!session_cacheconf.memcached.host.empty()) { - session_cache_memcached_dispatcher_ = make_unique( - &session_cacheconf.memcached.addr, loop, - tls_session_cache_memcached_ssl_ctx, - StringRef{session_cacheconf.memcached.host}, &mcpool_, randgen_); - } - - replace_downstream_config(std::move(downstreamconf)); -} - -void Worker::replace_downstream_config( - std::shared_ptr downstreamconf) { - for (auto &g : downstream_addr_groups_) { - g->retired = true; - - auto &shared_addr = g->shared_addr; - - if (shared_addr->affinity == AFFINITY_NONE) { - shared_addr->dconn_pool.remove_all(); - continue; - } - - for (auto &addr : shared_addr->addrs) { - addr.dconn_pool->remove_all(); - } - } - - downstreamconf_ = downstreamconf; - - // Making a copy is much faster with multiple thread on - // backendconfig API call. - auto groups = downstreamconf->addr_groups; - - downstream_addr_groups_ = - std::vector>(groups.size()); - - for (size_t i = 0; i < groups.size(); ++i) { - auto &src = groups[i]; - auto &dst = downstream_addr_groups_[i]; - - dst = std::make_shared(); - dst->pattern = src.pattern; - - // TODO for some reason, clang-3.6 which comes with Ubuntu 15.10 - // does not value initialize with std::make_shared. - auto shared_addr = std::make_shared(); - - shared_addr->addrs.resize(src.addrs.size()); - shared_addr->affinity = src.affinity; - shared_addr->affinity_hash = src.affinity_hash; - - size_t num_http1 = 0; - size_t num_http2 = 0; - - for (size_t j = 0; j < src.addrs.size(); ++j) { - auto &src_addr = src.addrs[j]; - auto &dst_addr = shared_addr->addrs[j]; - - dst_addr.addr = src_addr.addr; - dst_addr.host = src_addr.host; - dst_addr.hostport = src_addr.hostport; - dst_addr.port = src_addr.port; - dst_addr.host_unix = src_addr.host_unix; - dst_addr.proto = src_addr.proto; - dst_addr.tls = src_addr.tls; - dst_addr.sni = src_addr.sni; - dst_addr.fall = src_addr.fall; - dst_addr.rise = src_addr.rise; - - auto shared_addr_ptr = shared_addr.get(); - - dst_addr.connect_blocker = - make_unique(randgen_, loop_, - [shared_addr_ptr, &dst_addr]() { - switch (dst_addr.proto) { - case PROTO_HTTP1: - --shared_addr_ptr->http1_pri.weight; - break; - case PROTO_HTTP2: - --shared_addr_ptr->http2_pri.weight; - break; - default: - assert(0); - } - }, - [shared_addr_ptr, &dst_addr]() { - switch (dst_addr.proto) { - case PROTO_HTTP1: - ++shared_addr_ptr->http1_pri.weight; - break; - case PROTO_HTTP2: - ++shared_addr_ptr->http2_pri.weight; - break; - default: - assert(0); - } - }); - - dst_addr.live_check = - make_unique(loop_, cl_ssl_ctx_, this, &dst_addr, randgen_); - - if (dst_addr.proto == PROTO_HTTP2) { - ++num_http2; - } else { - assert(dst_addr.proto == PROTO_HTTP1); - ++num_http1; - } - } - - // share the connection if patterns have the same set of backend - // addresses. - auto end = std::begin(downstream_addr_groups_) + i; - auto it = std::find_if( - std::begin(downstream_addr_groups_), end, - [&shared_addr](const std::shared_ptr &group) { - return match_shared_downstream_addr(group->shared_addr, shared_addr); - }); - - if (it == end) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "number of http/1.1 backend: " << num_http1 - << ", number of h2 backend: " << num_http2; - } - - shared_addr->http1_pri.weight = num_http1; - shared_addr->http2_pri.weight = num_http2; - - if (shared_addr->affinity != AFFINITY_NONE) { - for (auto &addr : shared_addr->addrs) { - addr.dconn_pool = make_unique(); - } - } - - dst->shared_addr = shared_addr; - } else { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << dst->pattern << " shares the same backend group with " - << (*it)->pattern; - } - dst->shared_addr = (*it)->shared_addr; - } - } -} - -Worker::~Worker() { - ev_async_stop(loop_, &w_); - ev_timer_stop(loop_, &mcpool_clear_timer_); - ev_timer_stop(loop_, &proc_wev_timer_); -} - -void Worker::schedule_clear_mcpool() { - // libev manual says: "If the watcher is already active nothing will - // happen." Since we don't change any timeout here, we don't have - // to worry about querying ev_is_active. - ev_timer_start(loop_, &mcpool_clear_timer_); -} - -void Worker::wait() { -#ifndef NOTHREADS - fut_.get(); -#endif // !NOTHREADS -} - -void Worker::run_async() { -#ifndef NOTHREADS - fut_ = std::async(std::launch::async, [this] { - (void)reopen_log_files(); - ev_run(loop_); - delete log_config(); - }); -#endif // !NOTHREADS -} - -void Worker::send(const WorkerEvent &event) { - { - std::lock_guard g(m_); - - q_.push_back(event); - } - - ev_async_send(loop_, &w_); -} - -void Worker::process_events() { - WorkerEvent wev; - { - std::lock_guard g(m_); - - // Process event one at a time. This is important for - // NEW_CONNECTION event since accepting large number of new - // connections at once may delay time to 1st byte for existing - // connections. - - if (q_.empty()) { - ev_timer_stop(loop_, &proc_wev_timer_); - return; - } - - wev = q_.front(); - q_.pop_front(); - } - - ev_timer_start(loop_, &proc_wev_timer_); - - auto worker_connections = get_config()->conn.upstream.worker_connections; - - switch (wev.type) { - case NEW_CONNECTION: { - if (LOG_ENABLED(INFO)) { - WLOG(INFO, this) << "WorkerEvent: client_fd=" << wev.client_fd - << ", addrlen=" << wev.client_addrlen; - } - - if (worker_stat_.num_connections >= worker_connections) { - - if (LOG_ENABLED(INFO)) { - WLOG(INFO, this) << "Too many connections >= " << worker_connections; - } - - close(wev.client_fd); - - break; - } - - auto client_handler = - ssl::accept_connection(this, wev.client_fd, &wev.client_addr.sa, - wev.client_addrlen, wev.faddr); - if (!client_handler) { - if (LOG_ENABLED(INFO)) { - WLOG(ERROR, this) << "ClientHandler creation failed"; - } - close(wev.client_fd); - break; - } - - if (LOG_ENABLED(INFO)) { - WLOG(INFO, this) << "CLIENT_HANDLER:" << client_handler << " created "; - } - - break; - } - case REOPEN_LOG: - WLOG(NOTICE, this) << "Reopening log files: worker process (thread " << this - << ")"; - - reopen_log_files(); - - break; - case GRACEFUL_SHUTDOWN: - WLOG(NOTICE, this) << "Graceful shutdown commencing"; - - graceful_shutdown_ = true; - - if (worker_stat_.num_connections == 0) { - ev_break(loop_); - - return; - } +void Worker::run() { + (void)reopen_log_files(); - break; - case REPLACE_DOWNSTREAM: - WLOG(NOTICE, this) << "Replace downstream"; - - replace_downstream_config(wev.downstreamconf); - - break; - default: - if (LOG_ENABLED(INFO)) { - WLOG(INFO, this) << "unknown event type " << wev.type; - } - } -} - -ssl::CertLookupTree *Worker::get_cert_lookup_tree() const { return cert_tree_; } - -std::shared_ptr Worker::get_ticket_keys() { - std::lock_guard g(m_); - return ticket_keys_; -} - -void Worker::set_ticket_keys(std::shared_ptr ticket_keys) { - std::lock_guard g(m_); - ticket_keys_ = std::move(ticket_keys); -} - -WorkerStat *Worker::get_worker_stat() { return &worker_stat_; } - -struct ev_loop *Worker::get_loop() const { - return loop_; -} - -SSL_CTX *Worker::get_sv_ssl_ctx() const { return sv_ssl_ctx_; } - -SSL_CTX *Worker::get_cl_ssl_ctx() const { return cl_ssl_ctx_; } - -void Worker::set_graceful_shutdown(bool f) { graceful_shutdown_ = f; } - -bool Worker::get_graceful_shutdown() const { return graceful_shutdown_; } - -MemchunkPool *Worker::get_mcpool() { return &mcpool_; } - -MemcachedDispatcher *Worker::get_session_cache_memcached_dispatcher() { - return session_cache_memcached_dispatcher_.get(); -} - -std::mt19937 &Worker::get_randgen() { return randgen_; } - -#ifdef HAVE_MRUBY -int Worker::create_mruby_context() { - mruby_ctx_ = mruby::create_mruby_context(StringRef{get_config()->mruby_file}); - if (!mruby_ctx_) { - return -1; - } - - return 0; -} - -mruby::MRubyContext *Worker::get_mruby_context() const { - return mruby_ctx_.get(); -} -#endif // HAVE_MRUBY - -std::vector> & -Worker::get_downstream_addr_groups() { - return downstream_addr_groups_; -} - -ConnectBlocker *Worker::get_connect_blocker() const { - return connect_blocker_.get(); -} - -const DownstreamConfig *Worker::get_downstream_config() const { - return downstreamconf_.get(); -} - -ConnectionHandler *Worker::get_connection_handler() const { - return conn_handler_; -} - -namespace { -size_t match_downstream_addr_group_host( - const RouterConfig &routerconf, const StringRef &host, - const StringRef &path, - const std::vector> &groups, - size_t catch_all, BlockAllocator &balloc) { - - const auto &router = routerconf.router; - const auto &rev_wildcard_router = routerconf.rev_wildcard_router; - const auto &wildcard_patterns = routerconf.wildcard_patterns; - - if (path.empty() || path[0] != '/') { - auto group = router.match(host, StringRef::from_lit("/")); - if (group != -1) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Found pattern with query " << host - << ", matched pattern=" << groups[group]->pattern; - } - return group; - } - return catch_all; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Perform mapping selection, using host=" << host - << ", path=" << path; - } - - auto group = router.match(host, path); - if (group != -1) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Found pattern with query " << host << path - << ", matched pattern=" << groups[group]->pattern; - } - return group; - } - - if (!wildcard_patterns.empty() && !host.empty()) { - auto rev_host_src = make_byte_ref(balloc, host.size() - 1); - auto ep = - std::copy(std::begin(host) + 1, std::end(host), rev_host_src.base); - std::reverse(rev_host_src.base, ep); - auto rev_host = StringRef{rev_host_src.base, ep}; - - ssize_t best_group = -1; - const RNode *last_node = nullptr; - - for (;;) { - size_t nread = 0; - auto wcidx = - rev_wildcard_router.match_prefix(&nread, &last_node, rev_host); - if (wcidx == -1) { - break; - } - - rev_host = StringRef{std::begin(rev_host) + nread, std::end(rev_host)}; - - auto &wc = wildcard_patterns[wcidx]; - auto group = wc.router.match(StringRef{}, path); - if (group != -1) { - // We sorted wildcard_patterns in a way that first match is the - // longest host pattern. - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Found wildcard pattern with query " << host << path - << ", matched pattern=" << groups[group]->pattern; - } - - best_group = group; - } - } - - if (best_group != -1) { - return best_group; - } - } - - group = router.match(StringRef::from_lit(""), path); - if (group != -1) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Found pattern with query " << path - << ", matched pattern=" << groups[group]->pattern; - } - return group; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "None match. Use catch-all pattern"; - } - return catch_all; -} -} // namespace - -size_t match_downstream_addr_group( - const RouterConfig &routerconf, const StringRef &hostport, - const StringRef &raw_path, - const std::vector> &groups, - size_t catch_all, BlockAllocator &balloc) { - if (std::find(std::begin(hostport), std::end(hostport), '/') != - std::end(hostport)) { - // We use '/' specially, and if '/' is included in host, it breaks - // our code. Select catch-all case. - return catch_all; + auto evbase = std::unique_ptr( + event_base_new(), event_base_free); + if (!evbase) { + LOG(ERROR) << "event_base_new() failed"; + return; } - - auto fragment = std::find(std::begin(raw_path), std::end(raw_path), '#'); - auto query = std::find(std::begin(raw_path), fragment, '?'); - auto path = StringRef{std::begin(raw_path), query}; - - if (hostport.empty()) { - return match_downstream_addr_group_host(routerconf, hostport, path, groups, - catch_all, balloc); + auto bev = std::unique_ptr( + bufferevent_socket_new(evbase.get(), fd_, BEV_OPT_DEFER_CALLBACKS), + bufferevent_free); + if (!bev) { + LOG(ERROR) << "bufferevent_socket_new() failed"; + return; } - - StringRef host; - if (hostport[0] == '[') { - // assume this is IPv6 numeric address - auto p = std::find(std::begin(hostport), std::end(hostport), ']'); - if (p == std::end(hostport)) { - return catch_all; + std::unique_ptr http2session; + std::unique_ptr http1_connect_blocker; + if (get_config()->downstream_proto == PROTO_HTTP2) { + http2session = util::make_unique(evbase.get(), cl_ssl_ctx_); + if (http2session->init_notification() == -1) { + DIE(); } - if (p + 1 < std::end(hostport) && *(p + 1) != ':') { - return catch_all; - } - host = StringRef{std::begin(hostport), p + 1}; } else { - auto p = std::find(std::begin(hostport), std::end(hostport), ':'); - if (p == std::begin(hostport)) { - return catch_all; + http1_connect_blocker = util::make_unique(); + if (http1_connect_blocker->init(evbase.get()) == -1) { + DIE(); } - host = StringRef{std::begin(hostport), p}; - } - - if (std::find_if(std::begin(host), std::end(host), [](char c) { - return 'A' <= c || c <= 'Z'; - }) != std::end(host)) { - auto low_host = make_byte_ref(balloc, host.size() + 1); - auto ep = std::copy(std::begin(host), std::end(host), low_host.base); - *ep = '\0'; - util::inp_strlower(low_host.base, ep); - host = StringRef{low_host.base, ep}; - } - return match_downstream_addr_group_host(routerconf, host, path, groups, - catch_all, balloc); -} - -void downstream_failure(DownstreamAddr *addr) { - const auto &connect_blocker = addr->connect_blocker; - - if (connect_blocker->in_offline()) { - return; } - connect_blocker->on_failure(); - - if (addr->fall == 0) { - return; - } + auto receiver = util::make_unique( + evbase.get(), sv_ssl_ctx_, http2session.get(), + http1_connect_blocker.get()); - auto fail_count = connect_blocker->get_fail_count(); + util::bev_enable_unless(bev.get(), EV_READ); + bufferevent_setcb(bev.get(), readcb, nullptr, eventcb, receiver.get()); - if (fail_count >= addr->fall) { - LOG(WARN) << "Could not connect to " << util::to_numeric_addr(&addr->addr) - << " " << fail_count << " times in a row; considered as offline"; - - connect_blocker->offline(); + event_base_loop(evbase.get(), 0); +} - if (addr->rise) { - addr->live_check->schedule(); - } - } +void start_threaded_worker(WorkerInfo *info) { + Worker worker(info); + worker.run(); } } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_worker_config.cc nghttp2-0.6.7/src/shrpx_worker_config.cc --- nghttp2-1.13.0/src/shrpx_worker_config.cc 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_worker_config.cc 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 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. + */ +#include "shrpx_worker_config.h" + +namespace shrpx { + +WorkerConfig::WorkerConfig() + : accesslog_fd(-1), errorlog_fd(-1), errorlog_tty(false), + graceful_shutdown(false) {} + +#ifndef NOTHREADS +thread_local +#endif // NOTHREADS + WorkerConfig *worker_config = new WorkerConfig(); + +} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_worker_config.h nghttp2-0.6.7/src/shrpx_worker_config.h --- nghttp2-1.13.0/src/shrpx_worker_config.h 1970-01-01 00:00:00.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_worker_config.h 2014-11-30 14:15:07.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 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 SHRPX_WORKER_CONFIG_H +#define SHRPX_WORKER_CONFIG_H + +#include "shrpx.h" + +namespace shrpx { + +struct WorkerConfig { + int accesslog_fd; + int errorlog_fd; + // true if errorlog_fd is referring to a terminal. + bool errorlog_tty; + bool graceful_shutdown; + + WorkerConfig(); +}; + +// We need WorkerConfig per thread +extern +#ifndef NOTHREADS + thread_local +#endif // NOTHREADS + WorkerConfig *worker_config; + +} // namespace shrpx + +#endif // SHRPX_WORKER_CONFIG_H diff -Nru nghttp2-1.13.0/src/shrpx_worker.h nghttp2-0.6.7/src/shrpx_worker.h --- nghttp2-1.13.0/src/shrpx_worker.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_worker.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,269 +27,33 @@ #include "shrpx.h" -#include -#include -#include -#include -#include -#include -#ifndef NOTHREADS -#include -#endif // NOTHREADS - #include #include -#include - -#include "shrpx_config.h" -#include "shrpx_downstream_connection_pool.h" -#include "memchunk.h" -#include "shrpx_ssl.h" - -using namespace nghttp2; +#include "shrpx_listen_handler.h" namespace shrpx { -class Http2Session; -class ConnectBlocker; -class LiveCheck; -class MemcachedDispatcher; -struct UpstreamAddr; -class ConnectionHandler; - -#ifdef HAVE_MRUBY -namespace mruby { - -class MRubyContext; - -} // namespace mruby -#endif // HAVE_MRUBY - -namespace ssl { -class CertLookupTree; -} // namespace ssl - -struct DownstreamAddr { - Address addr; - // backend address. If |host_unix| is true, this is UNIX domain - // socket path. - ImmutableString host; - ImmutableString hostport; - // backend port. 0 if |host_unix| is true. - uint16_t port; - // true if |host| contains UNIX domain socket path. - bool host_unix; - - // sni field to send remote server if TLS is enabled. - ImmutableString sni; - - std::unique_ptr connect_blocker; - std::unique_ptr live_check; - // Connection pool for this particular address if session affinity - // is enabled - std::unique_ptr dconn_pool; - size_t fall; - size_t rise; - // Client side TLS session cache - ssl::TLSSessionCache tls_session_cache; - // Http2Session object created for this address. This list chains - // all Http2Session objects that is not in group scope - // http2_avail_freelist, and is not reached in maximum concurrency. - // - // If session affinity is enabled, http2_avail_freelist is not used, - // and this list is solely used. - DList http2_extra_freelist; - // true if Http2Session for this address is in group scope - // SharedDownstreamAddr.http2_avail_freelist - bool in_avail; - // total number of streams created in HTTP/2 connections for this - // address. - size_t num_dconn; - // Application protocol used in this backend - shrpx_proto proto; - // true if TLS is used in this backend - bool tls; -}; - -// Simplified weighted fair queuing. Actually we don't use queue here -// since we have just 2 items. This is the same algorithm used in -// stream priority, but ignores remainder. -struct WeightedPri { - // current cycle of this item. The lesser cycle has higher - // priority. This is unsigned 32 bit integer, so it may overflow. - // But with the same theory described in stream priority, it is no - // problem. - uint32_t cycle; - // weight, larger weight means more frequent use. - uint32_t weight; -}; - -struct SharedDownstreamAddr { - std::vector addrs; - // Bunch of session affinity hash. Only used if affinity == - // AFFINITY_IP. - std::vector affinity_hash; - // List of Http2Session which is not fully utilized (i.e., the - // server advertized maximum concurrency is not reached). We will - // coalesce as much stream as possible in one Http2Session to fully - // utilize TCP connection. - // - // If session affinity is enabled, this list is not used. Per - // address http2_extra_freelist is used instead. - // - // TODO Verify that this approach performs better in performance - // wise. - DList http2_avail_freelist; - DownstreamConnectionPool dconn_pool; - // Next http/1.1 downstream address index in addrs. - size_t next; - // http1_pri and http2_pri are used to which protocols are used - // between HTTP/1.1 or HTTP/2 if they both are available in - // backends. They are choosed proportional to the number available - // backend. Usually, if http1_pri.cycle < http2_pri.cycle, choose - // HTTP/1.1. Otherwise, choose HTTP/2. - WeightedPri http1_pri; - WeightedPri http2_pri; - // Session affinity - shrpx_session_affinity affinity; -}; - -struct DownstreamAddrGroup { - ImmutableString pattern; - std::shared_ptr shared_addr; - // true if this group is no longer used for new request. If this is - // true, the connection made using one of address in shared_addr - // must not be pooled. - bool retired; -}; - struct WorkerStat { - size_t num_connections; -}; + WorkerStat() : num_connections(0) {} -enum WorkerEventType { - NEW_CONNECTION = 0x01, - REOPEN_LOG = 0x02, - GRACEFUL_SHUTDOWN = 0x03, - REPLACE_DOWNSTREAM = 0x04, -}; - -struct WorkerEvent { - WorkerEventType type; - struct { - sockaddr_union client_addr; - size_t client_addrlen; - int client_fd; - const UpstreamAddr *faddr; - }; - std::shared_ptr ticket_keys; - std::shared_ptr downstreamconf; + size_t num_connections; }; class Worker { public: - Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx, - SSL_CTX *tls_session_cache_memcached_ssl_ctx, - ssl::CertLookupTree *cert_tree, - const std::shared_ptr &ticket_keys, - ConnectionHandler *conn_handler, - std::shared_ptr downstreamconf); + Worker(const WorkerInfo *info); ~Worker(); - void run_async(); - void wait(); - void process_events(); - void send(const WorkerEvent &event); - - ssl::CertLookupTree *get_cert_lookup_tree() const; - - // These 2 functions make a lock m_ to get/set ticket keys - // atomically. - std::shared_ptr get_ticket_keys(); - void set_ticket_keys(std::shared_ptr ticket_keys); - - WorkerStat *get_worker_stat(); - struct ev_loop *get_loop() const; - SSL_CTX *get_sv_ssl_ctx() const; - SSL_CTX *get_cl_ssl_ctx() const; - - void set_graceful_shutdown(bool f); - bool get_graceful_shutdown() const; - - MemchunkPool *get_mcpool(); - void schedule_clear_mcpool(); - - MemcachedDispatcher *get_session_cache_memcached_dispatcher(); - - std::mt19937 &get_randgen(); - -#ifdef HAVE_MRUBY - int create_mruby_context(); - - mruby::MRubyContext *get_mruby_context() const; -#endif // HAVE_MRUBY - - std::vector> & - get_downstream_addr_groups(); - - ConnectBlocker *get_connect_blocker() const; - - const DownstreamConfig *get_downstream_config() const; - - void - replace_downstream_config(std::shared_ptr downstreamconf); - - ConnectionHandler *get_connection_handler() const; + void run(); private: -#ifndef NOTHREADS - std::future fut_; -#endif // NOTHREADS - std::mutex m_; - std::deque q_; - std::mt19937 randgen_; - ev_async w_; - ev_timer mcpool_clear_timer_; - ev_timer proc_wev_timer_; - MemchunkPool mcpool_; - WorkerStat worker_stat_; - - std::shared_ptr downstreamconf_; - std::unique_ptr session_cache_memcached_dispatcher_; -#ifdef HAVE_MRUBY - std::unique_ptr mruby_ctx_; -#endif // HAVE_MRUBY - struct ev_loop *loop_; - - // Following fields are shared across threads if - // get_config()->tls_ctx_per_worker == true. SSL_CTX *sv_ssl_ctx_; SSL_CTX *cl_ssl_ctx_; - ssl::CertLookupTree *cert_tree_; - ConnectionHandler *conn_handler_; - - std::shared_ptr ticket_keys_; - std::vector> downstream_addr_groups_; - // Worker level blocker for downstream connection. For example, - // this is used when file decriptor is exhausted. - std::unique_ptr connect_blocker_; - - bool graceful_shutdown_; + // Channel to the main thread + int fd_; }; -// Selects group based on request's |hostport| and |path|. |hostport| -// is the value taken from :authority or host header field, and may -// contain port. The |path| may contain query part. We require the -// catch-all pattern in place, so this function always selects one -// group. The catch-all group index is given in |catch_all|. All -// patterns are given in |groups|. -size_t match_downstream_addr_group( - const RouterConfig &routerconfig, const StringRef &hostport, - const StringRef &path, - const std::vector> &groups, - size_t catch_all, BlockAllocator &balloc); - -void downstream_failure(DownstreamAddr *addr); +void start_threaded_worker(WorkerInfo *info); } // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_worker_process.cc nghttp2-0.6.7/src/shrpx_worker_process.cc --- nghttp2-1.13.0/src/shrpx_worker_process.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_worker_process.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,544 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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. - */ -#include "shrpx_worker_process.h" - -#include -#ifdef HAVE_UNISTD_H -#include -#endif // HAVE_UNISTD_H -#include -#include - -#include -#include - -#include - -#include - -#include "shrpx_config.h" -#include "shrpx_connection_handler.h" -#include "shrpx_log_config.h" -#include "shrpx_worker.h" -#include "shrpx_accept_handler.h" -#include "shrpx_http2_upstream.h" -#include "shrpx_http2_session.h" -#include "shrpx_memcached_dispatcher.h" -#include "shrpx_memcached_request.h" -#include "shrpx_process.h" -#include "shrpx_ssl.h" -#include "util.h" -#include "app_helper.h" -#include "template.h" - -using namespace nghttp2; - -namespace shrpx { - -namespace { -void drop_privileges( -#ifdef HAVE_NEVERBLEED - neverbleed_t *nb -#endif // HAVE_NEVERBLEED - ) { - if (getuid() == 0 && get_config()->uid != 0) { - if (initgroups(get_config()->user.c_str(), get_config()->gid) != 0) { - auto error = errno; - LOG(FATAL) << "Could not change supplementary groups: " - << strerror(error); - exit(EXIT_FAILURE); - } - if (setgid(get_config()->gid) != 0) { - auto error = errno; - LOG(FATAL) << "Could not change gid: " << strerror(error); - exit(EXIT_FAILURE); - } - if (setuid(get_config()->uid) != 0) { - auto error = errno; - LOG(FATAL) << "Could not change uid: " << strerror(error); - exit(EXIT_FAILURE); - } - if (setuid(0) != -1) { - LOG(FATAL) << "Still have root privileges?"; - exit(EXIT_FAILURE); - } -#ifdef HAVE_NEVERBLEED - if (nb) { - neverbleed_setuidgid(nb, get_config()->user.c_str(), 1); - } -#endif // HAVE_NEVERBLEED - } -} -} // namespace - -namespace { -void graceful_shutdown(ConnectionHandler *conn_handler) { - if (conn_handler->get_graceful_shutdown()) { - return; - } - - LOG(NOTICE) << "Graceful shutdown signal received"; - - conn_handler->set_graceful_shutdown(true); - - conn_handler->disable_acceptor(); - - // After disabling accepting new connection, disptach incoming - // connection in backlog. - - conn_handler->accept_pending_connection(); - - conn_handler->graceful_shutdown_worker(); - - if (get_config()->num_worker == 1) { - if (conn_handler->get_single_worker()->get_worker_stat()->num_connections == - 0) { - ev_break(conn_handler->get_loop()); - } - - return; - } -} -} // namespace - -namespace { -void reopen_log(ConnectionHandler *conn_handler) { - LOG(NOTICE) << "Reopening log files: worker process (thread main)"; - - (void)reopen_log_files(); - redirect_stderr_to_errorlog(); - - if (get_config()->num_worker > 1) { - conn_handler->worker_reopen_log_files(); - } -} -} // namespace - -namespace { -void ipc_readcb(struct ev_loop *loop, ev_io *w, int revents) { - auto conn_handler = static_cast(w->data); - std::array buf; - ssize_t nread; - while ((nread = read(w->fd, buf.data(), buf.size())) == -1 && errno == EINTR) - ; - if (nread == -1) { - auto error = errno; - LOG(ERROR) << "Failed to read data from ipc channel: errno=" << error; - return; - } - - if (nread == 0) { - // IPC socket closed. Perform immediate shutdown. - LOG(FATAL) << "IPC socket is closed. Perform immediate shutdown."; - _Exit(EXIT_FAILURE); - } - - for (ssize_t i = 0; i < nread; ++i) { - switch (buf[i]) { - case SHRPX_IPC_GRACEFUL_SHUTDOWN: - graceful_shutdown(conn_handler); - break; - case SHRPX_IPC_REOPEN_LOG: - reopen_log(conn_handler); - break; - } - } -} -} // namespace - -namespace { -int generate_ticket_key(TicketKey &ticket_key) { - ticket_key.cipher = get_config()->tls.ticket.cipher; - ticket_key.hmac = EVP_sha256(); - ticket_key.hmac_keylen = EVP_MD_size(ticket_key.hmac); - - assert(static_cast(EVP_CIPHER_key_length(ticket_key.cipher)) <= - ticket_key.data.enc_key.size()); - assert(ticket_key.hmac_keylen <= ticket_key.data.hmac_key.size()); - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "enc_keylen=" << EVP_CIPHER_key_length(ticket_key.cipher) - << ", hmac_keylen=" << ticket_key.hmac_keylen; - } - - if (RAND_bytes(reinterpret_cast(&ticket_key.data), - sizeof(ticket_key.data)) == 0) { - return -1; - } - - return 0; -} -} // namespace - -namespace { -void renew_ticket_key_cb(struct ev_loop *loop, ev_timer *w, int revents) { - auto conn_handler = static_cast(w->data); - const auto &old_ticket_keys = conn_handler->get_ticket_keys(); - - auto ticket_keys = std::make_shared(); - LOG(NOTICE) << "Renew new ticket keys"; - - // If old_ticket_keys is not empty, it should contain at least 2 - // keys: one for encryption, and last one for the next encryption - // key but decryption only. The keys in between are old keys and - // decryption only. The next key is provided to ensure to mitigate - // possible problem when one worker encrypt new key, but one worker, - // which did not take the that key yet, and cannot decrypt it. - // - // We keep keys for get_config()->tls_session_timeout seconds. The - // default is 12 hours. Thus the maximum ticket vector size is 12. - if (old_ticket_keys) { - auto &old_keys = old_ticket_keys->keys; - auto &new_keys = ticket_keys->keys; - - assert(!old_keys.empty()); - - auto max_tickets = - static_cast(std::chrono::duration_cast( - get_config()->tls.session_timeout).count()); - - new_keys.resize(std::min(max_tickets, old_keys.size() + 1)); - std::copy_n(std::begin(old_keys), new_keys.size() - 1, - std::begin(new_keys) + 1); - } else { - ticket_keys->keys.resize(1); - } - - auto &new_key = ticket_keys->keys[0]; - - if (generate_ticket_key(new_key) != 0) { - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "failed to generate ticket key"; - } - conn_handler->set_ticket_keys(nullptr); - conn_handler->set_ticket_keys_to_worker(nullptr); - return; - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "ticket keys generation done"; - assert(ticket_keys->keys.size() >= 1); - LOG(INFO) << 0 << " enc+dec: " - << util::format_hex(ticket_keys->keys[0].data.name); - for (size_t i = 1; i < ticket_keys->keys.size(); ++i) { - auto &key = ticket_keys->keys[i]; - LOG(INFO) << i << " dec: " << util::format_hex(key.data.name); - } - } - - conn_handler->set_ticket_keys(ticket_keys); - conn_handler->set_ticket_keys_to_worker(ticket_keys); -} -} // namespace - -namespace { -void memcached_get_ticket_key_cb(struct ev_loop *loop, ev_timer *w, - int revents) { - auto conn_handler = static_cast(w->data); - auto dispatcher = conn_handler->get_tls_ticket_key_memcached_dispatcher(); - - auto req = make_unique(); - req->key = "nghttpx:tls-ticket-key"; - req->op = MEMCACHED_OP_GET; - req->cb = [conn_handler, dispatcher, w](MemcachedRequest *req, - MemcachedResult res) { - switch (res.status_code) { - case MEMCACHED_ERR_NO_ERROR: - break; - case MEMCACHED_ERR_EXT_NETWORK_ERROR: - conn_handler->on_tls_ticket_key_network_error(w); - return; - default: - conn_handler->on_tls_ticket_key_not_found(w); - return; - } - - // |version (4bytes)|len (2bytes)|key (variable length)|... - // (len, key) pairs are repeated as necessary. - - auto &value = res.value; - if (value.size() < 4) { - LOG(WARN) << "Memcached: tls ticket key value is too small: got " - << value.size(); - conn_handler->on_tls_ticket_key_not_found(w); - return; - } - auto p = value.data(); - auto version = util::get_uint32(p); - // Currently supported version is 1. - if (version != 1) { - LOG(WARN) << "Memcached: tls ticket key version: want 1, got " << version; - conn_handler->on_tls_ticket_key_not_found(w); - return; - } - - auto end = p + value.size(); - p += 4; - - auto &ticketconf = get_config()->tls.ticket; - - size_t expectedlen; - size_t enc_keylen; - size_t hmac_keylen; - if (ticketconf.cipher == EVP_aes_128_cbc()) { - expectedlen = 48; - enc_keylen = 16; - hmac_keylen = 16; - } else if (ticketconf.cipher == EVP_aes_256_cbc()) { - expectedlen = 80; - enc_keylen = 32; - hmac_keylen = 32; - } else { - return; - } - - auto ticket_keys = std::make_shared(); - - for (; p != end;) { - if (end - p < 2) { - LOG(WARN) << "Memcached: tls ticket key data is too small"; - conn_handler->on_tls_ticket_key_not_found(w); - return; - } - auto len = util::get_uint16(p); - p += 2; - if (len != expectedlen) { - LOG(WARN) << "Memcached: wrong tls ticket key size: want " - << expectedlen << ", got " << len; - conn_handler->on_tls_ticket_key_not_found(w); - return; - } - if (p + len > end) { - LOG(WARN) << "Memcached: too short tls ticket key payload: want " << len - << ", got " << (end - p); - conn_handler->on_tls_ticket_key_not_found(w); - return; - } - auto key = TicketKey(); - key.cipher = ticketconf.cipher; - key.hmac = EVP_sha256(); - key.hmac_keylen = hmac_keylen; - - std::copy_n(p, key.data.name.size(), std::begin(key.data.name)); - p += key.data.name.size(); - - std::copy_n(p, enc_keylen, std::begin(key.data.enc_key)); - p += enc_keylen; - - std::copy_n(p, hmac_keylen, std::begin(key.data.hmac_key)); - p += hmac_keylen; - - ticket_keys->keys.push_back(std::move(key)); - } - - conn_handler->on_tls_ticket_key_get_success(ticket_keys, w); - }; - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Memcached: tls ticket key get request sent"; - } - - dispatcher->add_request(std::move(req)); -} - -} // namespace - -#ifdef HAVE_NEVERBLEED -namespace { -void nb_child_cb(struct ev_loop *loop, ev_child *w, int revents) { - log_chld(w->rpid, w->rstatus, "neverbleed process"); - - ev_child_stop(loop, w); - - LOG(FATAL) << "neverbleed process exitted; aborting now"; - - _Exit(EXIT_FAILURE); -} -} // namespace -#endif // HAVE_NEVERBLEED - -namespace { -std::random_device rd; -} // namespace - -int worker_process_event_loop(WorkerProcessConfig *wpconf) { - if (reopen_log_files() != 0) { - LOG(FATAL) << "Failed to open log file"; - return -1; - } - - auto loop = EV_DEFAULT; - - auto gen = std::mt19937(rd()); - - ConnectionHandler conn_handler(loop, gen); - - for (auto &addr : get_config()->conn.listener.addrs) { - conn_handler.add_acceptor(make_unique(&addr, &conn_handler)); - } - -#ifdef HAVE_NEVERBLEED - { - std::array errbuf; - auto nb = make_unique(); - if (neverbleed_init(nb.get(), errbuf.data()) != 0) { - LOG(FATAL) << "neverbleed_init failed: " << errbuf.data(); - return -1; - } - - LOG(NOTICE) << "neverbleed process [" << nb->daemon_pid << "] spawned"; - - conn_handler.set_neverbleed(std::move(nb)); - } - - auto nb = conn_handler.get_neverbleed(); - - ev_child nb_childev; - if (nb) { - ev_child_init(&nb_childev, nb_child_cb, nb->daemon_pid, 0); - nb_childev.data = nullptr; - ev_child_start(loop, &nb_childev); - } - -#endif // HAVE_NEVERBLEED - - MemchunkPool mcpool; - - ev_timer renew_ticket_key_timer; - if (ssl::upstream_tls_enabled()) { - auto &ticketconf = get_config()->tls.ticket; - auto &memcachedconf = ticketconf.memcached; - - if (!memcachedconf.host.empty()) { - SSL_CTX *ssl_ctx = nullptr; - - if (memcachedconf.tls) { - ssl_ctx = conn_handler.create_tls_ticket_key_memcached_ssl_ctx(); - } - - conn_handler.set_tls_ticket_key_memcached_dispatcher( - make_unique( - &ticketconf.memcached.addr, loop, ssl_ctx, - StringRef{memcachedconf.host}, &mcpool, gen)); - - ev_timer_init(&renew_ticket_key_timer, memcached_get_ticket_key_cb, 0., - 0.); - renew_ticket_key_timer.data = &conn_handler; - // Get first ticket keys. - memcached_get_ticket_key_cb(loop, &renew_ticket_key_timer, 0); - } else { - bool auto_tls_ticket_key = true; - if (!ticketconf.files.empty()) { - if (!ticketconf.cipher_given) { - LOG(WARN) - << "It is strongly recommended to specify " - "--tls-ticket-key-cipher=aes-128-cbc (or " - "tls-ticket-key-cipher=aes-128-cbc in configuration file) " - "when --tls-ticket-key-file is used for the smooth " - "transition when the default value of --tls-ticket-key-cipher " - "becomes aes-256-cbc"; - } - auto ticket_keys = read_tls_ticket_key_file( - ticketconf.files, ticketconf.cipher, EVP_sha256()); - if (!ticket_keys) { - LOG(WARN) << "Use internal session ticket key generator"; - } else { - conn_handler.set_ticket_keys(std::move(ticket_keys)); - auto_tls_ticket_key = false; - } - } - if (auto_tls_ticket_key) { - // Generate new ticket key every 1hr. - ev_timer_init(&renew_ticket_key_timer, renew_ticket_key_cb, 0., 1_h); - renew_ticket_key_timer.data = &conn_handler; - ev_timer_again(loop, &renew_ticket_key_timer); - - // Generate first session ticket key before running workers. - renew_ticket_key_cb(loop, &renew_ticket_key_timer, 0); - } - } - } - - int rv; - - if (get_config()->num_worker == 1) { - rv = conn_handler.create_single_worker(); - if (rv != 0) { - return -1; - } - } else { -#ifndef NOTHREADS - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGCHLD); - - rv = pthread_sigmask(SIG_BLOCK, &set, nullptr); - if (rv != 0) { - LOG(ERROR) << "Blocking SIGCHLD failed: " << strerror(rv); - return -1; - } -#endif // !NOTHREADS - - rv = conn_handler.create_worker_thread(get_config()->num_worker); - if (rv != 0) { - return -1; - } - -#ifndef NOTHREADS - rv = pthread_sigmask(SIG_UNBLOCK, &set, nullptr); - if (rv != 0) { - LOG(ERROR) << "Unblocking SIGCHLD failed: " << strerror(rv); - return -1; - } -#endif // !NOTHREADS - } - - drop_privileges( -#ifdef HAVE_NEVERBLEED - nb -#endif // HAVE_NEVERBLEED - ); - - ev_io ipcev; - ev_io_init(&ipcev, ipc_readcb, wpconf->ipc_fd, EV_READ); - ipcev.data = &conn_handler; - ev_io_start(loop, &ipcev); - - if (ssl::upstream_tls_enabled() && !get_config()->tls.ocsp.disabled) { - conn_handler.proceed_next_cert_ocsp(); - } - - if (LOG_ENABLED(INFO)) { - LOG(INFO) << "Entering event loop"; - } - - ev_run(loop, 0); - - conn_handler.cancel_ocsp_update(); - - return 0; -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_worker_process.h nghttp2-0.6.7/src/shrpx_worker_process.h --- nghttp2-1.13.0/src/shrpx_worker_process.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_worker_process.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 SHRPX_WORKER_PROCESS_H -#define SHRPX_WORKER_PROCESS_H - -#include "shrpx.h" - -using namespace nghttp2; - -namespace shrpx { - -class ConnectionHandler; - -struct WorkerProcessConfig { - // IPC socket to read event from master process - int ipc_fd; - // IPv4 or UNIX domain socket, or -1 if not used - int server_fd; - // IPv6 socket, or -1 if not used - int server_fd6; -}; - -int worker_process_event_loop(WorkerProcessConfig *wpconf); - -} // namespace shrpx - -#endif // SHRPX_WORKER_PROCESS_H diff -Nru nghttp2-1.13.0/src/shrpx_worker_test.cc nghttp2-0.6.7/src/shrpx_worker_test.cc --- nghttp2-1.13.0/src/shrpx_worker_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_worker_test.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,234 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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. - */ -#include "shrpx_worker_test.h" - -#ifdef HAVE_UNISTD_H -#include -#endif // HAVE_UNISTD_H - -#include - -#include - -#include "shrpx_worker.h" -#include "shrpx_connect_blocker.h" - -namespace shrpx { - -void test_shrpx_worker_match_downstream_addr_group(void) { - auto groups = std::vector>(); - for (auto &s : {"nghttp2.org/", "nghttp2.org/alpha/bravo/", - "nghttp2.org/alpha/charlie", "nghttp2.org/delta%3A", - "www.nghttp2.org/", "[::1]/", "nghttp2.org/alpha/bravo/delta", - // Check that match is done in the single node - "example.com/alpha/bravo", "192.168.0.1/alpha/", "/golf/"}) { - auto g = std::make_shared(); - g->pattern = ImmutableString(s); - groups.push_back(std::move(g)); - } - - BlockAllocator balloc(1024, 1024); - RouterConfig routerconf; - - auto &router = routerconf.router; - auto &wcrouter = routerconf.rev_wildcard_router; - auto &wp = routerconf.wildcard_patterns; - - for (size_t i = 0; i < groups.size(); ++i) { - auto &g = groups[i]; - router.add_route(StringRef{g->pattern}, i); - } - - CU_ASSERT(0 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/"), groups, 255, balloc)); - - // port is removed - CU_ASSERT(0 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org:8080"), - StringRef::from_lit("/"), groups, 255, balloc)); - - // host is case-insensitive - CU_ASSERT(4 == match_downstream_addr_group( - routerconf, StringRef::from_lit("WWW.nghttp2.org"), - StringRef::from_lit("/alpha"), groups, 255, balloc)); - - CU_ASSERT(1 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/"), groups, 255, - balloc)); - - // /alpha/bravo also matches /alpha/bravo/ - CU_ASSERT(1 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); - - // path part is case-sensitive - CU_ASSERT(0 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/Alpha/bravo"), groups, 255, balloc)); - - CU_ASSERT(1 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/charlie"), groups, 255, - balloc)); - - CU_ASSERT(2 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/charlie"), groups, 255, - balloc)); - - // pattern which does not end with '/' must match its entirely. So - // this matches to group 0, not group 2. - CU_ASSERT(0 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/charlie/"), groups, 255, - balloc)); - - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit("example.org"), - StringRef::from_lit("/"), groups, 255, balloc)); - - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit(""), - StringRef::from_lit("/"), groups, 255, balloc)); - - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit(""), - StringRef::from_lit("alpha"), groups, 255, balloc)); - - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit("foo/bar"), - StringRef::from_lit("/"), groups, 255, balloc)); - - // If path is StringRef::from_lit("*", only match with host + "/"). - CU_ASSERT(0 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("*"), groups, 255, balloc)); - - CU_ASSERT(5 == match_downstream_addr_group( - routerconf, StringRef::from_lit("[::1]"), - StringRef::from_lit("/"), groups, 255, balloc)); - CU_ASSERT(5 == match_downstream_addr_group( - routerconf, StringRef::from_lit("[::1]:8080"), - StringRef::from_lit("/"), groups, 255, balloc)); - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit("[::1"), - StringRef::from_lit("/"), groups, 255, balloc)); - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit("[::1]8000"), - StringRef::from_lit("/"), groups, 255, balloc)); - - // Check the case where adding route extends tree - CU_ASSERT(6 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/delta"), groups, 255, - balloc)); - - CU_ASSERT(1 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/delta/"), groups, 255, - balloc)); - - // Check the case where query is done in a single node - CU_ASSERT(7 == match_downstream_addr_group( - routerconf, StringRef::from_lit("example.com"), - StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); - - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit("example.com"), - StringRef::from_lit("/alpha/bravo/"), groups, 255, - balloc)); - - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit("example.com"), - StringRef::from_lit("/alpha"), groups, 255, balloc)); - - // Check the case where quey is done in a single node - CU_ASSERT(8 == match_downstream_addr_group( - routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alpha"), groups, 255, balloc)); - - CU_ASSERT(8 == match_downstream_addr_group( - routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alpha/"), groups, 255, balloc)); - - CU_ASSERT(8 == match_downstream_addr_group( - routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); - - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alph"), groups, 255, balloc)); - - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/"), groups, 255, balloc)); - - // Test for wildcard hosts - auto g1 = std::make_shared(); - g1->pattern = ImmutableString::from_lit("git.nghttp2.org"); - groups.push_back(std::move(g1)); - - auto g2 = std::make_shared(); - g2->pattern = ImmutableString::from_lit(".nghttp2.org"); - groups.push_back(std::move(g2)); - - wp.emplace_back(StringRef::from_lit("git.nghttp2.org")); - wcrouter.add_route(StringRef::from_lit("gro.2ptthgn.tig"), 0); - wp.back().router.add_route(StringRef::from_lit("/echo/"), 10); - - wp.emplace_back(StringRef::from_lit(".nghttp2.org")); - wcrouter.add_route(StringRef::from_lit("gro.2ptthgn."), 1); - wp.back().router.add_route(StringRef::from_lit("/echo/"), 11); - wp.back().router.add_route(StringRef::from_lit("/echo/foxtrot"), 12); - - CU_ASSERT(11 == match_downstream_addr_group( - routerconf, StringRef::from_lit("git.nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255, balloc)); - - CU_ASSERT(10 == match_downstream_addr_group( - routerconf, StringRef::from_lit("0git.nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255, balloc)); - - CU_ASSERT(11 == match_downstream_addr_group( - routerconf, StringRef::from_lit("it.nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255, balloc)); - - CU_ASSERT(255 == match_downstream_addr_group( - routerconf, StringRef::from_lit(".nghttp2.org"), - StringRef::from_lit("/echo/foxtrot"), groups, 255, - balloc)); - - CU_ASSERT(9 == match_downstream_addr_group( - routerconf, StringRef::from_lit("alpha.nghttp2.org"), - StringRef::from_lit("/golf"), groups, 255, balloc)); - - CU_ASSERT(0 == match_downstream_addr_group( - routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255, balloc)); -} - -} // namespace shrpx diff -Nru nghttp2-1.13.0/src/shrpx_worker_test.h nghttp2-0.6.7/src/shrpx_worker_test.h --- nghttp2-1.13.0/src/shrpx_worker_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/shrpx_worker_test.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 SHRPX_WORKER_TEST_H -#define SHRPX_WORKER_TEST_H - -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - -namespace shrpx { - -void test_shrpx_worker_match_downstream_addr_group(void); - -} // namespace shrpx - -#endif // SHRPX_WORKER_TEST_H diff -Nru nghttp2-1.13.0/src/ssl.cc nghttp2-0.6.7/src/ssl.cc --- nghttp2-1.13.0/src/ssl.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/ssl.cc 2014-11-30 14:15:07.000000000 +0000 @@ -30,37 +30,24 @@ #include #include -#include - -#include "ssl_compat.h" namespace nghttp2 { namespace ssl { -// Recommended general purpose "Intermediate compatibility" cipher -// suites by mozilla. +// Recommended general purpose "Non-Backward Compatible" cipher by +// mozilla. // // https://wiki.mozilla.org/Security/Server_Side_TLS const char *const DEFAULT_CIPHER_LIST = - "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-" - "AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-" - "SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-" - "AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-" - "ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-" - "AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-" - "SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-" - "ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-" - "SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-" - "SHA:DES-CBC3-SHA:!DSS"; - -#if OPENSSL_101_API - -// CRYPTO_LOCK is deprecated as of OpenSSL 1.1.0 -LibsslGlobalLock::LibsslGlobalLock() {} -LibsslGlobalLock::~LibsslGlobalLock() {} - -#else // !OPENSSL_101_API + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-" + "AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:" + "DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-" + "AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-" + "AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-" + "AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:" + "DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:" + "!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK"; namespace { std::vector ssl_global_locks; @@ -91,90 +78,6 @@ LibsslGlobalLock::~LibsslGlobalLock() { ssl_global_locks.clear(); } -#endif // !OPENSSL_101_API - -const char *get_tls_protocol(SSL *ssl) { - switch (SSL_version(ssl)) { - case SSL2_VERSION: - return "SSLv2"; - case SSL3_VERSION: - return "SSLv3"; - case TLS1_2_VERSION: - return "TLSv1.2"; - case TLS1_1_VERSION: - return "TLSv1.1"; - case TLS1_VERSION: - return "TLSv1"; - default: - return "unknown"; - } -} - -TLSSessionInfo *get_tls_session_info(TLSSessionInfo *tls_info, SSL *ssl) { - if (!ssl) { - return nullptr; - } - - auto session = SSL_get_session(ssl); - if (!session) { - return nullptr; - } - - tls_info->cipher = SSL_get_cipher_name(ssl); - tls_info->protocol = get_tls_protocol(ssl); - tls_info->session_reused = SSL_session_reused(ssl); - - unsigned int session_id_length; - tls_info->session_id = SSL_SESSION_get_id(session, &session_id_length); - tls_info->session_id_length = session_id_length; - - return tls_info; -} - -/* Conditional logic w/ lookup tables to check if id is one of the - the black listed cipher suites for HTTP/2 described in RFC 7540. - https://github.com/jay/http2_blacklisted_ciphers -*/ -#define IS_CIPHER_BANNED_METHOD2(id) \ - ((0x0000 <= id && id <= 0x00FF && \ - "\xFF\xFF\xFF\xCF\xFF\xFF\xFF\xFF\x7F\x00\x00\x00\x80\x3F\x00\x00" \ - "\xF0\xFF\xFF\x3F\xF3\xF3\xFF\xFF\x3F\x00\x00\x00\x00\x00\x00\x80" \ - [(id & 0xFF) / 8] & \ - (1 << (id % 8))) || \ - (0xC000 <= id && id <= 0xC0FF && \ - "\xFE\xFF\xFF\xFF\xFF\x67\xFE\xFF\xFF\xFF\x33\xCF\xFC\xCF\xFF\xCF" \ - "\x3C\xF3\xFC\x3F\x33\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ - [(id & 0xFF) / 8] & \ - (1 << (id % 8)))) - -bool check_http2_cipher_black_list(SSL *ssl) { - int id = SSL_CIPHER_get_id(SSL_get_current_cipher(ssl)) & 0xFFFFFF; - - return IS_CIPHER_BANNED_METHOD2(id); -} - -bool check_http2_tls_version(SSL *ssl) { - auto tls_ver = SSL_version(ssl); - - return tls_ver == TLS1_2_VERSION; -} - -bool check_http2_requirement(SSL *ssl) { - return check_http2_tls_version(ssl) && !check_http2_cipher_black_list(ssl); -} - -void libssl_init() { -// OPENSSL_config() is not available in BoringSSL. It is also -// deprecated as of OpenSSL 1.1.0. -#if !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_101_API - OPENSSL_config(nullptr); -#endif // !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_101_API - - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); -} - } // namespace ssl } // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/ssl_compat.h nghttp2-0.6.7/src/ssl_compat.h --- nghttp2-1.13.0/src/ssl_compat.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/ssl_compat.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 OPENSSL_COMPAT_H - -#define OPENSSL_101_API \ - (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100005L) - -#endif // OPENSSL_COMPAT_H diff -Nru nghttp2-1.13.0/src/ssl.h nghttp2-0.6.7/src/ssl.h --- nghttp2-1.13.0/src/ssl.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/ssl.h 2014-11-30 14:15:07.000000000 +0000 @@ -22,15 +22,8 @@ * 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 SSL_H -#define SSL_H - #include "nghttp2_config.h" -#include - -#include - namespace nghttp2 { namespace ssl { @@ -47,38 +40,6 @@ extern const char *const DEFAULT_CIPHER_LIST; -const char *get_tls_protocol(SSL *ssl); - -struct TLSSessionInfo { - const char *cipher; - const char *protocol; - const uint8_t *session_id; - bool session_reused; - size_t session_id_length; -}; - -TLSSessionInfo *get_tls_session_info(TLSSessionInfo *tls_info, SSL *ssl); - -// Returns true iff the negotiated protocol is TLSv1.2. -bool check_http2_tls_version(SSL *ssl); - -// Returns true iff the negotiated cipher suite is in HTTP/2 cipher -// black list. -bool check_http2_cipher_black_list(SSL *ssl); - -// Returns true if SSL/TLS requirement for HTTP/2 is fulfilled. -// To fulfill the requirement, the following 2 terms must be hold: -// -// 1. The negotiated protocol must be TLSv1.2. -// 2. The negotiated cipher cuite is not listed in the black list -// described in RFC 7540. -bool check_http2_requirement(SSL *ssl); - -// Initializes OpenSSL library -void libssl_init(); - } // namespace ssl } // namespace nghttp2 - -#endif // SSL_H diff -Nru nghttp2-1.13.0/src/template.h nghttp2-0.6.7/src/template.h --- nghttp2-1.13.0/src/template.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/template.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,555 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2015 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 TEMPLATE_H -#define TEMPLATE_H - -#include "nghttp2_config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nghttp2 { - -#if __cplusplus > 201103L -using std::make_unique; -#else // __cplusplus <= 201103L -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(U &&... u) { - return std::unique_ptr(new T(std::forward(u)...)); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(size_t size) { - return std::unique_ptr(new typename std::remove_extent::type[size]()); -} -#endif // __cplusplus <= 201103L - -// std::forward is constexpr since C++14 -template -constexpr std::array< - typename std::decay::type>::type, - sizeof...(T)> -make_array(T &&... t) { - return std::array< - typename std::decay::type>::type, - sizeof...(T)>{{std::forward(t)...}}; -} - -template constexpr size_t array_size(T(&)[N]) { - return N; -} - -template constexpr size_t str_size(T(&)[N]) { - return N - 1; -} - -// inspired by , but our -// template can take functions returning other than void. -template struct Defer { - Defer(F &&f, T &&... t) - : f(std::bind(std::forward(f), std::forward(t)...)) {} - Defer(Defer &&o) : f(std::move(o.f)) {} - ~Defer() { f(); } - - using ResultType = typename std::result_of::type( - typename std::decay::type...)>::type; - std::function f; -}; - -template Defer defer(F &&f, T &&... t) { - return Defer(std::forward(f), std::forward(t)...); -} - -template bool test_flags(T t, F flags) { - return (t & flags) == flags; -} - -// doubly linked list of element T*. T must have field T *dlprev and -// T *dlnext, which point to previous element and next element in the -// list respectively. -template struct DList { - DList() : head(nullptr), tail(nullptr), len(0) {} - - DList(const DList &) = delete; - DList &operator=(const DList &) = delete; - - DList(DList &&other) : head(other.head), tail(other.tail), len(other.len) { - other.head = other.tail = nullptr; - other.len = 0; - } - - DList &operator=(DList &&other) { - if (this == &other) { - return *this; - } - head = other.head; - tail = other.tail; - len = other.len; - - other.head = other.tail = nullptr; - other.len = 0; - - return *this; - } - - void append(T *t) { - ++len; - if (tail) { - tail->dlnext = t; - t->dlprev = tail; - tail = t; - return; - } - head = tail = t; - } - - void remove(T *t) { - --len; - auto p = t->dlprev; - auto n = t->dlnext; - if (p) { - p->dlnext = n; - } - if (head == t) { - head = n; - } - if (n) { - n->dlprev = p; - } - if (tail == t) { - tail = p; - } - t->dlprev = t->dlnext = nullptr; - } - - bool empty() const { return head == nullptr; } - - size_t size() const { return len; } - - T *head, *tail; - size_t len; -}; - -template void dlist_delete_all(DList &dl) { - for (auto e = dl.head; e;) { - auto next = e->dlnext; - delete e; - e = next; - } -} - -// User-defined literals for K, M, and G (powers of 1024) - -constexpr unsigned long long operator"" _k(unsigned long long k) { - return k * 1024; -} - -constexpr unsigned long long operator"" _m(unsigned long long m) { - return m * 1024 * 1024; -} - -constexpr unsigned long long operator"" _g(unsigned long long g) { - return g * 1024 * 1024 * 1024; -} - -// User-defined literals for time, converted into double in seconds - -// hours -constexpr double operator"" _h(unsigned long long h) { return h * 60 * 60; } - -// minutes -constexpr double operator"" _min(unsigned long long min) { return min * 60; } - -// seconds -constexpr double operator"" _s(unsigned long long s) { return s; } - -// milliseconds -constexpr double operator"" _ms(unsigned long long ms) { return ms / 1000.; } - -// Returns a copy of NULL-terminated string [first, last). -template -std::unique_ptr strcopy(InputIt first, InputIt last) { - auto res = make_unique(last - first + 1); - *std::copy(first, last, res.get()) = '\0'; - return res; -} - -// Returns a copy of NULL-terminated string |val|. -inline std::unique_ptr strcopy(const char *val) { - return strcopy(val, val + strlen(val)); -} - -inline std::unique_ptr strcopy(const char *val, size_t n) { - return strcopy(val, val + n); -} - -// Returns a copy of val.c_str(). -inline std::unique_ptr strcopy(const std::string &val) { - return strcopy(std::begin(val), std::end(val)); -} - -inline std::unique_ptr strcopy(const std::unique_ptr &val) { - if (!val) { - return nullptr; - } - return strcopy(val.get()); -} - -inline std::unique_ptr strcopy(const std::unique_ptr &val, - size_t n) { - if (!val) { - return nullptr; - } - return strcopy(val.get(), val.get() + n); -} - -// ImmutableString represents string that is immutable unlike -// std::string. It has c_str() and size() functions to mimic -// std::string. It manages buffer by itself. Just like std::string, -// c_str() returns NULL-terminated string, but NULL character may -// appear before the final terminal NULL. -class ImmutableString { -public: - using traits_type = std::char_traits; - using value_type = traits_type::char_type; - using allocator_type = std::allocator; - using size_type = std::allocator_traits::size_type; - using difference_type = - std::allocator_traits::difference_type; - using const_reference = const value_type &; - using const_pointer = const value_type *; - using const_iterator = const_pointer; - using const_reverse_iterator = std::reverse_iterator; - - ImmutableString() : len(0), base("") {} - ImmutableString(const char *s, size_t slen) - : len(slen), base(copystr(s, s + len)) {} - ImmutableString(const char *s) : len(strlen(s)), base(copystr(s, s + len)) {} - ImmutableString(const std::string &s) - : len(s.size()), base(copystr(std::begin(s), std::end(s))) {} - template - ImmutableString(InputIt first, InputIt last) - : len(std::distance(first, last)), base(copystr(first, last)) {} - ImmutableString(const ImmutableString &other) - : len(other.len), base(copystr(std::begin(other), std::end(other))) {} - ImmutableString(ImmutableString &&other) noexcept : len(other.len), - base(other.base) { - other.len = 0; - other.base = ""; - } - ~ImmutableString() { - if (len) { - delete[] base; - } - } - - ImmutableString &operator=(const ImmutableString &other) { - if (this == &other) { - return *this; - } - if (len) { - delete[] base; - } - len = other.len; - base = copystr(std::begin(other), std::end(other)); - return *this; - } - ImmutableString &operator=(ImmutableString &&other) noexcept { - if (this == &other) { - return *this; - } - if (len) { - delete[] base; - } - len = other.len; - base = other.base; - other.len = 0; - other.base = ""; - return *this; - } - - template static ImmutableString from_lit(const char(&s)[N]) { - return ImmutableString(s, N - 1); - } - - const_iterator begin() const { return base; }; - const_iterator cbegin() const { return base; }; - - const_iterator end() const { return base + len; }; - const_iterator cend() const { return base + len; }; - - const_reverse_iterator rbegin() const { - return const_reverse_iterator{base + len}; - } - const_reverse_iterator crbegin() const { - return const_reverse_iterator{base + len}; - } - - const_reverse_iterator rend() const { return const_reverse_iterator{base}; } - const_reverse_iterator crend() const { return const_reverse_iterator{base}; } - - const char *c_str() const { return base; } - size_type size() const { return len; } - bool empty() const { return len == 0; } - const_reference operator[](size_type pos) const { return *(base + pos); } - -private: - template const char *copystr(InputIt first, InputIt last) { - if (first == last) { - return ""; - } - auto res = new char[std::distance(first, last) + 1]; - *std::copy(first, last, res) = '\0'; - return res; - } - - size_type len; - const char *base; -}; - -inline bool operator==(const ImmutableString &lhs, const ImmutableString &rhs) { - return lhs.size() == rhs.size() && - std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); -} - -inline bool operator==(const ImmutableString &lhs, const std::string &rhs) { - return lhs.size() == rhs.size() && - std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); -} - -inline bool operator==(const std::string &lhs, const ImmutableString &rhs) { - return rhs == lhs; -} - -inline bool operator==(const ImmutableString &lhs, const char *rhs) { - return lhs.size() == strlen(rhs) && - std::equal(std::begin(lhs), std::end(lhs), rhs); -} - -inline bool operator==(const char *lhs, const ImmutableString &rhs) { - return rhs == lhs; -} - -inline bool operator!=(const ImmutableString &lhs, const ImmutableString &rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const ImmutableString &lhs, const std::string &rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const std::string &lhs, const ImmutableString &rhs) { - return !(rhs == lhs); -} - -inline bool operator!=(const ImmutableString &lhs, const char *rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const char *lhs, const ImmutableString &rhs) { - return !(rhs == lhs); -} - -inline std::ostream &operator<<(std::ostream &o, const ImmutableString &s) { - return o.write(s.c_str(), s.size()); -} - -inline std::string &operator+=(std::string &lhs, const ImmutableString &rhs) { - lhs.append(rhs.c_str(), rhs.size()); - return lhs; -} - -// StringRef is a reference to a string owned by something else. So -// it behaves like simple string, but it does not own pointer. When -// it is default constructed, it has empty string. You can freely -// copy or move around this struct, but never free its pointer. str() -// function can be used to export the content as std::string. -class StringRef { -public: - using traits_type = std::char_traits; - using value_type = traits_type::char_type; - using allocator_type = std::allocator; - using size_type = std::allocator_traits::size_type; - using difference_type = - std::allocator_traits::difference_type; - using const_reference = const value_type &; - using const_pointer = const value_type *; - using const_iterator = const_pointer; - using const_reverse_iterator = std::reverse_iterator; - - constexpr StringRef() : base(""), len(0) {} - explicit StringRef(const std::string &s) : base(s.c_str()), len(s.size()) {} - explicit StringRef(const ImmutableString &s) - : base(s.c_str()), len(s.size()) {} - explicit StringRef(const char *s) : base(s), len(strlen(s)) {} - constexpr StringRef(const char *s, size_t n) : base(s), len(n) {} - template - StringRef(const CharT *s, size_t n) - : base(reinterpret_cast(s)), len(n) {} - template - StringRef(InputIt first, InputIt last) - : base(reinterpret_cast(&*first)), - len(std::distance(first, last)) {} - template - StringRef(InputIt *first, InputIt *last) - : base(reinterpret_cast(first)), - len(std::distance(first, last)) {} - template - constexpr static StringRef from_lit(const CharT(&s)[N]) { - return StringRef{s, N - 1}; - } - static StringRef from_maybe_nullptr(const char *s) { - if (s == nullptr) { - return StringRef(); - } - - return StringRef(s); - } - - constexpr const_iterator begin() const { return base; }; - constexpr const_iterator cbegin() const { return base; }; - - constexpr const_iterator end() const { return base + len; }; - constexpr const_iterator cend() const { return base + len; }; - - const_reverse_iterator rbegin() const { - return const_reverse_iterator{base + len}; - } - const_reverse_iterator crbegin() const { - return const_reverse_iterator{base + len}; - } - - const_reverse_iterator rend() const { return const_reverse_iterator{base}; } - const_reverse_iterator crend() const { return const_reverse_iterator{base}; } - - constexpr const char *c_str() const { return base; } - constexpr size_type size() const { return len; } - constexpr bool empty() const { return len == 0; } - constexpr const_reference operator[](size_type pos) const { - return *(base + pos); - } - - std::string str() const { return std::string(base, len); } - const uint8_t *byte() const { - return reinterpret_cast(base); - } - -private: - const char *base; - size_type len; -}; - -inline bool operator==(const StringRef &lhs, const StringRef &rhs) { - return lhs.size() == rhs.size() && - std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); -} - -inline bool operator==(const StringRef &lhs, const std::string &rhs) { - return lhs.size() == rhs.size() && - std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); -} - -inline bool operator==(const std::string &lhs, const StringRef &rhs) { - return rhs == lhs; -} - -inline bool operator==(const StringRef &lhs, const char *rhs) { - return lhs.size() == strlen(rhs) && - std::equal(std::begin(lhs), std::end(lhs), rhs); -} - -inline bool operator==(const StringRef &lhs, const ImmutableString &rhs) { - return lhs.size() == rhs.size() && - std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); -} - -inline bool operator==(const ImmutableString &lhs, const StringRef &rhs) { - return rhs == lhs; -} - -inline bool operator==(const char *lhs, const StringRef &rhs) { - return rhs == lhs; -} - -inline bool operator!=(const StringRef &lhs, const StringRef &rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const StringRef &lhs, const std::string &rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const std::string &lhs, const StringRef &rhs) { - return !(rhs == lhs); -} - -inline bool operator!=(const StringRef &lhs, const char *rhs) { - return !(lhs == rhs); -} - -inline bool operator!=(const char *lhs, const StringRef &rhs) { - return !(rhs == lhs); -} - -inline bool operator<(const StringRef &lhs, const StringRef &rhs) { - return std::lexicographical_compare(std::begin(lhs), std::end(lhs), - std::begin(rhs), std::end(rhs)); -} - -inline std::ostream &operator<<(std::ostream &o, const StringRef &s) { - return o.write(s.c_str(), s.size()); -} - -inline std::string &operator+=(std::string &lhs, const StringRef &rhs) { - lhs.append(rhs.c_str(), rhs.size()); - return lhs; -} - -inline int run_app(std::function app, int argc, - char **argv) { - try { - return app(argc, argv); - } catch (const std::bad_alloc &) { - fputs("Out of memory\n", stderr); - } catch (const std::exception &x) { - fprintf(stderr, "Caught %s:\n%s\n", typeid(x).name(), x.what()); - } catch (...) { - fputs("Unknown exception caught\n", stderr); - } - return EXIT_FAILURE; -} - -} // namespace nghttp2 - -#endif // TEMPLATE_H diff -Nru nghttp2-1.13.0/src/template_test.cc nghttp2-0.6.7/src/template_test.cc --- nghttp2-1.13.0/src/template_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/template_test.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,204 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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. - */ -#include "template_test.h" - -#include -#include -#include - -#include - -#include "template.h" - -namespace nghttp2 { - -void test_template_immutable_string(void) { - ImmutableString null; - - CU_ASSERT("" == null); - CU_ASSERT(0 == null.size()); - CU_ASSERT(null.empty()); - - ImmutableString from_cstr("alpha"); - - CU_ASSERT(0 == strcmp("alpha", from_cstr.c_str())); - CU_ASSERT(5 == from_cstr.size()); - CU_ASSERT(!from_cstr.empty()); - CU_ASSERT("alpha" == from_cstr); - CU_ASSERT(from_cstr == "alpha"); - CU_ASSERT(std::string("alpha") == from_cstr); - CU_ASSERT(from_cstr == std::string("alpha")); - - // copy constructor - ImmutableString src("charlie"); - ImmutableString copy = src; - - CU_ASSERT("charlie" == copy); - CU_ASSERT(7 == copy.size()); - - // copy assignment - ImmutableString copy2; - copy2 = src; - - CU_ASSERT("charlie" == copy2); - CU_ASSERT(7 == copy2.size()); - - // move constructor - ImmutableString move = std::move(copy); - - CU_ASSERT("charlie" == move); - CU_ASSERT(7 == move.size()); - CU_ASSERT("" == copy); - CU_ASSERT(0 == copy.size()); - - // move assignment - move = std::move(from_cstr); - - CU_ASSERT("alpha" == move); - CU_ASSERT(5 == move.size()); - CU_ASSERT("" == from_cstr); - CU_ASSERT(0 == from_cstr.size()); - - // from string literal - auto from_lit = StringRef::from_lit("bravo"); - - CU_ASSERT("bravo" == from_lit); - CU_ASSERT(5 == from_lit.size()); - - // equality - ImmutableString eq("delta"); - - CU_ASSERT("delta1" != eq); - CU_ASSERT("delt" != eq); - CU_ASSERT(eq != "delta1"); - CU_ASSERT(eq != "delt"); - - // operator[] - ImmutableString br_op("foxtrot"); - - CU_ASSERT('f' == br_op[0]); - CU_ASSERT('o' == br_op[1]); - CU_ASSERT('t' == br_op[6]); - CU_ASSERT('\0' == br_op[7]); - - // operator==(const ImmutableString &, const ImmutableString &) - { - ImmutableString a("foo"); - ImmutableString b("foo"); - ImmutableString c("fo"); - - CU_ASSERT(a == b); - CU_ASSERT(a != c); - CU_ASSERT(c != b); - } - - // operator<< - { - ImmutableString a("foo"); - std::stringstream ss; - ss << a; - - CU_ASSERT("foo" == ss.str()); - } - - // operator +=(std::string &, const ImmutableString &) - { - std::string a = "alpha"; - a += ImmutableString("bravo"); - - CU_ASSERT("alphabravo" == a); - } -} - -void test_template_string_ref(void) { - StringRef empty; - - CU_ASSERT("" == empty); - CU_ASSERT(0 == empty.size()); - - // from std::string - std::string alpha = "alpha"; - - StringRef ref(alpha); - - CU_ASSERT("alpha" == ref); - CU_ASSERT(ref == "alpha"); - CU_ASSERT(alpha == ref); - CU_ASSERT(ref == alpha); - CU_ASSERT(5 == ref.size()); - - // from string literal - auto from_lit = StringRef::from_lit("alpha"); - - CU_ASSERT("alpha" == from_lit); - CU_ASSERT(5 == from_lit.size()); - - // from ImmutableString - ImmutableString im = "bravo"; - - StringRef imref(im); - - CU_ASSERT("bravo" == imref); - CU_ASSERT(5 == imref.size()); - - // from C-string - StringRef cstrref("charlie"); - - CU_ASSERT("charlie" == cstrref); - CU_ASSERT(7 == cstrref.size()); - - // from C-string and its length - StringRef cstrnref("delta", 5); - - CU_ASSERT("delta" == cstrnref); - CU_ASSERT(5 == cstrnref.size()); - - // operator[] - StringRef br_op("foxtrot"); - - CU_ASSERT('f' == br_op[0]); - CU_ASSERT('o' == br_op[1]); - CU_ASSERT('t' == br_op[6]); - CU_ASSERT('\0' == br_op[7]); - - // operator<< - { - StringRef a("foo"); - std::stringstream ss; - ss << a; - - CU_ASSERT("foo" == ss.str()); - } - - // operator +=(std::string &, const StringRef &) - { - std::string a = "alpha"; - a += StringRef("bravo"); - - CU_ASSERT("alphabravo" == a); - } -} - -} // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/template_test.h nghttp2-0.6.7/src/template_test.h --- nghttp2-1.13.0/src/template_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/template_test.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * nghttp2 - HTTP/2 C Library - * - * Copyright (c) 2016 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 TEMPLATE_TEST_H -#define TEMPLATE_TEST_H - -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - -namespace nghttp2 { - -void test_template_immutable_string(void); -void test_template_string_ref(void); - -} // namespace nghttp2 - -#endif // TEMPLATE_TEST_H diff -Nru nghttp2-1.13.0/src/test.example.com.pem nghttp2-0.6.7/src/test.example.com.pem --- nghttp2-1.13.0/src/test.example.com.pem 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/test.example.com.pem 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDwTCCAqmgAwIBAgIUDhKNhGRUq1TSHD6aG2k4TRR8iA0wDQYJKoZIhvcNAQEL -BQAwXjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoT -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMOY2EubmdodHRwMi5v -cmcwHhcNMTYwNjI1MDkzNzAwWhcNMjYwNjIzMDkzNzAwWjBgMQswCQYDVQQGEwJB -VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMRkwFwYDVQQDExB0ZXN0LmV4YW1wbGUuY29tMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEArf2UBsEh/xwd/4WZfVFf5sMyWcns/1idF2Fr -oLDwqVUYRlxpU/KbrIG8X8v3w4cVP/xOXd1y9Q+W9OLK2YScAeHeE97mHZXbcpow -UxvTDv/GNIHHXK/yvYM8R2EEnZR71qXdoXsCakv/aG2ewkkvA108eEbk0u7RxNmI -sYsO0Y4iBtwBM/MSkAYPfWdrdHhY9z0l4M8GAyUOuZc0t6j0zw3fzkjqmVgGEJvc -VzvSgZIzMLqSzvC89viXtj1pyzQjMLgmuDbs0l47uRHpZXgMGVyF3UuQipPzvhO7 -G/ZbX/4kUU5bPabdtvPbjju7dE5PfGrKOThM6HS93Y7QvYTUtwIDAQABo3UwczAO -BgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIw -ADAdBgNVHQ4EFgQUm8jn1FICope9qUce6ORQ0CtbmhYwHwYDVR0jBBgwFoAU0DnF -VHVlxrFEkv1ULqnO4ua924YwDQYJKoZIhvcNAQELBQADggEBAD7RPz/5rAnS1MNP -JfAj1TXZSBwlYgtmJL65yaFB6a1SNSTo15deAm/1Vl10LbmYdV4sVnGKeZjhKNk+ -bvVzetUSUS7Rh1fHtxlivJFkG1VrvPu9b416l2aKftBiaNyAWXbyjqXwLYli6Ehk -uu6jZd0040Ggh7bY+KMSnDFDrp7Rar7OvGu9Iovs+sPdkc/iEbvwEiXdMjf3gwkT -Wqx6br1VDLzhD83HAsFA9tt5fv6KTf91UgJnCmOi81Uo6fSEJG84g32T25gwwmCK -q4U049aGF/f4u3QuWDsfYqNePycurAg3m5PC0wCoqvpY2u/q+PGbjWMi2PfZsF8U -imgl/L0= ------END CERTIFICATE----- diff -Nru nghttp2-1.13.0/src/test.nghttp2.org.pem nghttp2-0.6.7/src/test.nghttp2.org.pem --- nghttp2-1.13.0/src/test.nghttp2.org.pem 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/test.nghttp2.org.pem 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEDjCCAvagAwIBAgIUQBCY8Nre85JT1c7P+HbXUF9yzg8wDQYJKoZIhvcNAQEL -BQAwXjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoT -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMOY2EubmdodHRwMi5v -cmcwHhcNMTYwNjI1MDkzMzAwWhcNMjYwNjIzMDkzMzAwWjBkMQswCQYDVQQGEwJB -VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMR0wGwYDVQQDExRub3QtdXNlZC5uZ2h0dHAyLm9yZzCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAO6eiimt3LUvkq/539rkyjbU7Ibg1c07 -AU22hsnY/KtGA5k95wpzj1l77xtTfoyb+aXAFzdmZ1fVKRodzeYPwmkXBU4EEPKP -jZQl2AXTyFwCfipG8ZYpg8N5/cSF33i+vldkLjza6oep9t8cA4OW6CmjZKX+1+Tq -409T4ee0hH19aKdxl28JAD9vt1pccWGLNIbUatoB/e6vSeDJYRzw2qYvrihrPtm9 -culMYH+Jw+YxFnT5slanirPn0+I2tp/t4Lo6XTqNpYOdOKedIC+Mz/M4QJXKpUAp -niRi9cRcwrZtsB0KO+lx0lnGuKSe68X9qCHbRO4pL4BZU1V5xtU90xECAwEAAaOB -vTCBujAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0T -AQH/BAIwADAdBgNVHQ4EFgQUGlxgxowH6jrQiyyFpCbwPkCXXIYwHwYDVR0jBBgw -FoAU0DnFVHVlxrFEkv1ULqnO4ua924YwRQYDVR0RBD4wPIIQVEVTVC5OR0hUVFAy -Lk9SR4ISKi50ZXN0Lm5naHR0cDIub3JnghR3KncudGVzdC5uZ2h0dHAyLm9yZzAN -BgkqhkiG9w0BAQsFAAOCAQEANCqM6ocfqOpgDEHYOOQTGFHJIptQhS3kRYAdTIo2 -G8XvGCoy+CDYe1GAUWbxE090+a1I1rsYMHcWKJnjKaCBZid7KMhyayIvrmgEsOCh -L8iLf3bxkCoyIAmCpxJwa3LMxm2QQLtRx8AoMXWf+N8are4HY6MLNn6aP4zaTrTZ -H+WkjKIh7WjSHtW/ro666PCXJDCCdRXljOf8v/fff3bYiLg8o70RBp7OFM0HaPtK -wCfcLLxBeoVIncWswB6GtVUFhLeGjepDzWpuDHOdw6DtpghwSXvWFu9bRtl+x02m -LAGfJ0kJrpYGfr9UB51NFX3aM/D3p2zxrjKwR2b59vJEcA== ------END CERTIFICATE----- diff -Nru nghttp2-1.13.0/src/timegm.c nghttp2-0.6.7/src/timegm.c --- nghttp2-1.13.0/src/timegm.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/timegm.c 2014-11-30 14:15:07.000000000 +0000 @@ -24,7 +24,9 @@ */ #include "timegm.h" -#include +#ifndef HAVE_TIMEGM + +#include /* Counter the number of leap year in the range [0, y). The |y| is the year, including century (e.g., 2012) */ @@ -33,27 +35,6 @@ return y / 4 - y / 100 + y / 400; } -/* Based on the algorithm of Python 2.7 calendar.timegm. */ -time_t nghttp2_timegm(struct tm *tm) { - int days; - int num_leap_year; - int64_t t; - if (tm->tm_mon > 11) { - return -1; - } - num_leap_year = count_leap_year(tm->tm_year + 1900) - count_leap_year(1970); - days = (tm->tm_year - 70) * 365 + num_leap_year + tm->tm_yday; - t = ((int64_t)days * 24 + tm->tm_hour) * 3600 + tm->tm_min * 60 + tm->tm_sec; - -#if SIZEOF_TIME_T == 4 - if (t < INT32_MIN || t > INT32_MAX) { - return -1; - } -#endif /* SIZEOF_TIME_T == 4 */ - - return (time_t)t; -} - /* Returns nonzero if the |y| is the leap year. The |y| is the year, including century (e.g., 2012) */ static int is_leap_year(int y) { @@ -63,7 +44,8 @@ /* The number of days before ith month begins */ static int daysum[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; -time_t nghttp2_timegm_without_yday(struct tm *tm) { +/* Based on the algorithm of Python 2.7 calendar.timegm. */ +time_t timegm(struct tm *tm) { int days; int num_leap_year; int64_t t; @@ -77,12 +59,12 @@ ++days; } t = ((int64_t)days * 24 + tm->tm_hour) * 3600 + tm->tm_min * 60 + tm->tm_sec; - -#if SIZEOF_TIME_T == 4 - if (t < INT32_MIN || t > INT32_MAX) { - return -1; + if (sizeof(time_t) == 4) { + if (t < INT32_MIN || t > INT32_MAX) { + return -1; + } } -#endif /* SIZEOF_TIME_T == 4 */ - return (time_t)t; } + +#endif /* !HAVE_TIMEGM */ diff -Nru nghttp2-1.13.0/src/timegm.h nghttp2-0.6.7/src/timegm.h --- nghttp2-1.13.0/src/timegm.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/timegm.h 2014-11-30 14:15:07.000000000 +0000 @@ -33,16 +33,13 @@ extern "C" { #endif /* __cplusplus */ -#ifdef HAVE_TIME_H #include -#endif // HAVE_TIME_H -time_t nghttp2_timegm(struct tm *tm); +#ifndef HAVE_TIMEGM -/* Just like nghttp2_timegm, but without using tm->tm_yday. This is - useful if we use tm from strptime, since some platforms do not - calculate tm_yday with that call. */ -time_t nghttp2_timegm_without_yday(struct tm *tm); +time_t timegm(struct tm *tm); + +#endif /* HAVE_TIMEGM */ #ifdef __cplusplus } diff -Nru nghttp2-1.13.0/src/util.cc nghttp2-0.6.7/src/util.cc --- nghttp2-1.13.0/src/util.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/util.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,72 +24,55 @@ */ #include "util.h" -#ifdef HAVE_TIME_H #include -#endif // HAVE_TIME_H #include -#ifdef HAVE_SYS_SOCKET_H #include -#endif // HAVE_SYS_SOCKET_H -#ifdef HAVE_NETDB_H #include -#endif // HAVE_NETDB_H #include -#ifdef HAVE_FCNTL_H #include -#endif // HAVE_FCNTL_H -#ifdef HAVE_NETINET_IN_H -#include -#endif // HAVE_NETINET_IN_H -#include -#ifdef HAVE_ARPA_INET_H -#include -#endif // HAVE_ARPA_INET_H -#include -#include #include #include #include #include -#include - -#include #include -#include "ssl_compat.h" #include "timegm.h" namespace nghttp2 { namespace util { +const char DEFAULT_STRIP_CHARSET[] = "\r\n\t "; + const char UPPER_XDIGITS[] = "0123456789ABCDEF"; -bool in_rfc3986_unreserved_chars(const char c) { - static constexpr char unreserved[] = {'-', '.', '_', '~'}; - return is_alpha(c) || is_digit(c) || - std::find(std::begin(unreserved), std::end(unreserved), c) != - std::end(unreserved); +bool isAlpha(const char c) { + return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'); +} + +bool isDigit(const char c) { return '0' <= c && c <= '9'; } + +bool isHexDigit(const char c) { + return isDigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); } -bool in_rfc3986_sub_delims(const char c) { - static constexpr char sub_delims[] = {'!', '$', '&', '\'', '(', ')', - '*', '+', ',', ';', '='}; - return std::find(std::begin(sub_delims), std::end(sub_delims), c) != - std::end(sub_delims); +bool inRFC3986UnreservedChars(const char c) { + static const char unreserved[] = {'-', '.', '_', '~'}; + return isAlpha(c) || isDigit(c) || + std::find(&unreserved[0], &unreserved[4], c) != &unreserved[4]; } -std::string percent_encode(const unsigned char *target, size_t len) { +std::string percentEncode(const unsigned char *target, size_t len) { std::string dest; for (size_t i = 0; i < len; ++i) { unsigned char c = target[i]; - if (in_rfc3986_unreserved_chars(c)) { + if (inRFC3986UnreservedChars(c)) { dest += c; } else { - dest += '%'; + dest += "%"; dest += UPPER_XDIGITS[c >> 4]; dest += UPPER_XDIGITS[(c & 0x0f)]; } @@ -97,73 +80,56 @@ return dest; } -std::string percent_encode(const std::string &target) { - return percent_encode(reinterpret_cast(target.c_str()), - target.size()); -} - -std::string percent_encode_path(const std::string &s) { - std::string dest; - for (auto c : s) { - if (in_rfc3986_unreserved_chars(c) || in_rfc3986_sub_delims(c) || - c == '/') { - dest += c; - continue; - } - - dest += '%'; - dest += UPPER_XDIGITS[(c >> 4) & 0x0f]; - dest += UPPER_XDIGITS[(c & 0x0f)]; - } - return dest; +std::string percentEncode(const std::string &target) { + return percentEncode(reinterpret_cast(target.c_str()), + target.size()); } bool in_token(char c) { - static constexpr char extra[] = {'!', '#', '$', '%', '&', '\'', '*', '+', - '-', '.', '^', '_', '`', '|', '~'}; - return is_alpha(c) || is_digit(c) || - std::find(std::begin(extra), std::end(extra), c) != std::end(extra); -} + static const char extra[] = {'!', '#', '$', '%', '&', '\'', '*', '+', + '-', '.', '^', '_', '`', '|', '~'}; -bool in_attr_char(char c) { - static constexpr char bad[] = {'*', '\'', '%'}; - return util::in_token(c) && - std::find(std::begin(bad), std::end(bad), c) == std::end(bad); + return isAlpha(c) || isDigit(c) || + std::find(&extra[0], &extra[sizeof(extra)], c) != + &extra[sizeof(extra)]; } std::string percent_encode_token(const std::string &target) { + auto len = target.size(); std::string dest; - dest.resize(target.size() * 3); - auto p = std::begin(dest); - - for (auto first = std::begin(target); first != std::end(target); ++first) { - uint8_t c = *first; + for (size_t i = 0; i < len; ++i) { + unsigned char c = target[i]; if (c != '%' && in_token(c)) { - *p++ = c; - continue; + dest += c; + } else { + dest += "%"; + dest += UPPER_XDIGITS[c >> 4]; + dest += UPPER_XDIGITS[(c & 0x0f)]; } - - *p++ = '%'; - *p++ = UPPER_XDIGITS[c >> 4]; - *p++ = UPPER_XDIGITS[(c & 0x0f)]; } - dest.resize(p - std::begin(dest)); return dest; } -uint32_t hex_to_uint(char c) { - if (c <= '9') { - return c - '0'; - } - if (c <= 'Z') { - return c - 'A' + 10; - } - if (c <= 'z') { - return c - 'a' + 10; +std::string percentDecode(std::string::const_iterator first, + std::string::const_iterator last) { + std::string result; + for (; first != last; ++first) { + if (*first == '%') { + if (first + 1 != last && first + 2 != last && isHexDigit(*(first + 1)) && + isHexDigit(*(first + 2))) { + std::string numstr(first + 1, first + 3); + result += strtol(numstr.c_str(), 0, 16); + first += 2; + } else { + result += *first; + } + } else { + result += *first; + } } - return c; + return result; } std::string quote_string(const std::string &target) { @@ -221,13 +187,13 @@ auto p = std::begin(res); auto s = DAY_OF_WEEK[tms.tm_wday]; - p = std::copy_n(s, 3, p); + p = std::copy(s, s + 3, p); *p++ = ','; *p++ = ' '; p = cpydig(p, tms.tm_mday, 2); *p++ = ' '; s = MONTH[tms.tm_mon]; - p = std::copy_n(s, 3, p); + p = std::copy(s, s + 3, p); *p++ = ' '; p = cpydig(p, tms.tm_year + 1900, 4); *p++ = ' '; @@ -237,7 +203,7 @@ *p++ = ':'; p = cpydig(p, tms.tm_sec, 2); s = " GMT"; - p = std::copy_n(s, 4, p); + p = std::copy(s, s + 4, p); return res; } @@ -249,6 +215,7 @@ return ""; } +#ifdef HAVE_STRUCT_TM_TM_GMTOFF // Format data like this: // 03/Jul/2014:00:19:38 +0900 std::string res; @@ -259,7 +226,7 @@ p = cpydig(p, tms.tm_mday, 2); *p++ = '/'; auto s = MONTH[tms.tm_mon]; - p = std::copy_n(s, 3, p); + p = std::copy(s, s + 3, p); *p++ = '/'; p = cpydig(p, tms.tm_year + 1900, 4); *p++ = ':'; @@ -270,11 +237,7 @@ p = cpydig(p, tms.tm_sec, 2); *p++ = ' '; -#ifdef HAVE_STRUCT_TM_TM_GMTOFF auto gmtoff = tms.tm_gmtoff; -#else // !HAVE_STRUCT_TM_TM_GMTOFF - auto gmtoff = nghttp2_timegm(&tms) - t; -#endif // !HAVE_STRUCT_TM_TM_GMTOFF if (gmtoff >= 0) { *p++ = '+'; } else { @@ -286,6 +249,13 @@ p = cpydig(p, (gmtoff % 3600) / 60, 2); return res; +#else // !HAVE_STRUCT_TM_TM_GMTOFF + char buf[32]; + + strftime(buf, sizeof(buf), "%d/%b/%Y:%T %z", &tms); + + return buf; +#endif // !HAVE_STRUCT_TM_TM_GMTOFF } std::string iso8601_date(int64_t ms) { @@ -296,6 +266,7 @@ return ""; } +#ifdef HAVE_STRUCT_TM_TM_GMTOFF // Format data like this: // 2014-11-15T12:58:24.741Z // 2014-11-15T12:58:24.741+09:00 @@ -318,11 +289,7 @@ *p++ = '.'; p = cpydig(p, ms % 1000, 3); -#ifdef HAVE_STRUCT_TM_TM_GMTOFF auto gmtoff = tms.tm_gmtoff; -#else // !HAVE_STRUCT_TM_TM_GMTOFF - auto gmtoff = nghttp2_timegm(&tms) - sec; -#endif // !HAVE_STRUCT_TM_TM_GMTOFF if (gmtoff == 0) { *p++ = 'Z'; } else { @@ -340,15 +307,139 @@ res.resize(p - std::begin(res)); return res; +#else // !HAVE_STRUCT_TM_TM_GMTOFF + char buf[128]; + + auto nwrite = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tms); + nwrite += snprintf(&buf[nwrite], sizeof(buf) - nwrite, ".%03d", + static_cast(ms % 1000)); + auto nzone = strftime(&buf[nwrite], sizeof(buf) - nwrite, "%z", &tms); + + // %z of strftime writes +hhmm or -hhmm not Z, +hh:mm or -hh:mm. Do + // %nothing if nzone is not 5. we don't know how to cope with this. + if (nzone == 5) { + if (memcmp(&buf[nwrite], "+0000", 5) == 0) { + // 0000 should be Z + memcpy(&buf[nwrite], "Z", 2); + } else { + // Move mm part to right by 1 including terminal \0 + memmove(&buf[nwrite + 4], &buf[nwrite + 3], 3); + // Insert ':' between hh and mm + buf[nwrite + 3] = ':'; + } + } + return buf; +#endif // !HAVE_STRUCT_TM_TM_GMTOFF } -time_t parse_http_date(const StringRef &s) { - tm tm{}; +time_t parse_http_date(const std::string &s) { + tm tm; + memset(&tm, 0, sizeof(tm)); char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm); if (r == 0) { return 0; } - return nghttp2_timegm_without_yday(&tm); + return timegm(&tm); +} + +bool startsWith(const std::string &a, const std::string &b) { + return startsWith(a.begin(), a.end(), b.begin(), b.end()); +} + +bool istartsWith(const std::string &a, const std::string &b) { + return istartsWith(a.begin(), a.end(), b.begin(), b.end()); +} + +namespace { +void streq_advance(const char **ap, const char **bp) { + for (; **ap && **bp && lowcase(**ap) == lowcase(**bp); ++*ap, ++*bp) + ; +} +} // namespace + +bool istartsWith(const char *a, const char *b) { + if (!a || !b) { + return false; + } + streq_advance(&a, &b); + return !*b; +} + +bool istartsWith(const char *a, size_t n, const char *b) { + return istartsWith(a, a + n, b, b + strlen(b)); +} + +bool endsWith(const std::string &a, const std::string &b) { + return endsWith(a.begin(), a.end(), b.begin(), b.end()); +} + +bool strieq(const std::string &a, const std::string &b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (lowcase(a[i]) != lowcase(b[i])) { + return false; + } + } + return true; +} + +bool strieq(const char *a, const char *b) { + if (!a || !b) { + return false; + } + for (; *a && *b && lowcase(*a) == lowcase(*b); ++a, ++b) + ; + return !*a && !*b; +} + +bool strieq(const char *a, const uint8_t *b, size_t bn) { + if (!a || !b) { + return false; + } + const uint8_t *blast = b + bn; + for (; *a && b != blast && lowcase(*a) == lowcase(*b); ++a, ++b) + ; + return !*a && b == blast; +} + +bool strieq(const char *a, const char *b, size_t bn) { + return strieq(a, reinterpret_cast(b), bn); +} + +int strcompare(const char *a, const uint8_t *b, size_t bn) { + assert(a && b); + const uint8_t *blast = b + bn; + for (; *a && b != blast; ++a, ++b) { + if (*a < *b) { + return -1; + } else if (*a > *b) { + return 1; + } + } + if (!*a && b == blast) { + return 0; + } else if (b == blast) { + return 1; + } else { + return -1; + } +} + +bool strifind(const char *a, const char *b) { + if (!a || !b) { + return false; + } + for (size_t i = 0; a[i]; ++i) { + const char *ap = &a[i], *bp = b; + for (; *ap && *bp && lowcase(*ap) == lowcase(*bp); ++ap, ++bp) + ; + if (!*bp) { + return true; + } + } + return false; } char upcase(char c) { @@ -377,46 +468,56 @@ } void to_token68(std::string &base64str) { - std::transform(std::begin(base64str), std::end(base64str), - std::begin(base64str), [](char c) { - switch (c) { - case '+': - return '-'; - case '/': - return '_'; - default: - return c; - } - }); - base64str.erase(std::find(std::begin(base64str), std::end(base64str), '='), - std::end(base64str)); + for (auto i = std::begin(base64str); i != std::end(base64str); ++i) { + switch (*i) { + case '+': + *i = '-'; + break; + case '/': + *i = '_'; + break; + case '=': + base64str.erase(i, std::end(base64str)); + return; + } + } + return; } void to_base64(std::string &token68str) { - std::transform(std::begin(token68str), std::end(token68str), - std::begin(token68str), [](char c) { - switch (c) { - case '-': - return '+'; - case '_': - return '/'; - default: - return c; - } - }); + for (auto i = std::begin(token68str); i != std::end(token68str); ++i) { + switch (*i) { + case '-': + *i = '+'; + break; + case '_': + *i = '/'; + break; + } + } if (token68str.size() & 0x3) { token68str.append(4 - (token68str.size() & 0x3), '='); } return; } +void inp_strlower(std::string &s) { + for (auto i = std::begin(s); i != std::end(s); ++i) { + if ('A' <= *i && *i <= 'Z') { + *i = (*i) - 'A' + 'a'; + } + } +} + namespace { // Calculates Damerau–Levenshtein distance between c-string a and b // with given costs. swapcost, subcost, addcost and delcost are cost // to swap 2 adjacent characters, substitute characters, add character // and delete character respectively. -int levenshtein(const char *a, int alen, const char *b, int blen, int swapcost, - int subcost, int addcost, int delcost) { +int levenshtein(const char *a, const char *b, int swapcost, int subcost, + int addcost, int delcost) { + int alen = strlen(a); + int blen = strlen(b); auto dp = std::vector>(3, std::vector(blen + 1)); for (int i = 0; i <= blen; ++i) { dp[1][i] = i; @@ -444,21 +545,15 @@ if (*unkopt == '\0') { return; } - auto unkoptend = unkopt; - for (; *unkoptend && *unkoptend != '='; ++unkoptend) - ; - auto unkoptlen = unkoptend - unkopt; - if (unkoptlen == 0) { - return; - } int prefix_match = 0; + auto unkoptlen = strlen(unkopt); auto cands = std::vector>(); for (size_t i = 0; options[i].name != nullptr; ++i) { auto optnamelen = strlen(options[i].name); // Use cost 0 for prefix match - if (istarts_with(options[i].name, options[i].name + optnamelen, unkopt, - unkopt + unkoptlen)) { - if (optnamelen == static_cast(unkoptlen)) { + if (istartsWith(options[i].name, options[i].name + optnamelen, unkopt, + unkopt + unkoptlen)) { + if (optnamelen == unkoptlen) { // Exact match, then we don't show any condidates. return; } @@ -468,14 +563,13 @@ } // Use cost 0 for suffix match, but match at least 3 characters if (unkoptlen >= 3 && - iends_with(options[i].name, options[i].name + optnamelen, unkopt, - unkopt + unkoptlen)) { + iendsWith(options[i].name, options[i].name + optnamelen, unkopt, + unkopt + unkoptlen)) { cands.emplace_back(0, options[i].name); continue; } // cost values are borrowed from git, help.c. - int sim = - levenshtein(unkopt, unkoptlen, options[i].name, optnamelen, 0, 2, 1, 3); + int sim = levenshtein(unkopt, options[i].name, 0, 2, 1, 3); cands.emplace_back(sim, options[i].name); } if (prefix_match == 1 || cands.empty()) { @@ -536,13 +630,13 @@ return i == len && !t[i]; } -StringRef get_uri_field(const char *uri, const http_parser_url &u, - http_parser_url_fields field) { - if (!util::has_uri_field(u, field)) { - return StringRef{}; +std::string get_uri_field(const char *uri, const http_parser_url &u, + http_parser_url_fields field) { + if (util::has_uri_field(u, field)) { + return std::string(uri + u.field_data[field].off, u.field_data[field].len); + } else { + return ""; } - - return StringRef{uri + u.field_data[field].off, u.field_data[field].len}; } uint16_t get_default_port(const char *uri, const http_parser_url &u) { @@ -573,97 +667,34 @@ } bool numeric_host(const char *hostname) { - return numeric_host(hostname, AF_INET) || numeric_host(hostname, AF_INET6); -} - -bool numeric_host(const char *hostname, int family) { - int rv; - std::array dst; - - rv = inet_pton(family, hostname, dst.data()); - - return rv == 1; -} - -std::string numeric_name(const struct sockaddr *sa, socklen_t salen) { - std::array host; - auto rv = getnameinfo(sa, salen, host.data(), host.size(), nullptr, 0, - NI_NUMERICHOST); - if (rv != 0) { - return "unknown"; + struct addrinfo hints; + struct addrinfo *res; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(hostname, nullptr, &hints, &res)) { + return false; } - return host.data(); + freeaddrinfo(res); + return true; } -std::string to_numeric_addr(const Address *addr) { - auto family = addr->su.storage.ss_family; - if (family == AF_UNIX) { - return addr->su.un.sun_path; - } - - std::array host; - std::array serv; - auto rv = - getnameinfo(&addr->su.sa, addr->len, host.data(), host.size(), - serv.data(), serv.size(), NI_NUMERICHOST | NI_NUMERICSERV); - if (rv != 0) { - return "unknown"; - } +int reopen_log_file(const char *path) { +#if defined(__ANDROID__) || defined(ANDROID) + int fd; - auto hostlen = strlen(host.data()); - auto servlen = strlen(serv.data()); + if (strcmp("/proc/self/fd/1", path) == 0 || + strcmp("/proc/self/fd/2", path) == 0) { - std::string s; - char *p; - if (family == AF_INET6) { - s.resize(hostlen + servlen + 2 + 1); - p = &s[0]; - *p++ = '['; - p = std::copy_n(host.data(), hostlen, p); - *p++ = ']'; + // We will get permission denied error when O_APPEND is used for + // these paths. + fd = + open(path, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP); } else { - s.resize(hostlen + servlen + 1); - p = &s[0]; - p = std::copy_n(host.data(), hostlen, p); - } - *p++ = ':'; - std::copy_n(serv.data(), servlen, p); - - return s; -} - -static int STDERR_COPY = -1; -static int STDOUT_COPY = -1; - -void store_original_fds() { - // consider dup'ing stdout too - STDERR_COPY = dup(STDERR_FILENO); - STDOUT_COPY = STDOUT_FILENO; - // no race here, since it is called early - make_socket_closeonexec(STDERR_COPY); -} - -void restore_original_fds() { dup2(STDERR_COPY, STDERR_FILENO); } - -void close_log_file(int &fd) { - if (fd != STDERR_COPY && fd != STDOUT_COPY && fd != -1) { - close(fd); - } - fd = -1; -} - -int open_log_file(const char *path) { - - if (strcmp(path, "/dev/stdout") == 0 || - strcmp(path, "/proc/self/fd/1") == 0) { - return STDOUT_COPY; + fd = open(path, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, + S_IRUSR | S_IWUSR | S_IRGRP); } - - if (strcmp(path, "/dev/stderr") == 0 || - strcmp(path, "/proc/self/fd/2") == 0) { - return STDERR_COPY; - } -#if defined O_CLOEXEC +#elif defined O_CLOEXEC auto fd = open(path, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP); @@ -674,7 +705,7 @@ // We get race condition if execve is called at the same time. if (fd != -1) { - make_socket_closeonexec(fd); + fcntl(fd, F_SETFD, FD_CLOEXEC); } #endif // !O_CLOEXEC @@ -695,7 +726,7 @@ if (c >= 0x20 && c < 0x7f) { res += c; } else { - res += '.'; + res += "."; } } @@ -714,16 +745,10 @@ if (argv0[0] == '/') { path = static_cast(malloc(len + 1)); - if (path == nullptr) { - return nullptr; - } memcpy(path, argv0, len + 1); } else { auto cwdlen = strlen(cwd); path = static_cast(malloc(len + 1 + cwdlen + 1)); - if (path == nullptr) { - return nullptr; - } memcpy(path, cwd, cwdlen); path[cwdlen] = '/'; memcpy(path + cwdlen + 1, argv0, len + 1); @@ -738,649 +763,28 @@ path.find('\\') == std::string::npos && path.find("/../") == std::string::npos && path.find("/./") == std::string::npos && - !util::ends_with_l(path, "/..") && !util::ends_with_l(path, "/."); + !util::endsWith(path, "/..") && !util::endsWith(path, "/."); } int64_t to_time64(const timeval &tv) { return tv.tv_sec * 1000000 + tv.tv_usec; } -bool check_h2_is_selected(const StringRef &proto) { - return streq(NGHTTP2_H2, proto) || streq(NGHTTP2_H2_16, proto) || - streq(NGHTTP2_H2_14, proto); -} - -namespace { -bool select_proto(const unsigned char **out, unsigned char *outlen, - const unsigned char *in, unsigned int inlen, - const StringRef &key) { - for (auto p = in, end = in + inlen; p + key.size() <= end; p += *p + 1) { - if (std::equal(std::begin(key), std::end(key), p)) { - *out = p + 1; - *outlen = *p; - return true; - } - } - return false; -} -} // namespace - -bool select_h2(const unsigned char **out, unsigned char *outlen, - const unsigned char *in, unsigned int inlen) { - return select_proto(out, outlen, in, inlen, NGHTTP2_H2_ALPN) || - select_proto(out, outlen, in, inlen, NGHTTP2_H2_16_ALPN) || - select_proto(out, outlen, in, inlen, NGHTTP2_H2_14_ALPN); -} - -bool select_protocol(const unsigned char **out, unsigned char *outlen, - const unsigned char *in, unsigned int inlen, - std::vector proto_list) { - for (const auto &proto : proto_list) { - if (select_proto(out, outlen, in, inlen, StringRef{proto})) { - return true; - } - } - - return false; +bool check_h2_is_selected(const unsigned char *proto, size_t len) { + return streq(NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN, proto, + len); } std::vector get_default_alpn() { - auto res = std::vector(NGHTTP2_H2_ALPN.size() + - NGHTTP2_H2_16_ALPN.size() + - NGHTTP2_H2_14_ALPN.size()); - auto p = std::begin(res); - - p = std::copy_n(std::begin(NGHTTP2_H2_ALPN), NGHTTP2_H2_ALPN.size(), p); - p = std::copy_n(std::begin(NGHTTP2_H2_16_ALPN), NGHTTP2_H2_16_ALPN.size(), p); - p = std::copy_n(std::begin(NGHTTP2_H2_14_ALPN), NGHTTP2_H2_14_ALPN.size(), p); - - return res; -} - -std::vector split_str(const StringRef &s, char delim) { - size_t len = 1; - auto last = std::end(s); - StringRef::const_iterator d; - for (auto first = std::begin(s); (d = std::find(first, last, delim)) != last; - ++len, first = d + 1) - ; - - auto list = std::vector(len); - - len = 0; - for (auto first = std::begin(s);; ++len) { - auto stop = std::find(first, last, delim); - list[len] = StringRef{first, stop}; - if (stop == last) { - break; - } - first = stop + 1; - } - return list; -} - -std::vector parse_config_str_list(const StringRef &s, char delim) { - auto sublist = split_str(s, delim); - auto res = std::vector(); - res.reserve(sublist.size()); - for (const auto &s : sublist) { - res.emplace_back(std::begin(s), std::end(s)); - } - return res; -} - -int make_socket_closeonexec(int fd) { - int flags; - int rv; - while ((flags = fcntl(fd, F_GETFD)) == -1 && errno == EINTR) - ; - while ((rv = fcntl(fd, F_SETFD, flags | FD_CLOEXEC)) == -1 && errno == EINTR) - ; - return rv; -} - -int make_socket_nonblocking(int fd) { - int flags; - int rv; - while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR) - ; - while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR) - ; - return rv; -} - -int make_socket_nodelay(int fd) { - int val = 1; - if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&val), - sizeof(val)) == -1) { - return -1; - } - return 0; -} - -int create_nonblock_socket(int family) { -#ifdef SOCK_NONBLOCK - auto fd = socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); - - if (fd == -1) { - return -1; - } -#else // !SOCK_NONBLOCK - auto fd = socket(family, SOCK_STREAM, 0); - - if (fd == -1) { - return -1; - } - - make_socket_nonblocking(fd); - make_socket_closeonexec(fd); -#endif // !SOCK_NONBLOCK - - if (family == AF_INET || family == AF_INET6) { - make_socket_nodelay(fd); - } - - return fd; -} - -bool check_socket_connected(int fd) { - int error; - socklen_t len = sizeof(error); - if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) { - return false; - } - - return error == 0; -} - -bool ipv6_numeric_addr(const char *host) { - uint8_t dst[16]; - return inet_pton(AF_INET6, host, dst) == 1; -} - -namespace { -std::pair parse_uint_digits(const void *ss, size_t len) { - const uint8_t *s = static_cast(ss); - int64_t n = 0; - size_t i; - if (len == 0) { - return {-1, 0}; - } - constexpr int64_t max = std::numeric_limits::max(); - for (i = 0; i < len; ++i) { - if ('0' <= s[i] && s[i] <= '9') { - if (n > max / 10) { - return {-1, 0}; - } - n *= 10; - if (n > max - (s[i] - '0')) { - return {-1, 0}; - } - n += s[i] - '0'; - continue; - } - break; - } - if (i == 0) { - return {-1, 0}; - } - return {n, i}; -} -} // namespace - -int64_t parse_uint_with_unit(const char *s) { - return parse_uint_with_unit(reinterpret_cast(s), strlen(s)); -} - -int64_t parse_uint_with_unit(const StringRef &s) { - return parse_uint_with_unit(s.byte(), s.size()); -} - -int64_t parse_uint_with_unit(const uint8_t *s, size_t len) { - int64_t n; - size_t i; - std::tie(n, i) = parse_uint_digits(s, len); - if (n == -1) { - return -1; - } - if (i == len) { - return n; - } - if (i + 1 != len) { - return -1; - } - int mul = 1; - switch (s[i]) { - case 'K': - case 'k': - mul = 1 << 10; - break; - case 'M': - case 'm': - mul = 1 << 20; - break; - case 'G': - case 'g': - mul = 1 << 30; - break; - default: - return -1; - } - constexpr int64_t max = std::numeric_limits::max(); - if (n > max / mul) { - return -1; - } - return n * mul; -} - -int64_t parse_uint(const char *s) { - return parse_uint(reinterpret_cast(s), strlen(s)); -} - -int64_t parse_uint(const std::string &s) { - return parse_uint(reinterpret_cast(s.c_str()), s.size()); -} - -int64_t parse_uint(const StringRef &s) { - return parse_uint(s.byte(), s.size()); -} - -int64_t parse_uint(const uint8_t *s, size_t len) { - int64_t n; - size_t i; - std::tie(n, i) = parse_uint_digits(s, len); - if (n == -1 || i != len) { - return -1; - } - return n; -} - -double parse_duration_with_unit(const char *s) { - return parse_duration_with_unit(reinterpret_cast(s), - strlen(s)); -} - -double parse_duration_with_unit(const StringRef &s) { - return parse_duration_with_unit(s.byte(), s.size()); -} - -double parse_duration_with_unit(const uint8_t *s, size_t len) { - constexpr auto max = std::numeric_limits::max(); - int64_t n; - size_t i; - - std::tie(n, i) = parse_uint_digits(s, len); - if (n == -1) { - goto fail; - } - if (i == len) { - return static_cast(n); - } - switch (s[i]) { - case 'S': - case 's': - // seconds - if (i + 1 != len) { - goto fail; - } - return static_cast(n); - case 'M': - case 'm': - if (i + 1 == len) { - // minutes - if (n > max / 60) { - goto fail; - } - return static_cast(n) * 60; - } - - if (i + 2 != len || (s[i + 1] != 's' && s[i + 1] != 'S')) { - goto fail; - } - // milliseconds - return static_cast(n) / 1000.; - case 'H': - case 'h': - // hours - if (i + 1 != len) { - goto fail; - } - if (n > max / 3600) { - goto fail; - } - return static_cast(n) * 3600; - } -fail: - return std::numeric_limits::infinity(); -} - -std::string duration_str(double t) { - if (t == 0.) { - return "0"; - } - auto frac = static_cast(t * 1000) % 1000; - if (frac > 0) { - return utos(static_cast(t * 1000)) + "ms"; - } - auto v = static_cast(t); - if (v % 60) { - return utos(v) + "s"; - } - v /= 60; - if (v % 60) { - return utos(v) + "m"; - } - v /= 60; - return utos(v) + "h"; -} - -std::string format_duration(const std::chrono::microseconds &u) { - const char *unit = "us"; - int d = 0; - auto t = u.count(); - if (t >= 1000000) { - d = 1000000; - unit = "s"; - } else if (t >= 1000) { - d = 1000; - unit = "ms"; - } else { - return utos(t) + unit; - } - return dtos(static_cast(t) / d) + unit; -} - -std::string format_duration(double t) { - const char *unit = "us"; - if (t >= 1.) { - unit = "s"; - } else if (t >= 0.001) { - t *= 1000.; - unit = "ms"; - } else { - t *= 1000000.; - return utos(static_cast(t)) + unit; - } - return dtos(t) + unit; -} + auto res = std::vector(1 + NGHTTP2_PROTO_VERSION_ID_LEN); + auto p = res.data(); -std::string dtos(double n) { - auto f = utos(static_cast(round(100. * n)) % 100); - return utos(static_cast(n)) + "." + (f.size() == 1 ? "0" : "") + f; -} - -std::string make_http_hostport(const StringRef &host, uint16_t port) { - if (port != 80 && port != 443) { - return make_hostport(host, port); - } - - auto ipv6 = ipv6_numeric_addr(host.c_str()); - - std::string hostport; - hostport.resize(host.size() + (ipv6 ? 2 : 0)); - - auto p = &hostport[0]; + *p++ = NGHTTP2_PROTO_VERSION_ID_LEN; + memcpy(p, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN); - if (ipv6) { - *p++ = '['; - } - - p = std::copy_n(host.c_str(), host.size(), p); - - if (ipv6) { - *p++ = ']'; - } - - return hostport; -} - -std::string make_hostport(const StringRef &host, uint16_t port) { - auto ipv6 = ipv6_numeric_addr(host.c_str()); - auto serv = utos(port); - - std::string hostport; - hostport.resize(host.size() + (ipv6 ? 2 : 0) + 1 + serv.size()); - - auto p = &hostport[0]; - - if (ipv6) { - *p++ = '['; - } - - p = std::copy_n(host.c_str(), host.size(), p); - - if (ipv6) { - *p++ = ']'; - } - - *p++ = ':'; - std::copy_n(serv.c_str(), serv.size(), p); - - return hostport; -} - -namespace { -void hexdump8(FILE *out, const uint8_t *first, const uint8_t *last) { - auto stop = std::min(first + 8, last); - for (auto k = first; k != stop; ++k) { - fprintf(out, "%02x ", *k); - } - // each byte needs 3 spaces (2 hex value and space) - for (; stop != first + 8; ++stop) { - fputs(" ", out); - } - // we have extra space after 8 bytes - fputc(' ', out); -} -} // namespace - -void hexdump(FILE *out, const uint8_t *src, size_t len) { - if (len == 0) { - return; - } - size_t buflen = 0; - auto repeated = false; - std::array buf{}; - auto end = src + len; - auto i = src; - for (;;) { - auto nextlen = - std::min(static_cast(16), static_cast(end - i)); - if (nextlen == buflen && - std::equal(std::begin(buf), std::begin(buf) + buflen, i)) { - // as long as adjacent 16 bytes block are the same, we just - // print single '*'. - if (!repeated) { - repeated = true; - fputs("*\n", out); - } - i += nextlen; - continue; - } - repeated = false; - fprintf(out, "%08lx", static_cast(i - src)); - if (i == end) { - fputc('\n', out); - break; - } - fputs(" ", out); - hexdump8(out, i, end); - hexdump8(out, i + 8, std::max(i + 8, end)); - fputc('|', out); - auto stop = std::min(i + 16, end); - buflen = stop - i; - auto p = buf.data(); - for (; i != stop; ++i) { - *p++ = *i; - if (0x20 <= *i && *i <= 0x7e) { - fputc(*i, out); - } else { - fputc('.', out); - } - } - fputs("|\n", out); - } -} - -void put_uint16be(uint8_t *buf, uint16_t n) { - uint16_t x = htons(n); - memcpy(buf, &x, sizeof(uint16_t)); -} - -void put_uint32be(uint8_t *buf, uint32_t n) { - uint32_t x = htonl(n); - memcpy(buf, &x, sizeof(uint32_t)); -} - -uint16_t get_uint16(const uint8_t *data) { - uint16_t n; - memcpy(&n, data, sizeof(uint16_t)); - return ntohs(n); -} - -uint32_t get_uint32(const uint8_t *data) { - uint32_t n; - memcpy(&n, data, sizeof(uint32_t)); - return ntohl(n); -} - -uint64_t get_uint64(const uint8_t *data) { - uint64_t n = 0; - n += static_cast(data[0]) << 56; - n += static_cast(data[1]) << 48; - n += static_cast(data[2]) << 40; - n += static_cast(data[3]) << 32; - n += static_cast(data[4]) << 24; - n += data[5] << 16; - n += data[6] << 8; - n += data[7]; - return n; -} - -int read_mime_types(std::map &res, - const char *filename) { - std::ifstream infile(filename); - if (!infile) { - return -1; - } - - auto delim_pred = [](char c) { return c == ' ' || c == '\t'; }; - - std::string line; - while (std::getline(infile, line)) { - if (line.empty() || line[0] == '#') { - continue; - } - - auto type_end = std::find_if(std::begin(line), std::end(line), delim_pred); - if (type_end == std::begin(line)) { - continue; - } - - auto ext_end = type_end; - for (;;) { - auto ext_start = std::find_if_not(ext_end, std::end(line), delim_pred); - if (ext_start == std::end(line)) { - break; - } - ext_end = std::find_if(ext_start, std::end(line), delim_pred); -#ifdef HAVE_STD_MAP_EMPLACE - res.emplace(std::string(ext_start, ext_end), - std::string(std::begin(line), type_end)); -#else // !HAVE_STD_MAP_EMPLACE - res.insert(std::make_pair(std::string(ext_start, ext_end), - std::string(std::begin(line), type_end))); -#endif // !HAVE_STD_MAP_EMPLACE - } - } - - return 0; -} - -StringRef percent_decode(BlockAllocator &balloc, const StringRef &src) { - auto iov = make_byte_ref(balloc, src.size() * 3 + 1); - auto p = iov.base; - for (auto first = std::begin(src); first != std::end(src); ++first) { - if (*first != '%') { - *p++ = *first; - continue; - } - - if (first + 1 != std::end(src) && first + 2 != std::end(src) && - is_hex_digit(*(first + 1)) && is_hex_digit(*(first + 2))) { - *p++ = (hex_to_uint(*(first + 1)) << 4) + hex_to_uint(*(first + 2)); - first += 2; - continue; - } - - *p++ = *first; - } - *p = '\0'; - return StringRef{iov.base, p}; -} - -// Returns x**y -double int_pow(double x, size_t y) { - auto res = 1.; - for (; y; --y) { - res *= x; - } return res; } -uint32_t hash32(const StringRef &s) { - /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */ - uint32_t h = 2166136261u; - size_t i; - - for (i = 0; i < s.size(); ++i) { - h ^= s[i]; - h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24); - } - - return h; -} - -#if !OPENSSL_101_API -namespace { -EVP_MD_CTX *EVP_MD_CTX_new(void) { return EVP_MD_CTX_create(); } -} // namespace - -namespace { -void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { EVP_MD_CTX_destroy(ctx); } -} // namespace -#endif - -int sha256(uint8_t *res, const StringRef &s) { - int rv; - - auto ctx = EVP_MD_CTX_new(); - if (ctx == nullptr) { - return -1; - } - - auto ctx_deleter = defer(EVP_MD_CTX_free, ctx); - - rv = EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr); - if (rv != 1) { - return -1; - } - - rv = EVP_DigestUpdate(ctx, s.c_str(), s.size()); - if (rv != 1) { - return -1; - } - - unsigned int mdlen = 32; - - rv = EVP_DigestFinal_ex(ctx, res, &mdlen); - if (rv != 1) { - return -1; - } - - return 0; -} - } // namespace util } // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/util.h nghttp2-0.6.7/src/util.h --- nghttp2-1.13.0/src/util.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/util.h 2014-11-30 14:15:07.000000000 +0000 @@ -27,15 +27,9 @@ #include "nghttp2_config.h" -#ifdef HAVE_UNISTD_H #include -#endif // HAVE_UNISTD_H #include -#ifdef HAVE_NETDB_H -#include -#endif // HAVE_NETDB_H -#include #include #include #include @@ -44,89 +38,145 @@ #include #include #include -#include -#include #include "http-parser/http_parser.h" -#include "template.h" -#include "network.h" -#include "allocator.h" - namespace nghttp2 { -constexpr auto NGHTTP2_H2_ALPN = StringRef::from_lit("\x2h2"); -constexpr auto NGHTTP2_H2 = StringRef::from_lit("h2"); +namespace util { -// The additional HTTP/2 protocol ALPN protocol identifier we also -// supports for our applications to make smooth migration into final -// h2 ALPN ID. -constexpr auto NGHTTP2_H2_16_ALPN = StringRef::from_lit("\x5h2-16"); -constexpr auto NGHTTP2_H2_16 = StringRef::from_lit("h2-16"); +template constexpr size_t array_size(T (&)[N]) { + return N; +} -constexpr auto NGHTTP2_H2_14_ALPN = StringRef::from_lit("\x5h2-14"); -constexpr auto NGHTTP2_H2_14 = StringRef::from_lit("h2-14"); +template struct Defer { + Defer(T t, F f) : t(t), f(std::move(f)) {} -constexpr auto NGHTTP2_H1_1_ALPN = StringRef::from_lit("\x8http/1.1"); -constexpr auto NGHTTP2_H1_1 = StringRef::from_lit("http/1.1"); + ~Defer() { f(t); } -namespace util { + T t; + F f; +}; -inline bool is_alpha(const char c) { - return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'); +template Defer defer(T &&t, F f) { + return Defer(std::forward(t), std::forward(f)); } -inline bool is_digit(const char c) { return '0' <= c && c <= '9'; } +extern const char DEFAULT_STRIP_CHARSET[]; -inline bool is_hex_digit(const char c) { - return is_digit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); +template +std::pair +stripIter(InputIterator first, InputIterator last, + const char *chars = DEFAULT_STRIP_CHARSET) { + for (; first != last && strchr(chars, *first) != 0; ++first) + ; + if (first == last) { + return std::make_pair(first, last); + } + InputIterator left = last - 1; + for (; left != first && strchr(chars, *left) != 0; --left) + ; + return std::make_pair(first, left + 1); } -bool in_rfc3986_unreserved_chars(const char c); +template +OutputIterator splitIter(InputIterator first, InputIterator last, + OutputIterator out, char delim, bool doStrip = false, + bool allowEmpty = false) { + for (InputIterator i = first; i != last;) { + InputIterator j = std::find(i, last, delim); + std::pair p(i, j); + if (doStrip) { + p = stripIter(i, j); + } + if (allowEmpty || p.first != p.second) { + *out++ = p; + } + i = j; + if (j != last) { + ++i; + } + } + if (allowEmpty && (first == last || *(last - 1) == delim)) { + *out++ = std::make_pair(last, last); + } + return out; +} -bool in_rfc3986_sub_delims(const char c); +template +OutputIterator split(InputIterator first, InputIterator last, + OutputIterator out, char delim, bool doStrip = false, + bool allowEmpty = false) { + for (InputIterator i = first; i != last;) { + InputIterator j = std::find(i, last, delim); + std::pair p(i, j); + if (doStrip) { + p = stripIter(i, j); + } + if (allowEmpty || p.first != p.second) { + *out++ = std::string(p.first, p.second); + } + i = j; + if (j != last) { + ++i; + } + } + if (allowEmpty && (first == last || *(last - 1) == delim)) { + *out++ = std::string(last, last); + } + return out; +} -// Returns true if |c| is in token (HTTP-p1, Section 3.2.6) -bool in_token(char c); +template +std::string strjoin(InputIterator first, InputIterator last, + const DelimiterType &delim) { + std::string result; + if (first == last) { + return result; + } + InputIterator beforeLast = last - 1; + for (; first != beforeLast; ++first) { + result += *first; + result += delim; + } + result += *beforeLast; + return result; +} -bool in_attr_char(char c); +template +std::string joinPath(InputIterator first, InputIterator last) { + std::vector elements; + for (; first != last; ++first) { + if (*first == "..") { + if (!elements.empty()) { + elements.pop_back(); + } + } else if (*first == ".") { + // do nothing + } else { + elements.push_back(*first); + } + } + return strjoin(elements.begin(), elements.end(), "/"); +} -// Returns integer corresponding to hex notation |c|. It is undefined -// if is_hex_digit(c) is false. -uint32_t hex_to_uint(char c); +bool isAlpha(const char c); -std::string percent_encode(const unsigned char *target, size_t len); +bool isDigit(const char c); -std::string percent_encode(const std::string &target); +bool isHexDigit(const char c); -// percent-encode path component of URI |s|. -std::string percent_encode_path(const std::string &s); +bool inRFC3986UnreservedChars(const char c); -template -std::string percent_decode(InputIt first, InputIt last) { - std::string result; - result.resize(last - first); - auto p = std::begin(result); - for (; first != last; ++first) { - if (*first != '%') { - *p++ = *first; - continue; - } +// Returns true if |c| is in token (HTTP-p1, Section 3.2.6) +bool in_token(char c); - if (first + 1 != last && first + 2 != last && is_hex_digit(*(first + 1)) && - is_hex_digit(*(first + 2))) { - *p++ = (hex_to_uint(*(first + 1)) << 4) + hex_to_uint(*(first + 2)); - first += 2; - continue; - } +std::string percentEncode(const unsigned char *target, size_t len); - *p++ = *first; - } - result.resize(p - std::begin(result)); - return result; -} +std::string percentEncode(const std::string &target); -StringRef percent_decode(BlockAllocator &balloc, const StringRef &src); +std::string percentDecode(std::string::const_iterator first, + std::string::const_iterator last); // Percent encode |target| if character is not in token or '%'. std::string percent_encode_token(const std::string &target); @@ -137,14 +187,6 @@ std::string format_hex(const unsigned char *s, size_t len); -template std::string format_hex(const unsigned char(&s)[N]) { - return format_hex(s, N); -} - -template std::string format_hex(const std::array &s) { - return format_hex(s.data(), s.size()); -} - std::string http_date(time_t t); // Returns given time |t| from epoch in Common Log format (e.g., @@ -155,170 +197,125 @@ // 2014-11-15T12:58:24.741Z) std::string iso8601_date(int64_t ms); -time_t parse_http_date(const StringRef &s); - -char upcase(char c); - -inline char lowcase(char c) { - static unsigned char tbl[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', - 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', - 'z', 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, - }; - return tbl[static_cast(c)]; -} +time_t parse_http_date(const std::string &s); template -bool starts_with(InputIterator1 first1, InputIterator1 last1, - InputIterator2 first2, InputIterator2 last2) { +bool startsWith(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) { if (last1 - first1 < last2 - first2) { return false; } return std::equal(first2, last2, first1); } -template bool starts_with(const S &a, const T &b) { - return starts_with(a.begin(), a.end(), b.begin(), b.end()); -} +bool startsWith(const std::string &a, const std::string &b); struct CaseCmp { bool operator()(char lhs, char rhs) const { - return lowcase(lhs) == lowcase(rhs); + if ('A' <= lhs && lhs <= 'Z') { + lhs += 'a' - 'A'; + } + if ('A' <= rhs && rhs <= 'Z') { + rhs += 'a' - 'A'; + } + return lhs == rhs; } }; template -bool istarts_with(InputIterator1 first1, InputIterator1 last1, - InputIterator2 first2, InputIterator2 last2) { +bool istartsWith(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) { if (last1 - first1 < last2 - first2) { return false; } return std::equal(first2, last2, first1, CaseCmp()); } -template bool istarts_with(const S &a, const T &b) { - return istarts_with(a.begin(), a.end(), b.begin(), b.end()); -} - -template -bool istarts_with_l(const T &a, const CharT(&b)[N]) { - return istarts_with(a.begin(), a.end(), b, b + N - 1); -} +bool istartsWith(const std::string &a, const std::string &b); +bool istartsWith(const char *a, const char *b); +bool istartsWith(const char *a, size_t n, const char *b); template -bool ends_with(InputIterator1 first1, InputIterator1 last1, - InputIterator2 first2, InputIterator2 last2) { +bool endsWith(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) { if (last1 - first1 < last2 - first2) { return false; } return std::equal(first2, last2, last1 - (last2 - first2)); } -template bool ends_with(const T &a, const S &b) { - return ends_with(a.begin(), a.end(), b.begin(), b.end()); -} - -template -bool ends_with_l(const T &a, const CharT(&b)[N]) { - return ends_with(a.begin(), a.end(), b, b + N - 1); -} - template -bool iends_with(InputIterator1 first1, InputIterator1 last1, - InputIterator2 first2, InputIterator2 last2) { +bool iendsWith(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) { if (last1 - first1 < last2 - first2) { return false; } return std::equal(first2, last2, last1 - (last2 - first2), CaseCmp()); } -template bool iends_with(const T &a, const S &b) { - return iends_with(a.begin(), a.end(), b.begin(), b.end()); -} +bool endsWith(const std::string &a, const std::string &b); -template -bool iends_with_l(const T &a, const CharT(&b)[N]) { - return iends_with(a.begin(), a.end(), b, b + N - 1); -} +int strcompare(const char *a, const uint8_t *b, size_t n); -template -bool strieq(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) { - if (std::distance(first1, last1) != std::distance(first2, last2)) { - return false; - } +bool strieq(const std::string &a, const std::string &b); - return std::equal(first1, last1, first2, CaseCmp()); -} +bool strieq(const char *a, const char *b); -template bool strieq(const T &a, const S &b) { - return strieq(a.begin(), a.end(), b.begin(), b.end()); -} +bool strieq(const char *a, const uint8_t *b, size_t n); -template -bool strieq_l(const CharT(&a)[N], InputIt b, size_t blen) { - return strieq(a, a + (N - 1), b, b + blen); -} +bool strieq(const char *a, const char *b, size_t n); -template -bool strieq_l(const CharT(&a)[N], const T &b) { - return strieq(a, a + (N - 1), b.begin(), b.end()); -} - -template -bool streq(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) { - if (std::distance(first1, last1) != std::distance(first2, last2)) { +template +bool streq(const A *a, const B *b, size_t bn) { + if (!a || !b) { return false; } - return std::equal(first1, last1, first2); + auto blast = b + bn; + for (; *a && b != blast && *a == *b; ++a, ++b) + ; + return !*a && b == blast; } -template bool streq(const T &a, const S &b) { - return streq(a.begin(), a.end(), b.begin(), b.end()); +template +bool streq(const A *a, size_t alen, const B *b, size_t blen) { + if (alen != blen) { + return false; + } + return memcmp(a, b, alen) == 0; } -template -bool streq_l(const CharT(&a)[N], InputIt b, size_t blen) { - return streq(a, a + (N - 1), b, b + blen); -} +bool strifind(const char *a, const char *b); -template -bool streq_l(const CharT(&a)[N], const T &b) { - return streq(a, a + (N - 1), b.begin(), b.end()); -} +char upcase(char c); -// Returns true if |a| contains |b|. If both |a| and |b| are empty, -// this function returns false. -template bool strifind(const S &a, const T &b) { - return std::search(a.begin(), a.end(), b.begin(), b.end(), CaseCmp()) != - a.end(); -} +char lowcase(char c); -template void inp_strlower(InputIt first, InputIt last) { - std::transform(first, last, first, lowcase); +inline char lowcase(char c) { + static unsigned char tbl[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z', 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255, + }; + return tbl[static_cast(c)]; } // Lowercase |s| in place. -inline void inp_strlower(std::string &s) { - inp_strlower(std::begin(s), std::end(s)); -} - -// Returns string representation of |n| with 2 fractional digits. -std::string dtos(double n); +void inp_strlower(std::string &s); template std::string utos(T n) { std::string res; @@ -338,71 +335,6 @@ return res; } -template OutputIt utos(OutputIt dst, T n) { - if (n == 0) { - *dst++ = '0'; - return dst; - } - int i = 0; - T t = n; - for (; t; t /= 10, ++i) - ; - --i; - auto p = dst + i; - auto res = p + 1; - for (; n; --i, n /= 10) { - *p-- = (n % 10) + '0'; - } - return res; -} - -template -StringRef make_string_ref_uint(BlockAllocator &balloc, T n) { - auto iov = make_byte_ref(balloc, str_size("18446744073709551615") + 1); - auto p = iov.base; - p = util::utos(p, n); - *p = '\0'; - return StringRef{iov.base, p}; -} - -template std::string utos_unit(T n) { - char u = 0; - if (n >= (1 << 30)) { - u = 'G'; - n /= (1 << 30); - } else if (n >= (1 << 20)) { - u = 'M'; - n /= (1 << 20); - } else if (n >= (1 << 10)) { - u = 'K'; - n /= (1 << 10); - } - if (u == 0) { - return utos(n); - } - return utos(n) + u; -} - -// Like utos_unit(), but 2 digits fraction part is followed. -template std::string utos_funit(T n) { - char u = 0; - int b = 0; - if (n >= (1 << 30)) { - u = 'G'; - b = 30; - } else if (n >= (1 << 20)) { - u = 'M'; - b = 20; - } else if (n >= (1 << 10)) { - u = 'K'; - b = 10; - } - if (b == 0) { - return utos(n); - } - return dtos(static_cast(n) / (1 << b)) + u; -} - extern const char UPPER_XDIGITS[]; template std::string utox(T n) { @@ -423,6 +355,18 @@ return res; } +template +typename std::enable_if::value, std::unique_ptr>::type +make_unique(U &&... u) { + return std::unique_ptr(new T(std::forward(u)...)); +} + +template +typename std::enable_if::value, std::unique_ptr>::type +make_unique(size_t size) { + return std::unique_ptr(new typename std::remove_extent::type[size]()); +} + void to_token68(std::string &base64str); void to_base64(std::string &token68str); @@ -436,8 +380,8 @@ bool fieldeq(const char *uri, const http_parser_url &u, http_parser_url_fields field, const char *t); -StringRef get_uri_field(const char *uri, const http_parser_url &u, - http_parser_url_fields field); +std::string get_uri_field(const char *uri, const http_parser_url &u, + http_parser_url_fields field); uint16_t get_default_port(const char *uri, const http_parser_url &u); @@ -449,35 +393,10 @@ bool numeric_host(const char *hostname); -bool numeric_host(const char *hostname, int family); - -// Returns numeric address string of |addr|. If getnameinfo() is -// failed, "unknown" is returned. -std::string numeric_name(const struct sockaddr *sa, socklen_t salen); - -// Returns string representation of numeric address and port of -// |addr|. If address family is AF_UNIX, this return path to UNIX -// domain socket. Otherwise, the format is like :. For -// IPv6 address, address is enclosed by square brackets ([]). -std::string to_numeric_addr(const Address *addr); - -// Makes internal copy of stderr (and possibly stdout in the future), -// which is then used as pointer to /dev/stderr or /proc/self/fd/2 -void store_original_fds(); - -// Restores the original stderr that was stored with copy_original_fds -// Used just before execv -void restore_original_fds(); - -// Closes |fd| which was returned by open_log_file (see below) -// and sets it to -1. In the case that |fd| points to stdout or -// stderr, or is -1, the descriptor is not closed (but still set to -1). -void close_log_file(int &fd); - // Opens |path| with O_APPEND enabled. If file does not exist, it is // created first. This function returns file descriptor referring the // opened file if it succeeds, or -1. -int open_log_file(const char *path); +int reopen_log_file(const char *path); // Returns ASCII dump of |data| of length |len|. Only ASCII printable // characters are preserved. Other characters are replaced with ".". @@ -501,38 +420,14 @@ // unit. int64_t to_time64(const timeval &tv); -// Returns true if ALPN ID |proto| is supported HTTP/2 protocol -// identifier. -bool check_h2_is_selected(const StringRef &proto); - -// Selects h2 protocol ALPN ID if one of supported h2 versions are -// present in |in| of length inlen. Returns true if h2 version is -// selected. -bool select_h2(const unsigned char **out, unsigned char *outlen, - const unsigned char *in, unsigned int inlen); - -// Selects protocol ALPN ID if one of identifiers contained in |protolist| is -// present in |in| of length inlen. Returns true if identifier is -// selected. -bool select_protocol(const unsigned char **out, unsigned char *outlen, - const unsigned char *in, unsigned int inlen, - std::vector proto_list); +// Returns true if ALPN ID |proto| of length |len| is supported HTTP/2 +// protocol identifier. +bool check_h2_is_selected(const unsigned char *alpn, size_t len); // Returns default ALPN protocol list, which only contains supported // HTTP/2 protocol identifier. std::vector get_default_alpn(); -// Parses delimited strings in |s| and returns the array of substring, -// delimited by |delim|. The any white spaces around substring are -// treated as a part of substring. -std::vector parse_config_str_list(const StringRef &s, - char delim = ','); - -// Parses delimited strings in |s| and returns Substrings in |s| -// delimited by |delim|. The any white spaces around substring are -// treated as a part of substring. -std::vector split_str(const StringRef &s, char delim); - // Returns given time |tp| in Common Log format (e.g., // 03/Jul/2014:00:19:38 +0900) // Expected type of |tp| is std::chrono::timepoint @@ -551,13 +446,6 @@ return iso8601_date(t.count()); } -// Returns given time |tp| in HTTP date format. -template std::string format_http_date(const T &tp) { - auto t = - std::chrono::duration_cast(tp.time_since_epoch()); - return http_date(t.count()); -} - // Return the system precision of the template parameter |Clock| as // a nanosecond value of type |Rep| template Rep clock_precision() { @@ -566,126 +454,6 @@ return duration.count(); } -int make_socket_closeonexec(int fd); -int make_socket_nonblocking(int fd); -int make_socket_nodelay(int fd); - -int create_nonblock_socket(int family); - -bool check_socket_connected(int fd); - -// Returns true if |host| is IPv6 numeric address (e.g., ::1) -bool ipv6_numeric_addr(const char *host); - -// Parses NULL terminated string |s| as unsigned integer and returns -// the parsed integer. Additionally, if |s| ends with 'k', 'm', 'g' -// and its upper case characters, multiply the integer by 1024, 1024 * -// 1024 and 1024 * 1024 respectively. If there is an error, returns -// -1. -int64_t parse_uint_with_unit(const char *s); -// The following overload does not require |s| is NULL terminated. -int64_t parse_uint_with_unit(const uint8_t *s, size_t len); -int64_t parse_uint_with_unit(const StringRef &s); - -// Parses NULL terminated string |s| as unsigned integer and returns -// the parsed integer. If there is an error, returns -1. -int64_t parse_uint(const char *s); -// The following overload does not require |s| is NULL terminated. -int64_t parse_uint(const uint8_t *s, size_t len); -int64_t parse_uint(const std::string &s); -int64_t parse_uint(const StringRef &s); - -// Parses NULL terminated string |s| as unsigned integer and returns -// the parsed integer casted to double. If |s| ends with "s", the -// parsed value's unit is a second. If |s| ends with "ms", the unit -// is millisecond. Similarly, it also supports 'm' and 'h' for -// minutes and hours respectively. If none of them are given, the -// unit is second. This function returns -// std::numeric_limits::infinity() if error occurs. -double parse_duration_with_unit(const char *s); -// The following overload does not require |s| is NULL terminated. -double parse_duration_with_unit(const uint8_t *s, size_t len); -double parse_duration_with_unit(const StringRef &s); - -// Returns string representation of time duration |t|. If t has -// fractional part (at least more than or equal to 1e-3), |t| is -// multiplied by 1000 and the unit "ms" is appended. Otherwise, |t| -// is left as is and "s" is appended. -std::string duration_str(double t); - -// Returns string representation of time duration |t|. It appends -// unit after the formatting. The available units are s, ms and us. -// The unit which is equal to or less than |t| is used and 2 -// fractional digits follow. -std::string format_duration(const std::chrono::microseconds &u); - -// Just like above, but this takes |t| as seconds. -std::string format_duration(double t); - -// Creates "host:port" string using given |host| and |port|. If -// |host| is numeric IPv6 address (e.g., ::1), it is enclosed by "[" -// and "]". If |port| is 80 or 443, port part is omitted. -std::string make_http_hostport(const StringRef &host, uint16_t port); - -// Just like make_http_hostport(), but doesn't treat 80 and 443 -// specially. -std::string make_hostport(const StringRef &host, uint16_t port); - -// Dumps |src| of length |len| in the format similar to `hexdump -C`. -void hexdump(FILE *out, const uint8_t *src, size_t len); - -// Copies 2 byte unsigned integer |n| in host byte order to |buf| in -// network byte order. -void put_uint16be(uint8_t *buf, uint16_t n); - -// Copies 4 byte unsigned integer |n| in host byte order to |buf| in -// network byte order. -void put_uint32be(uint8_t *buf, uint32_t n); - -// Retrieves 2 byte unsigned integer stored in |data| in network byte -// order and returns it in host byte order. -uint16_t get_uint16(const uint8_t *data); - -// Retrieves 4 byte unsigned integer stored in |data| in network byte -// order and returns it in host byte order. -uint32_t get_uint32(const uint8_t *data); - -// Retrieves 8 byte unsigned integer stored in |data| in network byte -// order and returns it in host byte order. -uint64_t get_uint64(const uint8_t *data); - -// Reads mime types file (see /etc/mime.types), and stores extension -// -> MIME type map in |res|. This function returns 0 if it succeeds, -// or -1. -int read_mime_types(std::map &res, - const char *filename); - -template -std::string random_alpha_digit(Generator &gen, size_t len) { - std::string res; - res.reserve(len); - std::uniform_int_distribution<> dis(0, 26 * 2 + 10 - 1); - for (; len > 0; --len) { - res += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"[dis( - gen)]; - } - return res; -} - -template -OutputIterator copy_lit(OutputIterator it, CharT(&s)[N]) { - return std::copy_n(s, N - 1, it); -} - -// Returns x**y -double int_pow(double x, size_t y); - -uint32_t hash32(const StringRef &s); - -// Computes SHA-256 of |s|, and stores it in |buf|. This function -// returns 0 if it succeeds, or -1. -int sha256(uint8_t *buf, const StringRef &s); - } // namespace util } // namespace nghttp2 diff -Nru nghttp2-1.13.0/src/util_test.cc nghttp2-0.6.7/src/util_test.cc --- nghttp2-1.13.0/src/util_test.cc 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/util_test.cc 2014-11-30 14:15:07.000000000 +0000 @@ -24,48 +24,37 @@ */ #include "util_test.h" -#include #include #include -#include - #include "util.h" -#include "template.h" using namespace nghttp2; namespace shrpx { void test_util_streq(void) { - CU_ASSERT( - util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alpha"))); - CU_ASSERT(!util::streq(StringRef::from_lit("alpha"), - StringRef::from_lit("alphabravo"))); - CU_ASSERT(!util::streq(StringRef::from_lit("alphabravo"), - StringRef::from_lit("alpha"))); - CU_ASSERT( - !util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alphA"))); - CU_ASSERT(!util::streq(StringRef{}, StringRef::from_lit("a"))); - CU_ASSERT(util::streq(StringRef{}, StringRef{})); - CU_ASSERT(!util::streq(StringRef::from_lit("alpha"), StringRef{})); - - CU_ASSERT( - !util::streq(StringRef::from_lit("alph"), StringRef::from_lit("alpha"))); - CU_ASSERT( - !util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alph"))); - CU_ASSERT( - !util::streq(StringRef::from_lit("alpha"), StringRef::from_lit("alphA"))); - - CU_ASSERT(util::streq_l("alpha", "alpha", 5)); - CU_ASSERT(util::streq_l("alpha", "alphabravo", 5)); - CU_ASSERT(!util::streq_l("alpha", "alphabravo", 6)); - CU_ASSERT(!util::streq_l("alphabravo", "alpha", 5)); - CU_ASSERT(!util::streq_l("alpha", "alphA", 5)); - CU_ASSERT(!util::streq_l("", "a", 1)); - CU_ASSERT(util::streq_l("", "", 0)); - CU_ASSERT(!util::streq_l("alpha", "", 0)); + CU_ASSERT(util::streq("alpha", (const uint8_t *)"alpha", 5)); + CU_ASSERT(util::streq("alpha", (const uint8_t *)"alphabravo", 5)); + CU_ASSERT(!util::streq("alpha", (const uint8_t *)"alphabravo", 6)); + CU_ASSERT(!util::streq("alphabravo", (const uint8_t *)"alpha", 5)); + CU_ASSERT(!util::streq("alpha", (const uint8_t *)"alphA", 5)); + CU_ASSERT(!util::streq("", (const uint8_t *)"a", 1)); + CU_ASSERT(util::streq("", (const uint8_t *)"", 0)); + CU_ASSERT(!util::streq("alpha", (const uint8_t *)"", 0)); + + CU_ASSERT( + util::streq((const uint8_t *)"alpha", 5, (const uint8_t *)"alpha", 5)); + CU_ASSERT( + !util::streq((const uint8_t *)"alpha", 4, (const uint8_t *)"alpha", 5)); + CU_ASSERT( + !util::streq((const uint8_t *)"alpha", 5, (const uint8_t *)"alpha", 4)); + CU_ASSERT( + !util::streq((const uint8_t *)"alpha", 5, (const uint8_t *)"alphA", 5)); + char *a = nullptr; + char *b = nullptr; + CU_ASSERT(util::streq(a, 0, b, 0)); } void test_util_strieq(void) { @@ -74,28 +63,6 @@ CU_ASSERT(util::strieq(std::string(), std::string())); CU_ASSERT(!util::strieq(std::string("alpha"), std::string("AlPhA "))); CU_ASSERT(!util::strieq(std::string(), std::string("AlPhA "))); - - CU_ASSERT( - util::strieq(StringRef::from_lit("alpha"), StringRef::from_lit("alpha"))); - CU_ASSERT( - util::strieq(StringRef::from_lit("alpha"), StringRef::from_lit("AlPhA"))); - CU_ASSERT(util::strieq(StringRef{}, StringRef{})); - CU_ASSERT(!util::strieq(StringRef::from_lit("alpha"), - StringRef::from_lit("AlPhA "))); - CU_ASSERT( - !util::strieq(StringRef::from_lit(""), StringRef::from_lit("AlPhA "))); - - CU_ASSERT(util::strieq_l("alpha", "alpha", 5)); - CU_ASSERT(util::strieq_l("alpha", "AlPhA", 5)); - CU_ASSERT(util::strieq_l("", static_cast(nullptr), 0)); - CU_ASSERT(!util::strieq_l("alpha", "AlPhA ", 6)); - CU_ASSERT(!util::strieq_l("", "AlPhA ", 6)); - - CU_ASSERT(util::strieq_l("alpha", StringRef::from_lit("alpha"))); - CU_ASSERT(util::strieq_l("alpha", StringRef::from_lit("AlPhA"))); - CU_ASSERT(util::strieq_l("", StringRef{})); - CU_ASSERT(!util::strieq_l("alpha", StringRef::from_lit("AlPhA "))); - CU_ASSERT(!util::strieq_l("", StringRef::from_lit("AlPhA "))); } void test_util_inp_strlower(void) { @@ -122,16 +89,6 @@ CU_ASSERT("AAA++B/B" == x); } -void test_util_to_token68(void) { - std::string x = "AAA++B/="; - util::to_token68(x); - CU_ASSERT("AAA--B_" == x); - - x = "AAA++B/B"; - util::to_token68(x); - CU_ASSERT("AAA--B_B" == x); -} - void test_util_percent_encode_token(void) { CU_ASSERT("h2" == util::percent_encode_token("h2")); CU_ASSERT("h3~" == util::percent_encode_token("h3~")); @@ -139,35 +96,6 @@ CU_ASSERT("http%202" == util::percent_encode_token("http 2")); } -void test_util_percent_encode_path(void) { - CU_ASSERT("/foo1/bar%3F&/%0A" == util::percent_encode_path("/foo1/bar?&/" - "\x0a")); -} - -void test_util_percent_decode(void) { - { - std::string s = "%66%6F%6f%62%61%72"; - CU_ASSERT("foobar" == util::percent_decode(std::begin(s), std::end(s))); - } - { - std::string s = "%66%6"; - CU_ASSERT("f%6" == util::percent_decode(std::begin(s), std::end(s))); - } - { - std::string s = "%66%"; - CU_ASSERT("f%" == util::percent_decode(std::begin(s), std::end(s))); - } - BlockAllocator balloc(1024, 1024); - - CU_ASSERT("foobar" == util::percent_decode( - balloc, StringRef::from_lit("%66%6F%6f%62%61%72"))); - - CU_ASSERT("f%6" == - util::percent_decode(balloc, StringRef::from_lit("%66%6"))); - - CU_ASSERT("f%" == util::percent_decode(balloc, StringRef::from_lit("%66%"))); -} - void test_util_quote_string(void) { CU_ASSERT("alpha" == util::quote_string("alpha")); CU_ASSERT("" == util::quote_string("")); @@ -188,344 +116,4 @@ CU_ASSERT("Wed, 29 Feb 2012 09:15:16 GMT" == util::http_date(1330506916)); } -void test_util_select_h2(void) { - const unsigned char *out = NULL; - unsigned char outlen = 0; - - // Check single entry and select it. - const unsigned char t1[] = "\x2h2"; - CU_ASSERT(util::select_h2(&out, &outlen, t1, sizeof(t1) - 1)); - CU_ASSERT( - memcmp(NGHTTP2_PROTO_VERSION_ID, out, NGHTTP2_PROTO_VERSION_ID_LEN) == 0); - CU_ASSERT(NGHTTP2_PROTO_VERSION_ID_LEN == outlen); - - out = NULL; - outlen = 0; - - // Check the case where id is correct but length is invalid and too - // long. - const unsigned char t2[] = "\x6h2-14"; - CU_ASSERT(!util::select_h2(&out, &outlen, t2, sizeof(t2) - 1)); - - // Check the case where h2 is located after bogus ID. - const unsigned char t3[] = "\x2h3\x2h2"; - CU_ASSERT(util::select_h2(&out, &outlen, t3, sizeof(t3) - 1)); - - CU_ASSERT( - memcmp(NGHTTP2_PROTO_VERSION_ID, out, NGHTTP2_PROTO_VERSION_ID_LEN) == 0); - CU_ASSERT(NGHTTP2_PROTO_VERSION_ID_LEN == outlen); - - out = NULL; - outlen = 0; - - // Check the case that last entry's length is invalid and too long. - const unsigned char t4[] = "\x2h3\x6h2-14"; - CU_ASSERT(!util::select_h2(&out, &outlen, t4, sizeof(t4) - 1)); - - // Check the case that all entries are not supported. - const unsigned char t5[] = "\x2h3\x2h4"; - CU_ASSERT(!util::select_h2(&out, &outlen, t5, sizeof(t5) - 1)); - - // Check the case where 2 values are eligible, but last one is - // picked up because it has precedence over the other. - const unsigned char t6[] = "\x5h2-14\x5h2-16"; - CU_ASSERT(util::select_h2(&out, &outlen, t6, sizeof(t6) - 1)); - CU_ASSERT(util::streq(NGHTTP2_H2_16, StringRef{out, outlen})); -} - -void test_util_ipv6_numeric_addr(void) { - CU_ASSERT(util::ipv6_numeric_addr("::1")); - CU_ASSERT(util::ipv6_numeric_addr("2001:0db8:85a3:0042:1000:8a2e:0370:7334")); - // IPv4 - CU_ASSERT(!util::ipv6_numeric_addr("127.0.0.1")); - // not numeric address - CU_ASSERT(!util::ipv6_numeric_addr("localhost")); -} - -void test_util_utos(void) { - uint8_t buf[32]; - - CU_ASSERT(("0" == StringRef{buf, util::utos(buf, 0)})); - CU_ASSERT(("123" == StringRef{buf, util::utos(buf, 123)})); - CU_ASSERT(("18446744073709551615" == - StringRef{buf, util::utos(buf, 18446744073709551615ULL)})); -} - -void test_util_make_string_ref_uint(void) { - BlockAllocator balloc(1024, 1024); - - CU_ASSERT("0" == util::make_string_ref_uint(balloc, 0)); - CU_ASSERT("123" == util::make_string_ref_uint(balloc, 123)); - CU_ASSERT("18446744073709551615" == - util::make_string_ref_uint(balloc, 18446744073709551615ULL)); -} - -void test_util_utos_unit(void) { - CU_ASSERT("0" == util::utos_unit(0)); - CU_ASSERT("1023" == util::utos_unit(1023)); - CU_ASSERT("1K" == util::utos_unit(1024)); - CU_ASSERT("1K" == util::utos_unit(1025)); - CU_ASSERT("1M" == util::utos_unit(1 << 20)); - CU_ASSERT("1G" == util::utos_unit(1 << 30)); - CU_ASSERT("1024G" == util::utos_unit(1LL << 40)); -} - -void test_util_utos_funit(void) { - CU_ASSERT("0" == util::utos_funit(0)); - CU_ASSERT("1023" == util::utos_funit(1023)); - CU_ASSERT("1.00K" == util::utos_funit(1024)); - CU_ASSERT("1.00K" == util::utos_funit(1025)); - CU_ASSERT("1.09K" == util::utos_funit(1119)); - CU_ASSERT("1.27K" == util::utos_funit(1300)); - CU_ASSERT("1.00M" == util::utos_funit(1 << 20)); - CU_ASSERT("1.18M" == util::utos_funit(1234567)); - CU_ASSERT("1.00G" == util::utos_funit(1 << 30)); - CU_ASSERT("4492450797.23G" == util::utos_funit(4823732313248234343LL)); - CU_ASSERT("1024.00G" == util::utos_funit(1LL << 40)); -} - -void test_util_parse_uint_with_unit(void) { - CU_ASSERT(0 == util::parse_uint_with_unit("0")); - CU_ASSERT(1023 == util::parse_uint_with_unit("1023")); - CU_ASSERT(1024 == util::parse_uint_with_unit("1k")); - CU_ASSERT(2048 == util::parse_uint_with_unit("2K")); - CU_ASSERT(1 << 20 == util::parse_uint_with_unit("1m")); - CU_ASSERT(1 << 21 == util::parse_uint_with_unit("2M")); - CU_ASSERT(1 << 30 == util::parse_uint_with_unit("1g")); - CU_ASSERT(1LL << 31 == util::parse_uint_with_unit("2G")); - CU_ASSERT(9223372036854775807LL == - util::parse_uint_with_unit("9223372036854775807")); - // check overflow case - CU_ASSERT(-1 == util::parse_uint_with_unit("9223372036854775808")); - CU_ASSERT(-1 == util::parse_uint_with_unit("10000000000000000000")); - CU_ASSERT(-1 == util::parse_uint_with_unit("9223372036854775807G")); - // bad characters - CU_ASSERT(-1 == util::parse_uint_with_unit("1.1")); - CU_ASSERT(-1 == util::parse_uint_with_unit("1a")); - CU_ASSERT(-1 == util::parse_uint_with_unit("a1")); - CU_ASSERT(-1 == util::parse_uint_with_unit("1T")); - CU_ASSERT(-1 == util::parse_uint_with_unit("")); -} - -void test_util_parse_uint(void) { - CU_ASSERT(0 == util::parse_uint("0")); - CU_ASSERT(1023 == util::parse_uint("1023")); - CU_ASSERT(-1 == util::parse_uint("1k")); - CU_ASSERT(9223372036854775807LL == util::parse_uint("9223372036854775807")); - // check overflow case - CU_ASSERT(-1 == util::parse_uint("9223372036854775808")); - CU_ASSERT(-1 == util::parse_uint("10000000000000000000")); - // bad characters - CU_ASSERT(-1 == util::parse_uint("1.1")); - CU_ASSERT(-1 == util::parse_uint("1a")); - CU_ASSERT(-1 == util::parse_uint("a1")); - CU_ASSERT(-1 == util::parse_uint("1T")); - CU_ASSERT(-1 == util::parse_uint("")); -} - -void test_util_parse_duration_with_unit(void) { - CU_ASSERT(0. == util::parse_duration_with_unit("0")); - CU_ASSERT(123. == util::parse_duration_with_unit("123")); - CU_ASSERT(123. == util::parse_duration_with_unit("123s")); - CU_ASSERT(0.500 == util::parse_duration_with_unit("500ms")); - CU_ASSERT(123. == util::parse_duration_with_unit("123S")); - CU_ASSERT(0.500 == util::parse_duration_with_unit("500MS")); - CU_ASSERT(180 == util::parse_duration_with_unit("3m")); - CU_ASSERT(3600 * 5 == util::parse_duration_with_unit("5h")); - - auto err = std::numeric_limits::infinity(); - // check overflow case - CU_ASSERT(err == util::parse_duration_with_unit("9223372036854775808")); - // bad characters - CU_ASSERT(err == util::parse_duration_with_unit("0u")); - CU_ASSERT(err == util::parse_duration_with_unit("0xs")); - CU_ASSERT(err == util::parse_duration_with_unit("0mt")); - CU_ASSERT(err == util::parse_duration_with_unit("0mss")); - CU_ASSERT(err == util::parse_duration_with_unit("s")); - CU_ASSERT(err == util::parse_duration_with_unit("ms")); -} - -void test_util_duration_str(void) { - CU_ASSERT("0" == util::duration_str(0.)); - CU_ASSERT("1s" == util::duration_str(1.)); - CU_ASSERT("500ms" == util::duration_str(0.5)); - CU_ASSERT("1500ms" == util::duration_str(1.5)); - CU_ASSERT("2m" == util::duration_str(120.)); - CU_ASSERT("121s" == util::duration_str(121.)); - CU_ASSERT("1h" == util::duration_str(3600.)); -} - -void test_util_format_duration(void) { - CU_ASSERT("0us" == util::format_duration(std::chrono::microseconds(0))); - CU_ASSERT("999us" == util::format_duration(std::chrono::microseconds(999))); - CU_ASSERT("1.00ms" == util::format_duration(std::chrono::microseconds(1000))); - CU_ASSERT("1.09ms" == util::format_duration(std::chrono::microseconds(1090))); - CU_ASSERT("1.01ms" == util::format_duration(std::chrono::microseconds(1009))); - CU_ASSERT("999.99ms" == - util::format_duration(std::chrono::microseconds(999990))); - CU_ASSERT("1.00s" == - util::format_duration(std::chrono::microseconds(1000000))); - CU_ASSERT("1.05s" == - util::format_duration(std::chrono::microseconds(1050000))); - - CU_ASSERT("0us" == util::format_duration(0.)); - CU_ASSERT("999us" == util::format_duration(0.000999)); - CU_ASSERT("1.00ms" == util::format_duration(0.001)); - CU_ASSERT("1.09ms" == util::format_duration(0.00109)); - CU_ASSERT("1.01ms" == util::format_duration(0.001009)); - CU_ASSERT("999.99ms" == util::format_duration(0.99999)); - CU_ASSERT("1.00s" == util::format_duration(1.)); - CU_ASSERT("1.05s" == util::format_duration(1.05)); -} - -void test_util_starts_with(void) { - CU_ASSERT(util::starts_with(StringRef::from_lit("foo"), - StringRef::from_lit("foo"))); - CU_ASSERT(util::starts_with(StringRef::from_lit("fooo"), - StringRef::from_lit("foo"))); - CU_ASSERT(util::starts_with(StringRef::from_lit("ofoo"), StringRef{})); - CU_ASSERT(!util::starts_with(StringRef::from_lit("ofoo"), - StringRef::from_lit("foo"))); - - CU_ASSERT(util::istarts_with(StringRef::from_lit("FOO"), - StringRef::from_lit("fOO"))); - CU_ASSERT(util::istarts_with(StringRef::from_lit("ofoo"), StringRef{})); - CU_ASSERT(util::istarts_with(StringRef::from_lit("fOOo"), - StringRef::from_lit("Foo"))); - CU_ASSERT(!util::istarts_with(StringRef::from_lit("ofoo"), - StringRef::from_lit("foo"))); - - CU_ASSERT(util::istarts_with_l(StringRef::from_lit("fOOo"), "Foo")); - CU_ASSERT(!util::istarts_with_l(StringRef::from_lit("ofoo"), "foo")); -} - -void test_util_ends_with(void) { - CU_ASSERT( - util::ends_with(StringRef::from_lit("foo"), StringRef::from_lit("foo"))); - CU_ASSERT(util::ends_with(StringRef::from_lit("foo"), StringRef{})); - CU_ASSERT( - util::ends_with(StringRef::from_lit("ofoo"), StringRef::from_lit("foo"))); - CU_ASSERT( - !util::ends_with(StringRef::from_lit("ofoo"), StringRef::from_lit("fo"))); - - CU_ASSERT( - util::iends_with(StringRef::from_lit("fOo"), StringRef::from_lit("Foo"))); - CU_ASSERT(util::iends_with(StringRef::from_lit("foo"), StringRef{})); - CU_ASSERT(util::iends_with(StringRef::from_lit("oFoo"), - StringRef::from_lit("fOO"))); - CU_ASSERT(!util::iends_with(StringRef::from_lit("ofoo"), - StringRef::from_lit("fo"))); - - CU_ASSERT(util::iends_with_l(StringRef::from_lit("oFoo"), "fOO")); - CU_ASSERT(!util::iends_with_l(StringRef::from_lit("ofoo"), "fo")); -} - -void test_util_parse_http_date(void) { - CU_ASSERT(1001939696 == util::parse_http_date(StringRef::from_lit( - "Mon, 1 Oct 2001 12:34:56 GMT"))); -} - -void test_util_localtime_date(void) { - auto tz = getenv("TZ"); - if (tz) { - tz = strdup(tz); - } - setenv("TZ", ":Pacific/Auckland", 1); - tzset(); - - CU_ASSERT_STRING_EQUAL("02/Oct/2001:00:34:56 +1200", - util::common_log_date(1001939696).c_str()); - CU_ASSERT_STRING_EQUAL("2001-10-02T00:34:56.123+12:00", - util::iso8601_date(1001939696000LL + 123).c_str()); - - if (tz) { - setenv("TZ", tz, 1); - } else { - unsetenv("TZ"); - } - tzset(); -} - -void test_util_get_uint64(void) { - { - auto v = std::array{ - {0x01, 0x12, 0x34, 0x56, 0xff, 0x9a, 0xab, 0xbc}}; - - auto n = util::get_uint64(v.data()); - - CU_ASSERT(0x01123456ff9aabbcULL == n); - } - { - auto v = std::array{ - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; - - auto n = util::get_uint64(v.data()); - - CU_ASSERT(0xffffffffffffffffULL == n); - } -} - -void test_util_parse_config_str_list(void) { - auto res = util::parse_config_str_list(StringRef::from_lit("a")); - CU_ASSERT(1 == res.size()); - CU_ASSERT("a" == res[0]); - - res = util::parse_config_str_list(StringRef::from_lit("a,")); - CU_ASSERT(2 == res.size()); - CU_ASSERT("a" == res[0]); - CU_ASSERT("" == res[1]); - - res = util::parse_config_str_list(StringRef::from_lit(":a::"), ':'); - CU_ASSERT(4 == res.size()); - CU_ASSERT("" == res[0]); - CU_ASSERT("a" == res[1]); - CU_ASSERT("" == res[2]); - CU_ASSERT("" == res[3]); - - res = util::parse_config_str_list(StringRef{}); - CU_ASSERT(1 == res.size()); - CU_ASSERT("" == res[0]); - - res = util::parse_config_str_list(StringRef::from_lit("alpha,bravo,charlie")); - CU_ASSERT(3 == res.size()); - CU_ASSERT("alpha" == res[0]); - CU_ASSERT("bravo" == res[1]); - CU_ASSERT("charlie" == res[2]); -} - -void test_util_make_http_hostport(void) { - CU_ASSERT("localhost" == - util::make_http_hostport(StringRef::from_lit("localhost"), 80)); - CU_ASSERT("[::1]" == - util::make_http_hostport(StringRef::from_lit("::1"), 443)); - CU_ASSERT("localhost:3000" == - util::make_http_hostport(StringRef::from_lit("localhost"), 3000)); -} - -void test_util_make_hostport(void) { - CU_ASSERT("localhost:80" == - util::make_hostport(StringRef::from_lit("localhost"), 80)); - CU_ASSERT("[::1]:443" == - util::make_hostport(StringRef::from_lit("::1"), 443)); -} - -void test_util_strifind(void) { - CU_ASSERT(util::strifind(StringRef::from_lit("gzip, deflate, bzip2"), - StringRef::from_lit("gzip"))); - - CU_ASSERT(util::strifind(StringRef::from_lit("gzip, deflate, bzip2"), - StringRef::from_lit("dEflate"))); - - CU_ASSERT(util::strifind(StringRef::from_lit("gzip, deflate, bzip2"), - StringRef::from_lit("BZIP2"))); - - CU_ASSERT(util::strifind(StringRef::from_lit("nghttp2"), StringRef{})); - - // Be aware this fact - CU_ASSERT(!util::strifind(StringRef{}, StringRef{})); - - CU_ASSERT(!util::strifind(StringRef::from_lit("nghttp2"), - StringRef::from_lit("http1"))); -} - } // namespace shrpx diff -Nru nghttp2-1.13.0/src/util_test.h nghttp2-0.6.7/src/util_test.h --- nghttp2-1.13.0/src/util_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/src/util_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,43 +25,16 @@ #ifndef UTIL_TEST_H #define UTIL_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif // HAVE_CONFIG_H - namespace shrpx { void test_util_streq(void); void test_util_strieq(void); void test_util_inp_strlower(void); void test_util_to_base64(void); -void test_util_to_token68(void); void test_util_percent_encode_token(void); -void test_util_percent_encode_path(void); -void test_util_percent_decode(void); void test_util_quote_string(void); void test_util_utox(void); void test_util_http_date(void); -void test_util_select_h2(void); -void test_util_ipv6_numeric_addr(void); -void test_util_utos(void); -void test_util_make_string_ref_uint(void); -void test_util_utos_unit(void); -void test_util_utos_funit(void); -void test_util_parse_uint_with_unit(void); -void test_util_parse_uint(void); -void test_util_parse_duration_with_unit(void); -void test_util_duration_str(void); -void test_util_format_duration(void); -void test_util_starts_with(void); -void test_util_ends_with(void); -void test_util_parse_http_date(void); -void test_util_localtime_date(void); -void test_util_get_uint64(void); -void test_util_parse_config_str_list(void); -void test_util_make_http_hostport(void); -void test_util_make_hostport(void); -void test_util_strifind(void); } // namespace shrpx diff -Nru nghttp2-1.13.0/test-driver nghttp2-0.6.7/test-driver --- nghttp2-1.13.0/test-driver 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/test-driver 2014-11-30 14:15:35.000000000 +0000 @@ -3,7 +3,7 @@ scriptversion=2013-07-13.22; # UTC -# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# Copyright (C) 2011-2013 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -106,14 +106,11 @@ # Test script is run here. "$@" >$log_file 2>&1 estatus=$? - if test $enable_hard_errors = no && test $estatus -eq 99; then - tweaked_estatus=1 -else - tweaked_estatus=$estatus + estatus=1 fi -case $tweaked_estatus:$expect_failure in +case $estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; @@ -122,12 +119,6 @@ *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac -# Report the test outcome and exit status in the logs, so that one can -# know whether the test passed or failed simply by looking at the '.log' -# file, without the need of also peaking into the corresponding '.trs' -# file (automake bug#11814). -echo "$res $test_name (exit status: $estatus)" >>$log_file - # Report outcome to console. echo "${col}${res}${std}: $test_name" diff -Nru nghttp2-1.13.0/tests/CMakeLists.txt nghttp2-0.6.7/tests/CMakeLists.txt --- nghttp2-1.13.0/tests/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -# XXX testdata/: EXTRA_DIST = cacert.pem index.html privkey.pem -if(HAVE_CUNIT) - string(REPLACE " " ";" c_flags "${WARNCFLAGS}") - add_compile_options(${c_flags}) - - include_directories( - "${CMAKE_SOURCE_DIR}/lib/includes" - "${CMAKE_SOURCE_DIR}/lib" - "${CMAKE_SOURCE_DIR}/src/includes" - "${CMAKE_BINARY_DIR}/lib/includes" - ${CUNIT_INCLUDE_DIRS} - ) - - set(MAIN_SOURCES - main.c nghttp2_pq_test.c nghttp2_map_test.c nghttp2_queue_test.c - nghttp2_test_helper.c - nghttp2_frame_test.c - nghttp2_stream_test.c - nghttp2_session_test.c - nghttp2_hd_test.c - nghttp2_npn_test.c - nghttp2_helper_test.c - nghttp2_buf_test.c - ) - - add_executable(main EXCLUDE_FROM_ALL - ${MAIN_SOURCES} - ) - target_include_directories(main PRIVATE ${CUNIT_INCLUDE_DIRS}) - target_link_libraries(main - nghttp2_static - ${CUNIT_LIBRARIES} - ) - add_test(main main) - add_dependencies(check main) - - if(ENABLE_FAILMALLOC) - set(FAILMALLOC_SOURCES - failmalloc.c failmalloc_test.c - malloc_wrapper.c - nghttp2_test_helper.c - ) - add_executable(failmalloc EXCLUDE_FROM_ALL - ${FAILMALLOC_SOURCES} - ) - target_link_libraries(failmalloc - nghttp2_static - ${CUNIT_LIBRARIES} - ) - add_test(failmalloc failmalloc) - add_dependencies(check failmalloc) - endif() - - if(ENABLE_APP) - # EXTRA_DIST = end_to_end.py - # TESTS += end_to_end.py - endif() -endif() diff -Nru nghttp2-1.13.0/tests/failmalloc.c nghttp2-0.6.7/tests/failmalloc.c --- nghttp2-1.13.0/tests/failmalloc.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/failmalloc.c 2014-11-30 14:15:07.000000000 +0000 @@ -22,22 +22,17 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - #include #include #include /* include test cases' include files here */ - #include "failmalloc_test.h" static int init_suite1(void) { return 0; } static int clean_suite1(void) { return 0; } -int main(int argc _U_, char *argv[] _U_) { +int main(int argc, char *argv[]) { CU_pSuite pSuite = NULL; unsigned int num_tests_failed; @@ -55,8 +50,6 @@ /* add the tests to the suite */ if (!CU_add_test(pSuite, "failmalloc_session_send", test_nghttp2_session_send) || - !CU_add_test(pSuite, "failmalloc_session_send_server", - test_nghttp2_session_send_server) || !CU_add_test(pSuite, "failmalloc_session_recv", test_nghttp2_session_recv) || !CU_add_test(pSuite, "failmalloc_frame", test_nghttp2_frame) || @@ -71,7 +64,7 @@ num_tests_failed = CU_get_number_of_tests_failed(); CU_cleanup_registry(); if (CU_get_error() == CUE_SUCCESS) { - return (int)num_tests_failed; + return num_tests_failed; } else { printf("CUnit Error: %s\n", CU_get_error_msg()); return CU_get_error(); diff -Nru nghttp2-1.13.0/tests/failmalloc_test.c nghttp2-0.6.7/tests/failmalloc_test.c --- nghttp2-1.13.0/tests/failmalloc_test.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/failmalloc_test.c 2014-11-30 14:15:07.000000000 +0000 @@ -59,27 +59,24 @@ df->datalimit = df->data + data_length; } -static ssize_t null_send_callback(nghttp2_session *session _U_, - const uint8_t *data _U_, size_t len, - int flags _U_, void *user_data _U_) { - return (ssize_t)len; +static ssize_t null_send_callback(nghttp2_session *session, const uint8_t *data, + size_t len, int flags, void *user_data) { + return len; } -static ssize_t data_feed_recv_callback(nghttp2_session *session _U_, - uint8_t *data, size_t len, int flags _U_, - void *user_data) { +static ssize_t data_feed_recv_callback(nghttp2_session *session, uint8_t *data, + size_t len, int flags, void *user_data) { data_feed *df = ((my_user_data *)user_data)->df; - size_t avail = (size_t)(df->datalimit - df->datamark); + size_t avail = df->datalimit - df->datamark; size_t wlen = nghttp2_min(avail, len); memcpy(data, df->datamark, wlen); df->datamark += wlen; - return (ssize_t)wlen; + return wlen; } static ssize_t fixed_length_data_source_read_callback( - nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_, - size_t len, uint32_t *data_flags, nghttp2_data_source *source _U_, - void *user_data) { + nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t len, + uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { my_user_data *ud = (my_user_data *)user_data; size_t wlen; if (len < ud->data_source_length) { @@ -91,12 +88,12 @@ if (ud->data_source_length == 0) { *data_flags = NGHTTP2_DATA_FLAG_EOF; } - return (ssize_t)wlen; + return wlen; } #define TEST_FAILMALLOC_RUN(FUN) \ do { \ - int nmalloc, i; \ + size_t nmalloc, i; \ \ nghttp2_failmalloc = 0; \ nghttp2_nmalloc = 0; \ @@ -134,8 +131,7 @@ iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; iv[1].value = 100; - rv = nghttp2_session_client_new3(&session, &callbacks, &ud, NULL, - nghttp2_mem_fm()); + rv = nghttp2_session_client_new(&session, &callbacks, &ud); if (rv != 0) { goto client_new_fail; } @@ -217,50 +213,6 @@ TEST_FAILMALLOC_RUN(run_nghttp2_session_send); } -static void run_nghttp2_session_send_server(void) { - nghttp2_session *session; - nghttp2_session_callbacks *callbacks; - int rv; - const uint8_t *txdata; - ssize_t txdatalen; - const uint8_t origin[] = "nghttp2.org"; - const uint8_t altsvc_field_value[] = "h2=\":443\""; - - rv = nghttp2_session_callbacks_new(&callbacks); - if (rv != 0) { - return; - } - - rv = nghttp2_session_server_new3(&session, callbacks, NULL, NULL, - nghttp2_mem_fm()); - - nghttp2_session_callbacks_del(callbacks); - - if (rv != 0) { - return; - } - - rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin, - sizeof(origin) - 1, altsvc_field_value, - sizeof(altsvc_field_value) - 1); - if (rv != 0) { - goto fail; - } - - txdatalen = nghttp2_session_mem_send(session, &txdata); - - if (txdatalen < 0) { - goto fail; - } - -fail: - nghttp2_session_del(session); -} - -void test_nghttp2_session_send_server(void) { - TEST_FAILMALLOC_RUN(run_nghttp2_session_send_server); -} - static void run_nghttp2_session_recv(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; @@ -274,7 +226,7 @@ data_feed df; int rv; nghttp2_nv *nva; - size_t nvlen; + ssize_t nvlen; rv = frame_pack_bufs_init(&bufs); @@ -288,10 +240,9 @@ nghttp2_failmalloc_pause(); nvlen = ARRLEN(nv); - nghttp2_nv_array_copy(&nva, nv, nvlen, nghttp2_mem_fm()); - nghttp2_hd_deflate_init(&deflater, nghttp2_mem_fm()); - nghttp2_session_server_new3(&session, &callbacks, &ud, NULL, - nghttp2_mem_fm()); + nghttp2_nv_array_copy(&nva, nv, nvlen); + nghttp2_hd_deflate_init(&deflater); + nghttp2_session_server_new(&session, &callbacks, &ud); nghttp2_failmalloc_unpause(); /* HEADERS */ @@ -299,7 +250,7 @@ nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen); nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); - nghttp2_frame_headers_free(&frame.headers, nghttp2_mem_fm()); + nghttp2_frame_headers_free(&frame.headers); data_feed_init(&df, &bufs); nghttp2_bufs_reset(&bufs); @@ -346,10 +297,9 @@ iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; iv[1].value = 100; nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, - nghttp2_frame_iv_copy(iv, 2, nghttp2_mem_fm()), - 2); + nghttp2_frame_iv_copy(iv, 2), 2); nghttp2_frame_pack_settings(&bufs, &frame.settings); - nghttp2_frame_settings_free(&frame.settings, nghttp2_mem_fm()); + nghttp2_frame_settings_free(&frame.settings); nghttp2_bufs_reset(&bufs); nghttp2_failmalloc_unpause(); @@ -378,7 +328,7 @@ MAKE_NV(":scheme", "https")}; int rv; nghttp2_nv *nva; - size_t nvlen; + ssize_t nvlen; rv = frame_pack_bufs_init(&bufs); @@ -386,16 +336,16 @@ return; } - rv = nghttp2_hd_deflate_init(&deflater, nghttp2_mem_fm()); + rv = nghttp2_hd_deflate_init(&deflater); if (rv != 0) { goto deflate_init_fail; } - rv = nghttp2_hd_inflate_init(&inflater, nghttp2_mem_fm()); + rv = nghttp2_hd_inflate_init(&inflater); if (rv != 0) { goto inflate_init_fail; } nvlen = ARRLEN(nv); - rv = nghttp2_nv_array_copy(&nva, nv, nvlen, nghttp2_mem_fm()); + rv = nghttp2_nv_array_copy(&nva, nv, nvlen); if (rv < 0) { goto nv_copy_fail; } @@ -409,10 +359,10 @@ if (rv != 0) { goto fail; } - nghttp2_frame_headers_free(&oframe.headers, nghttp2_mem_fm()); + nghttp2_frame_headers_free(&oframe.headers); fail: - nghttp2_frame_headers_free(&frame.headers, nghttp2_mem_fm()); + nghttp2_frame_headers_free(&frame.headers); nv_copy_fail: nghttp2_hd_inflate_free(&inflater); inflate_init_fail: @@ -439,7 +389,7 @@ iv[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; iv[1].value = 100; - iv_copy = nghttp2_frame_iv_copy(iv, 2, nghttp2_mem_fm()); + iv_copy = nghttp2_frame_iv_copy(iv, 2); if (iv_copy == NULL) { goto iv_copy_fail; @@ -457,15 +407,15 @@ rv = nghttp2_frame_unpack_settings_payload2( &oframe.settings.iv, &oframe.settings.niv, buf->pos + NGHTTP2_FRAME_HDLEN, - nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN, nghttp2_mem_fm()); + nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN); if (rv != 0) { goto fail; } - nghttp2_frame_settings_free(&oframe.settings, nghttp2_mem_fm()); + nghttp2_frame_settings_free(&oframe.settings); fail: - nghttp2_frame_settings_free(&frame.settings, nghttp2_mem_fm()); + nghttp2_frame_settings_free(&frame.settings); iv_copy_fail: nghttp2_bufs_free(&bufs); } @@ -477,7 +427,7 @@ static int deflate_inflate(nghttp2_hd_deflater *deflater, nghttp2_hd_inflater *inflater, nghttp2_bufs *bufs, - nghttp2_nv *nva, size_t nvlen, nghttp2_mem *mem) { + nghttp2_nv *nva, size_t nvlen) { int rv; rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, nva, nvlen); @@ -486,7 +436,7 @@ return rv; } - rv = (int)inflate_hd(inflater, NULL, bufs, 0, mem); + rv = inflate_hd(inflater, NULL, bufs, 0); if (rv < 0) { return rv; @@ -502,14 +452,13 @@ nghttp2_hd_inflater inflater; nghttp2_bufs bufs; int rv; - nghttp2_nv nva1[] = { - MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "example.org"), - MAKE_NV(":path", "/slashdot"), - MAKE_NV("accept-encoding", "gzip, deflate"), MAKE_NV("foo", "bar")}; + nghttp2_nv nva1[] = {MAKE_NV(":scheme", "https"), + MAKE_NV(":authority", "example.org"), + MAKE_NV(":path", "/slashdot"), + MAKE_NV("accept-encoding", "gzip, deflate")}; nghttp2_nv nva2[] = { MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "example.org"), - MAKE_NV(":path", "/style.css"), MAKE_NV("cookie", "nghttp2=FTW"), - MAKE_NV("foo", "bar2")}; + MAKE_NV(":path", "/style.css"), MAKE_NV("cookie", "nghttp2=FTW")}; rv = frame_pack_bufs_init(&bufs); @@ -517,27 +466,25 @@ return; } - rv = nghttp2_hd_deflate_init(&deflater, nghttp2_mem_fm()); + rv = nghttp2_hd_deflate_init(&deflater); if (rv != 0) { goto deflate_init_fail; } - rv = nghttp2_hd_inflate_init(&inflater, nghttp2_mem_fm()); + rv = nghttp2_hd_inflate_init(&inflater); if (rv != 0) { goto inflate_init_fail; } - rv = deflate_inflate(&deflater, &inflater, &bufs, nva1, ARRLEN(nva1), - nghttp2_mem_fm()); + rv = deflate_inflate(&deflater, &inflater, &bufs, nva1, ARRLEN(nva1)); if (rv != 0) { goto deflate_hd_fail; } - rv = deflate_inflate(&deflater, &inflater, &bufs, nva2, ARRLEN(nva2), - nghttp2_mem_fm()); + rv = deflate_inflate(&deflater, &inflater, &bufs, nva2, ARRLEN(nva2)); if (rv != 0) { goto deflate_hd_fail; diff -Nru nghttp2-1.13.0/tests/failmalloc_test.h nghttp2-0.6.7/tests/failmalloc_test.h --- nghttp2-1.13.0/tests/failmalloc_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/failmalloc_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,12 +25,7 @@ #ifndef FAILMALLOC_TEST_H #define FAILMALLOC_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - void test_nghttp2_session_send(void); -void test_nghttp2_session_send_server(void); void test_nghttp2_session_recv(void); void test_nghttp2_frame(void); void test_nghttp2_hd(void); diff -Nru nghttp2-1.13.0/tests/main.c nghttp2-0.6.7/tests/main.c --- nghttp2-1.13.0/tests/main.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/main.c 2014-11-30 14:15:07.000000000 +0000 @@ -41,7 +41,7 @@ #include "nghttp2_helper_test.h" #include "nghttp2_buf_test.h" -extern int nghttp2_enable_strict_preface; +extern int nghttp2_enable_strict_first_settings_check; static int init_suite1(void) { return 0; } @@ -51,7 +51,7 @@ CU_pSuite pSuite = NULL; unsigned int num_tests_failed; - nghttp2_enable_strict_preface = 0; + nghttp2_enable_strict_first_settings_check = 0; /* initialize the CUnit test registry */ if (CUE_SUCCESS != CU_initialize_registry()) @@ -67,7 +67,6 @@ /* add the tests to the suite */ if (!CU_add_test(pSuite, "pq", test_nghttp2_pq) || !CU_add_test(pSuite, "pq_update", test_nghttp2_pq_update) || - !CU_add_test(pSuite, "pq_remove", test_nghttp2_pq_remove) || !CU_add_test(pSuite, "map", test_nghttp2_map) || !CU_add_test(pSuite, "map_functional", test_nghttp2_map_functional) || !CU_add_test(pSuite, "map_each_free", test_nghttp2_map_each_free) || @@ -81,18 +80,14 @@ !CU_add_test(pSuite, "session_recv_eof", test_nghttp2_session_recv_eof) || !CU_add_test(pSuite, "session_recv_data", test_nghttp2_session_recv_data) || - !CU_add_test(pSuite, "session_recv_data_no_auto_flow_control", - test_nghttp2_session_recv_data_no_auto_flow_control) || !CU_add_test(pSuite, "session_recv_continuation", test_nghttp2_session_recv_continuation) || !CU_add_test(pSuite, "session_recv_headers_with_priority", test_nghttp2_session_recv_headers_with_priority) || - !CU_add_test(pSuite, "session_recv_headers_early_response", - test_nghttp2_session_recv_headers_early_response) || - !CU_add_test(pSuite, "session_server_recv_push_response", - test_nghttp2_session_server_recv_push_response) || !CU_add_test(pSuite, "session_recv_premature_headers", test_nghttp2_session_recv_premature_headers) || + !CU_add_test(pSuite, "session_recv_altsvc", + test_nghttp2_session_recv_altsvc) || !CU_add_test(pSuite, "session_recv_unknown_frame", test_nghttp2_session_recv_unknown_frame) || !CU_add_test(pSuite, "session_recv_unexpected_continuation", @@ -101,10 +96,6 @@ test_nghttp2_session_recv_settings_header_table_size) || !CU_add_test(pSuite, "session_recv_too_large_frame_length", test_nghttp2_session_recv_too_large_frame_length) || - !CU_add_test(pSuite, "session_recv_extension", - test_nghttp2_session_recv_extension) || - !CU_add_test(pSuite, "session_recv_altsvc", - test_nghttp2_session_recv_altsvc) || !CU_add_test(pSuite, "session_continue", test_nghttp2_session_continue) || !CU_add_test(pSuite, "session_add_frame", test_nghttp2_session_add_frame) || @@ -132,10 +123,6 @@ test_nghttp2_session_on_window_update_received) || !CU_add_test(pSuite, "session_on_data_received", test_nghttp2_session_on_data_received) || - !CU_add_test(pSuite, "session_on_data_received_fail_fast", - test_nghttp2_session_on_data_received_fail_fast) || - !CU_add_test(pSuite, "session_on_altsvc_received", - test_nghttp2_session_on_altsvc_received) || !CU_add_test(pSuite, "session_send_headers_start_stream", test_nghttp2_session_send_headers_start_stream) || !CU_add_test(pSuite, "session_send_headers_reply", @@ -150,17 +137,15 @@ test_nghttp2_session_send_push_promise) || !CU_add_test(pSuite, "session_is_my_stream_id", test_nghttp2_session_is_my_stream_id) || - !CU_add_test(pSuite, "session_upgrade2", test_nghttp2_session_upgrade2) || + !CU_add_test(pSuite, "session_upgrade", test_nghttp2_session_upgrade) || !CU_add_test(pSuite, "session_reprioritize_stream", test_nghttp2_session_reprioritize_stream) || !CU_add_test( - pSuite, "session_reprioritize_stream_with_idle_stream_dep", - test_nghttp2_session_reprioritize_stream_with_idle_stream_dep) || + pSuite, "session_reprioritize_stream_with_closed_stream_limit", + test_nghttp2_session_reprioritize_stream_with_closed_stream_limit) || !CU_add_test(pSuite, "submit_data", test_nghttp2_submit_data) || !CU_add_test(pSuite, "submit_data_read_length_too_large", test_nghttp2_submit_data_read_length_too_large) || - !CU_add_test(pSuite, "submit_data_read_length_smallest", - test_nghttp2_submit_data_read_length_smallest) || !CU_add_test(pSuite, "submit_data_twice", test_nghttp2_submit_data_twice) || !CU_add_test(pSuite, "submit_request_with_data", @@ -171,9 +156,6 @@ test_nghttp2_submit_response_with_data) || !CU_add_test(pSuite, "submit_response_without_data", test_nghttp2_submit_response_without_data) || - !CU_add_test(pSuite, "Submit_response_push_response", - test_nghttp2_submit_response_push_response) || - !CU_add_test(pSuite, "submit_trailer", test_nghttp2_submit_trailer) || !CU_add_test(pSuite, "submit_headers_start_stream", test_nghttp2_submit_headers_start_stream) || !CU_add_test(pSuite, "submit_headers_reply", @@ -183,31 +165,24 @@ !CU_add_test(pSuite, "submit_headers", test_nghttp2_submit_headers) || !CU_add_test(pSuite, "submit_headers_continuation", test_nghttp2_submit_headers_continuation) || - !CU_add_test(pSuite, "submit_headers_continuation_extra_large", - test_nghttp2_submit_headers_continuation_extra_large) || !CU_add_test(pSuite, "submit_priority", test_nghttp2_submit_priority) || !CU_add_test(pSuite, "session_submit_settings", test_nghttp2_submit_settings) || !CU_add_test(pSuite, "session_submit_settings_update_local_window_size", test_nghttp2_submit_settings_update_local_window_size) || - !CU_add_test(pSuite, "session_submit_settings_multiple_times", - test_nghttp2_submit_settings_multiple_times) || !CU_add_test(pSuite, "session_submit_push_promise", test_nghttp2_submit_push_promise) || !CU_add_test(pSuite, "submit_window_update", test_nghttp2_submit_window_update) || !CU_add_test(pSuite, "submit_window_update_local_window_size", test_nghttp2_submit_window_update_local_window_size) || - !CU_add_test(pSuite, "submit_shutdown_notice", - test_nghttp2_submit_shutdown_notice) || + !CU_add_test(pSuite, "submit_altsvc", test_nghttp2_submit_altsvc) || !CU_add_test(pSuite, "submit_invalid_nv", test_nghttp2_submit_invalid_nv) || - !CU_add_test(pSuite, "submit_extension", test_nghttp2_submit_extension) || - !CU_add_test(pSuite, "submit_altsvc", test_nghttp2_submit_altsvc) || !CU_add_test(pSuite, "session_open_stream", test_nghttp2_session_open_stream) || - !CU_add_test(pSuite, "session_open_stream_with_idle_stream_dep", - test_nghttp2_session_open_stream_with_idle_stream_dep) || + !CU_add_test(pSuite, "session_open_stream_with_closed_stream_limit", + test_nghttp2_session_open_stream_with_closed_stream_limit) || !CU_add_test(pSuite, "session_get_next_ob_item", test_nghttp2_session_get_next_ob_item) || !CU_add_test(pSuite, "session_pop_next_ob_item", @@ -216,6 +191,8 @@ test_nghttp2_session_reply_fail) || !CU_add_test(pSuite, "session_max_concurrent_streams", test_nghttp2_session_max_concurrent_streams) || + !CU_add_test(pSuite, "session_stream_close_on_headers_push", + test_nghttp2_session_stream_close_on_headers_push) || !CU_add_test(pSuite, "session_stop_data_with_rst_stream", test_nghttp2_session_stop_data_with_rst_stream) || !CU_add_test(pSuite, "session_defer_data", @@ -257,81 +234,32 @@ !CU_add_test( pSuite, "session_stream_dep_all_your_stream_are_belong_to_us", test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us) || - !CU_add_test(pSuite, "session_stream_attach_item", - test_nghttp2_session_stream_attach_item) || - !CU_add_test(pSuite, "session_stream_attach_item_subtree", - test_nghttp2_session_stream_attach_item_subtree) || - !CU_add_test(pSuite, "session_stream_get_state", - test_nghttp2_session_stream_get_state) || - !CU_add_test(pSuite, "session_stream_get_something", - test_nghttp2_session_stream_get_something) || - !CU_add_test(pSuite, "session_find_stream", - test_nghttp2_session_find_stream) || - !CU_add_test(pSuite, "session_keep_closed_stream", + !CU_add_test(pSuite, "session_stream_attach_data", + test_nghttp2_session_stream_attach_data) || + !CU_add_test(pSuite, "session_stream_attach_data_subtree", + test_nghttp2_session_stream_attach_data_subtree) || + !CU_add_test(pSuite, "session_stream_keep_closed_stream", test_nghttp2_session_keep_closed_stream) || - !CU_add_test(pSuite, "session_keep_idle_stream", - test_nghttp2_session_keep_idle_stream) || - !CU_add_test(pSuite, "session_detach_idle_stream", - test_nghttp2_session_detach_idle_stream) || + !CU_add_test(pSuite, "session_detach_closed_stream", + test_nghttp2_session_detach_closed_stream) || !CU_add_test(pSuite, "session_large_dep_tree", test_nghttp2_session_large_dep_tree) || !CU_add_test(pSuite, "session_graceful_shutdown", test_nghttp2_session_graceful_shutdown) || !CU_add_test(pSuite, "session_on_header_temporal_failure", test_nghttp2_session_on_header_temporal_failure) || - !CU_add_test(pSuite, "session_recv_client_magic", - test_nghttp2_session_recv_client_magic) || + !CU_add_test(pSuite, "session_recv_client_preface", + test_nghttp2_session_recv_client_preface) || !CU_add_test(pSuite, "session_delete_data_item", test_nghttp2_session_delete_data_item) || !CU_add_test(pSuite, "session_open_idle_stream", test_nghttp2_session_open_idle_stream) || - !CU_add_test(pSuite, "session_cancel_reserved_remote", - test_nghttp2_session_cancel_reserved_remote) || - !CU_add_test(pSuite, "session_reset_pending_headers", - test_nghttp2_session_reset_pending_headers) || - !CU_add_test(pSuite, "session_send_data_callback", - test_nghttp2_session_send_data_callback) || - !CU_add_test(pSuite, "session_on_begin_headers_temporal_failure", - test_nghttp2_session_on_begin_headers_temporal_failure) || - !CU_add_test(pSuite, "session_defer_then_close", - test_nghttp2_session_defer_then_close) || - !CU_add_test(pSuite, "session_detach_item_from_closed_stream", - test_nghttp2_session_detach_item_from_closed_stream) || - !CU_add_test(pSuite, "session_flooding", test_nghttp2_session_flooding) || - !CU_add_test(pSuite, "session_change_stream_priority", - test_nghttp2_session_change_stream_priority) || - !CU_add_test(pSuite, "session_repeated_priority_change", - test_nghttp2_session_repeated_priority_change) || - !CU_add_test(pSuite, "session_repeated_priority_submission", - test_nghttp2_session_repeated_priority_submission) || - !CU_add_test(pSuite, "session_set_local_window_size", - test_nghttp2_session_set_local_window_size) || - !CU_add_test(pSuite, "session_cancel_from_before_frame_send", - test_nghttp2_session_cancel_from_before_frame_send) || - !CU_add_test(pSuite, "http_mandatory_headers", - test_nghttp2_http_mandatory_headers) || - !CU_add_test(pSuite, "http_content_length", - test_nghttp2_http_content_length) || - !CU_add_test(pSuite, "http_content_length_mismatch", - test_nghttp2_http_content_length_mismatch) || - !CU_add_test(pSuite, "http_non_final_response", - test_nghttp2_http_non_final_response) || - !CU_add_test(pSuite, "http_trailer_headers", - test_nghttp2_http_trailer_headers) || - !CU_add_test(pSuite, "http_ignore_regular_header", - test_nghttp2_http_ignore_regular_header) || - !CU_add_test(pSuite, "http_ignore_content_length", - test_nghttp2_http_ignore_content_length) || - !CU_add_test(pSuite, "http_record_request_method", - test_nghttp2_http_record_request_method) || - !CU_add_test(pSuite, "http_push_promise", - test_nghttp2_http_push_promise) || - !CU_add_test(pSuite, "http_head_method_upgrade_workaround", - test_nghttp2_http_head_method_upgrade_workaround) || !CU_add_test(pSuite, "frame_pack_headers", test_nghttp2_frame_pack_headers) || !CU_add_test(pSuite, "frame_pack_headers_frame_too_large", test_nghttp2_frame_pack_headers_frame_too_large) || + !CU_add_test(pSuite, "frame_pack_headers_frame_smallest", + test_nghttp2_submit_data_read_length_smallest) || !CU_add_test(pSuite, "frame_pack_priority", test_nghttp2_frame_pack_priority) || !CU_add_test(pSuite, "frame_pack_rst_stream", @@ -368,10 +296,6 @@ test_nghttp2_hd_inflate_clearall_inc) || !CU_add_test(pSuite, "hd_inflate_zero_length_huffman", test_nghttp2_hd_inflate_zero_length_huffman) || - !CU_add_test(pSuite, "hd_inflate_expect_table_size_update", - test_nghttp2_hd_inflate_expect_table_size_update) || - !CU_add_test(pSuite, "hd_inflate_unexpected_table_size_update", - test_nghttp2_hd_inflate_unexpected_table_size_update) || !CU_add_test(pSuite, "hd_ringbuf_reserve", test_nghttp2_hd_ringbuf_reserve) || !CU_add_test(pSuite, "hd_change_table_size", @@ -382,7 +306,6 @@ !CU_add_test(pSuite, "hd_deflate_bound", test_nghttp2_hd_deflate_bound) || !CU_add_test(pSuite, "hd_public_api", test_nghttp2_hd_public_api) || !CU_add_test(pSuite, "hd_decode_length", test_nghttp2_hd_decode_length) || - !CU_add_test(pSuite, "hd_huff_encode", test_nghttp2_hd_huff_encode) || !CU_add_test(pSuite, "adjust_local_window_size", test_nghttp2_adjust_local_window_size) || !CU_add_test(pSuite, "check_header_name", @@ -390,8 +313,6 @@ !CU_add_test(pSuite, "check_header_value", test_nghttp2_check_header_value) || !CU_add_test(pSuite, "bufs_add", test_nghttp2_bufs_add) || - !CU_add_test(pSuite, "bufs_add_stack_buffer_overflow_bug", - test_nghttp2_bufs_add_stack_buffer_overflow_bug) || !CU_add_test(pSuite, "bufs_addb", test_nghttp2_bufs_addb) || !CU_add_test(pSuite, "bufs_orb", test_nghttp2_bufs_orb) || !CU_add_test(pSuite, "bufs_remove", test_nghttp2_bufs_remove) || @@ -410,7 +331,7 @@ num_tests_failed = CU_get_number_of_tests_failed(); CU_cleanup_registry(); if (CU_get_error() == CUE_SUCCESS) { - return (int)num_tests_failed; + return num_tests_failed; } else { printf("CUnit Error: %s\n", CU_get_error_msg()); return CU_get_error(); diff -Nru nghttp2-1.13.0/tests/Makefile.am nghttp2-0.6.7/tests/Makefile.am --- nghttp2-1.13.0/tests/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -22,8 +22,6 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = testdata -EXTRA_DIST = CMakeLists.txt - if HAVE_CUNIT check_PROGRAMS = main @@ -51,16 +49,8 @@ main_SOURCES = $(HFILES) $(OBJECTS) -if ENABLE_STATIC main_LDADD = ${top_builddir}/lib/libnghttp2.la -else -# With static lib disabled and symbol hiding enabled, we have to link object -# files directly because the tests use symbols not included in public API. -main_LDADD = ${top_builddir}/lib/.libs/*.o -endif - -main_LDADD += @CUNIT_LIBS@ @TESTLDADD@ -main_LDFLAGS = -static +main_LDFLAGS = -static @CUNIT_LIBS@ @TESTS_LIBS@ if ENABLE_FAILMALLOC failmalloc_SOURCES = failmalloc.c failmalloc_test.c failmalloc_test.h \ @@ -70,10 +60,7 @@ failmalloc_LDFLAGS = $(main_LDFLAGS) endif # ENABLE_FAILMALLOC -AM_CFLAGS = $(WARNCFLAGS) \ - -I${top_srcdir}/lib \ - -I${top_srcdir}/lib/includes \ - -I${top_builddir}/lib/includes \ +AM_CFLAGS = -Wall -I${top_srcdir}/lib -I${top_srcdir}/lib/includes -I${top_builddir}/lib/includes \ @CUNIT_CFLAGS@ @DEFS@ TESTS = main diff -Nru nghttp2-1.13.0/tests/Makefile.in nghttp2-0.6.7/tests/Makefile.in --- nghttp2-1.13.0/tests/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/tests/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -29,17 +29,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -105,10 +95,11 @@ target_triplet = @target@ @HAVE_CUNIT_TRUE@check_PROGRAMS = main$(EXEEXT) $(am__EXEEXT_1) @ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@am__append_1 = failmalloc -@HAVE_CUNIT_TRUE@am__append_2 = @CUNIT_LIBS@ @TESTLDADD@ @HAVE_CUNIT_TRUE@TESTS = main$(EXEEXT) $(am__EXEEXT_1) -@ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@am__append_3 = failmalloc +@ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@am__append_2 = failmalloc subdir = tests +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -118,13 +109,11 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -140,12 +129,8 @@ @ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@ malloc_wrapper.$(OBJEXT) \ @ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@ nghttp2_test_helper.$(OBJEXT) failmalloc_OBJECTS = $(am_failmalloc_OBJECTS) -am__DEPENDENCIES_1 = -@ENABLE_STATIC_FALSE@@HAVE_CUNIT_TRUE@am__DEPENDENCIES_2 = ${top_builddir}/lib/.libs/*.o \ -@ENABLE_STATIC_FALSE@@HAVE_CUNIT_TRUE@ $(am__DEPENDENCIES_1) -@ENABLE_STATIC_TRUE@@HAVE_CUNIT_TRUE@am__DEPENDENCIES_2 = ${top_builddir}/lib/libnghttp2.la \ -@ENABLE_STATIC_TRUE@@HAVE_CUNIT_TRUE@ $(am__DEPENDENCIES_1) -@ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@failmalloc_DEPENDENCIES = $(am__DEPENDENCIES_2) +@ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@failmalloc_DEPENDENCIES = \ +@ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@ $(main_LDADD) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent @@ -177,10 +162,8 @@ @HAVE_CUNIT_TRUE@ nghttp2_buf_test.$(OBJEXT) @HAVE_CUNIT_TRUE@am_main_OBJECTS = $(am__objects_1) $(am__objects_2) main_OBJECTS = $(am_main_OBJECTS) -@ENABLE_STATIC_FALSE@@HAVE_CUNIT_TRUE@main_DEPENDENCIES = ${top_builddir}/lib/.libs/*.o \ -@ENABLE_STATIC_FALSE@@HAVE_CUNIT_TRUE@ $(am__DEPENDENCIES_1) -@ENABLE_STATIC_TRUE@@HAVE_CUNIT_TRUE@main_DEPENDENCIES = ${top_builddir}/lib/libnghttp2.la \ -@ENABLE_STATIC_TRUE@@HAVE_CUNIT_TRUE@ $(am__DEPENDENCIES_1) +@HAVE_CUNIT_TRUE@main_DEPENDENCIES = \ +@HAVE_CUNIT_TRUE@ ${top_builddir}/lib/libnghttp2.la main_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(main_LDFLAGS) $(LDFLAGS) -o $@ @@ -464,8 +447,6 @@ TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DIST_SUBDIRS = $(SUBDIRS) -am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ - $(top_srcdir)/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -495,7 +476,6 @@ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -514,7 +494,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -530,7 +509,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -546,10 +524,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -561,7 +535,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -599,11 +572,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -658,7 +630,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -680,7 +651,6 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = testdata -EXTRA_DIST = CMakeLists.txt @HAVE_CUNIT_TRUE@OBJECTS = main.c nghttp2_pq_test.c nghttp2_map_test.c nghttp2_queue_test.c \ @HAVE_CUNIT_TRUE@ nghttp2_test_helper.c \ @HAVE_CUNIT_TRUE@ nghttp2_frame_test.c \ @@ -699,23 +669,15 @@ @HAVE_CUNIT_TRUE@ nghttp2_buf_test.h @HAVE_CUNIT_TRUE@main_SOURCES = $(HFILES) $(OBJECTS) -# With static lib disabled and symbol hiding enabled, we have to link object -# files directly because the tests use symbols not included in public API. -@ENABLE_STATIC_FALSE@@HAVE_CUNIT_TRUE@main_LDADD = ${top_builddir}/lib/.libs/*.o \ -@ENABLE_STATIC_FALSE@@HAVE_CUNIT_TRUE@ $(am__append_2) -@ENABLE_STATIC_TRUE@@HAVE_CUNIT_TRUE@main_LDADD = ${top_builddir}/lib/libnghttp2.la \ -@ENABLE_STATIC_TRUE@@HAVE_CUNIT_TRUE@ $(am__append_2) -@HAVE_CUNIT_TRUE@main_LDFLAGS = -static +@HAVE_CUNIT_TRUE@main_LDADD = ${top_builddir}/lib/libnghttp2.la +@HAVE_CUNIT_TRUE@main_LDFLAGS = -static @CUNIT_LIBS@ @TESTS_LIBS@ @ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@failmalloc_SOURCES = failmalloc.c failmalloc_test.c failmalloc_test.h \ @ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@ malloc_wrapper.c malloc_wrapper.h \ @ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@ nghttp2_test_helper.c nghttp2_test_helper.h @ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@failmalloc_LDADD = $(main_LDADD) @ENABLE_FAILMALLOC_TRUE@@HAVE_CUNIT_TRUE@failmalloc_LDFLAGS = $(main_LDFLAGS) -@HAVE_CUNIT_TRUE@AM_CFLAGS = $(WARNCFLAGS) \ -@HAVE_CUNIT_TRUE@ -I${top_srcdir}/lib \ -@HAVE_CUNIT_TRUE@ -I${top_srcdir}/lib/includes \ -@HAVE_CUNIT_TRUE@ -I${top_builddir}/lib/includes \ +@HAVE_CUNIT_TRUE@AM_CFLAGS = -Wall -I${top_srcdir}/lib -I${top_srcdir}/lib/includes -I${top_builddir}/lib/includes \ @HAVE_CUNIT_TRUE@ @CUNIT_CFLAGS@ @DEFS@ all: all-recursive @@ -734,6 +696,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu tests/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -950,7 +913,7 @@ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ - elif test -n "$$redo_logs"; then \ + else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ @@ -1273,8 +1236,6 @@ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am -.PRECIOUS: Makefile - # EXTRA_DIST = end_to_end.py # TESTS += end_to_end.py diff -Nru nghttp2-1.13.0/tests/malloc_wrapper.c nghttp2-0.6.7/tests/malloc_wrapper.c --- nghttp2-1.13.0/tests/malloc_wrapper.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/malloc_wrapper.c 2014-11-30 14:15:07.000000000 +0000 @@ -24,42 +24,32 @@ */ #include "malloc_wrapper.h" +#define __USE_GNU +#include + int nghttp2_failmalloc = 0; int nghttp2_failstart = 0; int nghttp2_countmalloc = 1; int nghttp2_nmalloc = 0; -#define CHECK_PREREQ \ - do { \ - if (nghttp2_failmalloc && nghttp2_nmalloc >= nghttp2_failstart) { \ - return NULL; \ - } \ - if (nghttp2_countmalloc) { \ - ++nghttp2_nmalloc; \ - } \ - } while (0) - -static void *my_malloc(size_t size, void *mud _U_) { - CHECK_PREREQ; - return malloc(size); -} - -static void my_free(void *ptr, void *mud _U_) { free(ptr); } +static void *(*real_malloc)(size_t) = NULL; -static void *my_calloc(size_t nmemb, size_t size, void *mud _U_) { - CHECK_PREREQ; - return calloc(nmemb, size); -} +static void init(void) { real_malloc = dlsym(RTLD_NEXT, "malloc"); } -static void *my_realloc(void *ptr, size_t size, void *mud _U_) { - CHECK_PREREQ; - return realloc(ptr, size); +void *malloc(size_t size) { + if (real_malloc == NULL) { + init(); + } + if (nghttp2_failmalloc && nghttp2_nmalloc >= nghttp2_failstart) { + return NULL; + } else { + if (nghttp2_countmalloc) { + ++nghttp2_nmalloc; + } + return real_malloc(size); + } } -static nghttp2_mem mem = {NULL, my_malloc, my_free, my_calloc, my_realloc}; - -nghttp2_mem *nghttp2_mem_fm(void) { return &mem; } - static int failmalloc_bk, countmalloc_bk; void nghttp2_failmalloc_pause(void) { diff -Nru nghttp2-1.13.0/tests/malloc_wrapper.h nghttp2-0.6.7/tests/malloc_wrapper.h --- nghttp2-1.13.0/tests/malloc_wrapper.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/malloc_wrapper.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,14 +25,8 @@ #ifndef MALLOC_WRAPPER_H #define MALLOC_WRAPPER_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - #include -#include "nghttp2_mem.h" - /* Global variables to control the behavior of malloc() */ /* If nonzero, malloc failure mode is on */ @@ -46,10 +40,7 @@ incremented if nghttp2_nmalloc is nonzero. */ extern int nghttp2_nmalloc; -/* Returns pointer to nghttp2_mem, which, when dereferenced, contains - specifically instrumented memory allocators for failmalloc - tests. */ -nghttp2_mem *nghttp2_mem_fm(void); +void *malloc(size_t size); /* Copies nghttp2_failmalloc and nghttp2_countmalloc to statically allocated space and sets 0 to them. This will effectively make diff -Nru nghttp2-1.13.0/tests/nghttp2_buf_test.c nghttp2-0.6.7/tests/nghttp2_buf_test.c --- nghttp2-1.13.0/tests/nghttp2_buf_test.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_buf_test.c 2014-11-30 14:15:07.000000000 +0000 @@ -33,11 +33,8 @@ int rv; nghttp2_bufs bufs; uint8_t data[2048]; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); - - rv = nghttp2_bufs_init(&bufs, 1000, 3, mem); + rv = nghttp2_bufs_init(&bufs, 1000, 3); CU_ASSERT(0 == rv); CU_ASSERT(bufs.cur->buf.pos == bufs.cur->buf.last); @@ -63,35 +60,12 @@ nghttp2_bufs_free(&bufs); } -/* Test for GH-232, stack-buffer-overflow */ -void test_nghttp2_bufs_add_stack_buffer_overflow_bug(void) { - int rv; - nghttp2_bufs bufs; - uint8_t data[1024]; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - - rv = nghttp2_bufs_init(&bufs, 100, 200, mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_bufs_add(&bufs, data, sizeof(data)); - - CU_ASSERT(0 == rv); - CU_ASSERT(sizeof(data) == nghttp2_bufs_len(&bufs)); - - nghttp2_bufs_free(&bufs); -} - void test_nghttp2_bufs_addb(void) { int rv; nghttp2_bufs bufs; ssize_t i; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - rv = nghttp2_bufs_init(&bufs, 1000, 3, mem); + rv = nghttp2_bufs_init(&bufs, 1000, 3); CU_ASSERT(0 == rv); rv = nghttp2_bufs_addb(&bufs, 14); @@ -104,8 +78,8 @@ rv = nghttp2_bufs_addb(&bufs, 254); CU_ASSERT(0 == rv); - CU_ASSERT((size_t)(i + 2) == nghttp2_buf_len(&bufs.cur->buf)); - CU_ASSERT((size_t)(i + 2) == nghttp2_bufs_len(&bufs)); + CU_ASSERT(i + 2 == nghttp2_buf_len(&bufs.cur->buf)); + CU_ASSERT(i + 2 == nghttp2_bufs_len(&bufs)); CU_ASSERT(254 == *(bufs.cur->buf.last - 1)); CU_ASSERT(bufs.cur == bufs.head); } @@ -152,11 +126,8 @@ void test_nghttp2_bufs_orb(void) { int rv; nghttp2_bufs bufs; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); - - rv = nghttp2_bufs_init(&bufs, 1000, 3, mem); + rv = nghttp2_bufs_init(&bufs, 1000, 3); CU_ASSERT(0 == rv); *(bufs.cur->buf.last) = 0; @@ -190,11 +161,8 @@ int i; uint8_t *out; ssize_t outlen; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - rv = nghttp2_bufs_init(&bufs, 1000, 3, mem); + rv = nghttp2_bufs_init(&bufs, 1000, 3); CU_ASSERT(0 == rv); nghttp2_buf_shift_right(&bufs.cur->buf, 10); @@ -217,10 +185,11 @@ outlen = nghttp2_bufs_remove(&bufs, &out); CU_ASSERT(11 == outlen); - CU_ASSERT(0 == memcmp("hello world", out, (size_t)outlen)); - CU_ASSERT(11 == nghttp2_bufs_len(&bufs)); + CU_ASSERT(0 == memcmp("hello world", out, outlen)); + CU_ASSERT(0 == nghttp2_bufs_len(&bufs)); + CU_ASSERT(bufs.cur->buf.pos == bufs.cur->buf.begin); - mem->free(out, NULL); + free(out); nghttp2_bufs_free(&bufs); } @@ -228,12 +197,9 @@ int rv; nghttp2_bufs bufs; nghttp2_buf_chain *ci; - size_t offset = 9; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); + ssize_t offset = 9; - rv = nghttp2_bufs_init3(&bufs, 250, 3, 1, offset, mem); + rv = nghttp2_bufs_init3(&bufs, 250, 3, 1, offset); CU_ASSERT(0 == rv); rv = nghttp2_bufs_add(&bufs, "foo", 3); @@ -253,7 +219,7 @@ CU_ASSERT(bufs.cur == bufs.head); for (ci = bufs.head; ci; ci = ci->next) { - CU_ASSERT((ssize_t)offset == ci->buf.pos - ci->buf.begin); + CU_ASSERT(offset == ci->buf.pos - ci->buf.begin); CU_ASSERT(ci->buf.pos == ci->buf.last); } @@ -266,11 +232,8 @@ int rv; nghttp2_bufs bufs; int i; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - rv = nghttp2_bufs_init(&bufs, 250, 3, mem); + rv = nghttp2_bufs_init(&bufs, 250, 3); CU_ASSERT(0 == rv); for (i = 0; i < 2; ++i) { @@ -287,11 +250,8 @@ void test_nghttp2_bufs_next_present(void) { int rv; nghttp2_bufs bufs; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); - - rv = nghttp2_bufs_init(&bufs, 250, 3, mem); + rv = nghttp2_bufs_init(&bufs, 250, 3); CU_ASSERT(0 == rv); CU_ASSERT(0 == nghttp2_bufs_next_present(&bufs)); @@ -318,11 +278,8 @@ void test_nghttp2_bufs_realloc(void) { int rv; nghttp2_bufs bufs; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - rv = nghttp2_bufs_init3(&bufs, 266, 3, 1, 10, mem); + rv = nghttp2_bufs_init3(&bufs, 266, 3, 1, 10); CU_ASSERT(0 == rv); /* Create new buffer to see that these buffers are deallocated on diff -Nru nghttp2-1.13.0/tests/nghttp2_buf_test.h nghttp2-0.6.7/tests/nghttp2_buf_test.h --- nghttp2-1.13.0/tests/nghttp2_buf_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_buf_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,12 +25,7 @@ #ifndef NGHTTP2_BUF_TEST_H #define NGHTTP2_BUF_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - void test_nghttp2_bufs_add(void); -void test_nghttp2_bufs_add_stack_buffer_overflow_bug(void); void test_nghttp2_bufs_addb(void); void test_nghttp2_bufs_orb(void); void test_nghttp2_bufs_remove(void); diff -Nru nghttp2-1.13.0/tests/nghttp2_frame_test.c nghttp2-0.6.7/tests/nghttp2_frame_test.c --- nghttp2-1.13.0/tests/nghttp2_frame_test.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_frame_test.c 2014-11-30 14:15:07.000000000 +0000 @@ -47,8 +47,8 @@ #define HEADERS_LENGTH 7 -static nghttp2_nv *headers(nghttp2_mem *mem) { - nghttp2_nv *nva = mem->malloc(sizeof(nghttp2_nv) * HEADERS_LENGTH, NULL); +static nghttp2_nv *headers(void) { + nghttp2_nv *nva = malloc(sizeof(nghttp2_nv) * HEADERS_LENGTH); nva[0] = make_nv("method", "GET"); nva[1] = make_nv("scheme", "https"); nva[2] = make_nv("url", "/"); @@ -75,20 +75,18 @@ nghttp2_bufs bufs; nghttp2_nv *nva; nghttp2_priority_spec pri_spec; - size_t nvlen; + ssize_t nvlen; nva_out out; - size_t hdblocklen; + ssize_t hdblocklen; int rv; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - nghttp2_hd_deflate_init(&deflater, mem); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_deflate_init(&deflater); + nghttp2_hd_inflate_init(&inflater); - nva = headers(mem); + nva = headers(); nvlen = HEADERS_LENGTH; nghttp2_priority_spec_default_init(&pri_spec); @@ -112,15 +110,15 @@ CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == oframe.pri_spec.weight); hdblocklen = nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN; - CU_ASSERT((ssize_t)hdblocklen == - inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem)); + CU_ASSERT(hdblocklen == + inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN)); CU_ASSERT(7 == out.nvlen); CU_ASSERT(nvnameeq("method", &out.nva[0])); CU_ASSERT(nvvalueeq("GET", &out.nva[0])); - nghttp2_frame_headers_free(&oframe, mem); - nva_out_reset(&out, mem); + nghttp2_frame_headers_free(&oframe); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); memset(&oframe, 0, sizeof(oframe)); @@ -146,21 +144,20 @@ hdblocklen = nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN - nghttp2_frame_priority_len(oframe.hd.flags); - CU_ASSERT((ssize_t)hdblocklen == + CU_ASSERT(hdblocklen == inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN + - nghttp2_frame_priority_len(oframe.hd.flags), - mem)); + nghttp2_frame_priority_len(oframe.hd.flags))); nghttp2_nv_array_sort(out.nva, out.nvlen); CU_ASSERT(nvnameeq("method", &out.nva[0])); - nghttp2_frame_headers_free(&oframe, mem); - nva_out_reset(&out, mem); + nghttp2_frame_headers_free(&oframe); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); nghttp2_bufs_free(&bufs); - nghttp2_frame_headers_free(&frame, mem); + nghttp2_frame_headers_free(&frame); nghttp2_hd_inflate_free(&inflater); nghttp2_hd_deflate_free(&deflater); } @@ -175,14 +172,12 @@ size_t big_hdslen = ARRLEN(big_hds); size_t i; int rv; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); for (i = 0; i < big_hdslen; ++i) { big_hds[i].name = (uint8_t *)"header"; - big_hds[i].value = mem->malloc(big_vallen + 1, NULL); + big_hds[i].value = malloc(big_vallen + 1); memset(big_hds[i].value, '0' + (int)i, big_vallen); big_hds[i].value[big_vallen] = '\0'; big_hds[i].namelen = strlen((char *)big_hds[i].name); @@ -190,18 +185,18 @@ big_hds[i].flags = NGHTTP2_NV_FLAG_NONE; } - nghttp2_nv_array_copy(&nva, big_hds, big_hdslen, mem); - nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_nv_array_copy(&nva, big_hds, big_hdslen); + nghttp2_hd_deflate_init(&deflater); nghttp2_frame_headers_init( &frame, NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS, 1000000007, NGHTTP2_HCAT_REQUEST, NULL, nva, big_hdslen); rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater); CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == rv); - nghttp2_frame_headers_free(&frame, mem); + nghttp2_frame_headers_free(&frame); nghttp2_bufs_free(&bufs); for (i = 0; i < big_hdslen; ++i) { - mem->free(big_hds[i].value, NULL); + free(big_hds[i].value); } nghttp2_hd_deflate_free(&deflater); } @@ -284,13 +279,11 @@ nghttp2_settings_entry iv[] = {{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 256}, {NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, 16384}, {NGHTTP2_SETTINGS_HEADER_TABLE_SIZE, 4096}}; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nghttp2_frame_settings_init(&frame, NGHTTP2_FLAG_NONE, - nghttp2_frame_iv_copy(iv, 3, mem), 3); + nghttp2_frame_iv_copy(iv, 3), 3); rv = nghttp2_frame_pack_settings(&bufs, &frame); CU_ASSERT(0 == rv); @@ -307,8 +300,8 @@ } nghttp2_bufs_free(&bufs); - nghttp2_frame_settings_free(&frame, mem); - nghttp2_frame_settings_free(&oframe, mem); + nghttp2_frame_settings_free(&frame); + nghttp2_frame_settings_free(&oframe); } void test_nghttp2_frame_pack_push_promise() { @@ -317,20 +310,18 @@ nghttp2_push_promise frame, oframe; nghttp2_bufs bufs; nghttp2_nv *nva; - size_t nvlen; + ssize_t nvlen; nva_out out; - size_t hdblocklen; + ssize_t hdblocklen; int rv; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - nghttp2_hd_deflate_init(&deflater, mem); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_deflate_init(&deflater); + nghttp2_hd_inflate_init(&inflater); - nva = headers(mem); + nva = headers(); nvlen = HEADERS_LENGTH; nghttp2_frame_push_promise_init(&frame, NGHTTP2_FLAG_END_HEADERS, 1000000007, (1U << 31) - 1, nva, nvlen); @@ -346,17 +337,17 @@ CU_ASSERT((1U << 31) - 1 == oframe.promised_stream_id); hdblocklen = nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN - 4; - CU_ASSERT((ssize_t)hdblocklen == - inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN + 4, mem)); + CU_ASSERT(hdblocklen == + inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN + 4)); CU_ASSERT(7 == out.nvlen); CU_ASSERT(nvnameeq("method", &out.nva[0])); CU_ASSERT(nvvalueeq("GET", &out.nva[0])); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_free(&bufs); - nghttp2_frame_push_promise_free(&oframe, mem); - nghttp2_frame_push_promise_free(&frame, mem); + nghttp2_frame_push_promise_free(&oframe); + nghttp2_frame_push_promise_free(&frame); nghttp2_hd_inflate_free(&inflater); nghttp2_hd_deflate_free(&deflater); } @@ -388,21 +379,18 @@ nghttp2_goaway frame, oframe; nghttp2_bufs bufs; size_t opaque_data_len = 16; - uint8_t *opaque_data; + uint8_t *opaque_data = malloc(opaque_data_len); int rv; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); - opaque_data = mem->malloc(opaque_data_len, NULL); memcpy(opaque_data, "0123456789abcdef", opaque_data_len); nghttp2_frame_goaway_init(&frame, 1000000007, NGHTTP2_PROTOCOL_ERROR, opaque_data, opaque_data_len); rv = nghttp2_frame_pack_goaway(&bufs, &frame); CU_ASSERT(0 == rv); - CU_ASSERT(NGHTTP2_FRAME_HDLEN + 8 + opaque_data_len == + CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 8 + opaque_data_len) == nghttp2_bufs_len(&bufs)); CU_ASSERT(0 == unpack_framebuf((nghttp2_frame *)&oframe, &bufs)); check_frame_header(24, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0, &oframe.hd); @@ -412,7 +400,7 @@ CU_ASSERT(opaque_data_len == oframe.opaque_data_len); CU_ASSERT(memcmp(opaque_data, oframe.opaque_data, opaque_data_len) == 0); - nghttp2_frame_goaway_free(&oframe, mem); + nghttp2_frame_goaway_free(&oframe); nghttp2_bufs_reset(&bufs); /* Unknown error code is passed to callback as is */ @@ -425,9 +413,9 @@ check_frame_header(24, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0, &oframe.hd); CU_ASSERT(1000000009 == oframe.error_code); - nghttp2_frame_goaway_free(&oframe, mem); + nghttp2_frame_goaway_free(&oframe); - nghttp2_frame_goaway_free(&frame, mem); + nghttp2_frame_goaway_free(&frame); nghttp2_bufs_free(&bufs); } @@ -458,53 +446,149 @@ nghttp2_extension frame, oframe; nghttp2_ext_altsvc altsvc, oaltsvc; nghttp2_bufs bufs; + nghttp2_buf *buf; + size_t protocol_id_len, host_len, origin_len; + uint8_t *protocol_id, *host, *origin; + uint8_t *data; + size_t datalen; int rv; size_t payloadlen; - static const uint8_t origin[] = "nghttp2.org"; - static const uint8_t field_value[] = "h2=\":443\""; - nghttp2_buf buf; - uint8_t *rawbuf; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); + protocol_id_len = strlen("h2"); + host_len = strlen("h2.example.org"); + origin_len = strlen("www.example.org"); + + datalen = protocol_id_len + host_len + origin_len; + data = malloc(datalen); + + memcpy(data, "h2", protocol_id_len); + protocol_id = data; + + memcpy(data + protocol_id_len, "h2.example.org", host_len); + host = data + protocol_id_len; + + memcpy(data + protocol_id_len + host_len, "http://www.example.org", + origin_len); + origin = data + protocol_id_len + host_len; frame_pack_bufs_init(&bufs); frame.payload = &altsvc; + + nghttp2_frame_altsvc_init(&frame, 1000000007, 1u << 31, 4000, protocol_id, + protocol_id_len, host, host_len, origin, + origin_len); + + rv = nghttp2_frame_pack_altsvc(&bufs, &frame); + + CU_ASSERT(0 == rv); + + CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_MINLEN + datalen) == + nghttp2_bufs_len(&bufs)); + oframe.payload = &oaltsvc; - rawbuf = nghttp2_mem_malloc(mem, 32); - nghttp2_buf_wrap_init(&buf, rawbuf, 32); + CU_ASSERT(0 == unpack_framebuf((nghttp2_frame *)&oframe, &bufs)); - buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1); - buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1); + check_frame_header(NGHTTP2_ALTSVC_MINLEN + datalen, NGHTTP2_EXT_ALTSVC, + NGHTTP2_FLAG_NONE, 1000000007, &oframe.hd); + CU_ASSERT(1u << 31 == oaltsvc.max_age); + CU_ASSERT(4000 == oaltsvc.port); + + CU_ASSERT(protocol_id_len == oaltsvc.protocol_id_len); + CU_ASSERT(memcmp(protocol_id, oaltsvc.protocol_id, protocol_id_len) == 0); - nghttp2_frame_altsvc_init(&frame, 1000000007, buf.pos, sizeof(origin) - 1, - buf.pos + sizeof(origin) - 1, - sizeof(field_value) - 1); + CU_ASSERT(host_len == oaltsvc.host_len); + CU_ASSERT(memcmp(host, oaltsvc.host, host_len) == 0); - payloadlen = 2 + sizeof(origin) - 1 + sizeof(field_value) - 1; + CU_ASSERT(origin_len == oaltsvc.origin_len); + CU_ASSERT(memcmp(origin, oaltsvc.origin, origin_len) == 0); - rv = nghttp2_frame_pack_altsvc(&bufs, &frame); + nghttp2_frame_altsvc_free(&oframe); + nghttp2_frame_altsvc_free(&frame); - CU_ASSERT(0 == rv); - CU_ASSERT(NGHTTP2_FRAME_HDLEN + payloadlen == nghttp2_bufs_len(&bufs)); + memset(&oframe, 0, sizeof(oframe)); + memset(&oaltsvc, 0, sizeof(oaltsvc)); - rv = unpack_framebuf((nghttp2_frame *)&oframe, &bufs); + buf = &bufs.head->buf; - CU_ASSERT(0 == rv); + CU_ASSERT(buf->pos - buf->begin == 1); - check_frame_header(payloadlen, NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 1000000007, - &oframe.hd); + /* Check no origin case */ + + payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len + host_len; + nghttp2_put_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3])); + + oframe.payload = &oaltsvc; - CU_ASSERT(sizeof(origin) - 1 == oaltsvc.origin_len); - CU_ASSERT(0 == memcmp(origin, oaltsvc.origin, sizeof(origin) - 1)); - CU_ASSERT(sizeof(field_value) - 1 == oaltsvc.field_value_len); CU_ASSERT(0 == - memcmp(field_value, oaltsvc.field_value, sizeof(field_value) - 1)); + nghttp2_frame_unpack_altsvc_payload( + &oframe, buf->pos + NGHTTP2_FRAME_HDLEN, + NGHTTP2_ALTSVC_FIXED_PARTLEN, + buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN, + payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN)); + + CU_ASSERT(protocol_id_len == oaltsvc.protocol_id_len); + CU_ASSERT(host_len == oaltsvc.host_len); + CU_ASSERT(0 == oaltsvc.origin_len); + + memset(&oframe, 0, sizeof(oframe)); + memset(&oaltsvc, 0, sizeof(oaltsvc)); + + /* Check insufficient payload length for host */ + payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len + host_len - 1; + nghttp2_put_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3])); + + oframe.payload = &oaltsvc; + + CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == + nghttp2_frame_unpack_altsvc_payload( + &oframe, buf->pos + NGHTTP2_FRAME_HDLEN, + NGHTTP2_ALTSVC_FIXED_PARTLEN, + buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN, + payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN)); + + memset(&oframe, 0, sizeof(oframe)); + memset(&oaltsvc, 0, sizeof(oaltsvc)); + + /* Check no host case */ + payloadlen = NGHTTP2_ALTSVC_MINLEN + protocol_id_len; + nghttp2_put_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3])); + buf->pos[NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN + + protocol_id_len] = 0; + + oframe.payload = &oaltsvc; + + CU_ASSERT(0 == + nghttp2_frame_unpack_altsvc_payload( + &oframe, buf->pos + NGHTTP2_FRAME_HDLEN, + NGHTTP2_ALTSVC_FIXED_PARTLEN, + buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN, + payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN)); + + CU_ASSERT(protocol_id_len == oaltsvc.protocol_id_len); + CU_ASSERT(0 == oaltsvc.host_len); + CU_ASSERT(0 == oaltsvc.origin_len); + + memset(&oframe, 0, sizeof(oframe)); + memset(&oaltsvc, 0, sizeof(oaltsvc)); + + /* Check missing Host-Len */ + payloadlen = NGHTTP2_ALTSVC_FIXED_PARTLEN + protocol_id_len; + nghttp2_put_uint32be(buf->pos, (uint32_t)((payloadlen << 8) + buf->pos[3])); + + oframe.payload = &oaltsvc; + + CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == + nghttp2_frame_unpack_altsvc_payload( + &oframe, buf->pos + NGHTTP2_FRAME_HDLEN, + NGHTTP2_ALTSVC_FIXED_PARTLEN, + buf->pos + NGHTTP2_FRAME_HDLEN + NGHTTP2_ALTSVC_FIXED_PARTLEN, + payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN)); + + memset(&oframe, 0, sizeof(oframe)); + memset(&oaltsvc, 0, sizeof(oaltsvc)); - nghttp2_frame_altsvc_free(&oframe, mem); - nghttp2_frame_altsvc_free(&frame, mem); nghttp2_bufs_free(&bufs); } @@ -514,49 +598,46 @@ nghttp2_nv emptynv[] = {MAKE_NV("", ""), MAKE_NV("", "")}; nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")}; nghttp2_nv bignv; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); bignv.name = (uint8_t *)"echo"; bignv.namelen = strlen("echo"); bignv.valuelen = (1 << 14) - 1; - bignv.value = mem->malloc(bignv.valuelen, NULL); + bignv.value = malloc(bignv.valuelen); memset(bignv.value, '0', bignv.valuelen); - rv = nghttp2_nv_array_copy(&nva, NULL, 0, mem); + rv = nghttp2_nv_array_copy(&nva, NULL, 0); CU_ASSERT(0 == rv); CU_ASSERT(NULL == nva); - rv = nghttp2_nv_array_copy(&nva, emptynv, ARRLEN(emptynv), mem); + rv = nghttp2_nv_array_copy(&nva, emptynv, ARRLEN(emptynv)); CU_ASSERT(0 == rv); CU_ASSERT(nva[0].namelen == 0); CU_ASSERT(nva[0].valuelen == 0); CU_ASSERT(nva[1].namelen == 0); CU_ASSERT(nva[1].valuelen == 0); - nghttp2_nv_array_del(nva, mem); + nghttp2_nv_array_del(nva); - rv = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv), mem); + rv = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv)); CU_ASSERT(0 == rv); CU_ASSERT(nva[0].namelen == 5); CU_ASSERT(0 == memcmp("alpha", nva[0].name, 5)); - CU_ASSERT(nva[0].valuelen == 5); + CU_ASSERT(nva[0].valuelen = 5); CU_ASSERT(0 == memcmp("bravo", nva[0].value, 5)); CU_ASSERT(nva[1].namelen == 7); CU_ASSERT(0 == memcmp("charlie", nva[1].name, 7)); CU_ASSERT(nva[1].valuelen == 5); CU_ASSERT(0 == memcmp("delta", nva[1].value, 5)); - nghttp2_nv_array_del(nva, mem); + nghttp2_nv_array_del(nva); /* Large header field is acceptable */ - rv = nghttp2_nv_array_copy(&nva, &bignv, 1, mem); + rv = nghttp2_nv_array_copy(&nva, &bignv, 1); CU_ASSERT(0 == rv); - nghttp2_nv_array_del(nva, mem); + nghttp2_nv_array_del(nva); - mem->free(bignv.value, NULL); + free(bignv.value); } void test_nghttp2_iv_check(void) { @@ -591,11 +672,10 @@ iv[1].value = 0; CU_ASSERT(nghttp2_iv_check(iv, 2)); - /* Full size SETTINGS_HEADER_TABLE_SIZE (UINT32_MAX) must be - accepted */ + /* Too large SETTINGS_HEADER_TABLE_SIZE */ iv[1].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; iv[1].value = UINT32_MAX; - CU_ASSERT(nghttp2_iv_check(iv, 2)); + CU_ASSERT(!nghttp2_iv_check(iv, 2)); /* Too small SETTINGS_MAX_FRAME_SIZE */ iv[0].settings_id = NGHTTP2_SETTINGS_MAX_FRAME_SIZE; diff -Nru nghttp2-1.13.0/tests/nghttp2_frame_test.h nghttp2-0.6.7/tests/nghttp2_frame_test.h --- nghttp2-1.13.0/tests/nghttp2_frame_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_frame_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,10 +25,6 @@ #ifndef NGHTTP2_FRAME_TEST_H #define NGHTTP2_FRAME_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - void test_nghttp2_frame_pack_headers(void); void test_nghttp2_frame_pack_headers_frame_too_large(void); void test_nghttp2_frame_pack_priority(void); diff -Nru nghttp2-1.13.0/tests/nghttp2_hd_test.c nghttp2-0.6.7/tests/nghttp2_hd_test.c --- nghttp2-1.13.0/tests/nghttp2_hd_test.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_hd_test.c 2014-11-30 14:15:07.000000000 +0000 @@ -33,6 +33,8 @@ #include "nghttp2_frame.h" #include "nghttp2_test_helper.h" +#define GET_TABLE_ENT(context, index) nghttp2_hd_table_get(context, index) + void test_nghttp2_hd_deflate(void) { nghttp2_hd_deflater deflater; nghttp2_hd_inflater inflater; @@ -50,83 +52,81 @@ ssize_t blocklen; nva_out out; int rv; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, mem)); - CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, mem)); + CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater)); + CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater)); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(3 == out.nvlen); - assert_nv_equal(nva1, out.nva, 3, mem); + assert_nv_equal(nva1, out.nva, 3); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* Second headers */ rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(2 == out.nvlen); - assert_nv_equal(nva2, out.nva, 2, mem); + assert_nv_equal(nva2, out.nva, 2); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* Third headers, including same header field name, but value is not the same. */ rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva3, ARRLEN(nva3)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(3 == out.nvlen); - assert_nv_equal(nva3, out.nva, 3, mem); + assert_nv_equal(nva3, out.nva, 3); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* Fourth headers, including duplicate header fields. */ rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva4, ARRLEN(nva4)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(3 == out.nvlen); - assert_nv_equal(nva4, out.nva, 3, mem); + assert_nv_equal(nva4, out.nva, 3); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* Fifth headers includes empty value */ rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva5, ARRLEN(nva5)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(2 == out.nvlen); - assert_nv_equal(nva5, out.nva, 2, mem); + assert_nv_equal(nva5, out.nva, 2); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* Cleanup */ @@ -138,48 +138,46 @@ void test_nghttp2_hd_deflate_same_indexed_repr(void) { nghttp2_hd_deflater deflater; nghttp2_hd_inflater inflater; - nghttp2_nv nva1[] = {MAKE_NV("host", "alpha"), MAKE_NV("host", "alpha")}; - nghttp2_nv nva2[] = {MAKE_NV("host", "alpha"), MAKE_NV("host", "alpha"), - MAKE_NV("host", "alpha")}; + nghttp2_nv nva1[] = {MAKE_NV("cookie", "alpha"), MAKE_NV("cookie", "alpha")}; + nghttp2_nv nva2[] = {MAKE_NV("cookie", "alpha"), MAKE_NV("cookie", "alpha"), + MAKE_NV("cookie", "alpha")}; nghttp2_bufs bufs; ssize_t blocklen; nva_out out; int rv; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, mem)); - CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, mem)); + CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater)); + CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater)); /* Encode 2 same headers. Emit 1 literal reprs and 1 index repr. */ rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(2 == out.nvlen); - assert_nv_equal(nva1, out.nva, 2, mem); + assert_nv_equal(nva1, out.nva, 2); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* Encode 3 same headers. This time, emits 3 index reprs. */ rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen == 3); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(3 == out.nvlen); - assert_nv_equal(nva2, out.nva, 3, mem); + assert_nv_equal(nva2, out.nva, 3); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* Cleanup */ @@ -194,36 +192,33 @@ ssize_t blocklen; nghttp2_nv nv = MAKE_NV(":path", "/"); nva_out out; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_inflate_init(&inflater); nghttp2_bufs_addb(&bufs, (1 << 7) | 4); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(1 == blocklen); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(1 == out.nvlen); - assert_nv_equal(&nv, out.nva, 1, mem); + assert_nv_equal(&nv, out.nva, 1); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* index = 0 is error */ nghttp2_bufs_addb(&bufs, 1 << 7); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(1 == blocklen); - CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == - inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == inflate_hd(&inflater, &out, &bufs, 0)); nghttp2_bufs_free(&bufs); nghttp2_hd_inflate_free(&inflater); @@ -239,29 +234,25 @@ MAKE_NV("user-agent", "x")}; size_t i; nva_out out; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_inflate_init(&inflater); for (i = 0; i < ARRLEN(nv); ++i) { - CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 57, &nv[i], - NGHTTP2_HD_WITHOUT_INDEXING)); + CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 57, &nv[i], 0)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(1 == out.nvlen); - assert_nv_equal(&nv[i], out.nva, 1, mem); + assert_nv_equal(&nv[i], out.nva, 1); CU_ASSERT(0 == inflater.ctx.hd_table.len); - CU_ASSERT(61 == nghttp2_hd_inflate_get_num_table_entries(&inflater)); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); } @@ -275,32 +266,28 @@ ssize_t blocklen; nghttp2_nv nv = MAKE_NV("user-agent", "nghttp2"); nva_out out; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_inflate_init(&inflater); - CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 57, &nv, - NGHTTP2_HD_WITH_INDEXING)); + CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 57, &nv, 1)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(1 == out.nvlen); - assert_nv_equal(&nv, out.nva, 1, mem); + assert_nv_equal(&nv, out.nva, 1); CU_ASSERT(1 == inflater.ctx.hd_table.len); - CU_ASSERT(62 == nghttp2_hd_inflate_get_num_table_entries(&inflater)); - assert_nv_equal(&nv, nghttp2_hd_inflate_get_table_entry( - &inflater, NGHTTP2_STATIC_TABLE_LENGTH + - inflater.ctx.hd_table.len), - 1, mem); + assert_nv_equal( + &nv, &GET_TABLE_ENT(&inflater.ctx, NGHTTP2_STATIC_TABLE_LENGTH + + inflater.ctx.hd_table.len - 1)->nv, + 1); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_free(&bufs); nghttp2_hd_inflate_free(&inflater); } @@ -309,49 +296,41 @@ nghttp2_hd_inflater inflater; nghttp2_bufs bufs; ssize_t blocklen; - uint8_t value[1025]; + uint8_t value[1024]; nva_out out; nghttp2_nv nv; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_inflate_init(&inflater); memset(value, '0', sizeof(value)); - value[sizeof(value) - 1] = '\0'; nv.value = value; - nv.valuelen = sizeof(value) - 1; + nv.valuelen = sizeof(value); nv.flags = NGHTTP2_NV_FLAG_NONE; - CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 14, &nv, - NGHTTP2_HD_WITH_INDEXING)); - CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 15, &nv, - NGHTTP2_HD_WITH_INDEXING)); - CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 16, &nv, - NGHTTP2_HD_WITH_INDEXING)); - CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 17, &nv, - NGHTTP2_HD_WITH_INDEXING)); + CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 14, &nv, 1)); + CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 15, &nv, 1)); + CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 16, &nv, 1)); + CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 17, &nv, 1)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(4 == out.nvlen); CU_ASSERT(14 == out.nva[0].namelen); CU_ASSERT(0 == memcmp("accept-charset", out.nva[0].name, out.nva[0].namelen)); - CU_ASSERT(sizeof(value) - 1 == out.nva[0].valuelen); + CU_ASSERT(sizeof(value) == out.nva[0].valuelen); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); CU_ASSERT(3 == inflater.ctx.hd_table.len); - CU_ASSERT(64 == nghttp2_hd_inflate_get_num_table_entries(&inflater)); nghttp2_bufs_free(&bufs); nghttp2_hd_inflate_free(&inflater); @@ -371,27 +350,24 @@ MAKE_NV("x", "nghttp2")}; size_t i; nva_out out; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_inflate_init(&inflater); for (i = 0; i < ARRLEN(nv); ++i) { - CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv[i], - NGHTTP2_HD_WITHOUT_INDEXING)); + CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv[i], 0)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(1 == out.nvlen); - assert_nv_equal(&nv[i], out.nva, 1, mem); + assert_nv_equal(&nv[i], out.nva, 1); CU_ASSERT(0 == inflater.ctx.hd_table.len); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); } @@ -405,31 +381,28 @@ ssize_t blocklen; nghttp2_nv nv = MAKE_NV("x-rel", "nghttp2"); nva_out out; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_inflate_init(&inflater); - CU_ASSERT( - 0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING)); + CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv, 1)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(1 == out.nvlen); - assert_nv_equal(&nv, out.nva, 1, mem); + assert_nv_equal(&nv, out.nva, 1); CU_ASSERT(1 == inflater.ctx.hd_table.len); - assert_nv_equal(&nv, nghttp2_hd_inflate_get_table_entry( - &inflater, NGHTTP2_STATIC_TABLE_LENGTH + - inflater.ctx.hd_table.len), - 1, mem); + assert_nv_equal( + &nv, &GET_TABLE_ENT(&inflater.ctx, NGHTTP2_STATIC_TABLE_LENGTH + + inflater.ctx.hd_table.len - 1)->nv, + 1); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_free(&bufs); nghttp2_hd_inflate_free(&inflater); } @@ -439,11 +412,9 @@ nghttp2_bufs bufs; ssize_t blocklen; nghttp2_nv nv; - uint8_t value[4061]; + uint8_t value[4060]; nva_out out; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); bufs_large_init(&bufs, 8192); nva_out_init(&out); @@ -451,55 +422,52 @@ nv.name = (uint8_t *)"alpha"; nv.namelen = strlen((char *)nv.name); memset(value, '0', sizeof(value)); - value[sizeof(value) - 1] = '\0'; nv.value = value; - nv.valuelen = sizeof(value) - 1; + nv.valuelen = sizeof(value); nv.flags = NGHTTP2_NV_FLAG_NONE; - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_inflate_init(&inflater); - CU_ASSERT( - 0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING)); + CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv, 1)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(1 == out.nvlen); - assert_nv_equal(&nv, out.nva, 1, mem); + assert_nv_equal(&nv, out.nva, 1); CU_ASSERT(0 == inflater.ctx.hd_table.len); - nva_out_reset(&out, mem); + nva_out_reset(&out); /* Do it again */ - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(1 == out.nvlen); - assert_nv_equal(&nv, out.nva, 1, mem); + assert_nv_equal(&nv, out.nva, 1); CU_ASSERT(0 == inflater.ctx.hd_table.len); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* This time, 4096 bytes space required, which is just fits in the header table */ - nv.valuelen = sizeof(value) - 2; + nv.valuelen = sizeof(value) - 1; - CU_ASSERT( - 0 == nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING)); + CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv, 1)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(1 == out.nvlen); - assert_nv_equal(&nv, out.nva, 1, mem); + assert_nv_equal(&nv, out.nva, 1); CU_ASSERT(1 == inflater.ctx.hd_table.len); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); nghttp2_bufs_free(&bufs); @@ -512,9 +480,7 @@ /* Literal header without indexing - new name */ uint8_t data[] = {0x40, 0x01, 0x78 /* 'x' */, 0x80}; nva_out out; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); @@ -527,8 +493,8 @@ /* ptr[2] = 'x'; */ /* ptr[3] = 0x80; */ - nghttp2_hd_inflate_init(&inflater, mem); - CU_ASSERT(4 == inflate_hd(&inflater, &out, &bufs, 0, mem)); + nghttp2_hd_inflate_init(&inflater); + CU_ASSERT(4 == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(1 == out.nvlen); CU_ASSERT(1 == out.nva[0].namelen); @@ -536,121 +502,7 @@ CU_ASSERT(NULL == out.nva[0].value); CU_ASSERT(0 == out.nva[0].valuelen); - nva_out_reset(&out, mem); - nghttp2_bufs_free(&bufs); - nghttp2_hd_inflate_free(&inflater); -} - -void test_nghttp2_hd_inflate_expect_table_size_update(void) { - nghttp2_hd_inflater inflater; - nghttp2_bufs bufs; - nghttp2_mem *mem; - /* Indexed Header: :method: GET */ - uint8_t data[] = {0x82}; - nva_out out; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - nva_out_init(&out); - - nghttp2_bufs_add(&bufs, data, sizeof(data)); - nghttp2_hd_inflate_init(&inflater, mem); - /* This will make inflater require table size update in the next - inflation. */ - nghttp2_hd_inflate_change_table_size(&inflater, 4095); - nghttp2_hd_inflate_change_table_size(&inflater, 4096); - CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == - inflate_hd(&inflater, &out, &bufs, 0, mem)); - - nva_out_reset(&out, mem); - nghttp2_hd_inflate_free(&inflater); - - /* This does not require for encoder to emit table size update since - * size is not changed. */ - nghttp2_hd_inflate_init(&inflater, mem); - nghttp2_hd_inflate_change_table_size(&inflater, 4096); - CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == - inflate_hd(&inflater, &out, &bufs, 0, mem)); - - nva_out_reset(&out, mem); - nghttp2_hd_inflate_free(&inflater); - - /* This does not require for encodre to emit table size update since - new size is larger than current size. */ - nghttp2_hd_inflate_init(&inflater, mem); - nghttp2_hd_inflate_change_table_size(&inflater, 4097); - CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == - inflate_hd(&inflater, &out, &bufs, 0, mem)); - - nva_out_reset(&out, mem); - nghttp2_hd_inflate_free(&inflater); - - /* Received table size is strictly larger than minimum table size */ - nghttp2_hd_inflate_init(&inflater, mem); - nghttp2_hd_inflate_change_table_size(&inflater, 111); - nghttp2_hd_inflate_change_table_size(&inflater, 4096); - - nghttp2_bufs_reset(&bufs); - nghttp2_hd_emit_table_size(&bufs, 112); - - CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == - inflate_hd(&inflater, &out, &bufs, 0, mem)); - - nva_out_reset(&out, mem); - nghttp2_hd_inflate_free(&inflater); - - /* Receiving 2 table size updates, min and last value */ - nghttp2_hd_inflate_init(&inflater, mem); - nghttp2_hd_inflate_change_table_size(&inflater, 111); - nghttp2_hd_inflate_change_table_size(&inflater, 4096); - - nghttp2_bufs_reset(&bufs); - nghttp2_hd_emit_table_size(&bufs, 111); - nghttp2_hd_emit_table_size(&bufs, 4096); - - CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == - inflate_hd(&inflater, &out, &bufs, 0, mem)); - - nva_out_reset(&out, mem); - nghttp2_hd_inflate_free(&inflater); - - /* 2nd update is larger than last value */ - nghttp2_hd_inflate_init(&inflater, mem); - nghttp2_hd_inflate_change_table_size(&inflater, 111); - nghttp2_hd_inflate_change_table_size(&inflater, 4095); - - nghttp2_bufs_reset(&bufs); - nghttp2_hd_emit_table_size(&bufs, 111); - nghttp2_hd_emit_table_size(&bufs, 4096); - - CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == - inflate_hd(&inflater, &out, &bufs, 0, mem)); - - nva_out_reset(&out, mem); - nghttp2_hd_inflate_free(&inflater); - - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_hd_inflate_unexpected_table_size_update(void) { - nghttp2_hd_inflater inflater; - nghttp2_bufs bufs; - nghttp2_mem *mem; - /* Indexed Header: :method: GET, followed by table size update. - This violates RFC 7541. */ - uint8_t data[] = {0x82, 0x20}; - nva_out out; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - nva_out_init(&out); - - nghttp2_bufs_add(&bufs, data, sizeof(data)); - nghttp2_hd_inflate_init(&inflater, mem); - CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == - inflate_hd(&inflater, &out, &bufs, 0, mem)); - - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_free(&bufs); nghttp2_hd_inflate_free(&inflater); } @@ -664,9 +516,7 @@ int i; ssize_t rv; ssize_t blocklen; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); @@ -674,11 +524,11 @@ nv.name = (uint8_t *)"a"; nv.namelen = strlen((const char *)nv.name); nv.valuelen = 4; - nv.value = mem->malloc(nv.valuelen + 1, NULL); + nv.value = malloc(nv.valuelen); memset(nv.value, 0, nv.valuelen); - nghttp2_hd_deflate_init2(&deflater, 8000, mem); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_deflate_init2(&deflater, 8000); + nghttp2_hd_inflate_init(&inflater); nghttp2_hd_inflate_change_table_size(&inflater, 8000); nghttp2_hd_deflate_change_table_size(&deflater, 8000); @@ -686,17 +536,17 @@ for (i = 0; i < 150; ++i) { memcpy(nv.value, &i, sizeof(i)); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv, 1); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(1 == out.nvlen); - assert_nv_equal(&nv, out.nva, 1, mem); + assert_nv_equal(&nv, out.nva, 1); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); } @@ -704,7 +554,7 @@ nghttp2_hd_inflate_free(&inflater); nghttp2_hd_deflate_free(&deflater); - mem->free(nv.value, NULL); + free(nv.value); } void test_nghttp2_hd_change_table_size(void) { @@ -716,15 +566,13 @@ ssize_t rv; nva_out out; ssize_t blocklen; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); - nghttp2_hd_deflate_init(&deflater, mem); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_deflate_init(&deflater); + nghttp2_hd_inflate_init(&inflater); /* inflater changes notifies 8000 max header table size */ CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 8000)); @@ -737,21 +585,19 @@ /* This will emit encoding context update with header table size 4096 */ rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); CU_ASSERT(2 == deflater.ctx.hd_table.len); - CU_ASSERT(63 == nghttp2_hd_deflate_get_num_table_entries(&deflater)); CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(2 == inflater.ctx.hd_table.len); - CU_ASSERT(63 == nghttp2_hd_inflate_get_num_table_entries(&inflater)); CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max); CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* inflater changes header table size to 1024 */ @@ -764,21 +610,19 @@ CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); CU_ASSERT(2 == deflater.ctx.hd_table.len); - CU_ASSERT(63 == nghttp2_hd_deflate_get_num_table_entries(&deflater)); CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(2 == inflater.ctx.hd_table.len); - CU_ASSERT(63 == nghttp2_hd_inflate_get_num_table_entries(&inflater)); CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max); CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* inflater changes header table size to 0 */ @@ -786,30 +630,26 @@ CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 0)); CU_ASSERT(0 == deflater.ctx.hd_table.len); - CU_ASSERT(61 == nghttp2_hd_deflate_get_num_table_entries(&deflater)); CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max); CU_ASSERT(0 == inflater.ctx.hd_table.len); - CU_ASSERT(61 == nghttp2_hd_inflate_get_num_table_entries(&inflater)); CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max); CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); CU_ASSERT(0 == deflater.ctx.hd_table.len); - CU_ASSERT(61 == nghttp2_hd_deflate_get_num_table_entries(&deflater)); CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(0 == inflater.ctx.hd_table.len); - CU_ASSERT(61 == nghttp2_hd_inflate_get_num_table_entries(&inflater)); CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max); CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); nghttp2_bufs_free(&bufs); @@ -819,69 +659,65 @@ /* Check table buffer is expanded */ frame_pack_bufs_init(&bufs); - nghttp2_hd_deflate_init2(&deflater, 8192, mem); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_deflate_init2(&deflater, 8192); + nghttp2_hd_inflate_init(&inflater); /* First inflater changes header table size to 8000 */ CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 8000)); CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 8000)); CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max); - CU_ASSERT(8000 == nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater)); + CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max); - CU_ASSERT(8000 == nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater)); CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); CU_ASSERT(2 == deflater.ctx.hd_table.len); CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(2 == inflater.ctx.hd_table.len); CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max); CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 16383)); CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 16383)); CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max); - CU_ASSERT(8192 == nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater)); CU_ASSERT(16383 == inflater.ctx.hd_table_bufsize_max); - CU_ASSERT(16383 == nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater)); CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); CU_ASSERT(2 == deflater.ctx.hd_table.len); CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(2 == inflater.ctx.hd_table.len); CU_ASSERT(8192 == inflater.ctx.hd_table_bufsize_max); CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); /* Lastly, check the error condition */ rv = nghttp2_hd_emit_table_size(&bufs, 25600); CU_ASSERT(rv == 0); - CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == - inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == inflate_hd(&inflater, &out, &bufs, 0)); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); nghttp2_hd_inflate_free(&inflater); @@ -889,57 +725,57 @@ /* Check that encoder can handle the case where its allowable buffer size is less than default size, 4096 */ - nghttp2_hd_deflate_init2(&deflater, 1024, mem); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_deflate_init2(&deflater, 1024); + nghttp2_hd_inflate_init(&inflater); CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max); /* This emits context update with buffer size 1024 */ rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); CU_ASSERT(2 == deflater.ctx.hd_table.len); CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(2 == inflater.ctx.hd_table.len); CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max); CU_ASSERT(4096 == inflater.settings_hd_table_bufsize_max); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); nghttp2_hd_inflate_free(&inflater); nghttp2_hd_deflate_free(&deflater); /* Check that table size UINT32_MAX can be received */ - nghttp2_hd_deflate_init2(&deflater, UINT32_MAX, mem); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_deflate_init2(&deflater, UINT32_MAX); + nghttp2_hd_inflate_init(&inflater); CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, UINT32_MAX)); CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, UINT32_MAX)); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(UINT32_MAX == deflater.ctx.hd_table_bufsize_max); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(UINT32_MAX == inflater.ctx.hd_table_bufsize_max); CU_ASSERT(UINT32_MAX == inflater.settings_hd_table_bufsize_max); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); nghttp2_hd_inflate_free(&inflater); nghttp2_hd_deflate_free(&deflater); /* Check that context update emitted twice */ - nghttp2_hd_deflate_init2(&deflater, 4096, mem); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_deflate_init2(&deflater, 4096); + nghttp2_hd_inflate_init(&inflater); CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 0)); CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 3000)); @@ -950,18 +786,18 @@ CU_ASSERT(3000 == deflater.ctx.hd_table_bufsize_max); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, 1); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(3 < blocklen); CU_ASSERT(3000 == deflater.ctx.hd_table_bufsize_max); CU_ASSERT(UINT32_MAX == deflater.min_hd_table_bufsize_max); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(3000 == inflater.ctx.hd_table_bufsize_max); CU_ASSERT(3000 == inflater.settings_hd_table_bufsize_max); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_reset(&bufs); nghttp2_hd_inflate_free(&inflater); @@ -972,8 +808,7 @@ static void check_deflate_inflate(nghttp2_hd_deflater *deflater, nghttp2_hd_inflater *inflater, - nghttp2_nv *nva, size_t nvlen, - nghttp2_mem *mem) { + nghttp2_nv *nva, size_t nvlen) { nghttp2_bufs bufs; ssize_t blocklen; nva_out out; @@ -983,17 +818,17 @@ nva_out_init(&out); rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nva, nvlen); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen >= 0); - CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0)); CU_ASSERT(nvlen == out.nvlen); - assert_nv_equal(nva, out.nva, nvlen, mem); + assert_nv_equal(nva, out.nva, nvlen); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_free(&bufs); } @@ -1001,20 +836,25 @@ nghttp2_hd_deflater deflater; nghttp2_hd_inflater inflater; nghttp2_nv nv1[] = { - MAKE_NV(":status", "200 OK"), MAKE_NV("access-control-allow-origin", "*"), + MAKE_NV(":status", "200 OK"), + MAKE_NV("access-control-allow-origin", "*"), MAKE_NV("cache-control", "private, max-age=0, must-revalidate"), - MAKE_NV("content-length", "76073"), MAKE_NV("content-type", "text/html"), + MAKE_NV("content-length", "76073"), + MAKE_NV("content-type", "text/html"), MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"), MAKE_NV("expires", "Sat, 27 Jul 2013 06:22:12 GMT"), - MAKE_NV("server", "Apache"), MAKE_NV("vary", "foobar"), + MAKE_NV("server", "Apache"), + MAKE_NV("vary", "foobar"), MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"), MAKE_NV("x-cache", "MISS from alphabravo"), - MAKE_NV("x-cache-action", "MISS"), MAKE_NV("x-cache-age", "0"), + MAKE_NV("x-cache-action", "MISS"), + MAKE_NV("x-cache-age", "0"), MAKE_NV("x-cache-lookup", "MISS from alphabravo:3128"), MAKE_NV("x-lb-nocache", "true"), }; nghttp2_nv nv2[] = { - MAKE_NV(":status", "304 Not Modified"), MAKE_NV("age", "0"), + MAKE_NV(":status", "304 Not Modified"), + MAKE_NV("age", "0"), MAKE_NV("cache-control", "max-age=56682045"), MAKE_NV("content-type", "text/css"), MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"), @@ -1025,7 +865,8 @@ MAKE_NV("x-cache", "HIT from alphabravo"), MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128")}; nghttp2_nv nv3[] = { - MAKE_NV(":status", "304 Not Modified"), MAKE_NV("age", "0"), + MAKE_NV(":status", "304 Not Modified"), + MAKE_NV("age", "0"), MAKE_NV("cache-control", "max-age=56682072"), MAKE_NV("content-type", "text/css"), MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"), @@ -1037,7 +878,8 @@ MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"), }; nghttp2_nv nv4[] = { - MAKE_NV(":status", "304 Not Modified"), MAKE_NV("age", "0"), + MAKE_NV(":status", "304 Not Modified"), + MAKE_NV("age", "0"), MAKE_NV("cache-control", "max-age=56682022"), MAKE_NV("content-type", "text/css"), MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"), @@ -1049,7 +891,8 @@ MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"), }; nghttp2_nv nv5[] = { - MAKE_NV(":status", "304 Not Modified"), MAKE_NV("age", "0"), + MAKE_NV(":status", "304 Not Modified"), + MAKE_NV("age", "0"), MAKE_NV("cache-control", "max-age=4461139"), MAKE_NV("content-type", "application/x-javascript"), MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"), @@ -1061,7 +904,8 @@ MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"), }; nghttp2_nv nv6[] = { - MAKE_NV(":status", "304 Not Modified"), MAKE_NV("age", "0"), + MAKE_NV(":status", "304 Not Modified"), + MAKE_NV("age", "0"), MAKE_NV("cache-control", "max-age=18645951"), MAKE_NV("content-type", "application/x-javascript"), MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"), @@ -1073,7 +917,8 @@ MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"), }; nghttp2_nv nv7[] = { - MAKE_NV(":status", "304 Not Modified"), MAKE_NV("age", "0"), + MAKE_NV(":status", "304 Not Modified"), + MAKE_NV("age", "0"), MAKE_NV("cache-control", "max-age=31536000"), MAKE_NV("content-type", "application/javascript"), MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"), @@ -1085,7 +930,8 @@ MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"), }; nghttp2_nv nv8[] = { - MAKE_NV(":status", "304 Not Modified"), MAKE_NV("age", "0"), + MAKE_NV(":status", "304 Not Modified"), + MAKE_NV("age", "0"), MAKE_NV("cache-control", "max-age=31536000"), MAKE_NV("content-type", "application/javascript"), MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"), @@ -1097,7 +943,8 @@ MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"), }; nghttp2_nv nv9[] = { - MAKE_NV(":status", "304 Not Modified"), MAKE_NV("age", "0"), + MAKE_NV(":status", "304 Not Modified"), + MAKE_NV("age", "0"), MAKE_NV("cache-control", "max-age=31536000"), MAKE_NV("content-type", "application/javascript"), MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"), @@ -1109,7 +956,8 @@ MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"), }; nghttp2_nv nv10[] = { - MAKE_NV(":status", "304 Not Modified"), MAKE_NV("age", "0"), + MAKE_NV(":status", "304 Not Modified"), + MAKE_NV("age", "0"), MAKE_NV("cache-control", "max-age=56682045"), MAKE_NV("content-type", "text/css"), MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"), @@ -1120,23 +968,20 @@ MAKE_NV("x-cache", "HIT from alphabravo"), MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"), }; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); + nghttp2_hd_deflate_init(&deflater); + nghttp2_hd_inflate_init(&inflater); - nghttp2_hd_deflate_init(&deflater, mem); - nghttp2_hd_inflate_init(&inflater, mem); - - check_deflate_inflate(&deflater, &inflater, nv1, ARRLEN(nv1), mem); - check_deflate_inflate(&deflater, &inflater, nv2, ARRLEN(nv2), mem); - check_deflate_inflate(&deflater, &inflater, nv3, ARRLEN(nv3), mem); - check_deflate_inflate(&deflater, &inflater, nv4, ARRLEN(nv4), mem); - check_deflate_inflate(&deflater, &inflater, nv5, ARRLEN(nv5), mem); - check_deflate_inflate(&deflater, &inflater, nv6, ARRLEN(nv6), mem); - check_deflate_inflate(&deflater, &inflater, nv7, ARRLEN(nv7), mem); - check_deflate_inflate(&deflater, &inflater, nv8, ARRLEN(nv8), mem); - check_deflate_inflate(&deflater, &inflater, nv9, ARRLEN(nv9), mem); - check_deflate_inflate(&deflater, &inflater, nv10, ARRLEN(nv10), mem); + check_deflate_inflate(&deflater, &inflater, nv1, ARRLEN(nv1)); + check_deflate_inflate(&deflater, &inflater, nv2, ARRLEN(nv2)); + check_deflate_inflate(&deflater, &inflater, nv3, ARRLEN(nv3)); + check_deflate_inflate(&deflater, &inflater, nv4, ARRLEN(nv4)); + check_deflate_inflate(&deflater, &inflater, nv5, ARRLEN(nv5)); + check_deflate_inflate(&deflater, &inflater, nv6, ARRLEN(nv6)); + check_deflate_inflate(&deflater, &inflater, nv7, ARRLEN(nv7)); + check_deflate_inflate(&deflater, &inflater, nv8, ARRLEN(nv8)); + check_deflate_inflate(&deflater, &inflater, nv9, ARRLEN(nv9)); + check_deflate_inflate(&deflater, &inflater, nv10, ARRLEN(nv10)); nghttp2_hd_inflate_free(&inflater); nghttp2_hd_deflate_free(&deflater); @@ -1155,9 +1000,6 @@ size_t i; nva_out out; int rv; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); /* 1st :method: GET can be indexable, last one is not */ for (i = 1; i < ARRLEN(nva); ++i) { @@ -1168,25 +1010,25 @@ nva_out_init(&out); - nghttp2_hd_deflate_init(&deflater, mem); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_deflate_init(&deflater); + nghttp2_hd_inflate_init(&inflater); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva)); - blocklen = (ssize_t)nghttp2_bufs_len(&bufs); + blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); CU_ASSERT(blocklen > 0); - CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(ARRLEN(nva) == out.nvlen); - assert_nv_equal(nva, out.nva, ARRLEN(nva), mem); + assert_nv_equal(nva, out.nva, ARRLEN(nva)); CU_ASSERT(out.nva[0].flags == NGHTTP2_NV_FLAG_NONE); for (i = 1; i < ARRLEN(nva); ++i) { CU_ASSERT(out.nva[i].flags == NGHTTP2_NV_FLAG_NO_INDEX); } - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_free(&bufs); nghttp2_hd_inflate_free(&inflater); @@ -1198,12 +1040,10 @@ nghttp2_nv nva[] = {MAKE_NV(":method", "GET"), MAKE_NV("alpha", "bravo")}; nghttp2_bufs bufs; size_t bound, bound2; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); - nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_hd_deflate_init(&deflater); bound = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva)); @@ -1231,9 +1071,6 @@ size_t buflen; ssize_t blocklen; nghttp2_bufs bufs; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); CU_ASSERT(0 == nghttp2_hd_deflate_new(&deflater, 4096)); CU_ASSERT(0 == nghttp2_hd_inflate_new(&inflater)); @@ -1244,10 +1081,10 @@ CU_ASSERT(blocklen > 0); - nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem); + nghttp2_bufs_wrap_init(&bufs, buf, blocklen); bufs.head->buf.last += blocklen; - CU_ASSERT(blocklen == inflate_hd(inflater, NULL, &bufs, 0, mem)); + CU_ASSERT(blocklen == inflate_hd(inflater, NULL, &bufs, 0)); nghttp2_bufs_wrap_free(&bufs); @@ -1257,8 +1094,8 @@ /* See NGHTTP2_ERR_INSUFF_BUFSIZE */ CU_ASSERT(0 == nghttp2_hd_deflate_new(&deflater, 4096)); - blocklen = nghttp2_hd_deflate_hd(deflater, buf, (size_t)(blocklen - 1), nva, - ARRLEN(nva)); + blocklen = + nghttp2_hd_deflate_hd(deflater, buf, blocklen - 1, nva, ARRLEN(nva)); CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == blocklen); @@ -1266,24 +1103,21 @@ } static size_t encode_length(uint8_t *buf, uint64_t n, size_t prefix) { - size_t k = (size_t)((1 << prefix) - 1); + size_t k = (1 << prefix) - 1; size_t len = 0; - *buf = (uint8_t)(*buf & ~k); + *buf &= ~k; if (n >= k) { - *buf = (uint8_t)(*buf | k); - ++buf; + *buf++ |= k; n -= k; ++len; } else { - *buf = (uint8_t)(*buf | n); - ++buf; + *buf++ |= n; return 1; } do { ++len; if (n >= 128) { - *buf = (uint8_t)((1 << 7) | (n & 0x7f)); - ++buf; + *buf++ = (1 << 7) | (n & 0x7f); n >>= 7; } else { *buf++ = (uint8_t)n; @@ -1342,33 +1176,3 @@ CU_ASSERT(-1 == rv); } - -void test_nghttp2_hd_huff_encode(void) { - int rv; - ssize_t len; - nghttp2_buf outbuf; - nghttp2_bufs bufs; - nghttp2_hd_huff_decode_context ctx; - const uint8_t t1[] = {22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, - 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; - uint8_t b[256]; - - nghttp2_buf_wrap_init(&outbuf, b, sizeof(b)); - frame_pack_bufs_init(&bufs); - - rv = nghttp2_hd_huff_encode(&bufs, t1, sizeof(t1)); - - CU_ASSERT(rv == 0); - - nghttp2_hd_huff_decode_context_init(&ctx); - - len = nghttp2_hd_huff_decode(&ctx, &outbuf, bufs.cur->buf.pos, - nghttp2_bufs_len(&bufs), 1); - - CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == len); - CU_ASSERT((ssize_t)sizeof(t1) == nghttp2_buf_len(&outbuf)); - - CU_ASSERT(0 == memcmp(t1, outbuf.pos, sizeof(t1))); - - nghttp2_bufs_free(&bufs); -} diff -Nru nghttp2-1.13.0/tests/nghttp2_hd_test.h nghttp2-0.6.7/tests/nghttp2_hd_test.h --- nghttp2-1.13.0/tests/nghttp2_hd_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_hd_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,10 +25,6 @@ #ifndef NGHTTP2_HD_TEST_H #define NGHTTP2_HD_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - void test_nghttp2_hd_deflate(void); void test_nghttp2_hd_deflate_same_indexed_repr(void); void test_nghttp2_hd_inflate_indexed(void); @@ -39,8 +35,6 @@ void test_nghttp2_hd_inflate_newname_inc(void); void test_nghttp2_hd_inflate_clearall_inc(void); void test_nghttp2_hd_inflate_zero_length_huffman(void); -void test_nghttp2_hd_inflate_expect_table_size_update(void); -void test_nghttp2_hd_inflate_unexpected_table_size_update(void); void test_nghttp2_hd_ringbuf_reserve(void); void test_nghttp2_hd_change_table_size(void); void test_nghttp2_hd_deflate_inflate(void); @@ -48,6 +42,5 @@ void test_nghttp2_hd_deflate_bound(void); void test_nghttp2_hd_public_api(void); void test_nghttp2_hd_decode_length(void); -void test_nghttp2_hd_huff_encode(void); #endif /* NGHTTP2_HD_TEST_H */ diff -Nru nghttp2-1.13.0/tests/nghttp2_helper_test.h nghttp2-0.6.7/tests/nghttp2_helper_test.h --- nghttp2-1.13.0/tests/nghttp2_helper_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_helper_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,10 +25,6 @@ #ifndef NGHTTP2_HELPER_TEST_H #define NGHTTP2_HELPER_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - void test_nghttp2_adjust_local_window_size(void); void test_nghttp2_check_header_name(void); void test_nghttp2_check_header_value(void); diff -Nru nghttp2-1.13.0/tests/nghttp2_map_test.c nghttp2-0.6.7/tests/nghttp2_map_test.c --- nghttp2-1.13.0/tests/nghttp2_map_test.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_map_test.c 2014-11-30 14:15:07.000000000 +0000 @@ -41,7 +41,7 @@ void test_nghttp2_map(void) { strentry foo, FOO, bar, baz, shrubbery; nghttp2_map map; - nghttp2_map_init(&map, nghttp2_mem_default()); + nghttp2_map_init(&map); strentry_init(&foo, 1, "foo"); strentry_init(&FOO, 1, "FOO"); @@ -93,7 +93,7 @@ static void shuffle(int *a, int n) { int i; for (i = n - 1; i >= 1; --i) { - size_t j = (size_t)((double)(i + 1) * rand() / (RAND_MAX + 1.0)); + size_t j = (int)((double)(i + 1) * rand() / (RAND_MAX + 1.0)); int t = a[j]; a[j] = a[i]; a[i] = t; @@ -103,14 +103,14 @@ static int eachfun(nghttp2_map_entry *entry _U_, void *ptr _U_) { return 0; } #define NUM_ENT 6000 -static strentry arr[NUM_ENT]; -static int order[NUM_ENT]; +strentry arr[NUM_ENT]; +int order[NUM_ENT]; void test_nghttp2_map_functional(void) { nghttp2_map map; int i; - nghttp2_map_init(&map, nghttp2_mem_default()); + nghttp2_map_init(&map); for (i = 0; i < NUM_ENT; ++i) { strentry_init(&arr[i], i + 1, "foo"); order[i] = i + 1; @@ -145,21 +145,17 @@ nghttp2_map_free(&map); } -static int entry_free(nghttp2_map_entry *entry, void *ptr) { - nghttp2_mem *mem = ptr; - - mem->free(entry, NULL); +static int entry_free(nghttp2_map_entry *entry, void *ptr _U_) { + free(entry); return 0; } void test_nghttp2_map_each_free(void) { - nghttp2_mem *mem = nghttp2_mem_default(); - strentry *foo = mem->malloc(sizeof(strentry), NULL), - *bar = mem->malloc(sizeof(strentry), NULL), - *baz = mem->malloc(sizeof(strentry), NULL), - *shrubbery = mem->malloc(sizeof(strentry), NULL); + strentry *foo = malloc(sizeof(strentry)), *bar = malloc(sizeof(strentry)), + *baz = malloc(sizeof(strentry)), + *shrubbery = malloc(sizeof(strentry)); nghttp2_map map; - nghttp2_map_init(&map, nghttp2_mem_default()); + nghttp2_map_init(&map); strentry_init(foo, 1, "foo"); strentry_init(bar, 2, "bar"); @@ -171,6 +167,6 @@ nghttp2_map_insert(&map, &baz->map_entry); nghttp2_map_insert(&map, &shrubbery->map_entry); - nghttp2_map_each_free(&map, entry_free, mem); + nghttp2_map_each_free(&map, entry_free, NULL); nghttp2_map_free(&map); } diff -Nru nghttp2-1.13.0/tests/nghttp2_map_test.h nghttp2-0.6.7/tests/nghttp2_map_test.h --- nghttp2-1.13.0/tests/nghttp2_map_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_map_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,10 +25,6 @@ #ifndef NGHTTP2_MAP_TEST_H #define NGHTTP2_MAP_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - void test_nghttp2_map(void); void test_nghttp2_map_functional(void); void test_nghttp2_map_each_free(void); diff -Nru nghttp2-1.13.0/tests/nghttp2_npn_test.c nghttp2-0.6.7/tests/nghttp2_npn_test.c --- nghttp2-1.13.0/tests/nghttp2_npn_test.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_npn_test.c 2014-11-30 14:15:07.000000000 +0000 @@ -30,8 +30,9 @@ #include static void http2(void) { - const unsigned char p[] = {8, 'h', 't', 't', 'p', '/', '1', '.', '1', 2, - 'h', '2', 6, 's', 'p', 'd', 'y', '/', '3'}; + const unsigned char p[] = {8, 'h', 't', 't', 'p', '/', '1', '.', + '1', 5, 'h', '2', '-', '1', '4', 6, + 's', 'p', 'd', 'y', '/', '3'}; unsigned char outlen; unsigned char *out; CU_ASSERT(1 == nghttp2_select_next_protocol(&out, &outlen, p, sizeof(p))); diff -Nru nghttp2-1.13.0/tests/nghttp2_npn_test.h nghttp2-0.6.7/tests/nghttp2_npn_test.h --- nghttp2-1.13.0/tests/nghttp2_npn_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_npn_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,10 +25,6 @@ #ifndef NGHTTP2_NPN_TEST_H #define NGHTTP2_NPN_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - void test_nghttp2_npn(void); #endif /* NGHTTP2_NPN_TEST_H */ diff -Nru nghttp2-1.13.0/tests/nghttp2_pq_test.c nghttp2-0.6.7/tests/nghttp2_pq_test.c --- nghttp2-1.13.0/tests/nghttp2_pq_test.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_pq_test.c 2014-11-30 14:15:07.000000000 +0000 @@ -28,87 +28,47 @@ #include "nghttp2_pq.h" -typedef struct { - nghttp2_pq_entry ent; - const char *s; -} string_entry; - -static string_entry *string_entry_new(const char *s) { - nghttp2_mem *mem; - string_entry *ent; - - mem = nghttp2_mem_default(); - - ent = nghttp2_mem_malloc(mem, sizeof(string_entry)); - ent->s = s; - - return ent; -} - -static void string_entry_del(string_entry *ent) { free(ent); } - -static int pq_less(const void *lhs, const void *rhs) { - return strcmp(((string_entry *)lhs)->s, ((string_entry *)rhs)->s) < 0; +static int pq_compar(const void *lhs, const void *rhs) { + return strcmp(lhs, rhs); } void test_nghttp2_pq(void) { int i; nghttp2_pq pq; - string_entry *top; - - nghttp2_pq_init(&pq, pq_less, nghttp2_mem_default()); + nghttp2_pq_init(&pq, pq_compar); CU_ASSERT(nghttp2_pq_empty(&pq)); CU_ASSERT(0 == nghttp2_pq_size(&pq)); - CU_ASSERT(0 == nghttp2_pq_push(&pq, &string_entry_new("foo")->ent)); + CU_ASSERT(0 == nghttp2_pq_push(&pq, (void *)"foo")); CU_ASSERT(0 == nghttp2_pq_empty(&pq)); CU_ASSERT(1 == nghttp2_pq_size(&pq)); - top = (string_entry *)nghttp2_pq_top(&pq); - CU_ASSERT(strcmp("foo", top->s) == 0); - CU_ASSERT(0 == nghttp2_pq_push(&pq, &string_entry_new("bar")->ent)); - top = (string_entry *)nghttp2_pq_top(&pq); - CU_ASSERT(strcmp("bar", top->s) == 0); - CU_ASSERT(0 == nghttp2_pq_push(&pq, &string_entry_new("baz")->ent)); - top = (string_entry *)nghttp2_pq_top(&pq); - CU_ASSERT(strcmp("bar", top->s) == 0); - CU_ASSERT(0 == nghttp2_pq_push(&pq, &string_entry_new("C")->ent)); + CU_ASSERT(strcmp("foo", nghttp2_pq_top(&pq)) == 0); + CU_ASSERT(0 == nghttp2_pq_push(&pq, (void *)"bar")); + CU_ASSERT(strcmp("bar", nghttp2_pq_top(&pq)) == 0); + CU_ASSERT(0 == nghttp2_pq_push(&pq, (void *)"baz")); + CU_ASSERT(strcmp("bar", nghttp2_pq_top(&pq)) == 0); + CU_ASSERT(0 == nghttp2_pq_push(&pq, (void *)"C")); CU_ASSERT(4 == nghttp2_pq_size(&pq)); - - top = (string_entry *)nghttp2_pq_top(&pq); - CU_ASSERT(strcmp("C", top->s) == 0); - string_entry_del(top); + CU_ASSERT(strcmp("C", nghttp2_pq_top(&pq)) == 0); nghttp2_pq_pop(&pq); - CU_ASSERT(3 == nghttp2_pq_size(&pq)); - - top = (string_entry *)nghttp2_pq_top(&pq); - CU_ASSERT(strcmp("bar", top->s) == 0); + CU_ASSERT(strcmp("bar", nghttp2_pq_top(&pq)) == 0); nghttp2_pq_pop(&pq); - string_entry_del(top); - - top = (string_entry *)nghttp2_pq_top(&pq); - CU_ASSERT(strcmp("baz", top->s) == 0); + CU_ASSERT(strcmp("baz", nghttp2_pq_top(&pq)) == 0); nghttp2_pq_pop(&pq); - string_entry_del(top); - - top = (string_entry *)nghttp2_pq_top(&pq); - CU_ASSERT(strcmp("foo", top->s) == 0); + CU_ASSERT(strcmp("foo", nghttp2_pq_top(&pq)) == 0); nghttp2_pq_pop(&pq); - string_entry_del(top); - CU_ASSERT(nghttp2_pq_empty(&pq)); CU_ASSERT(0 == nghttp2_pq_size(&pq)); CU_ASSERT(NULL == nghttp2_pq_top(&pq)); /* Add bunch of entry to see realloc works */ for (i = 0; i < 10000; ++i) { - CU_ASSERT(0 == nghttp2_pq_push(&pq, &string_entry_new("foo")->ent)); + CU_ASSERT(0 == nghttp2_pq_push(&pq, (void *)"foo")); CU_ASSERT((size_t)(i + 1) == nghttp2_pq_size(&pq)); } for (i = 10000; i > 0; --i) { - top = (string_entry *)nghttp2_pq_top(&pq); - CU_ASSERT(NULL != top); + CU_ASSERT(NULL != nghttp2_pq_top(&pq)); nghttp2_pq_pop(&pq); - string_entry_del(top); CU_ASSERT((size_t)(i - 1) == nghttp2_pq_size(&pq)); } @@ -116,18 +76,17 @@ } typedef struct { - nghttp2_pq_entry ent; int key; int val; } node; -static int node_less(const void *lhs, const void *rhs) { +static int node_compar(const void *lhs, const void *rhs) { node *ln = (node *)lhs; node *rn = (node *)rhs; - return ln->key < rn->key; + return ln->key - rn->key; } -static int node_update(nghttp2_pq_entry *item, void *arg _U_) { +static int node_update(void *item, void *arg _U_) { node *nd = (node *)item; if ((nd->key % 2) == 0) { nd->key *= -1; @@ -144,81 +103,21 @@ node *nd; int ans[] = {-8, -6, -4, -2, 0, 1, 3, 5, 7, 9}; - nghttp2_pq_init(&pq, node_less, nghttp2_mem_default()); + nghttp2_pq_init(&pq, node_compar); for (i = 0; i < (int)(sizeof(nodes) / sizeof(nodes[0])); ++i) { nodes[i].key = i; nodes[i].val = i; - nghttp2_pq_push(&pq, &nodes[i].ent); + nghttp2_pq_push(&pq, &nodes[i]); } nghttp2_pq_update(&pq, node_update, NULL); for (i = 0; i < (int)(sizeof(nodes) / sizeof(nodes[0])); ++i) { - nd = (node *)nghttp2_pq_top(&pq); + nd = nghttp2_pq_top(&pq); CU_ASSERT(ans[i] == nd->key); nghttp2_pq_pop(&pq); } nghttp2_pq_free(&pq); } - -static void push_nodes(nghttp2_pq *pq, node *dest, size_t n) { - size_t i; - for (i = 0; i < n; ++i) { - dest[i].key = (int)i; - dest[i].val = (int)i; - nghttp2_pq_push(pq, &dest[i].ent); - } -} - -static void check_nodes(nghttp2_pq *pq, size_t n, int *ans_key, int *ans_val) { - size_t i; - for (i = 0; i < n; ++i) { - node *nd = (node *)nghttp2_pq_top(pq); - CU_ASSERT(ans_key[i] == nd->key); - CU_ASSERT(ans_val[i] == nd->val); - nghttp2_pq_pop(pq); - } -} - -void test_nghttp2_pq_remove(void) { - nghttp2_pq pq; - node nodes[10]; - int ans_key1[] = {1, 2, 3, 4, 5}; - int ans_val1[] = {1, 2, 3, 4, 5}; - int ans_key2[] = {0, 1, 2, 4, 5}; - int ans_val2[] = {0, 1, 2, 4, 5}; - int ans_key3[] = {0, 1, 2, 3, 4}; - int ans_val3[] = {0, 1, 2, 3, 4}; - - nghttp2_pq_init(&pq, node_less, nghttp2_mem_default()); - - push_nodes(&pq, nodes, 6); - - nghttp2_pq_remove(&pq, &nodes[0].ent); - - check_nodes(&pq, 5, ans_key1, ans_val1); - - nghttp2_pq_free(&pq); - - nghttp2_pq_init(&pq, node_less, nghttp2_mem_default()); - - push_nodes(&pq, nodes, 6); - - nghttp2_pq_remove(&pq, &nodes[3].ent); - - check_nodes(&pq, 5, ans_key2, ans_val2); - - nghttp2_pq_free(&pq); - - nghttp2_pq_init(&pq, node_less, nghttp2_mem_default()); - - push_nodes(&pq, nodes, 6); - - nghttp2_pq_remove(&pq, &nodes[5].ent); - - check_nodes(&pq, 5, ans_key3, ans_val3); - - nghttp2_pq_free(&pq); -} diff -Nru nghttp2-1.13.0/tests/nghttp2_pq_test.h nghttp2-0.6.7/tests/nghttp2_pq_test.h --- nghttp2-1.13.0/tests/nghttp2_pq_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_pq_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,12 +25,7 @@ #ifndef NGHTTP2_PQ_TEST_H #define NGHTTP2_PQ_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - void test_nghttp2_pq(void); void test_nghttp2_pq_update(void); -void test_nghttp2_pq_remove(void); #endif /* NGHTTP2_PQ_TEST_H */ diff -Nru nghttp2-1.13.0/tests/nghttp2_queue_test.h nghttp2-0.6.7/tests/nghttp2_queue_test.h --- nghttp2-1.13.0/tests/nghttp2_queue_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_queue_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,10 +25,6 @@ #ifndef NGHTTP2_QUEUE_TEST_H #define NGHTTP2_QUEUE_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - void test_nghttp2_queue(void); #endif /* NGHTTP2_QUEUE_TEST_H */ diff -Nru nghttp2-1.13.0/tests/nghttp2_session_test.c nghttp2-0.6.7/tests/nghttp2_session_test.c --- nghttp2-1.13.0/tests/nghttp2_session_test.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_session_test.c 2014-11-30 14:15:07.000000000 +0000 @@ -36,6 +36,10 @@ #include "nghttp2_test_helper.h" #include "nghttp2_priority_spec.h" +#define OB_CTRL(ITEM) nghttp2_outbound_item_get_ctrl_frame(ITEM) +#define OB_CTRL_TYPE(ITEM) nghttp2_outbound_item_get_ctrl_frame_type(ITEM) +#define OB_DATA(ITEM) nghttp2_outbound_item_get_data_frame(ITEM) + typedef struct { uint8_t buf[65535]; size_t length; @@ -54,15 +58,12 @@ scripted_data_feed *df; int frame_recv_cb_called, invalid_frame_recv_cb_called; uint8_t recv_frame_type; - nghttp2_frame_hd recv_frame_hd; int frame_send_cb_called; uint8_t sent_frame_type; - int before_frame_send_cb_called; int frame_not_send_cb_called; uint8_t not_sent_frame_type; int not_sent_error; int stream_close_cb_called; - uint32_t stream_close_error_code; size_t data_source_length; int32_t stream_id; size_t block_count; @@ -75,25 +76,8 @@ size_t data_chunk_len; size_t padlen; int begin_frame_cb_called; - nghttp2_buf scratchbuf; } my_user_data; -static const nghttp2_nv reqnv[] = { - MAKE_NV(":method", "GET"), MAKE_NV(":path", "/"), - MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"), -}; - -static const nghttp2_nv resnv[] = { - MAKE_NV(":status", "200"), -}; - -static const nghttp2_nv trailernv[] = { - // from http://tools.ietf.org/html/rfc6249#section-7 - MAKE_NV("digest", "SHA-256=" - "MWVkMWQxYTRiMzk5MDQ0MzI3NGU5NDEyZTk5OWY1ZGFmNzgyZTJlODYz" - "YjRjYzFhOTlmNTQwYzI2M2QwM2U2MQ=="), -}; - static void scripted_data_feed_init2(scripted_data_feed *df, nghttp2_bufs *bufs) { nghttp2_buf_chain *ci; @@ -119,7 +103,7 @@ static ssize_t null_send_callback(nghttp2_session *session _U_, const uint8_t *data _U_, size_t len, int flags _U_, void *user_data _U_) { - return (ssize_t)len; + return len; } static ssize_t fail_send_callback(nghttp2_session *session _U_, @@ -132,7 +116,7 @@ const uint8_t *data _U_, size_t len, int flags _U_, void *user_data) { size_t fixed_sendlen = ((my_user_data *)user_data)->fixed_sendlen; - return (ssize_t)(fixed_sendlen < len ? fixed_sendlen : len); + return fixed_sendlen < len ? fixed_sendlen : len; } static ssize_t scripted_recv_callback(nghttp2_session *session _U_, @@ -146,7 +130,7 @@ if (df->feedseq[df->seqidx] == 0) { ++df->seqidx; } - return (ssize_t)wlen; + return wlen; } static ssize_t eof_recv_callback(nghttp2_session *session _U_, @@ -162,7 +146,7 @@ assert(acc->length + len < sizeof(acc->buf)); memcpy(acc->buf + acc->length, buf, len); acc->length += len; - return (ssize_t)len; + return len; } static int on_begin_frame_callback(nghttp2_session *session _U_, @@ -178,14 +162,12 @@ my_user_data *ud = (my_user_data *)user_data; ++ud->frame_recv_cb_called; ud->recv_frame_type = frame->hd.type; - ud->recv_frame_hd = frame->hd; - return 0; } static int on_invalid_frame_recv_callback(nghttp2_session *session _U_, const nghttp2_frame *frame _U_, - int lib_error_code _U_, + nghttp2_error_code error_code _U_, void *user_data) { my_user_data *ud = (my_user_data *)user_data; ++ud->invalid_frame_recv_cb_called; @@ -210,14 +192,6 @@ return 0; } -static int cancel_before_frame_send_callback(nghttp2_session *session _U_, - const nghttp2_frame *frame _U_, - void *user_data) { - my_user_data *ud = (my_user_data *)user_data; - ++ud->before_frame_send_cb_called; - return NGHTTP2_ERR_CANCEL; -} - static int on_data_chunk_recv_callback(nghttp2_session *session _U_, uint8_t flags _U_, int32_t stream_id _U_, const uint8_t *data _U_, size_t len, @@ -242,7 +216,7 @@ const nghttp2_frame *frame, size_t max_payloadlen, void *user_data) { my_user_data *ud = (my_user_data *)user_data; - return (ssize_t)nghttp2_min(max_payloadlen, frame->hd.length + ud->padlen); + return nghttp2_min(max_payloadlen, frame->hd.length + ud->padlen); } static ssize_t too_large_data_source_length_callback( @@ -276,7 +250,7 @@ if (ud->data_source_length == 0) { *data_flags |= NGHTTP2_DATA_FLAG_EOF; } - return (ssize_t)wlen; + return wlen; } static ssize_t temporal_failure_data_source_read_callback( @@ -295,69 +269,28 @@ return NGHTTP2_ERR_CALLBACK_FAILURE; } -static ssize_t no_end_stream_data_source_read_callback( - nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_, - size_t len _U_, uint32_t *data_flags, nghttp2_data_source *source _U_, - void *user_data _U_) { - *data_flags |= NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM; - return 0; -} - -static ssize_t no_copy_data_source_read_callback( - nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_, - size_t len, uint32_t *data_flags, nghttp2_data_source *source _U_, - void *user_data) { - my_user_data *ud = (my_user_data *)user_data; - size_t wlen; - if (len < ud->data_source_length) { - wlen = len; - } else { - wlen = ud->data_source_length; - } - - ud->data_source_length -= wlen; - - *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY; - - if (ud->data_source_length == 0) { - *data_flags |= NGHTTP2_DATA_FLAG_EOF; - } - return (ssize_t)wlen; -} - -static int send_data_callback(nghttp2_session *session _U_, - nghttp2_frame *frame, const uint8_t *framehd, - size_t length, nghttp2_data_source *source _U_, - void *user_data) { - accumulator *acc = ((my_user_data *)user_data)->acc; - - memcpy(acc->buf + acc->length, framehd, NGHTTP2_FRAME_HDLEN); - acc->length += NGHTTP2_FRAME_HDLEN; - - if (frame->data.padlen) { - *(acc->buf + acc->length++) = (uint8_t)(frame->data.padlen - 1); - } - - acc->length += length; - - if (frame->data.padlen) { - acc->length += frame->data.padlen - 1; - } - - return 0; -} +/* static void no_stream_user_data_stream_close_callback */ +/* (nghttp2_session *session, */ +/* int32_t stream_id, */ +/* nghttp2_error_code error_code, */ +/* void *user_data) */ +/* { */ +/* my_user_data* my_data = (my_user_data*)user_data; */ +/* ++my_data->stream_close_cb_called; */ +/* } */ static ssize_t block_count_send_callback(nghttp2_session *session _U_, const uint8_t *data _U_, size_t len, int flags _U_, void *user_data) { my_user_data *ud = (my_user_data *)user_data; - + ssize_t r; if (ud->block_count == 0) { - return NGHTTP2_ERR_WOULDBLOCK; + r = NGHTTP2_ERR_WOULDBLOCK; + } else { + --ud->block_count; + r = len; } - - --ud->block_count; - return (ssize_t)len; + return r; } static int on_header_callback(nghttp2_session *session _U_, @@ -403,12 +336,6 @@ return 0; } -static int temporal_failure_on_begin_headers_callback( - nghttp2_session *session, const nghttp2_frame *frame, void *user_data) { - on_begin_headers_callback(session, frame, user_data); - return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; -} - static ssize_t defer_data_source_read_callback(nghttp2_session *session _U_, int32_t stream_id _U_, uint8_t *buf _U_, size_t len _U_, @@ -424,62 +351,13 @@ void *user_data) { my_user_data *my_data = (my_user_data *)user_data; ++my_data->stream_close_cb_called; - my_data->stream_close_error_code = error_code; - - return 0; -} - -static ssize_t pack_extension_callback(nghttp2_session *session _U_, - uint8_t *buf, size_t len _U_, - const nghttp2_frame *frame, - void *user_data _U_) { - nghttp2_buf *p = frame->ext.payload; - - memcpy(buf, p->pos, nghttp2_buf_len(p)); - - return (ssize_t)nghttp2_buf_len(p); -} - -static int on_extension_chunk_recv_callback(nghttp2_session *session _U_, - const nghttp2_frame_hd *hd _U_, - const uint8_t *data, size_t len, - void *user_data) { - my_user_data *my_data = (my_user_data *)user_data; - nghttp2_buf *buf = &my_data->scratchbuf; - - buf->last = nghttp2_cpymem(buf->last, data, len); - - return 0; -} - -static int cancel_on_extension_chunk_recv_callback( - nghttp2_session *session _U_, const nghttp2_frame_hd *hd _U_, - const uint8_t *data _U_, size_t len _U_, void *user_data _U_) { - return NGHTTP2_ERR_CANCEL; -} - -static int unpack_extension_callback(nghttp2_session *session _U_, - void **payload, - const nghttp2_frame_hd *hd _U_, - void *user_data) { - my_user_data *my_data = (my_user_data *)user_data; - nghttp2_buf *buf = &my_data->scratchbuf; - - *payload = buf; return 0; } -static int cancel_unpack_extension_callback(nghttp2_session *session _U_, - void **payload _U_, - const nghttp2_frame_hd *hd _U_, - void *user_data _U_) { - return NGHTTP2_ERR_CANCEL; -} - static nghttp2_settings_entry *dup_iv(const nghttp2_settings_entry *iv, size_t niv) { - return nghttp2_frame_iv_copy(iv, niv, nghttp2_mem_default()); + return nghttp2_frame_iv_copy(iv, niv); } static nghttp2_priority_spec pri_spec_default = {0, NGHTTP2_DEFAULT_WEIGHT, 0}; @@ -489,18 +367,17 @@ nghttp2_session_callbacks callbacks; scripted_data_feed df; my_user_data user_data; + const nghttp2_nv nv[] = {MAKE_NV("url", "/")}; nghttp2_bufs bufs; - size_t framelen; + ssize_t framelen; nghttp2_frame frame; - size_t i; + ssize_t i; nghttp2_outbound_item *item; nghttp2_nv *nva; - size_t nvlen; + ssize_t nvlen; nghttp2_hd_deflater deflater; int rv; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); @@ -512,10 +389,10 @@ user_data.df = &df; nghttp2_session_server_new(&session, &callbacks, &user_data); - nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_hd_deflate_init(&deflater); - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); + nvlen = ARRLEN(nv); + nghttp2_nv_array_copy(&nva, nv, nvlen); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); @@ -531,12 +408,12 @@ df.feedseq[i] = 1; } - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); user_data.frame_recv_cb_called = 0; user_data.begin_frame_cb_called = 0; - while (df.seqidx < framelen) { + while ((ssize_t)df.seqidx < framelen) { CU_ASSERT(0 == nghttp2_session_recv(session)); } CU_ASSERT(1 == user_data.frame_recv_cb_called); @@ -544,6 +421,25 @@ nghttp2_bufs_reset(&bufs); + /* Received HEADERS without header block, which is valid */ + nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 5, + NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); + rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); + + CU_ASSERT(0 == rv); + + nghttp2_frame_headers_free(&frame.headers); + + scripted_data_feed_init2(&df, &bufs); + user_data.frame_recv_cb_called = 0; + user_data.begin_frame_cb_called = 0; + + CU_ASSERT(0 == nghttp2_session_recv(session)); + CU_ASSERT(1 == user_data.frame_recv_cb_called); + CU_ASSERT(1 == user_data.begin_frame_cb_called); + + nghttp2_bufs_reset(&bufs); + /* Receive PRIORITY */ nghttp2_frame_priority_init(&frame.priority, 5, &pri_spec_default); @@ -614,11 +510,7 @@ nghttp2_frame frame; nghttp2_hd_deflater deflater; int rv; - nghttp2_mem *mem; - nghttp2_nv *nva; - size_t nvlen; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); @@ -628,19 +520,17 @@ user_data.df = &df; user_data.invalid_frame_recv_cb_called = 0; nghttp2_session_server_new(&session, &callbacks, &user_data); - nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_hd_deflate_init(&deflater); - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2, - NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); + NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); CU_ASSERT(0 == rv); CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); scripted_data_feed_init2(&df, &bufs); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); CU_ASSERT(0 == nghttp2_session_recv(session)); CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called); @@ -655,15 +545,14 @@ nghttp2_session_callbacks callbacks; scripted_data_feed df; my_user_data user_data; + const nghttp2_nv nv[] = {MAKE_NV("url", "/")}; nghttp2_bufs bufs; nghttp2_frame frame; nghttp2_nv *nva; - size_t nvlen; + ssize_t nvlen; nghttp2_hd_deflater deflater; int rv; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); @@ -674,9 +563,9 @@ user_data.df = &df; user_data.frame_send_cb_called = 0; nghttp2_session_server_new(&session, &callbacks, &user_data); - nghttp2_hd_deflate_init(&deflater, mem); - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); + nghttp2_hd_deflate_init(&deflater); + nvlen = ARRLEN(nv); + nghttp2_nv_array_copy(&nva, nv, nvlen); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); @@ -690,17 +579,16 @@ CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == user_data.frame_send_cb_called); - /* Receive exactly same bytes of HEADERS is treated as error, because it has - * pseudo headers and without END_STREAM flag set */ + /* Receive exactly same bytes of HEADERS is treated as subsequent + HEADERS (e.g., trailers */ scripted_data_feed_init2(&df, &bufs); CU_ASSERT(0 == nghttp2_session_recv(session)); CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(1 == user_data.frame_send_cb_called); - CU_ASSERT(NGHTTP2_RST_STREAM == user_data.sent_frame_type); + CU_ASSERT(0 == user_data.frame_send_cb_called); nghttp2_bufs_free(&bufs); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_hd_deflate_free(&deflater); nghttp2_session_del(session); @@ -735,7 +623,6 @@ callbacks.send_callback = null_send_callback; callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; callbacks.on_frame_recv_callback = on_frame_recv_callback; - callbacks.on_frame_send_callback = on_frame_send_callback; nghttp2_session_client_new(&session, &callbacks, &ud); @@ -764,8 +651,9 @@ nghttp2_session_client_new(&session, &callbacks, &ud); /* Create stream 1 with CLOSING state. DATA is ignored. */ - stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING); - + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_CLOSING, NULL); /* Set initial window size 16383 to check stream flow control, isolating it from the conneciton flow control */ stream->local_window_size = 16383; @@ -842,220 +730,12 @@ CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code); nghttp2_session_del(session); - - /* Check window_update_queued flag in both session and stream */ - nghttp2_session_server_new(&session, &callbacks, &ud); - - hd.length = 4096; - hd.type = NGHTTP2_DATA; - hd.flags = NGHTTP2_FLAG_NONE; - hd.stream_id = 1; - nghttp2_frame_pack_frame_hd(data, &hd); - - stream = open_recv_stream(session, 1); - - /* Send 32767 bytes of DATA. In our current flow control algorithm, - it triggers first WINDOW_UPDATE of window_size_increment - 32767. */ - for (i = 0; i < 7; ++i) { - rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096); - CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv); - } - - hd.length = 4095; - nghttp2_frame_pack_frame_hd(data, &hd); - rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4095); - CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4095 == rv); - - /* Now 2 WINDOW_UPDATEs for session and stream should be queued. */ - CU_ASSERT(0 == stream->recv_window_size); - CU_ASSERT(0 == session->recv_window_size); - CU_ASSERT(1 == stream->window_update_queued); - CU_ASSERT(1 == session->window_update_queued); - - /* Then send 32768 bytes of DATA. Since we have not sent queued - WINDOW_UDPATE frame, recv_window_size should not be decreased */ - hd.length = 4096; - nghttp2_frame_pack_frame_hd(data, &hd); - - for (i = 0; i < 8; ++i) { - rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096); - CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv); - } - - /* WINDOW_UPDATE is blocked for session and stream, so - recv_window_size must not be decreased. */ - CU_ASSERT(32768 == stream->recv_window_size); - CU_ASSERT(32768 == session->recv_window_size); - CU_ASSERT(1 == stream->window_update_queued); - CU_ASSERT(1 == session->window_update_queued); - - ud.frame_send_cb_called = 0; - - /* This sends queued WINDOW_UPDATES. And then check - recv_window_size, and queue WINDOW_UPDATEs for both session and - stream, and send them at once. */ - CU_ASSERT(0 == nghttp2_session_send(session)); - - CU_ASSERT(4 == ud.frame_send_cb_called); - CU_ASSERT(0 == stream->recv_window_size); - CU_ASSERT(0 == session->recv_window_size); - CU_ASSERT(0 == stream->window_update_queued); - CU_ASSERT(0 == session->window_update_queued); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_recv_data_no_auto_flow_control(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - my_user_data ud; - nghttp2_option *option; - nghttp2_frame_hd hd; - size_t padlen; - uint8_t data[8192]; - ssize_t rv; - size_t sendlen; - nghttp2_stream *stream; - size_t i; - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - callbacks.on_frame_send_callback = on_frame_send_callback; - - nghttp2_option_new(&option); - nghttp2_option_set_no_auto_window_update(option, 1); - - nghttp2_session_server_new2(&session, &callbacks, &ud, option); - - /* Create DATA frame with length 4KiB + 11 bytes padding*/ - padlen = 11; - memset(data, 0, sizeof(data)); - hd.length = 4096 + 1 + padlen; - hd.type = NGHTTP2_DATA; - hd.flags = NGHTTP2_FLAG_PADDED; - hd.stream_id = 1; - nghttp2_frame_pack_frame_hd(data, &hd); - data[NGHTTP2_FRAME_HDLEN] = (uint8_t)padlen; - - /* First create stream 1, then close it. Check that data is - consumed for connection in this situation */ - open_recv_stream(session, 1); - - /* Receive first 100 bytes */ - sendlen = 100; - rv = nghttp2_session_mem_recv(session, data, sendlen); - CU_ASSERT((ssize_t)sendlen == rv); - - /* We consumed pad length field (1 byte) */ - CU_ASSERT(1 == session->consumed_size); - - /* close stream here */ - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1, NGHTTP2_NO_ERROR); - nghttp2_session_send(session); - - /* stream 1 has been closed, and we disabled auto flow-control, so - data must be immediately consumed for connection. */ - rv = nghttp2_session_mem_recv(session, data + sendlen, - NGHTTP2_FRAME_HDLEN + hd.length - sendlen); - CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length - sendlen) == rv); - - /* We already consumed pad length field (1 byte), so do +1 here */ - CU_ASSERT((int32_t)(NGHTTP2_FRAME_HDLEN + hd.length - sendlen + 1) == - session->consumed_size); - - nghttp2_session_del(session); - - /* Reuse DATA created previously. */ - - nghttp2_session_server_new2(&session, &callbacks, &ud, option); - - /* Now we are expecting final response header, which means receiving - DATA for that stream is illegal. */ - stream = open_recv_stream(session, 1); - stream->http_flags |= NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE; - - rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length); - CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + hd.length) == rv); - - /* Whole payload must be consumed now because HTTP messaging rule - was not honored. */ - CU_ASSERT((int32_t)hd.length == session->consumed_size); - - nghttp2_session_del(session); - - /* Check window_update_queued flag in both session and stream */ - nghttp2_session_server_new2(&session, &callbacks, &ud, option); - - stream = open_recv_stream(session, 1); - - hd.length = 4096; - hd.type = NGHTTP2_DATA; - hd.flags = NGHTTP2_FLAG_NONE; - hd.stream_id = 1; - nghttp2_frame_pack_frame_hd(data, &hd); - - /* Receive up to 65535 bytes of DATA */ - for (i = 0; i < 15; ++i) { - rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4096); - CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv); - } - - hd.length = 4095; - nghttp2_frame_pack_frame_hd(data, &hd); - - rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4095); - CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4095 == rv); - - CU_ASSERT(65535 == session->recv_window_size); - CU_ASSERT(65535 == stream->recv_window_size); - - /* The first call of nghttp2_session_consume_connection() will queue - WINDOW_UPDATE. Next call does not. */ - nghttp2_session_consume_connection(session, 32767); - nghttp2_session_consume_connection(session, 32768); - - CU_ASSERT(32768 == session->recv_window_size); - CU_ASSERT(65535 == stream->recv_window_size); - CU_ASSERT(1 == session->window_update_queued); - CU_ASSERT(0 == stream->window_update_queued); - - ud.frame_send_cb_called = 0; - - /* This will send WINDOW_UPDATE, and check whether we should send - WINDOW_UPDATE, and queue and send it at once. */ - CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(0 == session->recv_window_size); - CU_ASSERT(65535 == stream->recv_window_size); - CU_ASSERT(0 == session->window_update_queued); - CU_ASSERT(0 == stream->window_update_queued); - CU_ASSERT(2 == ud.frame_send_cb_called); - - /* Do the same for stream */ - nghttp2_session_consume_stream(session, 1, 32767); - nghttp2_session_consume_stream(session, 1, 32768); - - CU_ASSERT(0 == session->recv_window_size); - CU_ASSERT(32768 == stream->recv_window_size); - CU_ASSERT(0 == session->window_update_queued); - CU_ASSERT(1 == stream->window_update_queued); - - ud.frame_send_cb_called = 0; - - CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(0 == session->recv_window_size); - CU_ASSERT(0 == stream->recv_window_size); - CU_ASSERT(0 == session->window_update_queued); - CU_ASSERT(0 == stream->window_update_queued); - CU_ASSERT(2 == ud.frame_send_cb_called); - - nghttp2_session_del(session); - nghttp2_option_del(option); } void test_nghttp2_session_recv_continuation(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + const nghttp2_nv nv1[] = {MAKE_NV("method", "GET"), MAKE_NV("path", "/")}; nghttp2_nv *nva; size_t nvlen; nghttp2_frame frame; @@ -1068,9 +748,7 @@ size_t datalen; nghttp2_frame_hd cont_hd; nghttp2_priority_spec pri_spec; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); @@ -1080,11 +758,11 @@ nghttp2_session_server_new(&session, &callbacks, &ud); - nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_hd_deflate_init(&deflater); /* Make 1 HEADERS and insert CONTINUATION header */ - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); + nvlen = ARRLEN(nv1); + nghttp2_nv_array_copy(&nva, nv1, nvlen); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); @@ -1096,14 +774,14 @@ buf = &bufs.head->buf; assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); /* HEADERS's payload is 1 byte */ memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN + 1); datalen = NGHTTP2_FRAME_HDLEN + 1; buf->pos += NGHTTP2_FRAME_HDLEN + 1; - nghttp2_put_uint32be(data, (uint32_t)((1 << 8) + data[3])); + nghttp2_put_uint32be(data, (1 << 8) + data[3]); /* First CONTINUATION, 2 bytes */ nghttp2_frame_hd_init(&cont_hd, 2, NGHTTP2_CONTINUATION, NGHTTP2_FLAG_NONE, @@ -1134,77 +812,20 @@ rv = nghttp2_session_mem_recv(session, data, datalen); CU_ASSERT((ssize_t)datalen == rv); - CU_ASSERT(4 == ud.header_cb_called); + CU_ASSERT(2 == ud.header_cb_called); CU_ASSERT(3 == ud.begin_frame_cb_called); nghttp2_hd_deflate_free(&deflater); nghttp2_session_del(session); - /* HEADERS with padding followed by CONTINUATION */ - nghttp2_session_server_new(&session, &callbacks, &ud); - - nghttp2_hd_deflate_init(&deflater, mem); - - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); - nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1, - NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); - - nghttp2_bufs_reset(&bufs); - rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); - - CU_ASSERT(0 == rv); - - nghttp2_frame_headers_free(&frame.headers, mem); - - /* make sure that all data is in the first buf */ - buf = &bufs.head->buf; - assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); - - /* HEADERS payload is 3 byte (1 for padding field, 1 for padding) */ - memcpy(data, buf->pos, NGHTTP2_FRAME_HDLEN); - nghttp2_put_uint32be(data, (uint32_t)((3 << 8) + data[3])); - data[4] |= NGHTTP2_FLAG_PADDED; - /* padding field */ - data[NGHTTP2_FRAME_HDLEN] = 1; - data[NGHTTP2_FRAME_HDLEN + 1] = buf->pos[NGHTTP2_FRAME_HDLEN]; - /* padding */ - data[NGHTTP2_FRAME_HDLEN + 2] = 0; - datalen = NGHTTP2_FRAME_HDLEN + 3; - buf->pos += NGHTTP2_FRAME_HDLEN + 1; - - /* CONTINUATION, rest of the bytes */ - nghttp2_frame_hd_init(&cont_hd, nghttp2_buf_len(buf), NGHTTP2_CONTINUATION, - NGHTTP2_FLAG_END_HEADERS, 1); - nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd); - datalen += NGHTTP2_FRAME_HDLEN; - - memcpy(data + datalen, buf->pos, cont_hd.length); - datalen += cont_hd.length; - buf->pos += cont_hd.length; - - CU_ASSERT(0 == nghttp2_buf_len(buf)); - - ud.header_cb_called = 0; - ud.begin_frame_cb_called = 0; - - rv = nghttp2_session_mem_recv(session, data, datalen); - - CU_ASSERT((ssize_t)datalen == rv); - CU_ASSERT(4 == ud.header_cb_called); - CU_ASSERT(2 == ud.begin_frame_cb_called); - - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); - /* Expecting CONTINUATION, but get the other frame */ nghttp2_session_server_new(&session, &callbacks, &ud); - nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_hd_deflate_init(&deflater); /* HEADERS without END_HEADERS flag */ - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); + nvlen = ARRLEN(nv1); + nghttp2_nv_array_copy(&nva, nv1, nvlen); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); nghttp2_bufs_reset(&bufs); @@ -1213,7 +834,7 @@ CU_ASSERT(0 == rv); CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); /* make sure that all data is in the first buf */ buf = &bufs.head->buf; @@ -1252,6 +873,7 @@ void test_nghttp2_session_recv_headers_with_priority(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + const nghttp2_nv nv1[] = {MAKE_NV("method", "GET"), MAKE_NV("path", "/")}; nghttp2_nv *nva; size_t nvlen; nghttp2_frame frame; @@ -1263,9 +885,7 @@ nghttp2_outbound_item *item; nghttp2_priority_spec pri_spec; nghttp2_stream *stream; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); @@ -1273,13 +893,13 @@ nghttp2_session_server_new(&session, &callbacks, &ud); - nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_hd_deflate_init(&deflater); - open_recv_stream(session, 1); + open_stream(session, 1); /* With NGHTTP2_FLAG_PRIORITY without exclusive flag set */ - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); + nvlen = ARRLEN(nv1); + nghttp2_nv_array_copy(&nva, nv1, nvlen); nghttp2_priority_spec_init(&pri_spec, 1, 99, 0); @@ -1292,7 +912,7 @@ CU_ASSERT(0 == rv); CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); buf = &bufs.head->buf; assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); @@ -1301,7 +921,7 @@ rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + CU_ASSERT(nghttp2_buf_len(buf) == rv); CU_ASSERT(1 == ud.frame_recv_cb_called); stream = nghttp2_session_get_stream(session, 3); @@ -1313,8 +933,8 @@ /* With NGHTTP2_FLAG_PRIORITY, but cut last 1 byte to make it invalid. */ - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); + nvlen = ARRLEN(nv1); + nghttp2_nv_array_copy(&nva, nv1, nvlen); nghttp2_priority_spec_init(&pri_spec, 0, 99, 0); @@ -1325,20 +945,20 @@ rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); CU_ASSERT(0 == rv); - CU_ASSERT(nghttp2_bufs_len(&bufs) > NGHTTP2_FRAME_HDLEN + 5); + CU_ASSERT(NGHTTP2_FRAME_HDLEN + 5 + 2 == nghttp2_bufs_len(&bufs)); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); buf = &bufs.head->buf; - /* Make payload shorter than required length to store priority + /* Make payload shorter than required length to store priroty group */ - nghttp2_put_uint32be(buf->pos, (uint32_t)((4 << 8) + buf->pos[3])); + nghttp2_put_uint32be(buf->pos, (4 << 8) + buf->pos[3]); ud.frame_recv_cb_called = 0; rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + CU_ASSERT(nghttp2_buf_len(buf) == rv); CU_ASSERT(0 == ud.frame_recv_cb_called); stream = nghttp2_session_get_stream(session, 5); @@ -1358,10 +978,10 @@ /* Check dep_stream_id == stream_id */ nghttp2_session_server_new(&session, &callbacks, &ud); - nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_hd_deflate_init(&deflater); - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); + nvlen = ARRLEN(nv1); + nghttp2_nv_array_copy(&nva, nv1, nvlen); nghttp2_priority_spec_init(&pri_spec, 1, 0, 0); @@ -1374,7 +994,7 @@ CU_ASSERT(0 == rv); CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); buf = &bufs.head->buf; assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); @@ -1383,7 +1003,7 @@ rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + CU_ASSERT(nghttp2_buf_len(buf) == rv); CU_ASSERT(0 == ud.frame_recv_cb_called); stream = nghttp2_session_get_stream(session, 1); @@ -1402,212 +1022,153 @@ nghttp2_session_del(session); } -static int response_on_begin_frame_callback(nghttp2_session *session, - const nghttp2_frame_hd *hd, - void *user_data _U_) { - int rv; - - if (hd->type != NGHTTP2_HEADERS) { - return 0; - } - - rv = nghttp2_submit_response(session, hd->stream_id, resnv, ARRLEN(resnv), - NULL); - - CU_ASSERT(0 == rv); - - return 0; -} - -void test_nghttp2_session_recv_headers_early_response(void) { +void test_nghttp2_session_recv_premature_headers(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - nghttp2_bufs bufs; - nghttp2_buf *buf; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; + const nghttp2_nv nv1[] = {MAKE_NV("method", "GET"), MAKE_NV("path", "/")}; nghttp2_nv *nva; size_t nvlen; nghttp2_frame frame; + nghttp2_bufs bufs; + nghttp2_buf *buf; ssize_t rv; - nghttp2_stream *stream; + my_user_data ud; + nghttp2_hd_deflater deflater; + nghttp2_outbound_item *item; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - callbacks.on_begin_frame_callback = response_on_begin_frame_callback; - - nghttp2_session_server_new(&session, &callbacks, NULL); - nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_session_server_new(&session, &callbacks, &ud); - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); - nghttp2_frame_headers_init(&frame.headers, - NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, - 1, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen); + nghttp2_hd_deflate_init(&deflater); + nvlen = ARRLEN(nv1); + nghttp2_nv_array_copy(&nva, nv1, nvlen); + nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, + NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); CU_ASSERT(0 == rv); + CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); buf = &bufs.head->buf; + assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); - /* Only receive 9 bytes headers, and invoke - on_begin_frame_callback */ - rv = nghttp2_session_mem_recv(session, buf->pos, 9); - - CU_ASSERT(9 == rv); - - rv = nghttp2_session_send(session); - - CU_ASSERT(0 == rv); - - rv = - nghttp2_session_mem_recv(session, buf->pos + 9, nghttp2_buf_len(buf) - 9); - - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) - 9 == rv); + /* Intentionally feed payload cutting last 1 byte off */ + nghttp2_put_uint32be(buf->pos, + (uint32_t)(((frame.hd.length - 1) << 8) + buf->pos[3])); + rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1); - stream = nghttp2_session_get_stream_raw(session, 1); + CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv); - CU_ASSERT(stream->flags & NGHTTP2_STREAM_FLAG_CLOSED); + item = nghttp2_session_get_next_ob_item(session); + CU_ASSERT(NULL != item); + CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); + CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code); + nghttp2_bufs_free(&bufs); nghttp2_hd_deflate_free(&deflater); nghttp2_session_del(session); - nghttp2_bufs_free(&bufs); } -void test_nghttp2_session_server_recv_push_response(void) { +void test_nghttp2_session_recv_altsvc(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + nghttp2_frame frame; + nghttp2_ext_altsvc altsvc; + size_t protocol_id_len, host_len, origin_len; + uint8_t *protocol_id, *host, *origin; + uint8_t *data; + size_t datalen; nghttp2_bufs bufs; nghttp2_buf *buf; ssize_t rv; my_user_data ud; - nghttp2_mem *mem; - nghttp2_frame frame; - nghttp2_hd_deflater deflater; - nghttp2_nv *nva; - size_t nvlen; + nghttp2_outbound_item *item; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; - - nghttp2_session_server_new(&session, &callbacks, &ud); - - nghttp2_hd_deflate_init(&deflater, mem); - - open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); + callbacks.on_frame_recv_callback = on_frame_recv_callback; - nvlen = ARRLEN(resnv); - nghttp2_nv_array_copy(&nva, resnv, nvlen, mem); - nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2, - NGHTTP2_HCAT_HEADERS, &pri_spec_default, nva, - nvlen); - rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); + protocol_id_len = strlen("h2"); + host_len = strlen("h2.example.org"); + origin_len = strlen("www.example.org"); - CU_ASSERT(0 == rv); - CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); + datalen = protocol_id_len + host_len + origin_len; + data = malloc(datalen); - nghttp2_frame_headers_free(&frame.headers, mem); + memcpy(data, "h2", protocol_id_len); + protocol_id = data; - buf = &bufs.head->buf; + memcpy(data + protocol_id_len, "h2.example.org", host_len); + host = data + protocol_id_len; - ud.invalid_frame_recv_cb_called = 0; + memcpy(data + protocol_id_len + host_len, "http://www.example.org", + origin_len); + origin = data + protocol_id_len + host_len; - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); + frame.ext.payload = &altsvc; - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); - CU_ASSERT(1 == ud.invalid_frame_recv_cb_called); + nghttp2_frame_altsvc_init(&frame.ext, 1000000007, 1u << 31, 4000, protocol_id, + protocol_id_len, host, host_len, origin, + origin_len); - nghttp2_bufs_free(&bufs); - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); -} + rv = nghttp2_frame_pack_altsvc(&bufs, &frame.ext); -void test_nghttp2_session_recv_premature_headers(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_bufs bufs; - nghttp2_buf *buf; - ssize_t rv; - my_user_data ud; - nghttp2_hd_deflater deflater; - nghttp2_outbound_item *item; - nghttp2_mem *mem; - uint32_t payloadlen; + CU_ASSERT(0 == rv); + CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); + nghttp2_frame_altsvc_free(&frame.ext); - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; + buf = &bufs.head->buf; + assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); + /* error if server receives ALTSVC */ nghttp2_session_server_new(&session, &callbacks, &ud); - nghttp2_hd_deflate_init(&deflater, mem); - - pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv, - ARRLEN(reqnv), mem); + ud.frame_recv_cb_called = 0; - buf = &bufs.head->buf; - /* Intentionally feed payload cutting last 1 byte off */ - payloadlen = nghttp2_get_uint32(buf->pos) >> 8; - nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]); - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1); + rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv); + CU_ASSERT(rv == nghttp2_buf_len(buf)); + CU_ASSERT(0 == ud.frame_recv_cb_called); item = nghttp2_session_get_next_ob_item(session); + CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); - CU_ASSERT(NULL != item); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code); - CU_ASSERT(1 == item->frame.hd.stream_id); - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_bufs_reset(&bufs); - nghttp2_hd_deflate_free(&deflater); nghttp2_session_del(session); - /* Test for PUSH_PROMISE */ nghttp2_session_client_new(&session, &callbacks, &ud); - nghttp2_hd_deflate_init(&deflater, mem); - open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + ud.frame_recv_cb_called = 0; - rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, - reqnv, ARRLEN(reqnv), mem); + rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - CU_ASSERT(0 == rv); + CU_ASSERT(rv == nghttp2_buf_len(buf)); + CU_ASSERT(1 == ud.frame_recv_cb_called); + CU_ASSERT(NGHTTP2_EXT_ALTSVC == ud.recv_frame_type); - buf = &bufs.head->buf; - payloadlen = nghttp2_get_uint32(buf->pos) >> 8; - /* Intentionally feed payload cutting last 1 byte off */ - nghttp2_put_uint32be(buf->pos, ((payloadlen - 1) << 8) + buf->pos[3]); - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1); + /* premature payload */ + nghttp2_put_uint32be(buf->pos, (8 << 8) + buf->pos[3]); - CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv); + ud.frame_recv_cb_called = 0; + + rv = nghttp2_session_mem_recv(session, buf->pos, NGHTTP2_FRAME_HDLEN + 8); + + CU_ASSERT(rv == NGHTTP2_FRAME_HDLEN + 8); + CU_ASSERT(0 == ud.frame_recv_cb_called); item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NULL != item); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code); - CU_ASSERT(2 == item->frame.hd.stream_id); - CU_ASSERT(0 == nghttp2_session_send(session)); + CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); nghttp2_bufs_free(&bufs); + nghttp2_session_del(session); } void test_nghttp2_session_recv_unknown_frame(void) { @@ -1662,7 +1223,7 @@ nghttp2_session_server_new(&session, &callbacks, &ud); - open_recv_stream(session, 1); + open_stream(session, 1); ud.frame_recv_cb_called = 0; @@ -1689,9 +1250,7 @@ my_user_data ud; nghttp2_settings_entry iv[3]; nghttp2_nv nv = MAKE_NV(":authority", "example.org"); - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); @@ -1714,7 +1273,7 @@ CU_ASSERT(0 == rv); CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - nghttp2_frame_settings_free(&frame.settings, mem); + nghttp2_frame_settings_free(&frame.settings); buf = &bufs.head->buf; assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); @@ -1723,7 +1282,7 @@ rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + CU_ASSERT(rv == nghttp2_buf_len(buf)); CU_ASSERT(1 == ud.frame_recv_cb_called); CU_ASSERT(3000 == session->remote_settings.header_table_size); @@ -1749,7 +1308,7 @@ CU_ASSERT(0 == rv); CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - nghttp2_frame_settings_free(&frame.settings, mem); + nghttp2_frame_settings_free(&frame.settings); buf = &bufs.head->buf; assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); @@ -1758,7 +1317,7 @@ rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - CU_ASSERT((ssize_t)(nghttp2_buf_len(buf)) == rv); + CU_ASSERT(rv == nghttp2_buf_len(buf)); CU_ASSERT(1 == ud.frame_recv_cb_called); CU_ASSERT(3001 == session->remote_settings.header_table_size); @@ -1791,7 +1350,7 @@ CU_ASSERT(0 == rv); CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - nghttp2_frame_settings_free(&frame.settings, mem); + nghttp2_frame_settings_free(&frame.settings); buf = &bufs.head->buf; assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); @@ -1800,7 +1359,7 @@ rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + CU_ASSERT(rv == nghttp2_buf_len(buf)); CU_ASSERT(1 == ud.frame_recv_cb_called); CU_ASSERT(4096 == session->remote_settings.header_table_size); @@ -1834,7 +1393,7 @@ CU_ASSERT(0 == rv); CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - nghttp2_frame_settings_free(&frame.settings, mem); + nghttp2_frame_settings_free(&frame.settings); buf = &bufs.head->buf; assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); @@ -1843,7 +1402,7 @@ rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + CU_ASSERT(rv == nghttp2_buf_len(buf)); CU_ASSERT(1 == ud.frame_recv_cb_called); CU_ASSERT(0 == session->remote_settings.header_table_size); @@ -1883,205 +1442,6 @@ nghttp2_session_del(session); } -void test_nghttp2_session_recv_extension(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - my_user_data ud; - nghttp2_buf buf; - nghttp2_frame_hd hd; - nghttp2_mem *mem; - const char data[] = "Hello World!"; - ssize_t rv; - nghttp2_option *option; - - mem = nghttp2_mem_default(); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - - callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback; - callbacks.unpack_extension_callback = unpack_extension_callback; - callbacks.on_frame_recv_callback = on_frame_recv_callback; - - nghttp2_option_new(&option); - nghttp2_option_set_user_recv_extension_type(option, 111); - - nghttp2_buf_init2(&ud.scratchbuf, 4096, mem); - nghttp2_buf_init2(&buf, 4096, mem); - - nghttp2_frame_hd_init(&hd, sizeof(data), 111, 0xab, 1000000007); - nghttp2_frame_pack_frame_hd(buf.last, &hd); - buf.last += NGHTTP2_FRAME_HDLEN; - buf.last = nghttp2_cpymem(buf.last, data, sizeof(data)); - - nghttp2_session_client_new2(&session, &callbacks, &ud, option); - - nghttp2_frame_hd_init(&ud.recv_frame_hd, 0, 0, 0, 0); - rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf)); - - CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv); - CU_ASSERT(111 == ud.recv_frame_hd.type); - CU_ASSERT(0xab == ud.recv_frame_hd.flags); - CU_ASSERT(1000000007 == ud.recv_frame_hd.stream_id); - CU_ASSERT(0 == memcmp(data, ud.scratchbuf.pos, sizeof(data))); - - nghttp2_session_del(session); - - /* cancel in on_extension_chunk_recv_callback */ - nghttp2_buf_reset(&ud.scratchbuf); - - callbacks.on_extension_chunk_recv_callback = - cancel_on_extension_chunk_recv_callback; - - nghttp2_session_server_new2(&session, &callbacks, &ud, option); - - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf)); - - CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv); - CU_ASSERT(0 == ud.frame_recv_cb_called); - - nghttp2_session_del(session); - - /* cancel in unpack_extension_callback */ - nghttp2_buf_reset(&ud.scratchbuf); - - callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback; - callbacks.unpack_extension_callback = cancel_unpack_extension_callback; - - nghttp2_session_server_new2(&session, &callbacks, &ud, option); - - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf)); - - CU_ASSERT(NGHTTP2_FRAME_HDLEN + hd.length == (size_t)rv); - CU_ASSERT(0 == ud.frame_recv_cb_called); - - nghttp2_session_del(session); - - nghttp2_buf_free(&buf, mem); - nghttp2_buf_free(&ud.scratchbuf, mem); - - nghttp2_option_del(option); -} - -void test_nghttp2_session_recv_altsvc(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - my_user_data ud; - nghttp2_buf buf; - nghttp2_frame_hd hd; - nghttp2_mem *mem; - ssize_t rv; - nghttp2_option *option; - static const uint8_t origin[] = "nghttp2.org"; - static const uint8_t field_value[] = "h2=\":443\""; - - mem = nghttp2_mem_default(); - - nghttp2_buf_init2(&buf, NGHTTP2_FRAME_HDLEN + NGHTTP2_MAX_FRAME_SIZE_MIN, - mem); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - - callbacks.on_frame_recv_callback = on_frame_recv_callback; - - nghttp2_option_new(&option); - nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC); - - nghttp2_session_client_new2(&session, &callbacks, &ud, option); - - nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1, - NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0); - nghttp2_frame_pack_frame_hd(buf.last, &hd); - buf.last += NGHTTP2_FRAME_HDLEN; - nghttp2_put_uint16be(buf.last, sizeof(origin) - 1); - buf.last += 2; - buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1); - buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1); - - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv); - CU_ASSERT(1 == ud.frame_recv_cb_called); - CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_hd.type); - CU_ASSERT(NGHTTP2_FLAG_NONE == ud.recv_frame_hd.flags); - CU_ASSERT(0 == ud.recv_frame_hd.stream_id); - - nghttp2_session_del(session); - - /* size of origin is larger than frame length */ - nghttp2_buf_reset(&buf); - - nghttp2_session_client_new2(&session, &callbacks, &ud, option); - - nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 - 1, NGHTTP2_ALTSVC, - NGHTTP2_FLAG_NONE, 0); - nghttp2_frame_pack_frame_hd(buf.last, &hd); - buf.last += NGHTTP2_FRAME_HDLEN; - nghttp2_put_uint16be(buf.last, sizeof(origin) - 1); - buf.last += 2; - buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1 - 1); - - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv); - CU_ASSERT(0 == ud.frame_recv_cb_called); - - nghttp2_session_del(session); - - /* send large frame (16KiB) */ - nghttp2_buf_reset(&buf); - - nghttp2_session_client_new2(&session, &callbacks, &ud, option); - - nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN, NGHTTP2_ALTSVC, - NGHTTP2_FLAG_NONE, 0); - nghttp2_frame_pack_frame_hd(buf.last, &hd); - buf.last += NGHTTP2_FRAME_HDLEN; - nghttp2_put_uint16be(buf.last, sizeof(origin) - 1); - buf.last += 2; - buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1); - memset(buf.last, 0, nghttp2_buf_avail(&buf)); - buf.last += nghttp2_buf_avail(&buf); - - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv); - CU_ASSERT(1 == ud.frame_recv_cb_called); - CU_ASSERT(NGHTTP2_ALTSVC == ud.recv_frame_hd.type); - CU_ASSERT(NGHTTP2_MAX_FRAME_SIZE_MIN == ud.recv_frame_hd.length); - - nghttp2_session_del(session); - - /* received by server */ - nghttp2_buf_reset(&buf); - - nghttp2_session_server_new2(&session, &callbacks, &ud, option); - - nghttp2_frame_hd_init(&hd, 2 + sizeof(origin) - 1 + sizeof(field_value) - 1, - NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, 0); - nghttp2_frame_pack_frame_hd(buf.last, &hd); - buf.last += NGHTTP2_FRAME_HDLEN; - nghttp2_put_uint16be(buf.last, sizeof(origin) - 1); - buf.last += 2; - buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1); - buf.last = nghttp2_cpymem(buf.last, field_value, sizeof(field_value) - 1); - - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv); - CU_ASSERT(0 == ud.frame_recv_cb_called); - - nghttp2_session_del(session); - - nghttp2_buf_free(&buf, mem); - nghttp2_option_del(option); -} - void test_nghttp2_session_continue(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; @@ -2097,13 +1457,11 @@ nghttp2_buf databuf; nghttp2_frame frame; nghttp2_nv *nva; - size_t nvlen; + ssize_t nvlen; const nghttp2_frame *recv_frame; nghttp2_frame_hd data_hd; nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer)); @@ -2115,14 +1473,12 @@ callbacks.on_begin_headers_callback = on_begin_headers_callback; nghttp2_session_server_new(&session, &callbacks, &user_data); - /* disable strict HTTP layering checks */ - session->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING; - nghttp2_hd_deflate_init(&deflater, mem); + nghttp2_hd_deflate_init(&deflater); /* Make 2 HEADERS frames */ nvlen = ARRLEN(nv1); - nghttp2_nv_array_copy(&nva, nv1, nvlen, mem); + nghttp2_nv_array_copy(&nva, nv1, nvlen); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); @@ -2130,7 +1486,7 @@ CU_ASSERT(0 == rv); CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); buf = &bufs.head->buf; assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); @@ -2139,7 +1495,7 @@ databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf)); nvlen = ARRLEN(nv2); - nghttp2_nv_array_copy(&nva, nv2, nvlen, mem); + nghttp2_nv_array_copy(&nva, nv2, nvlen); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); nghttp2_bufs_reset(&bufs); @@ -2148,7 +1504,7 @@ CU_ASSERT(0 == rv); CU_ASSERT(nghttp2_bufs_len(&bufs) > 0); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf)); @@ -2275,13 +1631,13 @@ nghttp2_session_callbacks callbacks; accumulator acc; my_user_data user_data; + const nghttp2_nv nv[] = {MAKE_NV("method", "GET"), MAKE_NV("scheme", "https"), + MAKE_NV("url", "/"), MAKE_NV("version", "HTTP/1.1")}; nghttp2_outbound_item *item; nghttp2_frame *frame; nghttp2_nv *nva; - size_t nvlen; - nghttp2_mem *mem; + ssize_t nvlen; - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = accumulator_send_callback; @@ -2290,23 +1646,23 @@ CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &user_data)); - item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); + item = malloc(sizeof(nghttp2_outbound_item)); - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; - nvlen = ARRLEN(reqnv); - nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem); + nvlen = ARRLEN(nv); + nghttp2_nv_array_copy(&nva, nv, nvlen); nghttp2_frame_headers_init( &frame->headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY, - (int32_t)session->next_stream_id, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen); + session->next_stream_id, NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen); session->next_stream_id += 2; CU_ASSERT(0 == nghttp2_session_add_item(session, item)); - CU_ASSERT(NULL != nghttp2_outbound_queue_top(&session->ob_syn)); + CU_ASSERT(0 == nghttp2_pq_empty(&session->ob_ss_pq)); CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(NGHTTP2_HEADERS == acc.buf[3]); CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY) == acc.buf[4]); @@ -2327,9 +1683,7 @@ nghttp2_nv *nva; size_t nvlen; nghttp2_priority_spec pri_spec; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.on_begin_headers_callback = on_begin_headers_callback; callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; @@ -2351,7 +1705,7 @@ CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state); CU_ASSERT(255 == stream->weight); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); /* More than un-ACKed max concurrent streams leads REFUSED_STREAM */ session->pending_local_max_concurrent_stream = 1; @@ -2364,7 +1718,7 @@ CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called); CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND)); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); session->local_settings.max_concurrent_streams = NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS; @@ -2379,7 +1733,7 @@ CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called); CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND)); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); /* Stream ID is our side and it is idle stream ID, then treat it as connection error */ @@ -2392,7 +1746,7 @@ CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called); CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_session_del(session); @@ -2400,7 +1754,7 @@ nghttp2_session_server_new(&session, &callbacks, &user_data); nvlen = ARRLEN(malformed_nva); - nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem); + nghttp2_nv_array_copy(&nva, malformed_nva, nvlen); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY, 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen); @@ -2410,7 +1764,7 @@ CU_ASSERT(1 == user_data.begin_headers_cb_called); CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_session_del(session); @@ -2427,7 +1781,7 @@ CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called); CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_session_del(session); @@ -2443,14 +1797,13 @@ CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called); CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_session_del(session); nghttp2_session_client_new(&session, &callbacks, &user_data); session->next_stream_id = 5; - session->last_sent_stream_id = 3; /* Stream ID which is not idle and not in stream map is just ignored */ @@ -2463,7 +1816,7 @@ CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called); CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND)); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_session_del(session); @@ -2477,38 +1830,20 @@ CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame)); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); - /* If GOAWAY has been sent, new stream is ignored */ + /* Stream ID which is greater than local_last_stream_id is + ignored */ nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 5, NGHTTP2_HCAT_REQUEST, NULL, NULL, 0); - session->goaway_flags |= NGHTTP2_GOAWAY_SENT; user_data.invalid_frame_recv_cb_called = 0; CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == nghttp2_session_on_request_headers_received(session, &frame)); CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called); CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND)); - nghttp2_frame_headers_free(&frame.headers, mem); - - nghttp2_session_del(session); - - nghttp2_session_server_new(&session, &callbacks, &user_data); - - /* HEADERS to closed stream */ - stream = open_recv_stream(session, 1); - nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); - nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR); - - nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, - NGHTTP2_HCAT_REQUEST, NULL, NULL, 0); - - CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == - nghttp2_session_on_request_headers_received(session, &frame)); - CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND); - - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_session_del(session); } @@ -2519,15 +1854,15 @@ my_user_data user_data; nghttp2_frame frame; nghttp2_stream *stream; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.on_begin_headers_callback = on_begin_headers_callback; callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); @@ -2539,7 +1874,7 @@ CU_ASSERT(1 == user_data.begin_headers_cb_called); CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_session_del(session); } @@ -2549,15 +1884,15 @@ my_user_data user_data; nghttp2_frame frame; nghttp2_stream *stream; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.on_begin_headers_callback = on_begin_headers_callback; callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENED); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + NULL); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); @@ -2577,7 +1912,9 @@ /* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is discarded. */ - stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_CLOSING); + stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_CLOSING, NULL); frame.hd.stream_id = 3; frame.hd.flags = NGHTTP2_FLAG_END_HEADERS; CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == @@ -2587,14 +1924,17 @@ CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called); /* Server initiated stream */ - stream = open_recv_stream(session, 2); + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); + /* half closed (remote) */ frame.hd.flags = NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM; frame.hd.stream_id = 2; CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream)); CU_ASSERT(3 == user_data.begin_headers_cb_called); - CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state); + CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); @@ -2603,7 +1943,7 @@ nghttp2_session_on_headers_received(session, &frame, stream)); CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_session_del(session); } @@ -2615,16 +1955,16 @@ nghttp2_frame frame; nghttp2_stream *stream; nghttp2_outbound_item *item; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; callbacks.on_begin_headers_callback = on_begin_headers_callback; callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_RESERVED, NULL); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); /* nghttp2_session_on_push_response_headers_received assumes @@ -2634,19 +1974,18 @@ user_data.begin_headers_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0; - CU_ASSERT(1 == session->num_incoming_reserved_streams); CU_ASSERT(0 == nghttp2_session_on_push_response_headers_received( session, &frame, stream)); CU_ASSERT(1 == user_data.begin_headers_cb_called); - CU_ASSERT(0 == session->num_incoming_reserved_streams); CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state); CU_ASSERT(1 == session->num_incoming_streams); - CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_PUSH)); /* If un-ACKed max concurrent streams limit is exceeded, RST_STREAMed */ session->pending_local_max_concurrent_stream = 1; - stream = open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED); + stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_RESERVED, NULL); frame.hd.stream_id = 4; CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == nghttp2_session_on_push_response_headers_received(session, &frame, @@ -2655,7 +1994,6 @@ CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code); CU_ASSERT(1 == session->num_incoming_streams); - CU_ASSERT(1 == session->num_incoming_reserved_streams); CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(1 == session->num_incoming_streams); @@ -2664,7 +2002,9 @@ issued */ session->local_settings.max_concurrent_streams = 1; - stream = open_recv_stream2(session, 6, NGHTTP2_STREAM_RESERVED); + stream = nghttp2_session_open_stream(session, 6, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_RESERVED, NULL); frame.hd.stream_id = 6; CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == @@ -2672,11 +2012,10 @@ stream)); item = nghttp2_session_get_next_ob_item(session); CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); - CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code); + CU_ASSERT(NGHTTP2_ENHANCE_YOUR_CALM == item->frame.goaway.error_code); CU_ASSERT(1 == session->num_incoming_streams); - CU_ASSERT(1 == session->num_incoming_reserved_streams); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_session_del(session); } @@ -2694,7 +2033,9 @@ callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; nghttp2_session_server_new(&session, &callbacks, &user_data); - stream = open_recv_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); nghttp2_priority_spec_init(&pri_spec, 0, 2, 0); @@ -2705,8 +2046,13 @@ CU_ASSERT(2 == stream->weight); - stream = open_sent_stream(session, 2); - dep_stream = open_recv_stream(session, 3); + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); + + dep_stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); frame.hd.stream_id = 2; @@ -2732,7 +2078,8 @@ /* Check dep_stream_id == stream_id case */ nghttp2_session_server_new(&session, &callbacks, &user_data); - open_recv_stream(session, 1); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, NULL); nghttp2_priority_spec_init(&pri_spec, 1, 0, 0); @@ -2746,22 +2093,6 @@ nghttp2_frame_priority_free(&frame.priority); nghttp2_session_del(session); - - /* Check again dep_stream_id == stream_id, and stream_id is idle */ - nghttp2_session_server_new(&session, &callbacks, &user_data); - - nghttp2_priority_spec_init(&pri_spec, 1, 16, 0); - - nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec); - - CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame)); - - item = nghttp2_session_get_next_ob_item(session); - - CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); - - nghttp2_frame_priority_free(&frame.priority); - nghttp2_session_del(session); } void test_nghttp2_session_on_rst_stream_received(void) { @@ -2771,7 +2102,8 @@ nghttp2_frame frame; memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); nghttp2_session_server_new(&session, &callbacks, &user_data); - open_recv_stream(session, 1); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR); @@ -2792,9 +2124,6 @@ nghttp2_settings_entry iv[255]; nghttp2_outbound_item *item; nghttp2_nv nv = MAKE_NV(":authority", "example.org"); - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; iv[0].value = 50; @@ -2817,9 +2146,12 @@ nghttp2_session_client_new(&session, &callbacks, &user_data); session->remote_settings.initial_window_size = 16 * 1024; - stream1 = open_sent_stream(session, 1); - stream2 = open_recv_stream(session, 2); - + stream1 = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); + stream2 = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); /* Set window size for each streams and will see how settings updates these values */ stream1->remote_window_size = 16 * 1024; @@ -2849,7 +2181,7 @@ CU_ASSERT(0 == nghttp2_session_get_stream_remote_window_size( session, stream2->stream_id)); - nghttp2_frame_settings_free(&frame.settings, mem); + nghttp2_frame_settings_free(&frame.settings); nghttp2_session_del(session); @@ -2857,12 +2189,19 @@ nghttp2_session_server_new(&session, &callbacks, NULL); nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, dup_iv(iv, 1), 1); + /* Specify inflight_iv deliberately */ + session->inflight_iv = frame.settings.iv; + session->inflight_niv = frame.settings.niv; + CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0)); item = nghttp2_session_get_next_ob_item(session); CU_ASSERT(item != NULL); CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); - nghttp2_frame_settings_free(&frame.settings, mem); + session->inflight_iv = NULL; + session->inflight_niv = -1; + + nghttp2_frame_settings_free(&frame.settings); nghttp2_session_del(session); /* Check ACK against no inflight SETTINGS */ @@ -2874,7 +2213,7 @@ CU_ASSERT(item != NULL); CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); - nghttp2_frame_settings_free(&frame.settings, mem); + nghttp2_frame_settings_free(&frame.settings); nghttp2_session_del(session); /* Check that 2 SETTINGS_HEADER_TABLE_SIZE 0 and 4096 are included @@ -2902,7 +2241,7 @@ CU_ASSERT(2048 == session->hd_deflater.ctx.hd_table_bufsize_max); CU_ASSERT(2048 == session->remote_settings.header_table_size); - nghttp2_frame_settings_free(&frame.settings, mem); + nghttp2_frame_settings_free(&frame.settings); nghttp2_session_del(session); /* Check too large SETTINGS_MAX_FRAME_SIZE */ @@ -2921,45 +2260,7 @@ CU_ASSERT(item != NULL); CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); - nghttp2_frame_settings_free(&frame.settings, mem); - nghttp2_session_del(session); - - /* Check the case where stream window size overflows */ - nghttp2_session_server_new(&session, &callbacks, NULL); - - stream1 = open_recv_stream(session, 1); - - /* This will increment window size by 1 */ - nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1, - 1); - - CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame)); - - nghttp2_frame_window_update_free(&frame.window_update); - - iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; - iv[0].value = NGHTTP2_MAX_WINDOW_SIZE; - - nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1), - 1); - - /* Now window size gets NGHTTP2_MAX_WINDOW_SIZE + 1, which is - unacceptable situation in protocol spec. */ - CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0)); - - nghttp2_frame_settings_free(&frame.settings, mem); - - item = nghttp2_session_get_next_ob_item(session); - - CU_ASSERT(NULL != item); - CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type); - - item = nghttp2_outbound_queue_top(&session->ob_reg); - - CU_ASSERT(NULL != item); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream1->state); - + nghttp2_frame_settings_free(&frame.settings); nghttp2_session_del(session); } @@ -2973,10 +2274,7 @@ nghttp2_nv malformed_nva[] = {MAKE_NV(":path", "\x01")}; nghttp2_nv *nva; size_t nvlen; - nghttp2_mem *mem; - nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_ENABLE_PUSH, 0}; - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; callbacks.on_begin_headers_callback = on_begin_headers_callback; @@ -2984,8 +2282,9 @@ nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = open_sent_stream(session, 1); - + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS, 1, 2, NULL, 0); @@ -2995,7 +2294,6 @@ CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame)); CU_ASSERT(1 == user_data.begin_headers_cb_called); - CU_ASSERT(1 == session->num_incoming_reserved_streams); promised_stream = nghttp2_session_get_stream(session, 2); CU_ASSERT(NGHTTP2_STREAM_RESERVED == promised_stream->state); CU_ASSERT(2 == session->last_recv_stream_id); @@ -3011,21 +2309,16 @@ CU_ASSERT(0 == user_data.begin_headers_cb_called); CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called); - CU_ASSERT(1 == session->num_incoming_reserved_streams); CU_ASSERT(NULL == nghttp2_session_get_stream(session, 4)); item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); - CU_ASSERT(NGHTTP2_STREAM_CLOSED == item->frame.goaway.error_code); + CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); + CU_ASSERT(4 == item->frame.hd.stream_id); + CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.rst_stream.error_code); CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(4 == session->last_recv_stream_id); - nghttp2_session_del(session); - - nghttp2_session_client_new(&session, &callbacks, &user_data); - - stream = open_sent_stream(session, 1); - /* Attempt to PUSH_PROMISE against stream in closing state */ + stream->shut_flags = NGHTTP2_SHUT_NONE; stream->state = NGHTTP2_STREAM_CLOSING; frame.push_promise.promised_stream_id = 6; @@ -3035,15 +2328,14 @@ nghttp2_session_on_push_promise_received(session, &frame)); CU_ASSERT(0 == user_data.begin_headers_cb_called); - CU_ASSERT(0 == session->num_incoming_reserved_streams); CU_ASSERT(NULL == nghttp2_session_get_stream(session, 6)); item = nghttp2_session_get_next_ob_item(session); CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); CU_ASSERT(6 == item->frame.hd.stream_id); - CU_ASSERT(NGHTTP2_CANCEL == item->frame.rst_stream.error_code); + CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code); CU_ASSERT(0 == nghttp2_session_send(session)); - /* Attempt to PUSH_PROMISE against idle stream */ + /* Attempt to PUSH_PROMISE against non-existent stream */ frame.hd.stream_id = 3; frame.push_promise.promised_stream_id = 8; @@ -3053,7 +2345,6 @@ nghttp2_session_on_push_promise_received(session, &frame)); CU_ASSERT(0 == user_data.begin_headers_cb_called); - CU_ASSERT(0 == session->num_incoming_reserved_streams); CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8)); item = nghttp2_session_get_next_ob_item(session); CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); @@ -3065,19 +2356,12 @@ nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = open_sent_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); /* Same ID twice */ - frame.hd.stream_id = 1; - frame.push_promise.promised_stream_id = 2; - - user_data.begin_headers_cb_called = 0; - user_data.invalid_frame_recv_cb_called = 0; - CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame)); - - CU_ASSERT(1 == user_data.begin_headers_cb_called); - CU_ASSERT(1 == session->num_incoming_reserved_streams); - CU_ASSERT(NULL != nghttp2_session_get_stream(session, 2)); + stream->state = NGHTTP2_STREAM_OPENING; user_data.begin_headers_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0; @@ -3085,7 +2369,6 @@ nghttp2_session_on_push_promise_received(session, &frame)); CU_ASSERT(0 == user_data.begin_headers_cb_called); - CU_ASSERT(1 == session->num_incoming_reserved_streams); CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8)); item = nghttp2_session_get_next_ob_item(session); CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); @@ -3101,17 +2384,17 @@ nghttp2_session_on_push_promise_received(session, &frame)); CU_ASSERT(0 == user_data.begin_headers_cb_called); - CU_ASSERT(1 == session->num_incoming_reserved_streams); CU_ASSERT(NULL == nghttp2_session_get_stream(session, 10)); CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - nghttp2_frame_push_promise_free(&frame.push_promise, mem); + nghttp2_frame_push_promise_free(&frame.push_promise); nghttp2_session_del(session); nghttp2_session_client_new(&session, &callbacks, &user_data); - open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); - + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_RESERVED, NULL); /* Attempt to PUSH_PROMISE against reserved (remote) stream */ nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS, 2, 4, NULL, 0); @@ -3123,15 +2406,16 @@ CU_ASSERT(0 == user_data.begin_headers_cb_called); CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called); - CU_ASSERT(1 == session->num_incoming_reserved_streams); - nghttp2_frame_push_promise_free(&frame.push_promise, mem); + nghttp2_frame_push_promise_free(&frame.push_promise); nghttp2_session_del(session); /* Disable PUSH */ nghttp2_session_client_new(&session, &callbacks, &user_data); - open_sent_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); session->local_settings.enable_push = 0; @@ -3145,18 +2429,18 @@ CU_ASSERT(0 == user_data.begin_headers_cb_called); CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called); - CU_ASSERT(0 == session->num_incoming_reserved_streams); - nghttp2_frame_push_promise_free(&frame.push_promise, mem); + nghttp2_frame_push_promise_free(&frame.push_promise); nghttp2_session_del(session); /* Check malformed headers. We accept malformed headers */ nghttp2_session_client_new(&session, &callbacks, &user_data); - open_sent_stream(session, 1); - + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); nvlen = ARRLEN(malformed_nva); - nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem); + nghttp2_nv_array_copy(&nva, malformed_nva, nvlen); nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS, 1, 2, nva, nvlen); user_data.begin_headers_cb_called = 0; @@ -3166,52 +2450,7 @@ CU_ASSERT(1 == user_data.begin_headers_cb_called); CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called); - nghttp2_frame_push_promise_free(&frame.push_promise, mem); - nghttp2_session_del(session); - - /* If local_settings.enable_push = 0 is pending, but not acked from - peer, incoming PUSH_PROMISE is rejected */ - nghttp2_session_client_new(&session, &callbacks, &user_data); - - open_sent_stream(session, 1); - - /* Submit settings with ENABLE_PUSH = 0 (thus disabling push) */ - nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1); - - nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS, - 1, 2, NULL, 0); - - CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == - nghttp2_session_on_push_promise_received(session, &frame)); - - CU_ASSERT(0 == session->num_incoming_reserved_streams); - - nghttp2_frame_push_promise_free(&frame.push_promise, mem); - nghttp2_session_del(session); - - /* Check max_incoming_reserved_streams */ - nghttp2_session_client_new(&session, &callbacks, &user_data); - session->max_incoming_reserved_streams = 1; - - open_sent_stream(session, 1); - open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); - - CU_ASSERT(1 == session->num_incoming_reserved_streams); - - nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS, - 1, 4, NULL, 0); - - CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == - nghttp2_session_on_push_promise_received(session, &frame)); - - CU_ASSERT(1 == session->num_incoming_reserved_streams); - - item = nghttp2_session_get_next_ob_item(session); - - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(NGHTTP2_CANCEL == item->frame.rst_stream.error_code); - - nghttp2_frame_push_promise_free(&frame.push_promise, mem); + nghttp2_frame_push_promise_free(&frame.push_promise); nghttp2_session_del(session); } @@ -3222,7 +2461,6 @@ nghttp2_frame frame; nghttp2_outbound_item *top; const uint8_t opaque_data[] = "01234567"; - nghttp2_option *option; user_data.frame_recv_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0; @@ -3237,39 +2475,22 @@ CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame)); CU_ASSERT(1 == user_data.frame_recv_cb_called); - /* Since this ping frame has ACK flag set, no further action is + /* Since this ping frame has PONG flag set, no further action is performed. */ - CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_urgent)); + CU_ASSERT(NULL == nghttp2_session_get_ob_pq_top(session)); /* Clear the flag, and receive it again */ frame.hd.flags = NGHTTP2_FLAG_NONE; CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame)); CU_ASSERT(2 == user_data.frame_recv_cb_called); - top = nghttp2_outbound_queue_top(&session->ob_urgent); + top = nghttp2_session_get_ob_pq_top(session); CU_ASSERT(NGHTTP2_PING == top->frame.hd.type); CU_ASSERT(NGHTTP2_FLAG_ACK == top->frame.hd.flags); CU_ASSERT(memcmp(opaque_data, top->frame.ping.opaque_data, 8) == 0); nghttp2_frame_ping_free(&frame.ping); nghttp2_session_del(session); - - /* Use nghttp2_option_set_no_auto_ping_ack() */ - nghttp2_option_new(&option); - nghttp2_option_set_no_auto_ping_ack(option, 1); - - nghttp2_session_server_new2(&session, &callbacks, &user_data, option); - nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL); - - user_data.frame_recv_cb_called = 0; - - CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame)); - CU_ASSERT(1 == user_data.frame_recv_cb_called); - CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_urgent)); - - nghttp2_frame_ping_free(&frame.ping); - nghttp2_session_del(session); - nghttp2_option_del(option); } void test_nghttp2_session_on_goaway_received(void) { @@ -3278,9 +2499,7 @@ my_user_data user_data; nghttp2_frame frame; int i; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); user_data.frame_recv_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0; @@ -3292,11 +2511,7 @@ nghttp2_session_client_new(&session, &callbacks, &user_data); for (i = 1; i <= 7; ++i) { - if (nghttp2_session_is_my_stream_id(session, i)) { - open_sent_stream(session, i); - } else { - open_recv_stream(session, i); - } + open_stream(session, i); } nghttp2_frame_goaway_init(&frame.goaway, 3, NGHTTP2_PROTOCOL_ERROR, NULL, 0); @@ -3318,7 +2533,7 @@ CU_ASSERT(NULL != nghttp2_session_get_stream(session, 6)); CU_ASSERT(NULL == nghttp2_session_get_stream(session, 7)); - nghttp2_frame_goaway_free(&frame.goaway, mem); + nghttp2_frame_goaway_free(&frame.goaway); nghttp2_session_del(session); } @@ -3329,10 +2544,6 @@ nghttp2_frame frame; nghttp2_stream *stream; nghttp2_outbound_item *data_item; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.on_frame_recv_callback = on_frame_recv_callback; callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; @@ -3341,11 +2552,13 @@ nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = open_sent_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + NULL); - data_item = create_data_ob_item(mem); + data_item = create_data_ob_item(); - CU_ASSERT(0 == nghttp2_stream_attach_item(stream, data_item)); + CU_ASSERT(0 == nghttp2_stream_attach_data(stream, data_item, session)); nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 1, 16 * 1024); @@ -3355,8 +2568,9 @@ CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 16 * 1024 == stream->remote_window_size); - CU_ASSERT(0 == nghttp2_stream_defer_item( - stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL)); + CU_ASSERT(0 == + nghttp2_stream_defer_data( + stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, session)); CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame)); CU_ASSERT(2 == user_data.frame_recv_cb_called); @@ -3368,7 +2582,9 @@ /* Receiving WINDOW_UPDATE on reserved (remote) stream is a connection error */ - open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_RESERVED, NULL); nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2, 4096); @@ -3384,7 +2600,9 @@ /* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */ nghttp2_session_server_new(&session, &callbacks, &user_data); - stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_RESERVED, NULL); nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2, 4096); @@ -3410,7 +2628,9 @@ memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = open_recv_stream(session, 2); + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); nghttp2_frame_hd_init(&frame.hd, 4096, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 2); @@ -3423,327 +2643,170 @@ CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags); /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */ - open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING); + stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_CLOSING, NULL); frame.hd.flags = NGHTTP2_FLAG_NONE; - frame.hd.stream_id = 1; + frame.hd.stream_id = 4; CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame)); - CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_reg)); + CU_ASSERT(NULL == nghttp2_session_get_ob_pq_top(session)); /* Check INVALID_STREAM case: DATA frame with stream ID which does not exist. */ - frame.hd.stream_id = 3; + frame.hd.stream_id = 6; CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame)); - top = nghttp2_outbound_queue_top(&session->ob_reg); - /* DATA against nonexistent stream is just ignored for now. */ + top = nghttp2_session_get_ob_pq_top(session); + /* DATA against nonexistent stream is just ignored for now */ CU_ASSERT(top == NULL); + /* CU_ASSERT(NGHTTP2_RST_STREAM == top->frame.hd.type); */ + /* CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == top->frame.rst_stream.error_code); */ nghttp2_session_del(session); } -void test_nghttp2_session_on_data_received_fail_fast(void) { +void test_nghttp2_session_send_headers_start_stream(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - uint8_t buf[9]; - nghttp2_stream *stream; - nghttp2_frame_hd hd; nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_stream *stream; - memset(&callbacks, 0, sizeof(callbacks)); + memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); + callbacks.send_callback = null_send_callback; - nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 1); - nghttp2_frame_pack_frame_hd(buf, &hd); + nghttp2_session_client_new(&session, &callbacks, NULL); - nghttp2_session_server_new(&session, &callbacks, NULL); + item = malloc(sizeof(nghttp2_outbound_item)); - /* DATA to closed (remote) */ - stream = open_recv_stream(session, 1); - nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); + nghttp2_session_outbound_item_init(session, item); - CU_ASSERT((ssize_t)sizeof(buf) == - nghttp2_session_mem_recv(session, buf, sizeof(buf))); + frame = &item->frame; - item = nghttp2_session_get_next_ob_item(session); + nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, + session->next_stream_id, NGHTTP2_HCAT_REQUEST, + NULL, NULL, 0); + session->next_stream_id += 2; - CU_ASSERT(NULL != item); - CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); + nghttp2_session_add_item(session, item); + CU_ASSERT(0 == nghttp2_session_send(session)); + stream = nghttp2_session_get_stream(session, 1); + CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state); nghttp2_session_del(session); +} - nghttp2_session_server_new(&session, &callbacks, NULL); +void test_nghttp2_session_send_headers_reply(void) { + nghttp2_session *session; + nghttp2_session_callbacks callbacks; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_stream *stream; - /* DATA to closed stream with explicit closed (remote) */ - stream = open_recv_stream(session, 1); - nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); - nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR); + memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); + callbacks.send_callback = null_send_callback; + + CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL)); + nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); - CU_ASSERT((ssize_t)sizeof(buf) == - nghttp2_session_mem_recv(session, buf, sizeof(buf))); + item = malloc(sizeof(nghttp2_outbound_item)); - item = nghttp2_session_get_next_ob_item(session); + nghttp2_session_outbound_item_init(session, item); - CU_ASSERT(NULL != item); - CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); + frame = &item->frame; + + nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2, + NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); + nghttp2_session_add_item(session, item); + CU_ASSERT(0 == nghttp2_session_send(session)); + stream = nghttp2_session_get_stream(session, 2); + CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state); nghttp2_session_del(session); } -void test_nghttp2_session_on_altsvc_received(void) { +void test_nghttp2_session_send_headers_frame_size_error(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_nv *nva; + ssize_t nvlen; + size_t vallen = NGHTTP2_HD_MAX_NV; + nghttp2_nv nv[28]; + size_t nnv = ARRLEN(nv); + size_t i; my_user_data ud; - nghttp2_frame frame; - nghttp2_option *option; - uint8_t origin[] = "nghttp2.org"; - uint8_t field_value[] = "h2=\":443\""; - int rv; - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.on_frame_recv_callback = on_frame_recv_callback; - nghttp2_option_new(&option); - nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC); + for (i = 0; i < nnv; ++i) { + nv[i].name = (uint8_t *)"header"; + nv[i].namelen = strlen((const char *)nv[i].name); + nv[i].value = malloc(vallen + 1); + memset(nv[i].value, '0' + (int)i, vallen); + nv[i].value[vallen] = '\0'; + nv[i].valuelen = vallen; + nv[i].flags = NGHTTP2_NV_FLAG_NONE; + } - nghttp2_session_client_new2(&session, &callbacks, &ud, option); + memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); + callbacks.send_callback = null_send_callback; + callbacks.on_frame_not_send_callback = on_frame_not_send_callback; - frame.ext.payload = &session->iframe.ext_frame_payload; + nghttp2_session_client_new(&session, &callbacks, &ud); + nvlen = nnv; + nghttp2_nv_array_copy(&nva, nv, nvlen); - /* We just pass the strings without making a copy. This is OK, - since we never call nghttp2_frame_altsvc_free(). */ - nghttp2_frame_altsvc_init(&frame.ext, 0, origin, sizeof(origin) - 1, - field_value, sizeof(field_value) - 1); + item = malloc(sizeof(nghttp2_outbound_item)); - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_on_altsvc_received(session, &frame); + nghttp2_session_outbound_item_init(session, item); - CU_ASSERT(0 == rv); - CU_ASSERT(1 == ud.frame_recv_cb_called); + frame = &item->frame; - nghttp2_session_del(session); + nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, + session->next_stream_id, NGHTTP2_HCAT_REQUEST, + NULL, nva, nvlen); - /* Receiving empty origin with stream ID == 0 */ - nghttp2_session_client_new2(&session, &callbacks, &ud, option); + session->next_stream_id += 2; - frame.ext.payload = &session->iframe.ext_frame_payload; + nghttp2_session_add_item(session, item); - nghttp2_frame_altsvc_init(&frame.ext, 0, origin, 0, field_value, - sizeof(field_value) - 1); + ud.frame_not_send_cb_called = 0; - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_on_altsvc_received(session, &frame); + CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(0 == rv); - CU_ASSERT(0 == ud.frame_recv_cb_called); + CU_ASSERT(1 == ud.frame_not_send_cb_called); + CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type); + CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == ud.not_sent_error); + for (i = 0; i < nnv; ++i) { + free(nv[i].value); + } nghttp2_session_del(session); +} - /* Receiving non-empty origin with stream ID != 0 */ - nghttp2_session_client_new2(&session, &callbacks, &ud, option); +void test_nghttp2_session_send_headers_push_reply(void) { + nghttp2_session *session; + nghttp2_session_callbacks callbacks; + nghttp2_outbound_item *item; + nghttp2_frame *frame; + nghttp2_stream *stream; - frame.ext.payload = &session->iframe.ext_frame_payload; + memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); + callbacks.send_callback = null_send_callback; - open_sent_stream(session, 1); + CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL)); + nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL); - nghttp2_frame_altsvc_init(&frame.ext, 1, origin, sizeof(origin) - 1, - field_value, sizeof(field_value) - 1); + item = malloc(sizeof(nghttp2_outbound_item)); - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_on_altsvc_received(session, &frame); + nghttp2_session_outbound_item_init(session, item); - CU_ASSERT(0 == rv); - CU_ASSERT(0 == ud.frame_recv_cb_called); - - nghttp2_session_del(session); - - /* Receiving empty origin with stream ID != 0; this is OK */ - nghttp2_session_client_new2(&session, &callbacks, &ud, option); - - frame.ext.payload = &session->iframe.ext_frame_payload; - - open_sent_stream(session, 1); - - nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value, - sizeof(field_value) - 1); - - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_on_altsvc_received(session, &frame); - - CU_ASSERT(0 == rv); - CU_ASSERT(1 == ud.frame_recv_cb_called); - - nghttp2_session_del(session); - - /* Stream does not exist; ALTSVC will be ignored. */ - nghttp2_session_client_new2(&session, &callbacks, &ud, option); - - frame.ext.payload = &session->iframe.ext_frame_payload; - - nghttp2_frame_altsvc_init(&frame.ext, 1, origin, 0, field_value, - sizeof(field_value) - 1); - - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_on_altsvc_received(session, &frame); - - CU_ASSERT(0 == rv); - CU_ASSERT(0 == ud.frame_recv_cb_called); - - nghttp2_session_del(session); - - nghttp2_option_del(option); -} - -void test_nghttp2_session_send_headers_start_stream(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_outbound_item *item; - nghttp2_frame *frame; - nghttp2_stream *stream; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - - item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); - - nghttp2_outbound_item_init(item); - - frame = &item->frame; - - nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, - (int32_t)session->next_stream_id, - NGHTTP2_HCAT_REQUEST, NULL, NULL, 0); - session->next_stream_id += 2; - - nghttp2_session_add_item(session, item); - CU_ASSERT(0 == nghttp2_session_send(session)); - stream = nghttp2_session_get_stream(session, 1); - CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_send_headers_reply(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_outbound_item *item; - nghttp2_frame *frame; - nghttp2_stream *stream; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL)); - open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); - - item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); - - nghttp2_outbound_item_init(item); - - frame = &item->frame; - - nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 1, - NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); - nghttp2_session_add_item(session, item); - CU_ASSERT(0 == nghttp2_session_send(session)); - stream = nghttp2_session_get_stream(session, 1); - CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_send_headers_frame_size_error(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_outbound_item *item; - nghttp2_frame *frame; - nghttp2_nv *nva; - size_t nvlen; - size_t vallen = NGHTTP2_HD_MAX_NV; - nghttp2_nv nv[28]; - size_t nnv = ARRLEN(nv); - size_t i; - my_user_data ud; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - - for (i = 0; i < nnv; ++i) { - nv[i].name = (uint8_t *)"header"; - nv[i].namelen = strlen((const char *)nv[i].name); - nv[i].value = mem->malloc(vallen + 1, NULL); - memset(nv[i].value, '0' + (int)i, vallen); - nv[i].value[vallen] = '\0'; - nv[i].valuelen = vallen; - nv[i].flags = NGHTTP2_NV_FLAG_NONE; - } - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - callbacks.on_frame_not_send_callback = on_frame_not_send_callback; - - nghttp2_session_client_new(&session, &callbacks, &ud); - nvlen = nnv; - nghttp2_nv_array_copy(&nva, nv, nvlen, mem); - - item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); - - nghttp2_outbound_item_init(item); - - frame = &item->frame; - - nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, - (int32_t)session->next_stream_id, - NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen); - - session->next_stream_id += 2; - - nghttp2_session_add_item(session, item); - - ud.frame_not_send_cb_called = 0; - - CU_ASSERT(0 == nghttp2_session_send(session)); - - CU_ASSERT(1 == ud.frame_not_send_cb_called); - CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type); - CU_ASSERT(NGHTTP2_ERR_FRAME_SIZE_ERROR == ud.not_sent_error); - - for (i = 0; i < nnv; ++i) { - mem->free(nv[i].value, NULL); - } - nghttp2_session_del(session); -} - -void test_nghttp2_session_send_headers_push_reply(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_outbound_item *item; - nghttp2_frame *frame; - nghttp2_stream *stream; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL)); - open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); - - item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); - - nghttp2_outbound_item_init(item); - - frame = &item->frame; + frame = &item->frame; nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); @@ -3753,7 +2816,7 @@ CU_ASSERT(1 == session->num_outgoing_streams); stream = nghttp2_session_get_stream(session, 2); CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state); - CU_ASSERT(0 == (stream->flags & NGHTTP2_STREAM_FLAG_PUSH)); + nghttp2_session_del(session); } @@ -3763,18 +2826,16 @@ my_user_data user_data; nghttp2_outbound_item *item; nghttp2_frame *frame; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; nghttp2_session_client_new(&session, &callbacks, &user_data); - open_sent_stream(session, 1); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); - item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); + item = malloc(sizeof(nghttp2_outbound_item)); - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; @@ -3795,25 +2856,24 @@ nghttp2_stream *stream; nghttp2_settings_entry iv; my_user_data ud; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; callbacks.on_frame_not_send_callback = on_frame_not_send_callback; nghttp2_session_server_new(&session, &callbacks, &ud); - open_recv_stream(session, 1); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); - item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); + item = malloc(sizeof(nghttp2_outbound_item)); - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; nghttp2_frame_push_promise_init(&frame->push_promise, NGHTTP2_FLAG_END_HEADERS, 1, - (int32_t)session->next_stream_id, NULL, 0); + session->next_stream_id, NULL, 0); session->next_stream_id += 2; @@ -3826,16 +2886,16 @@ /* Received ENABLE_PUSH = 0 */ iv.settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; iv.value = 0; - frame = mem->malloc(sizeof(nghttp2_frame), NULL); + frame = malloc(sizeof(nghttp2_frame)); nghttp2_frame_settings_init(&frame->settings, NGHTTP2_FLAG_NONE, dup_iv(&iv, 1), 1); nghttp2_session_on_settings_received(session, frame, 1); - nghttp2_frame_settings_free(&frame->settings, mem); - mem->free(frame, NULL); + nghttp2_frame_settings_free(&frame->settings); + free(frame); - item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); + item = malloc(sizeof(nghttp2_outbound_item)); - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; @@ -3854,10 +2914,11 @@ /* PUSH_PROMISE from client is error */ nghttp2_session_client_new(&session, &callbacks, &ud); - open_sent_stream(session, 1); - item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + item = malloc(sizeof(nghttp2_outbound_item)); - nghttp2_outbound_item_init(item); + nghttp2_session_outbound_item_init(session, item); frame = &item->frame; @@ -3892,7 +2953,7 @@ nghttp2_session_del(session); } -void test_nghttp2_session_upgrade2(void) { +void test_nghttp2_session_upgrade(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; uint8_t settings_payload[128]; @@ -3900,14 +2961,6 @@ nghttp2_settings_entry iv[16]; nghttp2_stream *stream; nghttp2_outbound_item *item; - ssize_t rv; - nghttp2_bufs bufs; - nghttp2_buf *buf; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; @@ -3915,14 +2968,13 @@ iv[0].value = 1; iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; iv[1].value = 4095; - settings_payloadlen = (size_t)nghttp2_pack_settings_payload( + settings_payloadlen = nghttp2_pack_settings_payload( settings_payload, sizeof(settings_payload), iv, 2); /* Check client side */ nghttp2_session_client_new(&session, &callbacks, NULL); - CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload, - settings_payloadlen, 0, &callbacks)); - CU_ASSERT(1 == session->last_sent_stream_id); + CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload, + settings_payloadlen, &callbacks)); stream = nghttp2_session_get_stream(session, 1); CU_ASSERT(stream != NULL); CU_ASSERT(&callbacks == stream->stream_user_data); @@ -3937,45 +2989,16 @@ item->frame.settings.iv[1].settings_id); CU_ASSERT(4095 == item->frame.settings.iv[1].value); - /* Call nghttp2_session_upgrade2() again is error */ + /* Call nghttp2_session_upgrade() again is error */ CU_ASSERT(NGHTTP2_ERR_PROTO == - nghttp2_session_upgrade2(session, settings_payload, - settings_payloadlen, 0, &callbacks)); - nghttp2_session_del(session); - - /* Make sure that response from server can be received */ - nghttp2_session_client_new(&session, &callbacks, NULL); - - CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload, - settings_payloadlen, 0, &callbacks)); - - stream = nghttp2_session_get_stream(session, 1); - - CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state); - - nghttp2_hd_deflate_init(&deflater, mem); - rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, resnv, - ARRLEN(resnv), mem); - - CU_ASSERT(0 == rv); - - buf = &bufs.head->buf; - - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - - CU_ASSERT(rv == (ssize_t)nghttp2_buf_len(buf)); - CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state); - - nghttp2_hd_deflate_free(&deflater); + nghttp2_session_upgrade(session, settings_payload, + settings_payloadlen, &callbacks)); nghttp2_session_del(session); - nghttp2_bufs_reset(&bufs); - /* Check server side */ nghttp2_session_server_new(&session, &callbacks, NULL); - CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload, - settings_payloadlen, 0, &callbacks)); - CU_ASSERT(1 == session->last_recv_stream_id); + CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload, + settings_payloadlen, &callbacks)); stream = nghttp2_session_get_stream(session, 1); CU_ASSERT(stream != NULL); CU_ASSERT(NULL == stream->stream_user_data); @@ -3983,21 +3006,20 @@ CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); CU_ASSERT(1 == session->remote_settings.max_concurrent_streams); CU_ASSERT(4095 == session->remote_settings.initial_window_size); - /* Call nghttp2_session_upgrade2() again is error */ + /* Call nghttp2_session_upgrade() again is error */ CU_ASSERT(NGHTTP2_ERR_PROTO == - nghttp2_session_upgrade2(session, settings_payload, - settings_payloadlen, 0, &callbacks)); + nghttp2_session_upgrade(session, settings_payload, + settings_payloadlen, &callbacks)); nghttp2_session_del(session); /* Empty SETTINGS is OK */ - settings_payloadlen = (size_t)nghttp2_pack_settings_payload( + settings_payloadlen = nghttp2_pack_settings_payload( settings_payload, sizeof(settings_payload), NULL, 0); nghttp2_session_client_new(&session, &callbacks, NULL); - CU_ASSERT(0 == nghttp2_session_upgrade2(session, settings_payload, - settings_payloadlen, 0, NULL)); + CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload, + settings_payloadlen, NULL)); nghttp2_session_del(session); - nghttp2_bufs_free(&bufs); } void test_nghttp2_session_reprioritize_stream(void) { @@ -4013,14 +3035,16 @@ nghttp2_session_server_new(&session, &callbacks, &ud); - stream = open_recv_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); nghttp2_priority_spec_init(&pri_spec, 0, 10, 0); nghttp2_session_reprioritize_stream(session, stream, &pri_spec); CU_ASSERT(10 == stream->weight); - CU_ASSERT(&session->root == stream->dep_prev); + CU_ASSERT(NULL == stream->dep_prev); /* If depenency to idle stream which is not in depdenency tree yet */ @@ -4035,7 +3059,7 @@ CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == dep_stream->weight); - dep_stream = open_recv_stream(session, 3); + dep_stream = open_stream(session, 3); /* Change weight */ pri_spec.weight = 128; @@ -4045,15 +3069,6 @@ CU_ASSERT(128 == stream->weight); CU_ASSERT(dep_stream == stream->dep_prev); - /* Change weight again to test short-path case */ - pri_spec.weight = 100; - - nghttp2_session_reprioritize_stream(session, stream, &pri_spec); - - CU_ASSERT(100 == stream->weight); - CU_ASSERT(dep_stream == stream->dep_prev); - CU_ASSERT(100 == dep_stream->sum_dep_weight); - /* Test circular dependency; stream 1 is first removed and becomes root. Then stream 3 depends on it. */ nghttp2_priority_spec_init(&pri_spec, 1, 1, 0); @@ -4076,7 +3091,7 @@ nghttp2_session_del(session); } -void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void) { +void test_nghttp2_session_reprioritize_stream_with_closed_stream_limit(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; nghttp2_stream *stream; @@ -4087,7 +3102,9 @@ nghttp2_session_server_new(&session, &callbacks, NULL); - stream = open_recv_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); session->pending_local_max_concurrent_stream = 1; @@ -4095,7 +3112,16 @@ nghttp2_session_reprioritize_stream(session, stream, &pri_spec); - /* idle stream is not counteed to max concurrent streams */ + /* No room to create idle stream, so default priority was applied. */ + + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight); + CU_ASSERT(NULL == stream->dep_prev); + + session->pending_local_max_concurrent_stream = 2; + + /* Now idle stream can be created */ + + nghttp2_session_reprioritize_stream(session, stream, &pri_spec); CU_ASSERT(10 == stream->weight); CU_ASSERT(101 == stream->dep_prev->stream_id); @@ -4127,8 +3153,8 @@ aob = &session->aob; framebufs = &aob->framebufs; - open_sent_stream(session, 1); - + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); CU_ASSERT( 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd)); @@ -4169,8 +3195,8 @@ aob = &session->aob; framebufs = &aob->framebufs; - open_sent_stream(session, 1); - + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); CU_ASSERT( 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd)); @@ -4196,8 +3222,8 @@ session->remote_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MAX; - open_sent_stream(session, 1); - + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); CU_ASSERT( 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd)); @@ -4248,8 +3274,8 @@ aob = &session->aob; framebufs = &aob->framebufs; - open_sent_stream(session, 1); - + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); CU_ASSERT( 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd)); @@ -4274,7 +3300,7 @@ size_t len, uint32_t *data_flags, nghttp2_data_source *source _U_, void *user_data _U_) { *data_flags |= NGHTTP2_DATA_FLAG_EOF; - return (ssize_t)nghttp2_min(len, 16); + return nghttp2_min(len, 16); } static int submit_data_twice_on_frame_send_callback(nghttp2_session *session, @@ -4315,9 +3341,11 @@ CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud)); - open_sent_stream(session, 1); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &data_prd)); + CU_ASSERT(0 == nghttp2_session_send(session)); /* We should have sent 2 DATA frame with 16 bytes payload each */ @@ -4329,12 +3357,10 @@ void test_nghttp2_submit_request_with_data(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + nghttp2_nv nva[] = {MAKE_NV(":version", "HTTP/1.1")}; nghttp2_data_provider data_prd; my_user_data ud; nghttp2_outbound_item *item; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; @@ -4342,31 +3368,21 @@ data_prd.read_callback = fixed_length_data_source_read_callback; ud.data_source_length = 64 * 1024 - 1; CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud)); - CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), + CU_ASSERT(1 == nghttp2_submit_request(session, NULL, nva, ARRLEN(nva), &data_prd, NULL)); item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen); - assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen, - mem); + CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0])); CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == ud.data_source_length); nghttp2_session_del(session); - - /* nghttp2_submit_request() with server session is error */ - nghttp2_session_server_new(&session, &callbacks, NULL); - - CU_ASSERT(NGHTTP2_ERR_PROTO == nghttp2_submit_request(session, NULL, reqnv, - ARRLEN(reqnv), NULL, - NULL)); - - nghttp2_session_del(session); } void test_nghttp2_submit_request_without_data(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; accumulator acc; + nghttp2_nv nva[] = {MAKE_NV(":version", "HTTP/1.1")}; nghttp2_data_provider data_prd = {{-1}, NULL}; nghttp2_outbound_item *item; my_user_data ud; @@ -4374,10 +3390,7 @@ nghttp2_hd_inflater inflater; nva_out out; nghttp2_bufs bufs; - nghttp2_mem *mem; - nghttp2_priority_spec pri_spec; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); @@ -4387,49 +3400,35 @@ callbacks.send_callback = accumulator_send_callback; CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud)); - nghttp2_hd_inflate_init(&inflater, mem); - CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), + nghttp2_hd_inflate_init(&inflater); + CU_ASSERT(1 == nghttp2_submit_request(session, NULL, nva, ARRLEN(nva), &data_prd, NULL)); item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen); - assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen, - mem); + CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0])); CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM); CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length)); nghttp2_bufs_add(&bufs, acc.buf, acc.length); - inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem); + inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN); - CU_ASSERT(ARRLEN(reqnv) == out.nvlen); - assert_nv_equal(reqnv, out.nva, out.nvlen, mem); - nghttp2_frame_headers_free(&frame.headers, mem); - nva_out_reset(&out, mem); + CU_ASSERT(nvnameeq(":version", &out.nva[0])); + nghttp2_frame_headers_free(&frame.headers); + nva_out_reset(&out); nghttp2_bufs_free(&bufs); nghttp2_hd_inflate_free(&inflater); - - /* Try to depend on itself is error */ - nghttp2_priority_spec_init(&pri_spec, (int32_t)session->next_stream_id, 16, - 0); - - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == - nghttp2_submit_request(session, &pri_spec, reqnv, ARRLEN(reqnv), - NULL, NULL)); - nghttp2_session_del(session); } void test_nghttp2_submit_response_with_data(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + nghttp2_nv nva[] = {MAKE_NV(":version", "HTTP/1.1")}; nghttp2_data_provider data_prd; my_user_data ud; nghttp2_outbound_item *item; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; @@ -4437,36 +3436,23 @@ data_prd.read_callback = fixed_length_data_source_read_callback; ud.data_source_length = 64 * 1024 - 1; CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); - open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); - CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), - &data_prd)); - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen); - assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen, - mem); + nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + CU_ASSERT(0 == + nghttp2_submit_response(session, 1, nva, ARRLEN(nva), &data_prd)); + item = nghttp2_session_get_next_ob_item(session); + CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0])); CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == ud.data_source_length); nghttp2_session_del(session); - - /* Various error cases */ - nghttp2_session_client_new(&session, &callbacks, NULL); - - /* Calling nghttp2_submit_response() with client session is error */ - CU_ASSERT(NGHTTP2_ERR_PROTO == - nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL)); - - /* Stream ID <= 0 is error */ - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == - nghttp2_submit_response(session, 0, resnv, ARRLEN(resnv), NULL)); - - nghttp2_session_del(session); } void test_nghttp2_submit_response_without_data(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; accumulator acc; + nghttp2_nv nva[] = {MAKE_NV(":version", "HTTP/1.1")}; nghttp2_data_provider data_prd = {{-1}, NULL}; nghttp2_outbound_item *item; my_user_data ud; @@ -4474,9 +3460,7 @@ nghttp2_hd_inflater inflater; nva_out out; nghttp2_bufs bufs; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); @@ -4486,158 +3470,56 @@ callbacks.send_callback = accumulator_send_callback; CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); - nghttp2_hd_inflate_init(&inflater, mem); - open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); - CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), - &data_prd)); - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen); - assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen, - mem); + nghttp2_hd_inflate_init(&inflater); + nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + CU_ASSERT(0 == + nghttp2_submit_response(session, 1, nva, ARRLEN(nva), &data_prd)); + item = nghttp2_session_get_next_ob_item(session); + CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0])); CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM); CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length)); nghttp2_bufs_add(&bufs, acc.buf, acc.length); - inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem); + inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN); - CU_ASSERT(ARRLEN(resnv) == out.nvlen); - assert_nv_equal(resnv, out.nva, out.nvlen, mem); + CU_ASSERT(nvnameeq(":version", &out.nva[0])); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_free(&bufs); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_hd_inflate_free(&inflater); nghttp2_session_del(session); } -void test_nghttp2_submit_response_push_response(void) { +void test_nghttp2_submit_headers_start_stream(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - my_user_data ud; + const nghttp2_nv nv[] = {MAKE_NV(":version", "HTTP/1.1")}; + nghttp2_outbound_item *item; memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - callbacks.on_frame_not_send_callback = on_frame_not_send_callback; - - nghttp2_session_server_new(&session, &callbacks, &ud); - - open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); - - session->goaway_flags |= NGHTTP2_GOAWAY_RECV; - - CU_ASSERT(0 == - nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL)); - - ud.frame_not_send_cb_called = 0; - - CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(1 == ud.frame_not_send_cb_called); + CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL)); + CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, + NULL, nv, ARRLEN(nv), NULL)); + item = nghttp2_session_get_next_ob_item(session); + CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0])); + CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM) == + item->frame.hd.flags); + CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY)); nghttp2_session_del(session); } -void test_nghttp2_submit_trailer(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - accumulator acc; - nghttp2_data_provider data_prd; - nghttp2_outbound_item *item; - my_user_data ud; - nghttp2_frame frame; - nghttp2_hd_inflater inflater; - nva_out out; - nghttp2_bufs bufs; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - data_prd.read_callback = no_end_stream_data_source_read_callback; - nva_out_init(&out); - acc.length = 0; - ud.acc = &acc; - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); - - nghttp2_hd_inflate_init(&inflater, mem); - open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); - CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), - &data_prd)); - CU_ASSERT(0 == nghttp2_session_send(session)); - - CU_ASSERT(0 == - nghttp2_submit_trailer(session, 1, trailernv, ARRLEN(trailernv))); - - session->callbacks.send_callback = accumulator_send_callback; - - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type); - CU_ASSERT(NGHTTP2_HCAT_HEADERS == item->frame.headers.cat); - CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM); - - CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length)); - - nghttp2_bufs_add(&bufs, acc.buf, acc.length); - inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem); - - CU_ASSERT(ARRLEN(trailernv) == out.nvlen); - assert_nv_equal(trailernv, out.nva, out.nvlen, mem); - - nva_out_reset(&out, mem); - nghttp2_bufs_free(&bufs); - nghttp2_frame_headers_free(&frame.headers, mem); - nghttp2_hd_inflate_free(&inflater); - nghttp2_session_del(session); - - /* Specifying stream ID <= 0 is error */ - nghttp2_session_server_new(&session, &callbacks, NULL); - open_recv_stream(session, 1); - - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == - nghttp2_submit_trailer(session, 0, trailernv, ARRLEN(trailernv))); - - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == - nghttp2_submit_trailer(session, -1, trailernv, ARRLEN(trailernv))); - - nghttp2_session_del(session); -} - -void test_nghttp2_submit_headers_start_stream(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_outbound_item *item; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL)); - CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, - NULL, reqnv, ARRLEN(reqnv), NULL)); - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen); - assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen, - mem); - CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM) == - item->frame.hd.flags); - CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY)); - - nghttp2_session_del(session); -} - -void test_nghttp2_submit_headers_reply(void) { +void test_nghttp2_submit_headers_reply(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + const nghttp2_nv nv[] = {MAKE_NV(":version", "HTTP/1.1")}; my_user_data ud; nghttp2_outbound_item *item; nghttp2_stream *stream; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; @@ -4645,11 +3527,9 @@ CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, - NULL, resnv, ARRLEN(resnv), NULL)); + NULL, nv, ARRLEN(nv), NULL)); item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(ARRLEN(resnv) == item->frame.headers.nvlen); - assert_nv_equal(resnv, item->frame.headers.nva, item->frame.headers.nvlen, - mem); + CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0])); CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) == item->frame.hd.flags); @@ -4660,10 +3540,12 @@ CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == ud.frame_send_cb_called); - stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, - NULL, resnv, ARRLEN(resnv), NULL)); + NULL, nv, ARRLEN(nv), NULL)); CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(1 == ud.frame_send_cb_called); CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type); @@ -4675,6 +3557,7 @@ void test_nghttp2_submit_headers_push_reply(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + const nghttp2_nv nv[] = {MAKE_NV(":version", "HTTP/1.1")}; my_user_data ud; nghttp2_stream *stream; int foo; @@ -4684,9 +3567,11 @@ callbacks.on_frame_send_callback = on_frame_send_callback; CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); - stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); - CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL, - resnv, ARRLEN(resnv), &foo)); + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_RESERVED, NULL); + CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL, nv, + ARRLEN(nv), &foo)); ud.frame_send_cb_called = 0; ud.sent_frame_type = 0; @@ -4701,9 +3586,11 @@ /* Sending HEADERS from client against stream in reserved state is error */ CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud)); - open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); - CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL, - reqnv, ARRLEN(reqnv), NULL)); + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_RESERVED, NULL); + CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL, nv, + ARRLEN(nv), NULL)); ud.frame_send_cb_called = 0; ud.sent_frame_type = 0; @@ -4716,6 +3603,7 @@ void test_nghttp2_submit_headers(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + const nghttp2_nv nv[] = {MAKE_NV(":version", "HTTP/1.1")}; my_user_data ud; nghttp2_outbound_item *item; nghttp2_stream *stream; @@ -4724,10 +3612,7 @@ nghttp2_hd_inflater inflater; nva_out out; nghttp2_bufs bufs; - nghttp2_mem *mem; - nghttp2_priority_spec pri_spec; - mem = nghttp2_mem_default(); frame_pack_bufs_init(&bufs); nva_out_init(&out); @@ -4739,13 +3624,11 @@ CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud)); - nghttp2_hd_inflate_init(&inflater, mem); + nghttp2_hd_inflate_init(&inflater); CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, - NULL, reqnv, ARRLEN(reqnv), NULL)); + NULL, nv, ARRLEN(nv), NULL)); item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(ARRLEN(reqnv) == item->frame.headers.nvlen); - assert_nv_equal(reqnv, item->frame.headers.nva, item->frame.headers.nvlen, - mem); + CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0])); CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) == item->frame.hd.flags); @@ -4756,10 +3639,12 @@ CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == ud.frame_send_cb_called); - stream = open_sent_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, - NULL, reqnv, ARRLEN(reqnv), NULL)); + NULL, nv, ARRLEN(nv), NULL)); CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(1 == ud.frame_send_cb_called); CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type); @@ -4768,47 +3653,15 @@ CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length)); nghttp2_bufs_add(&bufs, acc.buf, acc.length); - inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem); + inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN); - CU_ASSERT(ARRLEN(reqnv) == out.nvlen); - assert_nv_equal(reqnv, out.nva, out.nvlen, mem); + CU_ASSERT(nvnameeq(":version", &out.nva[0])); - nva_out_reset(&out, mem); + nva_out_reset(&out); nghttp2_bufs_free(&bufs); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_hd_inflate_free(&inflater); - - /* Try to depend on itself */ - nghttp2_priority_spec_init(&pri_spec, 3, 16, 0); - - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == - nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, &pri_spec, - reqnv, ARRLEN(reqnv), NULL)); - - session->next_stream_id = 5; - nghttp2_priority_spec_init(&pri_spec, 5, 16, 0); - - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == - nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, &pri_spec, - reqnv, ARRLEN(reqnv), NULL)); - - nghttp2_session_del(session); - - /* Error cases with invalid stream ID */ - nghttp2_session_server_new(&session, &callbacks, NULL); - - /* Sending nghttp2_submit_headers() with stream_id == 1 and server - session is error */ - CU_ASSERT(NGHTTP2_ERR_PROTO == - nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, reqnv, - ARRLEN(reqnv), NULL)); - - /* Sending stream ID <= 0 is error */ - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == - nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 0, NULL, resnv, - ARRLEN(resnv), NULL)); - nghttp2_session_del(session); } @@ -4851,51 +3704,6 @@ nghttp2_session_del(session); } -void test_nghttp2_submit_headers_continuation_extra_large(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_nv nv[] = { - MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""), - MAKE_NV("h1", ""), MAKE_NV("h1", ""), MAKE_NV("h1", ""), - }; - nghttp2_outbound_item *item; - uint8_t data[16384]; - size_t i; - my_user_data ud; - nghttp2_option *opt; - - memset(data, '0', sizeof(data)); - for (i = 0; i < ARRLEN(nv); ++i) { - nv[i].valuelen = sizeof(data); - nv[i].value = data; - } - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - callbacks.on_frame_send_callback = on_frame_send_callback; - - /* The default size of max send header block length is too small to - send these header fields. Expand it. */ - nghttp2_option_new(&opt); - nghttp2_option_set_max_send_header_block_length(opt, 102400); - - CU_ASSERT(0 == nghttp2_session_client_new2(&session, &callbacks, &ud, opt)); - CU_ASSERT(1 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, - NULL, nv, ARRLEN(nv), NULL)); - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type); - CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) == - item->frame.hd.flags); - CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY)); - - ud.frame_send_cb_called = 0; - CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(1 == ud.frame_send_cb_called); - - nghttp2_session_del(session); - nghttp2_option_del(opt); -} - void test_nghttp2_submit_priority(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; @@ -4908,7 +3716,9 @@ callbacks.on_frame_send_callback = on_frame_send_callback; nghttp2_session_client_new(&session, &callbacks, &ud); - stream = open_sent_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); nghttp2_priority_spec_init(&pri_spec, 0, 3, 0); @@ -4938,9 +3748,6 @@ nghttp2_settings_entry iv[7]; nghttp2_frame ack_frame; const int32_t UNKNOWN_ID = 1000000007; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; iv[0].value = 5; @@ -4952,16 +3759,13 @@ iv[2].value = 50; iv[3].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; - iv[3].value = 111; + iv[3].value = 0; iv[4].settings_id = UNKNOWN_ID; iv[4].value = 999; - iv[5].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; - iv[5].value = 1023; - - iv[6].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; - iv[6].value = (uint32_t)NGHTTP2_MAX_WINDOW_SIZE + 1; + iv[5].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; + iv[5].value = (uint32_t)NGHTTP2_MAX_WINDOW_SIZE + 1; memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; @@ -4969,7 +3773,7 @@ nghttp2_session_server_new(&session, &callbacks, &ud); CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == - nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 7)); + nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 6)); /* Make sure that local settings are not changed */ CU_ASSERT(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS == @@ -4978,14 +3782,14 @@ session->local_settings.initial_window_size); /* Now sends without 6th one */ - CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 6)); + CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 5)); item = nghttp2_session_get_next_ob_item(session); CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type); frame = &item->frame; - CU_ASSERT(6 == frame->settings.niv); + CU_ASSERT(5 == frame->settings.niv); CU_ASSERT(5 == frame->settings.iv[0].value); CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS == frame->settings.iv[0].settings_id); @@ -5005,14 +3809,13 @@ nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0); CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0)); - nghttp2_frame_settings_free(&ack_frame.settings, mem); + nghttp2_frame_settings_free(&ack_frame.settings); CU_ASSERT(16 * 1024 == session->local_settings.initial_window_size); - CU_ASSERT(1023 == session->hd_inflater.ctx.hd_table_bufsize_max); - CU_ASSERT(111 == session->hd_inflater.min_hd_table_bufsize_max); + CU_ASSERT(0 == session->hd_inflater.ctx.hd_table_bufsize_max); CU_ASSERT(50 == session->local_settings.max_concurrent_streams); - /* We just keep the last seen value */ - CU_ASSERT(50 == session->pending_local_max_concurrent_stream); + CU_ASSERT(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS == + session->pending_local_max_concurrent_stream); nghttp2_session_del(session); } @@ -5024,9 +3827,7 @@ nghttp2_settings_entry iv[4]; nghttp2_stream *stream; nghttp2_frame ack_frame; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0); iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; @@ -5037,11 +3838,15 @@ nghttp2_session_server_new(&session, &callbacks, NULL); - stream = open_recv_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + NULL); stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100; stream->recv_window_size = 32768; - open_recv_stream(session, 3); + stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + NULL); CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1)); CU_ASSERT(0 == nghttp2_session_send(session)); @@ -5063,7 +3868,9 @@ /* Check overflow case */ iv[0].value = 128 * 1024; nghttp2_session_server_new(&session, &callbacks, NULL); - stream = open_recv_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + NULL); stream->local_window_size = NGHTTP2_MAX_WINDOW_SIZE; CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1)); @@ -5071,134 +3878,39 @@ CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0)); item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(NGHTTP2_FLOW_CONTROL_ERROR == item->frame.rst_stream.error_code); - - nghttp2_session_del(session); - nghttp2_frame_settings_free(&ack_frame.settings, mem); -} - -void test_nghttp2_submit_settings_multiple_times(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_settings_entry iv[4]; - nghttp2_frame frame; - nghttp2_inflight_settings *inflight_settings; - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - - /* first SETTINGS */ - iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; - iv[0].value = 100; - - iv[1].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; - iv[1].value = 0; - - CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 2)); - - inflight_settings = session->inflight_settings_head; - - CU_ASSERT(NULL != inflight_settings); - CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS == - inflight_settings->iv[0].settings_id); - CU_ASSERT(100 == inflight_settings->iv[0].value); - CU_ASSERT(2 == inflight_settings->niv); - CU_ASSERT(NULL == inflight_settings->next); - - CU_ASSERT(100 == session->pending_local_max_concurrent_stream); - CU_ASSERT(0 == session->pending_enable_push); - - /* second SETTINGS */ - iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; - iv[0].value = 99; - - CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1)); - - inflight_settings = session->inflight_settings_head->next; - - CU_ASSERT(NULL != inflight_settings); - CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS == - inflight_settings->iv[0].settings_id); - CU_ASSERT(99 == inflight_settings->iv[0].value); - CU_ASSERT(1 == inflight_settings->niv); - CU_ASSERT(NULL == inflight_settings->next); - - CU_ASSERT(99 == session->pending_local_max_concurrent_stream); - CU_ASSERT(0 == session->pending_enable_push); - - nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_ACK, NULL, 0); - - /* receive SETTINGS ACK */ - CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0)); - - inflight_settings = session->inflight_settings_head; - - /* first inflight SETTINGS was removed */ - CU_ASSERT(NULL != inflight_settings); - CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS == - inflight_settings->iv[0].settings_id); - CU_ASSERT(99 == inflight_settings->iv[0].value); - CU_ASSERT(1 == inflight_settings->niv); - CU_ASSERT(NULL == inflight_settings->next); - - CU_ASSERT(100 == session->local_settings.max_concurrent_streams); - - /* receive SETTINGS ACK again */ - CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0)); - - CU_ASSERT(NULL == session->inflight_settings_head); - CU_ASSERT(99 == session->local_settings.max_concurrent_streams); + CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); + CU_ASSERT(NGHTTP2_FLOW_CONTROL_ERROR == item->frame.goaway.error_code); nghttp2_session_del(session); + nghttp2_frame_settings_free(&ack_frame.settings); } void test_nghttp2_submit_push_promise(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + const nghttp2_nv nv[] = {MAKE_NV(":version", "HTTP/1.1")}; my_user_data ud; nghttp2_stream *stream; memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; callbacks.on_frame_send_callback = on_frame_send_callback; - callbacks.on_frame_not_send_callback = on_frame_not_send_callback; CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); - open_recv_stream(session, 1); - CU_ASSERT(2 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, - reqnv, ARRLEN(reqnv), &ud)); - - stream = nghttp2_session_get_stream(session, 2); - - CU_ASSERT(NULL != stream); - CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state); - CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2)); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + CU_ASSERT(2 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, nv, + ARRLEN(nv), &ud)); ud.frame_send_cb_called = 0; ud.sent_frame_type = 0; - CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(1 == ud.frame_send_cb_called); CU_ASSERT(NGHTTP2_PUSH_PROMISE == ud.sent_frame_type); - stream = nghttp2_session_get_stream(session, 2); - CU_ASSERT(NGHTTP2_STREAM_RESERVED == stream->state); CU_ASSERT(&ud == nghttp2_session_get_stream_user_data(session, 2)); - /* submit PUSH_PROMISE while associated stream is not opened */ - CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == - nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 3, reqnv, - ARRLEN(reqnv), NULL)); - - /* Stream ID <= 0 is error */ - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == - nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 0, reqnv, - ARRLEN(reqnv), NULL)); - nghttp2_session_del(session); } @@ -5213,7 +3925,9 @@ callbacks.send_callback = null_send_callback; nghttp2_session_client_new(&session, &callbacks, &ud); - stream = open_recv_stream(session, 2); + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + NULL); stream->recv_window_size = 4096; CU_ASSERT(0 == @@ -5260,7 +3974,9 @@ callbacks.send_callback = null_send_callback; nghttp2_session_client_new(&session, &callbacks, NULL); - stream = open_recv_stream(session, 2); + stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + NULL); stream->recv_window_size = 4096; CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, @@ -5336,58 +4052,69 @@ nghttp2_session_del(session); } -void test_nghttp2_submit_shutdown_notice(void) { +void test_nghttp2_submit_altsvc(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; + const char protocol_id[] = "h2"; + const char host[] = "localhost"; + const char origin[] = "http://localhost/"; + nghttp2_frame *frame; + nghttp2_ext_altsvc *altsvc; + nghttp2_outbound_item *item; my_user_data ud; memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; callbacks.on_frame_send_callback = on_frame_send_callback; - callbacks.on_frame_not_send_callback = on_frame_not_send_callback; - nghttp2_session_server_new(&session, &callbacks, &ud); + nghttp2_session_client_new(&session, &callbacks, NULL); - CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session)); + CU_ASSERT(NGHTTP2_ERR_PROTO == + nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, 0, 3000, + (const uint8_t *)protocol_id, + strlen(protocol_id), (const uint8_t *)host, + strlen(host), (const uint8_t *)origin, + strlen(origin))); - ud.frame_send_cb_called = 0; + nghttp2_session_del(session); - nghttp2_session_send(session); + nghttp2_session_server_new(&session, &callbacks, &ud); - CU_ASSERT(1 == ud.frame_send_cb_called); - CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type); - CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id); + open_stream(session, 9); - /* After another GOAWAY, nghttp2_submit_shutdown_notice() is - noop. */ - CU_ASSERT(0 == nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR)); + CU_ASSERT(0 == nghttp2_submit_altsvc( + session, NGHTTP2_FLAG_NONE, 9, 12345, 3000, + (const uint8_t *)protocol_id, strlen(protocol_id), + (const uint8_t *)host, strlen(host), + (const uint8_t *)origin, strlen(origin))); - ud.frame_send_cb_called = 0; + item = nghttp2_session_get_next_ob_item(session); - nghttp2_session_send(session); + frame = &item->frame; - CU_ASSERT(1 == ud.frame_send_cb_called); - CU_ASSERT(NGHTTP2_GOAWAY == ud.sent_frame_type); - CU_ASSERT(0 == session->local_last_stream_id); + CU_ASSERT(NGHTTP2_EXT_ALTSVC == frame->hd.type); + CU_ASSERT(9 == frame->hd.stream_id); - CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session)); + altsvc = frame->ext.payload; - ud.frame_send_cb_called = 0; - ud.frame_not_send_cb_called = 0; + CU_ASSERT(12345 == altsvc->max_age); + CU_ASSERT(3000 == altsvc->port); - nghttp2_session_send(session); + CU_ASSERT(strlen(protocol_id) == altsvc->protocol_id_len); + CU_ASSERT(strlen(host) == altsvc->host_len); + CU_ASSERT(strlen(origin) == altsvc->origin_len); - CU_ASSERT(0 == ud.frame_send_cb_called); - CU_ASSERT(0 == ud.frame_not_send_cb_called); + CU_ASSERT(0 == + memcmp(protocol_id, altsvc->protocol_id, altsvc->protocol_id_len)); + CU_ASSERT(0 == memcmp(host, altsvc->host, altsvc->host_len)); + CU_ASSERT(0 == memcmp(origin, altsvc->origin, altsvc->origin_len)); - nghttp2_session_del(session); + ud.frame_send_cb_called = 0; - /* Using nghttp2_submit_shutdown_notice() with client side session - is error */ - nghttp2_session_client_new(&session, &callbacks, NULL); + CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == - nghttp2_submit_shutdown_notice(session)); + CU_ASSERT(1 == ud.frame_send_cb_called); + CU_ASSERT(NGHTTP2_EXT_ALTSVC == ud.sent_frame_type); nghttp2_session_del(session); } @@ -5405,171 +4132,34 @@ CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL)); + /* nghttp2_submit_request */ + CU_ASSERT(0 < nghttp2_submit_request(session, NULL, empty_name_nv, + ARRLEN(empty_name_nv), NULL, NULL)); + /* nghttp2_submit_response */ CU_ASSERT(0 == nghttp2_submit_response(session, 2, empty_name_nv, ARRLEN(empty_name_nv), NULL)); + /* nghttp2_submit_headers */ + CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, + empty_name_nv, ARRLEN(empty_name_nv), + NULL)); + /* nghttp2_submit_push_promise */ - open_recv_stream(session, 1); + open_stream(session, 1); CU_ASSERT(0 < nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, empty_name_nv, ARRLEN(empty_name_nv), NULL)); nghttp2_session_del(session); - - CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL)); - - /* nghttp2_submit_request */ - CU_ASSERT(0 < nghttp2_submit_request(session, NULL, empty_name_nv, - ARRLEN(empty_name_nv), NULL, NULL)); - - /* nghttp2_submit_headers */ - CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, - empty_name_nv, ARRLEN(empty_name_nv), - NULL)); - - nghttp2_session_del(session); } -void test_nghttp2_submit_extension(void) { +void test_nghttp2_session_open_stream(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - my_user_data ud; - accumulator acc; - nghttp2_mem *mem; - const char data[] = "Hello World!"; - size_t len; - int32_t stream_id; - int rv; - - mem = nghttp2_mem_default(); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - - callbacks.pack_extension_callback = pack_extension_callback; - callbacks.send_callback = accumulator_send_callback; - - nghttp2_buf_init2(&ud.scratchbuf, 4096, mem); - - nghttp2_session_client_new(&session, &callbacks, &ud); - - ud.scratchbuf.last = nghttp2_cpymem(ud.scratchbuf.last, data, sizeof(data)); - ud.acc = &acc; - - rv = nghttp2_submit_extension(session, 211, 0x01, 3, &ud.scratchbuf); - - CU_ASSERT(0 == rv); - - acc.length = 0; - - rv = nghttp2_session_send(session); - - CU_ASSERT(0 == rv); - CU_ASSERT(NGHTTP2_FRAME_HDLEN + sizeof(data) == acc.length); - - len = nghttp2_get_uint32(acc.buf) >> 8; - - CU_ASSERT(sizeof(data) == len); - CU_ASSERT(211 == acc.buf[3]); - CU_ASSERT(0x01 == acc.buf[4]); - - stream_id = (int32_t)nghttp2_get_uint32(acc.buf + 5); - - CU_ASSERT(3 == stream_id); - CU_ASSERT(0 == memcmp(data, &acc.buf[NGHTTP2_FRAME_HDLEN], sizeof(data))); - - nghttp2_session_del(session); - - /* submitting standard HTTP/2 frame is error */ - nghttp2_session_server_new(&session, &callbacks, &ud); - - rv = nghttp2_submit_extension(session, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0, - NULL); - - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv); - - nghttp2_session_del(session); - nghttp2_buf_free(&ud.scratchbuf, mem); -} - -void test_nghttp2_submit_altsvc(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - my_user_data ud; - int rv; - ssize_t len; - const uint8_t *data; - nghttp2_frame_hd hd; - size_t origin_len; - const uint8_t origin[] = "nghttp2.org"; - const uint8_t field_value[] = "h2=\":443\""; - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - - nghttp2_session_server_new(&session, &callbacks, &ud); - - rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin, - sizeof(origin) - 1, field_value, - sizeof(field_value) - 1); - - CU_ASSERT(0 == rv); - - ud.frame_send_cb_called = 0; - - len = nghttp2_session_mem_send(session, &data); - - CU_ASSERT(len == - NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1 + sizeof(field_value) - - 1); - - nghttp2_frame_unpack_frame_hd(&hd, data); - - CU_ASSERT(2 + sizeof(origin) - 1 + sizeof(field_value) - 1 == hd.length); - CU_ASSERT(NGHTTP2_ALTSVC == hd.type); - CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags); - - origin_len = nghttp2_get_uint16(data + NGHTTP2_FRAME_HDLEN); - - CU_ASSERT(sizeof(origin) - 1 == origin_len); - CU_ASSERT(0 == - memcmp(origin, data + NGHTTP2_FRAME_HDLEN + 2, sizeof(origin) - 1)); - CU_ASSERT(0 == memcmp(field_value, - data + NGHTTP2_FRAME_HDLEN + 2 + sizeof(origin) - 1, - hd.length - (sizeof(origin) - 1) - 2)); - - /* submitting empty origin with stream_id == 0 is error */ - rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, NULL, 0, - field_value, sizeof(field_value) - 1); - - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv); - - /* submitting non-empty origin with stream_id != 0 is error */ - rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 1, origin, - sizeof(origin) - 1, field_value, - sizeof(field_value) - 1); - - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv); - - nghttp2_session_del(session); - - /* submitting from client side session is error */ - nghttp2_session_client_new(&session, &callbacks, NULL); - - rv = nghttp2_submit_altsvc(session, NGHTTP2_FLAG_NONE, 0, origin, - sizeof(origin) - 1, field_value, - sizeof(field_value) - 1); - - CU_ASSERT(NGHTTP2_ERR_INVALID_STATE == rv); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_open_stream(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_stream *stream; - nghttp2_priority_spec pri_spec; + nghttp2_stream *stream; + nghttp2_priority_spec pri_spec; memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); nghttp2_session_server_new(&session, &callbacks, NULL); @@ -5582,7 +4172,7 @@ CU_ASSERT(0 == session->num_outgoing_streams); CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state); CU_ASSERT(245 == stream->weight); - CU_ASSERT(&session->root == stream->dep_prev); + CU_ASSERT(NULL == stream->dep_prev); CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags); stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, @@ -5590,7 +4180,7 @@ NGHTTP2_STREAM_OPENING, NULL); CU_ASSERT(1 == session->num_incoming_streams); CU_ASSERT(1 == session->num_outgoing_streams); - CU_ASSERT(&session->root == stream->dep_prev); + CU_ASSERT(NULL == stream->dep_prev); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight); CU_ASSERT(NGHTTP2_SHUT_NONE == stream->shut_flags); @@ -5599,7 +4189,7 @@ NGHTTP2_STREAM_RESERVED, NULL); CU_ASSERT(1 == session->num_incoming_streams); CU_ASSERT(1 == session->num_outgoing_streams); - CU_ASSERT(&session->root == stream->dep_prev); + CU_ASSERT(NULL == stream->dep_prev); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight); CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags); @@ -5621,7 +4211,7 @@ stream = nghttp2_session_get_stream_raw(session, 1000000007); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight); - CU_ASSERT(&session->root == stream->dep_prev); + CU_ASSERT(NULL != stream->root_next); /* Dependency to closed stream which is not in dependency tree */ session->last_recv_stream_id = 7; @@ -5632,7 +4222,6 @@ NGHTTP2_STREAM_OPENED, NULL); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight); - CU_ASSERT(&session->root == stream->dep_prev); nghttp2_session_del(session); @@ -5642,14 +4231,14 @@ NGHTTP2_STREAM_RESERVED, NULL); CU_ASSERT(0 == session->num_incoming_streams); CU_ASSERT(0 == session->num_outgoing_streams); - CU_ASSERT(&session->root == stream->dep_prev); + CU_ASSERT(NULL == stream->dep_prev); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight); CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags); nghttp2_session_del(session); } -void test_nghttp2_session_open_stream_with_idle_stream_dep(void) { +void test_nghttp2_session_open_stream_with_closed_stream_limit(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; nghttp2_stream *stream; @@ -5658,12 +4247,22 @@ memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); nghttp2_session_server_new(&session, &callbacks, NULL); + session->pending_local_max_concurrent_stream = 1; + /* Dependency to idle stream */ nghttp2_priority_spec_init(&pri_spec, 101, 245, 0); stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_OPENED, NULL); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight); + + session->pending_local_max_concurrent_stream = 3; + + /* Now another 2 streams can be added */ + stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec, NGHTTP2_STREAM_OPENED, NULL); + CU_ASSERT(245 == stream->weight); CU_ASSERT(101 == stream->dep_prev->stream_id); @@ -5672,9 +4271,14 @@ CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight); + session->pending_local_max_concurrent_stream = 4; + + /* Now another 1 stream can be added */ + nghttp2_priority_spec_init(&pri_spec, 211, 1, 0); - /* stream 101 was already created as idle. */ + /* stream 101 was already created and does not consume another + limit. */ stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_OPENED, NULL); @@ -5697,7 +4301,7 @@ memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; - nghttp2_session_client_new(&session, &callbacks, NULL); + nghttp2_session_server_new(&session, &callbacks, NULL); session->remote_settings.max_concurrent_streams = 2; CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); @@ -5705,7 +4309,7 @@ CU_ASSERT(NGHTTP2_PING == nghttp2_session_get_next_ob_item(session)->frame.hd.type); - CU_ASSERT(1 == nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL)); + nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL); CU_ASSERT(NGHTTP2_PING == nghttp2_session_get_next_ob_item(session)->frame.hd.type); @@ -5714,18 +4318,17 @@ /* Incoming stream does not affect the number of outgoing max concurrent streams. */ - open_recv_stream(session, 2); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0); - CU_ASSERT(3 == - nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL)); + nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL); CU_ASSERT(NGHTTP2_HEADERS == nghttp2_session_get_next_ob_item(session)->frame.hd.type); CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(5 == - nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL)); + nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL); CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); session->remote_settings.max_concurrent_streams = 3; @@ -5734,16 +4337,6 @@ nghttp2_session_get_next_ob_item(session)->frame.hd.type); nghttp2_session_del(session); - - /* Check that push reply HEADERS are queued into ob_ss_pq */ - nghttp2_session_server_new(&session, &callbacks, NULL); - session->remote_settings.max_concurrent_streams = 0; - open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); - CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2, - NULL, NULL, 0, NULL)); - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn)); - nghttp2_session_del(session); } void test_nghttp2_session_pop_next_ob_item(void) { @@ -5751,13 +4344,12 @@ nghttp2_session_callbacks callbacks; nghttp2_outbound_item *item; nghttp2_priority_spec pri_spec; - nghttp2_mem *mem; + nghttp2_stream *stream; - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; - nghttp2_session_client_new(&session, &callbacks, NULL); + nghttp2_session_server_new(&session, &callbacks, NULL); session->remote_settings.max_concurrent_streams = 1; CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session)); @@ -5770,25 +4362,39 @@ item = nghttp2_session_pop_next_ob_item(session); CU_ASSERT(NGHTTP2_PING == item->frame.hd.type); - nghttp2_outbound_item_free(item, mem); - mem->free(item, NULL); + nghttp2_outbound_item_free(item); + free(item); item = nghttp2_session_pop_next_ob_item(session); CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type); - nghttp2_outbound_item_free(item, mem); - mem->free(item, NULL); + nghttp2_outbound_item_free(item); + free(item); CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session)); /* Incoming stream does not affect the number of outgoing max concurrent streams. */ - open_recv_stream(session, 4); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); /* In-flight outgoing stream */ - open_sent_stream(session, 1); + nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0); nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL); + nghttp2_submit_response(session, 1, NULL, 0, NULL); + + item = nghttp2_session_pop_next_ob_item(session); + CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type); + CU_ASSERT(1 == item->frame.hd.stream_id); + + stream = nghttp2_session_get_stream(session, 1); + + nghttp2_stream_detach_data(stream, session); + + nghttp2_outbound_item_free(item); + free(item); CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session)); @@ -5796,19 +4402,20 @@ item = nghttp2_session_pop_next_ob_item(session); CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type); - nghttp2_outbound_item_free(item, mem); - mem->free(item, NULL); + nghttp2_outbound_item_free(item); + free(item); nghttp2_session_del(session); /* Check that push reply HEADERS are queued into ob_ss_pq */ nghttp2_session_server_new(&session, &callbacks, NULL); session->remote_settings.max_concurrent_streams = 0; - open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); + nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL); CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2, NULL, NULL, 0, NULL)); CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session)); - CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn)); + CU_ASSERT(1 == nghttp2_pq_size(&session->ob_ss_pq)); nghttp2_session_del(session); } @@ -5824,7 +4431,8 @@ data_prd.read_callback = fixed_length_data_source_read_callback; ud.data_source_length = 4 * 1024; CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); - open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd)); CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session)); nghttp2_session_del(session); @@ -5835,14 +4443,13 @@ nghttp2_session_callbacks callbacks; nghttp2_frame frame; nghttp2_outbound_item *item; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; nghttp2_session_server_new(&session, &callbacks, NULL); - open_recv_stream(session, 1); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, NULL); /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */ nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3, @@ -5852,7 +4459,7 @@ CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == nghttp2_session_on_request_headers_received(session, &frame)); - item = nghttp2_outbound_queue_top(&session->ob_reg); + item = nghttp2_session_get_ob_pq_top(session); CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code); @@ -5865,14 +4472,46 @@ CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == nghttp2_session_on_request_headers_received(session, &frame)); - item = nghttp2_outbound_queue_top(&session->ob_reg); + item = nghttp2_session_get_ob_pq_top(session); CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type); - CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code); + CU_ASSERT(NGHTTP2_ENHANCE_YOUR_CALM == item->frame.goaway.error_code); - nghttp2_frame_headers_free(&frame.headers, mem); + nghttp2_frame_headers_free(&frame.headers); nghttp2_session_del(session); } +/* + * Check that on_stream_close_callback is called when server pushed + * HEADERS have NGHTTP2_FLAG_END_STREAM. + */ +void test_nghttp2_session_stream_close_on_headers_push(void) { + /* nghttp2_session *session; */ + /* nghttp2_session_callbacks callbacks; */ + /* const char *nv[] = { NULL }; */ + /* my_user_data ud; */ + /* nghttp2_frame frame; */ + + /* memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); */ + /* callbacks.on_stream_close_callback = */ + /* no_stream_user_data_stream_close_callback; */ + /* ud.stream_close_cb_called = 0; */ + + /* nghttp2_session_client_new(&session, NGHTTP2_PROTO_SPDY2, &callbacks, &ud); + */ + /* nghttp2_session_open_stream(session, 1, NGHTTP2_CTRL_FLAG_NONE, 3, */ + /* NGHTTP2_STREAM_OPENING, NULL); */ + /* nghttp2_frame_syn_stream_init(&frame.syn_stream, NGHTTP2_PROTO_SPDY2, */ + /* NGHTTP2_CTRL_FLAG_FIN | */ + /* NGHTTP2_CTRL_FLAG_UNIDIRECTIONAL, */ + /* 2, 1, 3, dup_nv(nv)); */ + + /* CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, + * &frame)); */ + + /* nghttp2_frame_syn_stream_free(&frame.syn_stream); */ + /* nghttp2_session_del(session); */ +} + void test_nghttp2_session_stop_data_with_rst_stream(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; @@ -5889,7 +4528,8 @@ ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4; nghttp2_session_server_new(&session, &callbacks, &ud); - open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); nghttp2_submit_response(session, 1, NULL, 0, &data_prd); ud.block_count = 2; @@ -5922,7 +4562,6 @@ my_user_data ud; nghttp2_data_provider data_prd; nghttp2_outbound_item *item; - nghttp2_stream *stream; memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.on_frame_send_callback = on_frame_send_callback; @@ -5933,11 +4572,8 @@ ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4; nghttp2_session_server_new(&session, &callbacks, &ud); - stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); - - session->remote_window_size = 1 << 20; - stream->remote_window_size = 1 << 20; - + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); nghttp2_submit_response(session, 1, NULL, 0, &data_prd); ud.block_count = 1; @@ -5955,7 +4591,7 @@ /* Resume deferred DATA */ CU_ASSERT(0 == nghttp2_session_resume_data(session, 1)); - item = stream->item; + item = (nghttp2_outbound_item *)nghttp2_pq_top(&session->ob_da_pq); item->aux_data.data.data_prd.read_callback = fixed_length_data_source_read_callback; ud.block_count = 1; @@ -5965,7 +4601,7 @@ /* Deferred again */ item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback; - /* This is needed since 16KiB block is already read and waiting to be + /* This is needed since 4KiB block is already read and waiting to be sent. No read_callback invocation. */ ud.block_count = 1; CU_ASSERT(0 == nghttp2_session_send(session)); @@ -5973,10 +4609,11 @@ /* Resume deferred DATA */ CU_ASSERT(0 == nghttp2_session_resume_data(session, 1)); + item = (nghttp2_outbound_item *)nghttp2_pq_top(&session->ob_da_pq); item->aux_data.data.data_prd.read_callback = fixed_length_data_source_read_callback; ud.block_count = 1; - /* Reads 2 16KiB blocks */ + /* Reads 2 4KiB blocks */ CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(ud.data_source_length == 0); @@ -5993,9 +4630,7 @@ int32_t new_initial_window_size; nghttp2_settings_entry iv[1]; nghttp2_frame settings_frame; - nghttp2_mem *mem; - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = fixed_bytes_send_callback; callbacks.on_frame_send_callback = on_frame_send_callback; @@ -6041,11 +4676,9 @@ negative. */ new_initial_window_size = 16 * 1024; stream->remote_window_size = - new_initial_window_size - - ((int32_t)session->remote_settings.initial_window_size - - stream->remote_window_size); - session->remote_settings.initial_window_size = - (uint32_t)new_initial_window_size; + new_initial_window_size - (session->remote_settings.initial_window_size - + stream->remote_window_size); + session->remote_settings.initial_window_size = new_initial_window_size; CU_ASSERT(-48 * 1024 == stream->remote_window_size); /* Back 48KiB to stream window */ @@ -6078,7 +4711,7 @@ nghttp2_frame_settings_init(&settings_frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 1), 1); nghttp2_session_on_settings_received(session, &settings_frame, 1); - nghttp2_frame_settings_free(&settings_frame.settings, mem); + nghttp2_frame_settings_free(&settings_frame.settings); /* Sends another 8KiB data */ CU_ASSERT(0 == nghttp2_session_send(session)); @@ -6113,7 +4746,11 @@ /* Initial window size to 64KiB - 1*/ nghttp2_session_client_new(&session, &callbacks, NULL); - stream = open_sent_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + NULL); + + session->next_stream_id = 3; nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); @@ -6179,11 +4816,14 @@ nghttp2_option_del(option); - stream = open_sent_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + NULL); /* Create DATA frame */ memset(data, 0, sizeof(data)); - nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, NGHTTP2_FLAG_PADDED, 1); + nghttp2_frame_hd_init(&hd, 357, NGHTTP2_DATA, + NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PADDED, 1); nghttp2_frame_pack_frame_hd(data, &hd); /* Set Pad Length field, which itself is padding */ @@ -6197,58 +4837,6 @@ CU_ASSERT((int32_t)hd.length == stream->recv_window_size); CU_ASSERT(256 == session->consumed_size); CU_ASSERT(256 == stream->consumed_size); - CU_ASSERT(357 == session->recv_window_size); - CU_ASSERT(357 == stream->recv_window_size); - - /* Receive the same DATA frame, but in 2 parts: first 9 + 1 + 102 - bytes which includes 1st padding byte, and remainder */ - CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 103) == - nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 103)); - CU_ASSERT(258 == session->consumed_size); - CU_ASSERT(258 == stream->consumed_size); - CU_ASSERT(460 == session->recv_window_size); - CU_ASSERT(460 == stream->recv_window_size); - - /* 357 - 103 = 254 bytes left */ - CU_ASSERT(254 == nghttp2_session_mem_recv(session, data, 254)); - CU_ASSERT(512 == session->consumed_size); - CU_ASSERT(512 == stream->consumed_size); - CU_ASSERT(714 == session->recv_window_size); - CU_ASSERT(714 == stream->recv_window_size); - - /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 101 - bytes which only includes data without padding, 2nd part is - padding only */ - CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 102) == - nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 102)); - CU_ASSERT(513 == session->consumed_size); - CU_ASSERT(513 == stream->consumed_size); - CU_ASSERT(816 == session->recv_window_size); - CU_ASSERT(816 == stream->recv_window_size); - - /* 357 - 102 = 255 bytes left */ - CU_ASSERT(255 == nghttp2_session_mem_recv(session, data, 255)); - CU_ASSERT(768 == session->consumed_size); - CU_ASSERT(768 == stream->consumed_size); - CU_ASSERT(1071 == session->recv_window_size); - CU_ASSERT(1071 == stream->recv_window_size); - - /* Receive the same DATA frame, but in 2 parts: first 9 = 1 + 50 - bytes which includes byte up to middle of data, 2nd part is the - remainder */ - CU_ASSERT((ssize_t)(NGHTTP2_FRAME_HDLEN + 51) == - nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 51)); - CU_ASSERT(769 == session->consumed_size); - CU_ASSERT(769 == stream->consumed_size); - CU_ASSERT(1122 == session->recv_window_size); - CU_ASSERT(1122 == stream->recv_window_size); - - /* 357 - 51 = 306 bytes left */ - CU_ASSERT(306 == nghttp2_session_mem_recv(session, data, 306)); - CU_ASSERT(1024 == session->consumed_size); - CU_ASSERT(1024 == stream->consumed_size); - CU_ASSERT(1428 == session->recv_window_size); - CU_ASSERT(1428 == stream->recv_window_size); nghttp2_session_del(session); } @@ -6279,9 +4867,10 @@ CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length); stream = nghttp2_session_get_stream(session, 1); - CU_ASSERT(NGHTTP2_DATA == stream->item->frame.hd.type); + CU_ASSERT(nghttp2_stream_check_deferred_by_flow_control(stream)); + CU_ASSERT(NGHTTP2_DATA == stream->data_item->frame.hd.type); - stream->item->aux_data.data.data_prd.read_callback = + stream->data_item->aux_data.data.data_prd.read_callback = temporal_failure_data_source_read_callback; /* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and @@ -6320,9 +4909,9 @@ user_data.stream_close_cb_called = 0; nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = - open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default, - NGHTTP2_STREAM_OPENED, &user_data); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + &user_data); CU_ASSERT(stream != NULL); CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0); CU_ASSERT(user_data.stream_close_cb_called == 1); @@ -6343,9 +4932,9 @@ user_data.not_sent_error = 0; nghttp2_session_server_new(&session, &callbacks, &user_data); - stream = - open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default, - NGHTTP2_STREAM_OPENING, &user_data); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, + NGHTTP2_STREAM_OPENING, &user_data); /* Check response HEADERS */ /* Send bogus stream ID */ @@ -6390,8 +4979,10 @@ NULL, 0, NULL)); user_data.frame_not_send_cb_called = 0; - /* GOAWAY received */ - session->goaway_flags |= NGHTTP2_GOAWAY_RECV; + /* Terminating session */ + CU_ASSERT(0 == nghttp2_session_add_goaway(session, 0, NGHTTP2_NO_ERROR, NULL, + 0, 1)); + session->next_stream_id = 9; CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, @@ -6430,7 +5021,9 @@ memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL)); - stream = open_sent_stream(session, 1); + stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENED, + NULL); CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE == nghttp2_session_get_effective_local_window_size(session)); @@ -6512,22 +5105,6 @@ CU_ASSERT(100 == session->remote_settings.max_concurrent_streams); nghttp2_session_del(session); - nghttp2_option_set_max_reserved_remote_streams(option, 99); - - nghttp2_session_client_new2(&session, &callbacks, NULL, option); - - CU_ASSERT(99 == session->max_incoming_reserved_streams); - nghttp2_session_del(session); - - /* Test for nghttp2_option_set_no_auto_ping_ack */ - nghttp2_option_set_no_auto_ping_ack(option, 1); - - nghttp2_session_client_new2(&session, &callbacks, NULL, option); - - CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK); - - nghttp2_session_del(session); - nghttp2_option_del(option); } @@ -6549,15 +5126,9 @@ nghttp2_session_client_new(&session, &callbacks, &ud); nghttp2_submit_request(session, NULL, NULL, 0, &data_prd, NULL); - session->remote_window_size = 1 << 20; - ud.block_count = 2; /* Sends request HEADERS + DATA[0] */ CU_ASSERT(0 == nghttp2_session_send(session)); - - stream = nghttp2_session_get_stream(session, 1); - stream->remote_window_size = 1 << 20; - CU_ASSERT(NGHTTP2_DATA == ud.sent_frame_type); /* data for DATA[1] is read from data_prd but it is not sent */ CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2); @@ -6574,14 +5145,14 @@ /* Sends DATA[2..3] */ CU_ASSERT(0 == nghttp2_session_send(session)); + stream = nghttp2_session_get_stream(session, 1); CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_WR); nghttp2_session_del(session); } static void check_session_recv_data_with_padding(nghttp2_bufs *bufs, - size_t datalen, - nghttp2_mem *mem) { + size_t datalen) { nghttp2_session *session; my_user_data ud; nghttp2_session_callbacks callbacks; @@ -6593,9 +5164,10 @@ callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; nghttp2_session_server_new(&session, &callbacks, &ud); - open_recv_stream(session, 1); + nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, + &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); - inlen = (size_t)nghttp2_bufs_remove(bufs, &in); + inlen = nghttp2_bufs_remove(bufs, &in); ud.frame_recv_cb_called = 0; ud.data_chunk_len = 0; @@ -6605,7 +5177,7 @@ CU_ASSERT(1 == ud.frame_recv_cb_called); CU_ASSERT(datalen == ud.data_chunk_len); - mem->free(in, NULL); + free(in); nghttp2_session_del(session); } @@ -6616,9 +5188,6 @@ nghttp2_data_provider data_prd; nghttp2_frame *frame; size_t datalen = 55; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(callbacks)); callbacks.send_callback = block_count_send_callback; @@ -6644,7 +5213,7 @@ CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED); /* Check reception of this DATA frame */ - check_session_recv_data_with_padding(&session->aob.framebufs, datalen, mem); + check_session_recv_data_with_padding(&session->aob.framebufs, datalen); nghttp2_session_del(session); } @@ -6654,6 +5223,7 @@ accumulator acc; my_user_data ud; nghttp2_session_callbacks callbacks; + nghttp2_nv nv = MAKE_NV(":path", "/"); memset(&callbacks, 0, sizeof(callbacks)); callbacks.send_callback = accumulator_send_callback; @@ -6669,8 +5239,7 @@ ud.padlen = 163; - CU_ASSERT(1 == nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), - NULL, NULL)); + CU_ASSERT(1 == nghttp2_submit_request(session, NULL, &nv, 1, NULL, NULL)); CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN); @@ -6690,9 +5259,6 @@ ssize_t len; nghttp2_settings_entry *resiv; size_t resniv; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE; iv[0].value = 1023; @@ -6701,15 +5267,15 @@ len = nghttp2_pack_settings_payload(buf, sizeof(buf), iv, 2); CU_ASSERT(2 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == len); - CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf, - (size_t)len, mem)); + CU_ASSERT(0 == + nghttp2_frame_unpack_settings_payload2(&resiv, &resniv, buf, len)); CU_ASSERT(2 == resniv); CU_ASSERT(NGHTTP2_SETTINGS_HEADER_TABLE_SIZE == resiv[0].settings_id); CU_ASSERT(1023 == resiv[0].value); CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[1].settings_id); CU_ASSERT(4095 == resiv[1].value); - mem->free(resiv, NULL); + free(resiv); len = nghttp2_pack_settings_payload(buf, 9 /* too small */, iv, 2); CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == len); @@ -6729,14 +5295,12 @@ void test_nghttp2_session_stream_dep_add(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - nghttp2_stream *a, *b, *c, *d, *e, *root; + nghttp2_stream *a, *b, *c, *d, *e; memset(&callbacks, 0, sizeof(callbacks)); nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); c = open_stream_with_dep(session, 5, a); @@ -6750,17 +5314,24 @@ * d */ + CU_ASSERT(4 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(2 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); CU_ASSERT(0 == d->sum_dep_weight); - check_stream_dep_sib(a, root, b, NULL, NULL); + check_stream_dep_sib(a, NULL, b, NULL, NULL); check_stream_dep_sib(b, a, NULL, NULL, c); - check_stream_dep_sib(c, a, d, b, NULL); + check_stream_dep_sib(c, NULL, d, b, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); - CU_ASSERT(a == session->root.dep_next); + CU_ASSERT(4 == session->roots.num_streams); + CU_ASSERT(a == session->roots.head); + CU_ASSERT(NULL == a->root_next); e = open_stream_with_dep_excl(session, 9, a); @@ -6773,19 +5344,27 @@ * d */ + CU_ASSERT(5 == a->num_substreams); + CU_ASSERT(4 == e->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(2 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == e->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); CU_ASSERT(0 == d->sum_dep_weight); - check_stream_dep_sib(a, root, e, NULL, NULL); + check_stream_dep_sib(a, NULL, e, NULL, NULL); check_stream_dep_sib(e, a, b, NULL, NULL); check_stream_dep_sib(b, e, NULL, NULL, c); - check_stream_dep_sib(c, e, d, b, NULL); + check_stream_dep_sib(c, NULL, d, b, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); - CU_ASSERT(a == session->root.dep_next); + CU_ASSERT(5 == session->roots.num_streams); + CU_ASSERT(a == session->roots.head); + CU_ASSERT(NULL == a->root_next); nghttp2_session_del(session); } @@ -6793,15 +5372,13 @@ void test_nghttp2_session_stream_dep_remove(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - nghttp2_stream *a, *b, *c, *d, *e, *f, *root; + nghttp2_stream *a, *b, *c, *d, *e, *f; memset(&callbacks, 0, sizeof(callbacks)); /* Remove root */ nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); c = open_stream_with_dep(session, 5, a); @@ -6817,30 +5394,36 @@ nghttp2_stream_dep_remove(a); /* becomes: - * c b - * | - * d + * b c + * | + * d */ + CU_ASSERT(1 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(2 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(0 == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); CU_ASSERT(0 == d->sum_dep_weight); check_stream_dep_sib(a, NULL, NULL, NULL, NULL); - check_stream_dep_sib(b, root, NULL, c, NULL); - check_stream_dep_sib(c, root, d, NULL, b); + check_stream_dep_sib(b, NULL, NULL, NULL, NULL); + check_stream_dep_sib(c, NULL, d, NULL, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); - CU_ASSERT(c == session->root.dep_next); + CU_ASSERT(3 == session->roots.num_streams); + CU_ASSERT(b == session->roots.head); + CU_ASSERT(c == b->root_next); + CU_ASSERT(NULL == c->root_next); nghttp2_session_del(session); - /* Remove right most stream */ + /* Remove left most stream */ nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); c = open_stream_with_dep(session, 5, a); @@ -6863,36 +5446,40 @@ * d */ + CU_ASSERT(3 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(2 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); CU_ASSERT(0 == d->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); - check_stream_dep_sib(a, root, c, NULL, NULL); + check_stream_dep_sib(a, NULL, c, NULL, NULL); check_stream_dep_sib(b, NULL, NULL, NULL, NULL); check_stream_dep_sib(c, a, d, NULL, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); - CU_ASSERT(a == session->root.dep_next); + CU_ASSERT(3 == session->roots.num_streams); + CU_ASSERT(a == session->roots.head); + CU_ASSERT(NULL == a->root_next); nghttp2_session_del(session); - /* Remove left most stream */ + /* Remove right most stream */ nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); c = open_stream_with_dep(session, 5, a); d = open_stream_with_dep(session, 7, c); - e = open_stream_with_dep(session, 9, c); /* a * | * c--b * | - * e--d + * d */ nghttp2_stream_dep_remove(c); @@ -6900,28 +5487,29 @@ /* becomes: * a * | - * e--d--b + * d--b */ + CU_ASSERT(3 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(1 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(0 == d->sum_dep_weight); CU_ASSERT(0 == c->sum_dep_weight); - CU_ASSERT(0 == e->sum_dep_weight); - check_stream_dep_sib(a, root, e, NULL, NULL); - check_stream_dep_sib(b, a, NULL, d, NULL); + check_stream_dep_sib(a, NULL, d, NULL, NULL); + check_stream_dep_sib(b, NULL, NULL, d, NULL); check_stream_dep_sib(c, NULL, NULL, NULL, NULL); - check_stream_dep_sib(d, a, NULL, e, b); - check_stream_dep_sib(e, a, NULL, NULL, d); + check_stream_dep_sib(d, a, NULL, NULL, b); nghttp2_session_del(session); /* Remove middle stream */ nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); c = open_stream_with_dep(session, 5, a); @@ -6936,6 +5524,13 @@ * f--e */ + CU_ASSERT(6 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(3 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(1 == e->num_substreams); + CU_ASSERT(1 == f->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight); @@ -6951,6 +5546,13 @@ * d--f--e--b */ + CU_ASSERT(5 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(1 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(1 == e->num_substreams); + CU_ASSERT(1 == f->num_substreams); + /* c's weight 16 is distributed evenly to e and f. Each weight of e and f becomes 8. */ CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 + 8 * 2 == a->sum_dep_weight); @@ -6960,11 +5562,11 @@ CU_ASSERT(0 == e->sum_dep_weight); CU_ASSERT(0 == f->sum_dep_weight); - check_stream_dep_sib(a, root, d, NULL, NULL); - check_stream_dep_sib(b, a, NULL, e, NULL); + check_stream_dep_sib(a, NULL, d, NULL, NULL); + check_stream_dep_sib(b, NULL, NULL, e, NULL); check_stream_dep_sib(c, NULL, NULL, NULL, NULL); - check_stream_dep_sib(e, a, NULL, f, b); - check_stream_dep_sib(f, a, NULL, d, e); + check_stream_dep_sib(e, NULL, NULL, f, b); + check_stream_dep_sib(f, NULL, NULL, d, e); check_stream_dep_sib(d, a, NULL, NULL, f); nghttp2_session_del(session); @@ -6973,15 +5575,13 @@ void test_nghttp2_session_stream_dep_add_subtree(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - nghttp2_stream *a, *b, *c, *d, *e, *f, *root; + nghttp2_stream *a, *b, *c, *d, *e, *f; memset(&callbacks, 0, sizeof(callbacks)); /* dep_stream has dep_next */ nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); c = open_stream_with_dep(session, 5, a); @@ -6997,8 +5597,7 @@ * d */ - nghttp2_stream_dep_remove_subtree(e); - nghttp2_stream_dep_add_subtree(a, e); + nghttp2_stream_dep_add_subtree(a, e, session); /* becomes * a @@ -7008,6 +5607,13 @@ * f d */ + CU_ASSERT(6 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(2 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(2 == e->num_substreams); + CU_ASSERT(1 == f->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); @@ -7015,9 +5621,9 @@ CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == e->sum_dep_weight); CU_ASSERT(0 == f->sum_dep_weight); - check_stream_dep_sib(a, root, e, NULL, NULL); - check_stream_dep_sib(b, a, NULL, c, NULL); - check_stream_dep_sib(c, a, d, e, b); + check_stream_dep_sib(a, NULL, e, NULL, NULL); + check_stream_dep_sib(b, NULL, NULL, c, NULL); + check_stream_dep_sib(c, NULL, d, e, b); check_stream_dep_sib(d, c, NULL, NULL, NULL); check_stream_dep_sib(e, a, f, NULL, c); check_stream_dep_sib(f, e, NULL, NULL, NULL); @@ -7027,8 +5633,6 @@ /* dep_stream has dep_next and now we insert subtree */ nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); c = open_stream_with_dep(session, 5, a); @@ -7044,8 +5648,7 @@ * d */ - nghttp2_stream_dep_remove_subtree(e); - nghttp2_stream_dep_insert_subtree(a, e); + nghttp2_stream_dep_insert_subtree(a, e, session); /* becomes * a @@ -7057,6 +5660,13 @@ * d */ + CU_ASSERT(6 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(2 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(5 == e->num_substreams); + CU_ASSERT(1 == f->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); @@ -7064,11 +5674,11 @@ CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 3 == e->sum_dep_weight); CU_ASSERT(0 == f->sum_dep_weight); - check_stream_dep_sib(a, root, e, NULL, NULL); + check_stream_dep_sib(a, NULL, e, NULL, NULL); check_stream_dep_sib(e, a, f, NULL, NULL); check_stream_dep_sib(f, e, NULL, NULL, c); - check_stream_dep_sib(b, e, NULL, c, NULL); - check_stream_dep_sib(c, e, d, f, b); + check_stream_dep_sib(b, NULL, NULL, c, NULL); + check_stream_dep_sib(c, NULL, d, f, b); check_stream_dep_sib(d, c, NULL, NULL, NULL); nghttp2_session_del(session); @@ -7077,15 +5687,13 @@ void test_nghttp2_session_stream_dep_remove_subtree(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - nghttp2_stream *a, *b, *c, *d, *e, *root; + nghttp2_stream *a, *b, *c, *d, *e; memset(&callbacks, 0, sizeof(callbacks)); /* Remove left most stream */ nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); c = open_stream_with_dep(session, 5, a); @@ -7106,12 +5714,17 @@ * b d */ + CU_ASSERT(2 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(2 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); CU_ASSERT(0 == d->sum_dep_weight); - check_stream_dep_sib(a, root, b, NULL, NULL); + check_stream_dep_sib(a, NULL, b, NULL, NULL); check_stream_dep_sib(b, a, NULL, NULL, NULL); check_stream_dep_sib(c, NULL, d, NULL, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); @@ -7121,8 +5734,6 @@ /* Remove right most stream */ nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); c = open_stream_with_dep(session, 5, a); @@ -7145,12 +5756,17 @@ * d */ + CU_ASSERT(3 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(2 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); CU_ASSERT(0 == d->sum_dep_weight); - check_stream_dep_sib(a, root, c, NULL, NULL); + check_stream_dep_sib(a, NULL, c, NULL, NULL); check_stream_dep_sib(c, a, d, NULL, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); check_stream_dep_sib(b, NULL, NULL, NULL, NULL); @@ -7160,8 +5776,6 @@ /* Remove middle stream */ nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); e = open_stream_with_dep(session, 9, a); c = open_stream_with_dep(session, 5, a); @@ -7183,15 +5797,21 @@ * b--e d */ + CU_ASSERT(3 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(1 == e->num_substreams); + CU_ASSERT(2 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); CU_ASSERT(0 == d->sum_dep_weight); CU_ASSERT(0 == e->sum_dep_weight); - check_stream_dep_sib(a, root, b, NULL, NULL); + check_stream_dep_sib(a, NULL, b, NULL, NULL); check_stream_dep_sib(b, a, NULL, NULL, e); - check_stream_dep_sib(e, a, NULL, b, NULL); + check_stream_dep_sib(e, NULL, NULL, b, NULL); check_stream_dep_sib(c, NULL, d, NULL, NULL); check_stream_dep_sib(d, c, NULL, NULL, NULL); @@ -7201,18 +5821,12 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - nghttp2_stream *a, *b, *c, *d, *root; - nghttp2_outbound_item *db, *dc; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); + nghttp2_stream *a, *b, *c, *d; memset(&callbacks, 0, sizeof(callbacks)); nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); @@ -7224,7 +5838,8 @@ */ nghttp2_stream_dep_remove_subtree(c); - CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c)); + CU_ASSERT(0 == + nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session)); /* * c @@ -7234,15 +5849,15 @@ * b */ + CU_ASSERT(3 == c->num_substreams); + CU_ASSERT(2 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == c->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); - CU_ASSERT(nghttp2_pq_empty(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(nghttp2_pq_empty(&c->obq)); - - check_stream_dep_sib(c, root, a, NULL, NULL); + check_stream_dep_sib(c, NULL, a, NULL, NULL); check_stream_dep_sib(a, c, b, NULL, NULL); check_stream_dep_sib(b, a, NULL, NULL, NULL); @@ -7250,10 +5865,10 @@ nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); + b = open_stream(session, 3); + c = open_stream(session, 5); /* @@ -7261,7 +5876,8 @@ */ nghttp2_stream_dep_remove_subtree(c); - CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c)); + CU_ASSERT(0 == + nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session)); /* * c @@ -7269,24 +5885,22 @@ * b--a */ + CU_ASSERT(3 == c->num_substreams); + CU_ASSERT(1 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); CU_ASSERT(0 == a->sum_dep_weight); - CU_ASSERT(nghttp2_pq_empty(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(nghttp2_pq_empty(&c->obq)); - - check_stream_dep_sib(c, root, b, NULL, NULL); + check_stream_dep_sib(c, NULL, b, NULL, NULL); check_stream_dep_sib(b, c, NULL, NULL, a); - check_stream_dep_sib(a, c, NULL, b, NULL); + check_stream_dep_sib(a, NULL, NULL, b, NULL); nghttp2_session_del(session); nghttp2_session_server_new(&session, &callbacks, NULL); - root = &session->root; - a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); @@ -7299,347 +5913,155 @@ */ nghttp2_stream_dep_remove_subtree(c); - CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c)); + CU_ASSERT(0 == + nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session)); /* * c * | - * d--a - * | - * b + * a--d + * | + * b */ + CU_ASSERT(4 == c->num_substreams); + CU_ASSERT(1 == d->num_substreams); + CU_ASSERT(2 == a->num_substreams); + CU_ASSERT(1 == b->num_substreams); + CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == c->sum_dep_weight); CU_ASSERT(0 == d->sum_dep_weight); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight); CU_ASSERT(0 == b->sum_dep_weight); - CU_ASSERT(nghttp2_pq_empty(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(nghttp2_pq_empty(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - - check_stream_dep_sib(c, root, d, NULL, NULL); - check_stream_dep_sib(d, c, NULL, NULL, a); - check_stream_dep_sib(a, c, b, d, NULL); + check_stream_dep_sib(c, NULL, a, NULL, NULL); + check_stream_dep_sib(d, NULL, NULL, a, NULL); + check_stream_dep_sib(a, c, b, NULL, d); check_stream_dep_sib(b, a, NULL, NULL, NULL); nghttp2_session_del(session); +} - nghttp2_session_server_new(&session, &callbacks, NULL); +void test_nghttp2_session_stream_attach_data(void) { + nghttp2_session *session; + nghttp2_session_callbacks callbacks; + nghttp2_stream *a, *b, *c, *d; + nghttp2_outbound_item *da, *db, *dc, *dd; + + memset(&callbacks, 0, sizeof(callbacks)); - root = &session->root; + nghttp2_session_server_new(&session, &callbacks, NULL); a = open_stream(session, 1); b = open_stream_with_dep(session, 3, a); - - c = open_stream(session, 5); + c = open_stream_with_dep(session, 5, a); d = open_stream_with_dep(session, 7, c); - /* a c - * | | - * b d + /* a + * | + * c--b + * | + * d */ - db = create_data_ob_item(mem); + db = create_data_ob_item(); - nghttp2_stream_attach_item(b, db); + nghttp2_stream_attach_data(b, db, session); - nghttp2_stream_dep_remove_subtree(c); - CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c)); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri); - /* - * c - * | - * d--a - * | - * b - */ + CU_ASSERT(16 == b->effective_weight); - CU_ASSERT(c->queued); - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(!d->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - - check_stream_dep_sib(c, root, d, NULL, NULL); - check_stream_dep_sib(d, c, NULL, NULL, a); - check_stream_dep_sib(a, c, b, d, NULL); - check_stream_dep_sib(b, a, NULL, NULL, NULL); + CU_ASSERT(16 == a->sum_norest_weight); - nghttp2_session_del(session); + CU_ASSERT(1 == db->queued); - nghttp2_session_server_new(&session, &callbacks, NULL); + dc = create_data_ob_item(); - root = &session->root; + nghttp2_stream_attach_data(c, dc, session); - a = open_stream(session, 1); - b = open_stream_with_dep(session, 3, a); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri); - c = open_stream(session, 5); - d = open_stream_with_dep(session, 7, c); + CU_ASSERT(16 * 16 / 32 == b->effective_weight); + CU_ASSERT(16 * 16 / 32 == c->effective_weight); - /* a c - * | | - * b d - */ + CU_ASSERT(32 == a->sum_norest_weight); - db = create_data_ob_item(mem); - dc = create_data_ob_item(mem); + CU_ASSERT(1 == dc->queued); - nghttp2_stream_attach_item(b, db); - nghttp2_stream_attach_item(c, dc); + da = create_data_ob_item(); - nghttp2_stream_dep_remove_subtree(c); - CU_ASSERT(0 == nghttp2_stream_dep_insert_subtree(&session->root, c)); + nghttp2_stream_attach_data(a, da, session); - /* - * c - * | - * d--a - * | - * b - */ + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri); - CU_ASSERT(c->queued); - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(!d->queued); - - check_stream_dep_sib(c, root, d, NULL, NULL); - check_stream_dep_sib(d, c, NULL, NULL, a); - check_stream_dep_sib(a, c, b, d, NULL); - check_stream_dep_sib(b, a, NULL, NULL, NULL); + CU_ASSERT(16 == a->effective_weight); - nghttp2_session_del(session); -} + CU_ASSERT(1 == da->queued); -void test_nghttp2_session_stream_attach_item(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_stream *a, *b, *c, *d, *e; - nghttp2_outbound_item *da, *db, *dc, *dd; - nghttp2_mem *mem; + nghttp2_stream_detach_data(a, session); - mem = nghttp2_mem_default(); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri); - memset(&callbacks, 0, sizeof(callbacks)); + CU_ASSERT(16 * 16 / 32 == b->effective_weight); + CU_ASSERT(16 * 16 / 32 == c->effective_weight); - nghttp2_session_server_new(&session, &callbacks, NULL); + dd = create_data_ob_item(); - a = open_stream(session, 1); - b = open_stream_with_dep(session, 3, a); - c = open_stream_with_dep(session, 5, a); - d = open_stream_with_dep(session, 7, c); + nghttp2_stream_attach_data(d, dd, session); - /* a - * | - * c--b - * | - * d - */ - - db = create_data_ob_item(mem); - - nghttp2_stream_attach_item(b, db); - - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(!c->queued); - CU_ASSERT(!d->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - - /* Attach item to c */ - dc = create_data_ob_item(mem); - - nghttp2_stream_attach_item(c, dc); - - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(!d->queued); - - CU_ASSERT(2 == nghttp2_pq_size(&a->obq)); - - /* Attach item to a */ - da = create_data_ob_item(mem); - - nghttp2_stream_attach_item(a, da); - - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(!d->queued); - - CU_ASSERT(2 == nghttp2_pq_size(&a->obq)); - - /* Detach item from a */ - nghttp2_stream_detach_item(a); - - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(!d->queued); - - CU_ASSERT(2 == nghttp2_pq_size(&a->obq)); - - /* Attach item to d */ - dd = create_data_ob_item(mem); - - nghttp2_stream_attach_item(d, dd); - - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - - CU_ASSERT(2 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - - /* Detach item from c */ - nghttp2_stream_detach_item(c); - - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - - CU_ASSERT(2 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - - /* Detach item from b */ - nghttp2_stream_detach_item(b); - - CU_ASSERT(a->queued); - CU_ASSERT(!b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - - /* exercises insertion */ - e = open_stream_with_dep_excl(session, 9, a); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri); - /* a - * | - * e - * | - * c--b - * | - * d - */ - - CU_ASSERT(a->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - - /* exercises deletion */ - nghttp2_stream_dep_remove(e); - - /* a - * | - * c--b - * | - * d - */ - - CU_ASSERT(a->queued); - CU_ASSERT(!b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - - /* e's weight 16 is distributed equally among c and b, both now have - weight 8 each. */ - CU_ASSERT(8 == b->weight); - CU_ASSERT(8 == c->weight); - - /* da, db, dc have been detached */ - nghttp2_outbound_item_free(da, mem); - nghttp2_outbound_item_free(db, mem); - nghttp2_outbound_item_free(dc, mem); - free(da); - free(db); - free(dc); - - nghttp2_session_del(session); - - nghttp2_session_server_new(&session, &callbacks, NULL); - - a = open_stream(session, 1); - b = open_stream_with_dep(session, 3, a); - c = open_stream_with_dep(session, 5, a); - d = open_stream_with_dep(session, 7, c); + CU_ASSERT(16 * 16 / 32 == b->effective_weight); + CU_ASSERT(16 * 16 / 32 == c->effective_weight); - /* a - * | - * c--b - * | - * d - */ + CU_ASSERT(0 == dd->queued); - da = create_data_ob_item(mem); - db = create_data_ob_item(mem); - dc = create_data_ob_item(mem); + nghttp2_stream_detach_data(c, session); - nghttp2_stream_attach_item(a, da); - nghttp2_stream_attach_item(b, db); - nghttp2_stream_attach_item(c, dc); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri); - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(!d->queued); + CU_ASSERT(16 * 16 / 16 == b->effective_weight); - CU_ASSERT(2 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(nghttp2_pq_empty(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); + CU_ASSERT(0 == dd->queued); - /* Detach item from a */ - nghttp2_stream_detach_item(a); + nghttp2_stream_detach_data(b, session); - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(!d->queued); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri); - CU_ASSERT(2 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(nghttp2_pq_empty(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); + CU_ASSERT(16 * 16 / 16 == d->effective_weight); - /* da has been detached */ - nghttp2_outbound_item_free(da, mem); - free(da); + CU_ASSERT(1 == dd->queued); nghttp2_session_del(session); } -void test_nghttp2_session_stream_attach_item_subtree(void) { +void test_nghttp2_session_stream_attach_data_subtree(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; nghttp2_stream *a, *b, *c, *d, *e, *f; - nghttp2_outbound_item *da, *db, *dd, *de; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); + nghttp2_outbound_item *db, *dd, *de; memset(&callbacks, 0, sizeof(callbacks)); @@ -7650,9 +6072,8 @@ c = open_stream_with_dep(session, 5, a); d = open_stream_with_dep(session, 7, c); - e = open_stream_with_dep_weight(session, 9, 32, &session->root); + e = open_stream(session, 9); f = open_stream_with_dep(session, 11, e); - /* * a e * | | @@ -7661,32 +6082,28 @@ * d */ - de = create_data_ob_item(mem); + de = create_data_ob_item(); - nghttp2_stream_attach_item(e, de); + nghttp2_stream_attach_data(e, de, session); - db = create_data_ob_item(mem); + db = create_data_ob_item(); - nghttp2_stream_attach_item(b, db); + nghttp2_stream_attach_data(b, db, session); - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(!c->queued); - CU_ASSERT(!d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!f->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(nghttp2_pq_empty(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(nghttp2_pq_empty(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&f->obq)); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri); + + CU_ASSERT(16 == b->effective_weight); + CU_ASSERT(16 == e->effective_weight); /* Insert subtree e under a */ nghttp2_stream_dep_remove_subtree(e); - nghttp2_stream_dep_insert_subtree(a, e); + nghttp2_stream_dep_insert_subtree(a, e, session); /* * a @@ -7698,25 +6115,20 @@ * d */ - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(!c->queued); - CU_ASSERT(!d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!f->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(nghttp2_pq_empty(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&f->obq)); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri); + + CU_ASSERT(16 == e->effective_weight); /* Remove subtree b */ nghttp2_stream_dep_remove_subtree(b); - CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b)); + nghttp2_stream_dep_make_root(b, session); /* * a b @@ -7728,45 +6140,34 @@ * d */ - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(!c->queued); - CU_ASSERT(!d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!f->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(nghttp2_pq_empty(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(nghttp2_pq_empty(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&f->obq)); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri); - /* Remove subtree a, and add it to root again */ + CU_ASSERT(16 == b->effective_weight); + CU_ASSERT(16 == e->effective_weight); + + /* Remove subtree a */ nghttp2_stream_dep_remove_subtree(a); - CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, a)); + nghttp2_stream_dep_make_root(a, session); - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(!c->queued); - CU_ASSERT(!d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!f->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(nghttp2_pq_empty(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(nghttp2_pq_empty(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&f->obq)); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri); /* Remove subtree c */ nghttp2_stream_dep_remove_subtree(c); - CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, c)); + nghttp2_stream_dep_make_root(c, session); /* * a b c @@ -7776,28 +6177,21 @@ * f */ - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(!c->queued); - CU_ASSERT(!d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!f->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(nghttp2_pq_empty(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(nghttp2_pq_empty(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&f->obq)); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == d->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri); - dd = create_data_ob_item(mem); + dd = create_data_ob_item(); - nghttp2_stream_attach_item(d, dd); + nghttp2_stream_attach_data(d, dd, session); /* Add subtree c to a */ nghttp2_stream_dep_remove_subtree(c); - nghttp2_stream_dep_add_subtree(a, c); + nghttp2_stream_dep_add_subtree(a, c, session); /* * a b @@ -7807,53 +6201,50 @@ * d f */ - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!f->queued); - - CU_ASSERT(2 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(nghttp2_pq_empty(&b->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(nghttp2_pq_empty(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&f->obq)); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri); + + CU_ASSERT(16 == b->effective_weight); + CU_ASSERT(16 * 16 / 16 == e->effective_weight); + + CU_ASSERT(32 == a->sum_norest_weight); + CU_ASSERT(16 == c->sum_norest_weight); /* Insert b under a */ nghttp2_stream_dep_remove_subtree(b); - nghttp2_stream_dep_insert_subtree(a, b); + nghttp2_stream_dep_insert_subtree(a, b, session); /* * a * | * b * | - * c--e + * e--c * | | - * d f + * f d */ - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!f->queued); - - CU_ASSERT(1 == nghttp2_pq_size(&a->obq)); - CU_ASSERT(2 == nghttp2_pq_size(&b->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(nghttp2_pq_empty(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&f->obq)); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == e->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri); + + CU_ASSERT(16 == b->effective_weight); + + CU_ASSERT(16 == a->sum_norest_weight); + CU_ASSERT(0 == b->sum_norest_weight); /* Remove subtree b */ nghttp2_stream_dep_remove_subtree(b); - CU_ASSERT(0 == nghttp2_stream_dep_add_subtree(&session->root, b)); + nghttp2_stream_dep_make_root(b, session); /* * b a @@ -7863,2785 +6254,426 @@ * f d */ - CU_ASSERT(!a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!f->queued); - - CU_ASSERT(nghttp2_pq_empty(&a->obq)); - CU_ASSERT(2 == nghttp2_pq_size(&b->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(nghttp2_pq_empty(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&f->obq)); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == a->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == c->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == e->dpri); + CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_DATA == f->dpri); - /* Remove subtree c, and detach item from b, and then re-add - subtree c under b */ + CU_ASSERT(0 == a->sum_norest_weight); + CU_ASSERT(0 == b->sum_norest_weight); - nghttp2_stream_dep_remove_subtree(c); - nghttp2_stream_detach_item(b); - nghttp2_stream_dep_add_subtree(b, c); + nghttp2_session_del(session); +} - /* - * b a - * | - * e--c - * | | - * f d - */ +void test_nghttp2_session_keep_closed_stream(void) { + nghttp2_session *session; + nghttp2_session_callbacks callbacks; + const size_t max_concurrent_streams = 5; + nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, + max_concurrent_streams}; + size_t i; + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.send_callback = null_send_callback; - CU_ASSERT(!a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!f->queued); - - CU_ASSERT(nghttp2_pq_empty(&a->obq)); - CU_ASSERT(2 == nghttp2_pq_size(&b->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(nghttp2_pq_empty(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&f->obq)); + nghttp2_session_server_new(&session, &callbacks, NULL); - /* Attach data to a, and add subtree a under b */ + nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1); - da = create_data_ob_item(mem); - nghttp2_stream_attach_item(a, da); - nghttp2_stream_dep_remove_subtree(a); - nghttp2_stream_dep_add_subtree(b, a); + for (i = 0; i < max_concurrent_streams; ++i) { + open_stream(session, (int)i * 2 + 1); + } - /* - * b - * | - * a--e--c - * | | - * f d - */ + CU_ASSERT(0 == session->num_closed_streams); - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(!f->queued); - - CU_ASSERT(nghttp2_pq_empty(&a->obq)); - CU_ASSERT(3 == nghttp2_pq_size(&b->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(nghttp2_pq_empty(&e->obq)); - CU_ASSERT(nghttp2_pq_empty(&f->obq)); + nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR); - /* Remove subtree c, and add under f */ - nghttp2_stream_dep_remove_subtree(c); - nghttp2_stream_dep_insert_subtree(f, c); + CU_ASSERT(1 == session->num_closed_streams); + CU_ASSERT(1 == session->closed_stream_tail->stream_id); + CU_ASSERT(session->closed_stream_tail == session->closed_stream_head); - /* - * b - * | - * a--e - * | - * f - * | - * c - * | - * d - */ + nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR); + + CU_ASSERT(2 == session->num_closed_streams); + CU_ASSERT(5 == session->closed_stream_tail->stream_id); + CU_ASSERT(1 == session->closed_stream_head->stream_id); + CU_ASSERT(session->closed_stream_head == + session->closed_stream_tail->closed_prev); + CU_ASSERT(NULL == session->closed_stream_tail->closed_next); + CU_ASSERT(session->closed_stream_tail == + session->closed_stream_head->closed_next); + CU_ASSERT(NULL == session->closed_stream_head->closed_prev); - CU_ASSERT(a->queued); - CU_ASSERT(b->queued); - CU_ASSERT(c->queued); - CU_ASSERT(d->queued); - CU_ASSERT(e->queued); - CU_ASSERT(f->queued); + open_stream(session, 11); + + CU_ASSERT(1 == session->num_closed_streams); + CU_ASSERT(5 == session->closed_stream_tail->stream_id); + CU_ASSERT(session->closed_stream_tail == session->closed_stream_head); + CU_ASSERT(NULL == session->closed_stream_head->closed_prev); + CU_ASSERT(NULL == session->closed_stream_head->closed_next); - CU_ASSERT(nghttp2_pq_empty(&a->obq)); - CU_ASSERT(2 == nghttp2_pq_size(&b->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&c->obq)); - CU_ASSERT(nghttp2_pq_empty(&d->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&e->obq)); - CU_ASSERT(1 == nghttp2_pq_size(&f->obq)); + open_stream(session, 13); - /* db has been detached */ - nghttp2_outbound_item_free(db, mem); - free(db); + CU_ASSERT(0 == session->num_closed_streams); + CU_ASSERT(NULL == session->closed_stream_tail); + CU_ASSERT(NULL == session->closed_stream_head); nghttp2_session_del(session); } -void test_nghttp2_session_stream_get_state(void) { +void test_nghttp2_session_detach_closed_stream(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - nghttp2_mem *mem; - nghttp2_hd_deflater deflater; - nghttp2_bufs bufs; - nghttp2_buf *buf; + int i; nghttp2_stream *stream; - ssize_t rv; - nghttp2_data_provider data_prd; - nghttp2_frame frame; - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - memset(&data_prd, 0, sizeof(data_prd)); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); + memset(&callbacks, 0, sizeof(callbacks)); callbacks.send_callback = null_send_callback; nghttp2_session_server_new(&session, &callbacks, NULL); - nghttp2_hd_deflate_init(&deflater, mem); - CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE == - nghttp2_stream_get_state(nghttp2_session_get_root_stream(session))); - - /* stream 1 HEADERS; without END_STREAM flag set */ - pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv, - ARRLEN(reqnv), mem); + for (i = 0; i < 3; ++i) { + open_stream(session, i); + nghttp2_session_close_stream(session, i, NGHTTP2_NO_ERROR); + } - buf = &bufs.head->buf; - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); + CU_ASSERT(3 == session->num_closed_streams); - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + stream = nghttp2_session_get_stream_raw(session, 1); - stream = nghttp2_session_find_stream(session, 1); + CU_ASSERT(session->closed_stream_head == stream->closed_prev); + CU_ASSERT(session->closed_stream_tail == stream->closed_next); + CU_ASSERT(stream == session->closed_stream_head->closed_next); + CU_ASSERT(stream == session->closed_stream_tail->closed_prev); - CU_ASSERT(NULL != stream); - CU_ASSERT(1 == stream->stream_id); - CU_ASSERT(NGHTTP2_STREAM_STATE_OPEN == nghttp2_stream_get_state(stream)); + nghttp2_session_detach_closed_stream(session, stream); - nghttp2_bufs_reset(&bufs); + CU_ASSERT(2 == session->num_closed_streams); - /* stream 3 HEADERS; with END_STREAM flag set */ - pack_headers(&bufs, &deflater, 3, - NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv, - ARRLEN(reqnv), mem); + CU_ASSERT(NULL == stream->closed_prev); + CU_ASSERT(NULL == stream->closed_next); - buf = &bufs.head->buf; - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); + CU_ASSERT(session->closed_stream_head == + session->closed_stream_tail->closed_prev); + CU_ASSERT(session->closed_stream_tail == + session->closed_stream_head->closed_next); - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + /* Close head stream */ + stream = session->closed_stream_head; - stream = nghttp2_session_find_stream(session, 3); + nghttp2_session_detach_closed_stream(session, stream); - CU_ASSERT(NULL != stream); - CU_ASSERT(3 == stream->stream_id); - CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE == - nghttp2_stream_get_state(stream)); + CU_ASSERT(1 == session->num_closed_streams); - nghttp2_bufs_reset(&bufs); + CU_ASSERT(session->closed_stream_head == session->closed_stream_tail); + CU_ASSERT(NULL == session->closed_stream_head->closed_prev); + CU_ASSERT(NULL == session->closed_stream_head->closed_next); - /* Respond to stream 1 */ - nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL); + /* Close last stream */ - rv = nghttp2_session_send(session); + stream = session->closed_stream_head; - CU_ASSERT(0 == rv); + nghttp2_session_detach_closed_stream(session, stream); - stream = nghttp2_session_find_stream(session, 1); + CU_ASSERT(0 == session->num_closed_streams); - CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL == - nghttp2_stream_get_state(stream)); + CU_ASSERT(NULL == session->closed_stream_head); + CU_ASSERT(NULL == session->closed_stream_tail); - /* Respond to stream 3 */ - nghttp2_submit_response(session, 3, resnv, ARRLEN(resnv), NULL); + for (i = 3; i < 5; ++i) { + open_stream(session, i); + nghttp2_session_close_stream(session, i, NGHTTP2_NO_ERROR); + } - rv = nghttp2_session_send(session); + CU_ASSERT(2 == session->num_closed_streams); - CU_ASSERT(0 == rv); + /* Close tail stream */ - stream = nghttp2_session_find_stream(session, 3); + stream = session->closed_stream_tail; - CU_ASSERT(NGHTTP2_STREAM_STATE_CLOSED == nghttp2_stream_get_state(stream)); + nghttp2_session_detach_closed_stream(session, stream); - /* stream 5 HEADERS; with END_STREAM flag set */ - pack_headers(&bufs, &deflater, 5, - NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, reqnv, - ARRLEN(reqnv), mem); + CU_ASSERT(1 == session->num_closed_streams); - buf = &bufs.head->buf; - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); + CU_ASSERT(session->closed_stream_head == session->closed_stream_tail); + CU_ASSERT(NULL == session->closed_stream_head->closed_prev); + CU_ASSERT(NULL == session->closed_stream_head->closed_next); - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + nghttp2_session_del(session); +} - nghttp2_bufs_reset(&bufs); +void test_nghttp2_session_large_dep_tree(void) { + nghttp2_session *session; + nghttp2_session_callbacks callbacks; + size_t i; + nghttp2_stream *dep_stream = NULL; + nghttp2_stream *root_stream; + int32_t stream_id; - /* Push stream 2 associated to stream 5 */ - rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv, - ARRLEN(reqnv), NULL); + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.send_callback = null_send_callback; - CU_ASSERT(2 == rv); + nghttp2_session_server_new(&session, &callbacks, NULL); - rv = nghttp2_session_send(session); + stream_id = 1; + for (i = 0; i < NGHTTP2_MAX_DEP_TREE_LENGTH; ++i) { + dep_stream = open_stream_with_dep(session, stream_id, dep_stream); + stream_id += 2; + } - CU_ASSERT(0 == rv); + root_stream = nghttp2_session_get_stream(session, 1); - stream = nghttp2_session_find_stream(session, 2); + /* Check that last dep_stream must be part of tree */ + CU_ASSERT(nghttp2_stream_dep_subtree_find(root_stream, dep_stream)); - CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL == - nghttp2_stream_get_state(stream)); + dep_stream = open_stream_with_dep(session, stream_id, dep_stream); - /* Send resposne to push stream 2 with END_STREAM set */ - nghttp2_submit_response(session, 2, resnv, ARRLEN(resnv), NULL); + /* We exceeded NGHTTP2_MAX_DEP_TREE_LENGTH limit. dep_stream is now + root node and has no descendants. */ + CU_ASSERT(!nghttp2_stream_dep_subtree_find(root_stream, dep_stream)); + CU_ASSERT(nghttp2_stream_in_dep_tree(dep_stream)); - rv = nghttp2_session_send(session); + nghttp2_session_del(session); +} - CU_ASSERT(0 == rv); +void test_nghttp2_session_graceful_shutdown(void) { + nghttp2_session *session; + nghttp2_session_callbacks callbacks; + my_user_data ud; - stream = nghttp2_session_find_stream(session, 2); + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.send_callback = block_count_send_callback; + callbacks.on_frame_send_callback = on_frame_send_callback; + callbacks.on_stream_close_callback = on_stream_close_callback; - /* At server, pushed stream object is not retained after closed */ - CU_ASSERT(NULL == stream); + nghttp2_session_server_new(&session, &callbacks, &ud); - /* Push stream 4 associated to stream 5 */ - rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv, - ARRLEN(reqnv), NULL); + open_stream(session, 301); + open_stream(session, 302); + open_stream(session, 311); + open_stream(session, 319); + + CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, + (1u << 31) - 1, NGHTTP2_NO_ERROR, NULL, + 0)); - CU_ASSERT(4 == rv); + ud.block_count = 1; + ud.frame_send_cb_called = 0; - rv = nghttp2_session_send(session); + CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(0 == rv); + CU_ASSERT(1 == ud.frame_send_cb_called); + CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id); - stream = nghttp2_session_find_stream(session, 4); + CU_ASSERT(0 == + nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR)); - CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_LOCAL == - nghttp2_stream_get_state(stream)); + ud.block_count = 1; + ud.frame_send_cb_called = 0; + ud.stream_close_cb_called = 0; - /* Send response to push stream 4 without closing */ - data_prd.read_callback = defer_data_source_read_callback; + CU_ASSERT(0 == nghttp2_session_send(session)); - nghttp2_submit_response(session, 4, resnv, ARRLEN(resnv), &data_prd); + CU_ASSERT(1 == ud.frame_send_cb_called); + CU_ASSERT(301 == session->local_last_stream_id); + CU_ASSERT(2 == ud.stream_close_cb_called); - rv = nghttp2_session_send(session); + CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301)); + CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302)); + CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311)); + CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319)); - CU_ASSERT(0 == rv); + nghttp2_session_del(session); +} - stream = nghttp2_session_find_stream(session, 4); +void test_nghttp2_session_on_header_temporal_failure(void) { + nghttp2_session *session; + nghttp2_session_callbacks callbacks; + my_user_data ud; + nghttp2_bufs bufs; + nghttp2_buf *buf; + nghttp2_hd_deflater deflater; + nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")}; + nghttp2_nv *nva; + size_t hdpos; + ssize_t rv; + nghttp2_frame frame; + nghttp2_frame_hd hd; + nghttp2_outbound_item *item; - CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE == - nghttp2_stream_get_state(stream)); + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.on_header_callback = temporal_failure_on_header_callback; - /* Create idle stream by PRIORITY frame */ - nghttp2_frame_priority_init(&frame.priority, 7, &pri_spec_default); + nghttp2_session_server_new(&session, &callbacks, &ud); - rv = nghttp2_frame_pack_priority(&bufs, &frame.priority); + frame_pack_bufs_init(&bufs); - CU_ASSERT(0 == rv); + nghttp2_hd_deflate_init(&deflater); - nghttp2_frame_priority_free(&frame.priority); + nghttp2_nv_array_copy(&nva, nv, 1); - buf = &bufs.head->buf; - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); - - stream = nghttp2_session_find_stream(session, 7); - - CU_ASSERT(NGHTTP2_STREAM_STATE_IDLE == nghttp2_stream_get_state(stream)); - - nghttp2_bufs_reset(&bufs); - - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); - - /* Test for client side */ - - nghttp2_session_client_new(&session, &callbacks, NULL); - nghttp2_hd_deflate_init(&deflater, mem); - - nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL); - - rv = nghttp2_session_send(session); - - CU_ASSERT(0 == rv); + nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1, + NGHTTP2_HCAT_REQUEST, NULL, nva, 1); + nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); + nghttp2_frame_headers_free(&frame.headers); - /* Receive PUSH_PROMISE 2 associated to stream 1 */ - pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv, - ARRLEN(reqnv), mem); + /* We are going to create CONTINUATION. First serialize header + block, and then frame header. */ + hdpos = nghttp2_bufs_len(&bufs); buf = &bufs.head->buf; - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + buf->last += NGHTTP2_FRAME_HDLEN; - stream = nghttp2_session_find_stream(session, 2); + nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1); - CU_ASSERT(NGHTTP2_STREAM_STATE_RESERVED_REMOTE == - nghttp2_stream_get_state(stream)); + nghttp2_frame_hd_init(&hd, + nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN, + NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1); - nghttp2_bufs_reset(&bufs); + nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd); - /* Receive push response for stream 2 without END_STREAM set */ - pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv, - ARRLEN(resnv), mem); + rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs)); - buf = &bufs.head->buf; - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)); + CU_ASSERT(rv == nghttp2_bufs_len(&bufs)); - CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv); + item = nghttp2_session_get_next_ob_item(session); - stream = nghttp2_session_find_stream(session, 2); + CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL == - nghttp2_stream_get_state(stream)); + /* Make sure no header decompression error occurred */ + CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags); - nghttp2_bufs_reset(&bufs); + nghttp2_bufs_free(&bufs); nghttp2_hd_deflate_free(&deflater); nghttp2_session_del(session); - - nghttp2_bufs_free(&bufs); } -void test_nghttp2_session_stream_get_something(void) { +void test_nghttp2_session_recv_client_preface(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - nghttp2_stream *a, *b, *c; + nghttp2_option *option; + ssize_t rv; + nghttp2_frame ping_frame; + uint8_t buf[16]; memset(&callbacks, 0, sizeof(callbacks)); - nghttp2_session_server_new(&session, &callbacks, NULL); + nghttp2_option_new(&option); + nghttp2_option_set_recv_client_preface(option, 1); - a = open_stream(session, 1); + /* Check success case */ + nghttp2_session_server_new2(&session, &callbacks, NULL, option); - CU_ASSERT(nghttp2_session_get_root_stream(session) == - nghttp2_stream_get_parent(a)); - CU_ASSERT(NULL == nghttp2_stream_get_previous_sibling(a)); - CU_ASSERT(NULL == nghttp2_stream_get_next_sibling(a)); - CU_ASSERT(NULL == nghttp2_stream_get_first_child(a)); + CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_RECV_CLIENT_PREFACE); - b = open_stream_with_dep(session, 3, a); - c = open_stream_with_dep_weight(session, 5, 11, a); + rv = nghttp2_session_mem_recv( + session, (const uint8_t *)NGHTTP2_CLIENT_CONNECTION_PREFACE, + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); - CU_ASSERT(a == nghttp2_stream_get_parent(c)); - CU_ASSERT(a == nghttp2_stream_get_parent(b)); + CU_ASSERT(rv == NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN); + CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state); - CU_ASSERT(c == nghttp2_stream_get_first_child(a)); + /* Receiving PING is error */ + nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL); - CU_ASSERT(b == nghttp2_stream_get_next_sibling(c)); - CU_ASSERT(c == nghttp2_stream_get_previous_sibling(b)); + nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd); - CU_ASSERT(27 == nghttp2_stream_get_sum_dependency_weight(a)); + rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN); + CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv); + CU_ASSERT(NGHTTP2_IB_IGN_PAYLOAD == session->iframe.state); + CU_ASSERT(8 == session->iframe.payloadleft); - CU_ASSERT(11 == nghttp2_stream_get_weight(c)); - CU_ASSERT(5 == nghttp2_stream_get_stream_id(c)); - CU_ASSERT(0 == nghttp2_stream_get_stream_id(&session->root)); + nghttp2_frame_ping_free(&ping_frame.ping); nghttp2_session_del(session); -} - -void test_nghttp2_session_find_stream(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_stream *stream; - - memset(&callbacks, 0, sizeof(callbacks)); - nghttp2_session_server_new(&session, &callbacks, NULL); - - open_recv_stream(session, 1); - - stream = nghttp2_session_find_stream(session, 1); - - CU_ASSERT(NULL != stream); - CU_ASSERT(1 == stream->stream_id); + /* Check bad case */ + nghttp2_session_server_new2(&session, &callbacks, NULL, option); - stream = nghttp2_session_find_stream(session, 0); + /* Feed preface with one byte less */ + rv = nghttp2_session_mem_recv( + session, (const uint8_t *)NGHTTP2_CLIENT_CONNECTION_PREFACE, + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - 1); - CU_ASSERT(&session->root == stream); - CU_ASSERT(0 == stream->stream_id); + CU_ASSERT(rv == NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN - 1); + CU_ASSERT(NGHTTP2_IB_READ_CLIENT_PREFACE == session->iframe.state); + CU_ASSERT(1 == session->iframe.payloadleft); - stream = nghttp2_session_find_stream(session, 2); + rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1); - CU_ASSERT(NULL == stream); + CU_ASSERT(NGHTTP2_ERR_BAD_PREFACE == rv); nghttp2_session_del(session); -} - -void test_nghttp2_session_keep_closed_stream(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - const size_t max_concurrent_streams = 5; - nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, - (uint32_t)max_concurrent_streams}; - size_t i; - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_server_new(&session, &callbacks, NULL); - - nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1); - - for (i = 0; i < max_concurrent_streams; ++i) { - open_recv_stream(session, (int32_t)i * 2 + 1); - } - - CU_ASSERT(0 == session->num_closed_streams); - - nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR); - - CU_ASSERT(1 == session->num_closed_streams); - CU_ASSERT(1 == session->closed_stream_tail->stream_id); - CU_ASSERT(session->closed_stream_tail == session->closed_stream_head); - - nghttp2_session_close_stream(session, 5, NGHTTP2_NO_ERROR); - - CU_ASSERT(2 == session->num_closed_streams); - CU_ASSERT(5 == session->closed_stream_tail->stream_id); - CU_ASSERT(1 == session->closed_stream_head->stream_id); - CU_ASSERT(session->closed_stream_head == - session->closed_stream_tail->closed_prev); - CU_ASSERT(NULL == session->closed_stream_tail->closed_next); - CU_ASSERT(session->closed_stream_tail == - session->closed_stream_head->closed_next); - CU_ASSERT(NULL == session->closed_stream_head->closed_prev); - - open_recv_stream(session, 11); - nghttp2_session_adjust_closed_stream(session); - - CU_ASSERT(1 == session->num_closed_streams); - CU_ASSERT(5 == session->closed_stream_tail->stream_id); - CU_ASSERT(session->closed_stream_tail == session->closed_stream_head); - CU_ASSERT(NULL == session->closed_stream_head->closed_prev); - CU_ASSERT(NULL == session->closed_stream_head->closed_next); - - open_recv_stream(session, 13); - nghttp2_session_adjust_closed_stream(session); - - CU_ASSERT(0 == session->num_closed_streams); - CU_ASSERT(NULL == session->closed_stream_tail); - CU_ASSERT(NULL == session->closed_stream_head); - - nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR); - - CU_ASSERT(1 == session->num_closed_streams); - CU_ASSERT(3 == session->closed_stream_head->stream_id); - - /* server initiated stream is not counted to max concurrent limit */ - open_sent_stream(session, 2); - nghttp2_session_adjust_closed_stream(session); - - CU_ASSERT(1 == session->num_closed_streams); - CU_ASSERT(3 == session->closed_stream_head->stream_id); - nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR); - - CU_ASSERT(1 == session->num_closed_streams); - CU_ASSERT(3 == session->closed_stream_head->stream_id); - - nghttp2_session_del(session); + nghttp2_option_del(option); } -void test_nghttp2_session_keep_idle_stream(void) { +void test_nghttp2_session_delete_data_item(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - const size_t max_concurrent_streams = 1; - nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, - (uint32_t)max_concurrent_streams}; - int i; - int32_t stream_id; + nghttp2_stream *a; + nghttp2_data_provider prd; memset(&callbacks, 0, sizeof(callbacks)); - callbacks.send_callback = null_send_callback; nghttp2_session_server_new(&session, &callbacks, NULL); - nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1); - - /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if - max concurrent streams is very low. */ - for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) { - open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE); - nghttp2_session_adjust_idle_stream(session); - } - - CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams); - - stream_id = (NGHTTP2_MIN_IDLE_STREAMS - 1) * 2 + 1; - CU_ASSERT(1 == session->idle_stream_head->stream_id); - CU_ASSERT(stream_id == session->idle_stream_tail->stream_id); - - stream_id += 2; + a = open_stream(session, 1); + open_stream_with_dep(session, 3, a); - open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE); - nghttp2_session_adjust_idle_stream(session); + /* We don't care about these members, since we won't send data */ + prd.source.ptr = NULL; + prd.read_callback = fail_data_source_read_callback; - CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams); - CU_ASSERT(3 == session->idle_stream_head->stream_id); - CU_ASSERT(stream_id == session->idle_stream_tail->stream_id); + /* This data item will be marked as TOP */ + CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd)); + /* This data item will be marked as REST */ + CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd)); nghttp2_session_del(session); } -void test_nghttp2_session_detach_idle_stream(void) { +void test_nghttp2_session_open_idle_stream(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; - int i; nghttp2_stream *stream; + nghttp2_stream *opened_stream; + nghttp2_priority_spec pri_spec; + nghttp2_frame frame; - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.send_callback = null_send_callback; + memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); nghttp2_session_server_new(&session, &callbacks, NULL); - for (i = 1; i <= 3; ++i) { - nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL); - } - - CU_ASSERT(3 == session->num_idle_streams); - - /* Detach middle stream */ - stream = nghttp2_session_get_stream_raw(session, 2); + nghttp2_priority_spec_init(&pri_spec, 0, 3, 0); - CU_ASSERT(session->idle_stream_head == stream->closed_prev); - CU_ASSERT(session->idle_stream_tail == stream->closed_next); - CU_ASSERT(stream == session->idle_stream_head->closed_next); - CU_ASSERT(stream == session->idle_stream_tail->closed_prev); + nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec); - nghttp2_session_detach_idle_stream(session, stream); + CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame)); - CU_ASSERT(2 == session->num_idle_streams); + stream = nghttp2_session_get_stream_raw(session, 1); + CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state); CU_ASSERT(NULL == stream->closed_prev); CU_ASSERT(NULL == stream->closed_next); + CU_ASSERT(1 == session->num_closed_streams); + CU_ASSERT(session->closed_stream_head == stream); + CU_ASSERT(session->closed_stream_tail == stream); - CU_ASSERT(session->idle_stream_head == - session->idle_stream_tail->closed_prev); - CU_ASSERT(session->idle_stream_tail == - session->idle_stream_head->closed_next); - - /* Detach head stream */ - stream = session->idle_stream_head; - - nghttp2_session_detach_idle_stream(session, stream); - - CU_ASSERT(1 == session->num_idle_streams); - - CU_ASSERT(session->idle_stream_head == session->idle_stream_tail); - CU_ASSERT(NULL == session->idle_stream_head->closed_prev); - CU_ASSERT(NULL == session->idle_stream_head->closed_next); - - /* Detach last stream */ - - stream = session->idle_stream_head; - - nghttp2_session_detach_idle_stream(session, stream); - - CU_ASSERT(0 == session->num_idle_streams); - - CU_ASSERT(NULL == session->idle_stream_head); - CU_ASSERT(NULL == session->idle_stream_tail); - - for (i = 4; i <= 5; ++i) { - nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL); - } - - CU_ASSERT(2 == session->num_idle_streams); - - /* Detach tail stream */ - - stream = session->idle_stream_tail; - - nghttp2_session_detach_idle_stream(session, stream); - - CU_ASSERT(1 == session->num_idle_streams); - - CU_ASSERT(session->idle_stream_head == session->idle_stream_tail); - CU_ASSERT(NULL == session->idle_stream_head->closed_prev); - CU_ASSERT(NULL == session->idle_stream_head->closed_next); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_large_dep_tree(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - size_t i; - nghttp2_stream *dep_stream = NULL; - nghttp2_stream *stream; - int32_t stream_id; - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_server_new(&session, &callbacks, NULL); + opened_stream = nghttp2_session_open_stream( + session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); - stream_id = 1; - for (i = 0; i < 250; ++i, stream_id += 2) { - dep_stream = open_stream_with_dep(session, stream_id, dep_stream); - } + CU_ASSERT(stream == opened_stream); + CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state); + CU_ASSERT(0 == session->num_closed_streams); + CU_ASSERT(NULL == session->closed_stream_head); + CU_ASSERT(NULL == session->closed_stream_tail); - stream_id = 1; - for (i = 0; i < 250; ++i, stream_id += 2) { - stream = nghttp2_session_get_stream(session, stream_id); - CU_ASSERT(nghttp2_stream_dep_find_ancestor(stream, &session->root)); - CU_ASSERT(nghttp2_stream_in_dep_tree(stream)); - } + nghttp2_frame_priority_free(&frame.priority); nghttp2_session_del(session); } - -void test_nghttp2_session_graceful_shutdown(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - my_user_data ud; - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.send_callback = null_send_callback; - callbacks.on_frame_send_callback = on_frame_send_callback; - callbacks.on_stream_close_callback = on_stream_close_callback; - - nghttp2_session_server_new(&session, &callbacks, &ud); - - open_recv_stream(session, 301); - open_sent_stream(session, 302); - open_recv_stream(session, 309); - open_recv_stream(session, 311); - open_recv_stream(session, 319); - - CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session)); - - ud.frame_send_cb_called = 0; - - CU_ASSERT(0 == nghttp2_session_send(session)); - - CU_ASSERT(1 == ud.frame_send_cb_called); - CU_ASSERT((1u << 31) - 1 == session->local_last_stream_id); - - CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, 311, - NGHTTP2_NO_ERROR, NULL, 0)); - - ud.frame_send_cb_called = 0; - ud.stream_close_cb_called = 0; - - CU_ASSERT(0 == nghttp2_session_send(session)); - - CU_ASSERT(1 == ud.frame_send_cb_called); - CU_ASSERT(311 == session->local_last_stream_id); - CU_ASSERT(1 == ud.stream_close_cb_called); - - CU_ASSERT(0 == - nghttp2_session_terminate_session2(session, 301, NGHTTP2_NO_ERROR)); - - ud.frame_send_cb_called = 0; - ud.stream_close_cb_called = 0; - - CU_ASSERT(0 == nghttp2_session_send(session)); - - CU_ASSERT(1 == ud.frame_send_cb_called); - CU_ASSERT(301 == session->local_last_stream_id); - CU_ASSERT(2 == ud.stream_close_cb_called); - - CU_ASSERT(NULL != nghttp2_session_get_stream(session, 301)); - CU_ASSERT(NULL != nghttp2_session_get_stream(session, 302)); - CU_ASSERT(NULL == nghttp2_session_get_stream(session, 309)); - CU_ASSERT(NULL == nghttp2_session_get_stream(session, 311)); - CU_ASSERT(NULL == nghttp2_session_get_stream(session, 319)); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_on_header_temporal_failure(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - my_user_data ud; - nghttp2_bufs bufs; - nghttp2_buf *buf; - nghttp2_hd_deflater deflater; - nghttp2_nv nv[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")}; - nghttp2_nv *nva; - size_t hdpos; - ssize_t rv; - nghttp2_frame frame; - nghttp2_frame_hd hd; - nghttp2_outbound_item *item; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.on_header_callback = temporal_failure_on_header_callback; - - nghttp2_session_server_new(&session, &callbacks, &ud); - - frame_pack_bufs_init(&bufs); - - nghttp2_hd_deflate_init(&deflater, mem); - - nghttp2_nv_array_copy(&nva, reqnv, ARRLEN(reqnv), mem); - - nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_STREAM, 1, - NGHTTP2_HCAT_REQUEST, NULL, nva, ARRLEN(reqnv)); - nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); - nghttp2_frame_headers_free(&frame.headers, mem); - - /* We are going to create CONTINUATION. First serialize header - block, and then frame header. */ - hdpos = nghttp2_bufs_len(&bufs); - - buf = &bufs.head->buf; - buf->last += NGHTTP2_FRAME_HDLEN; - - nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv[1], 1); - - nghttp2_frame_hd_init(&hd, - nghttp2_bufs_len(&bufs) - hdpos - NGHTTP2_FRAME_HDLEN, - NGHTTP2_CONTINUATION, NGHTTP2_FLAG_END_HEADERS, 1); - - nghttp2_frame_pack_frame_hd(&buf->pos[hdpos], &hd); - - ud.header_cb_called = 0; - rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_bufs_len(&bufs)); - - CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv); - CU_ASSERT(1 == ud.header_cb_called); - - item = nghttp2_session_get_next_ob_item(session); - - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(1 == item->frame.hd.stream_id); - - /* Make sure no header decompression error occurred */ - CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags); - - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); - - nghttp2_bufs_reset(&bufs); - - /* Check for PUSH_PROMISE */ - nghttp2_hd_deflate_init(&deflater, mem); - nghttp2_session_client_new(&session, &callbacks, &ud); - - open_sent_stream(session, 1); - - rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, - reqnv, ARRLEN(reqnv), mem); - CU_ASSERT(0 == rv); - - ud.header_cb_called = 0; - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_bufs_len(&bufs)); - CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv); - CU_ASSERT(1 == ud.header_cb_called); - - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(2 == item->frame.hd.stream_id); - CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code); - - nghttp2_session_del(session); - nghttp2_hd_deflate_free(&deflater); - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_session_recv_client_magic(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - ssize_t rv; - nghttp2_frame ping_frame; - uint8_t buf[16]; - - /* enable global nghttp2_enable_strict_preface here */ - nghttp2_enable_strict_preface = 1; - - memset(&callbacks, 0, sizeof(callbacks)); - - /* Check success case */ - nghttp2_session_server_new(&session, &callbacks, NULL); - - rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC, - NGHTTP2_CLIENT_MAGIC_LEN); - - CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN); - CU_ASSERT(NGHTTP2_IB_READ_FIRST_SETTINGS == session->iframe.state); - - /* Receiving PING is error because we want SETTINGS. */ - nghttp2_frame_ping_init(&ping_frame.ping, NGHTTP2_FLAG_NONE, NULL); - - nghttp2_frame_pack_frame_hd(buf, &ping_frame.ping.hd); - - rv = nghttp2_session_mem_recv(session, buf, NGHTTP2_FRAME_HDLEN); - CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv); - CU_ASSERT(NGHTTP2_IB_IGN_ALL == session->iframe.state); - CU_ASSERT(0 == session->iframe.payloadleft); - - nghttp2_frame_ping_free(&ping_frame.ping); - - nghttp2_session_del(session); - - /* Check bad case */ - nghttp2_session_server_new(&session, &callbacks, NULL); - - /* Feed magic with one byte less */ - rv = nghttp2_session_mem_recv(session, (const uint8_t *)NGHTTP2_CLIENT_MAGIC, - NGHTTP2_CLIENT_MAGIC_LEN - 1); - - CU_ASSERT(rv == NGHTTP2_CLIENT_MAGIC_LEN - 1); - CU_ASSERT(NGHTTP2_IB_READ_CLIENT_MAGIC == session->iframe.state); - CU_ASSERT(1 == session->iframe.payloadleft); - - rv = nghttp2_session_mem_recv(session, (const uint8_t *)"\0", 1); - - CU_ASSERT(NGHTTP2_ERR_BAD_CLIENT_MAGIC == rv); - - nghttp2_session_del(session); - - /* disable global nghttp2_enable_strict_preface here */ - nghttp2_enable_strict_preface = 0; -} - -void test_nghttp2_session_delete_data_item(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_stream *a; - nghttp2_data_provider prd; - - memset(&callbacks, 0, sizeof(callbacks)); - - nghttp2_session_server_new(&session, &callbacks, NULL); - - a = open_recv_stream(session, 1); - open_recv_stream_with_dep(session, 3, a); - - /* We don't care about these members, since we won't send data */ - prd.source.ptr = NULL; - prd.read_callback = fail_data_source_read_callback; - - CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd)); - CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd)); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_open_idle_stream(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_stream *stream; - nghttp2_stream *opened_stream; - nghttp2_priority_spec pri_spec; - nghttp2_frame frame; - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - - nghttp2_session_server_new(&session, &callbacks, NULL); - - nghttp2_priority_spec_init(&pri_spec, 0, 3, 0); - - nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec); - - CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame)); - - stream = nghttp2_session_get_stream_raw(session, 1); - - CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state); - CU_ASSERT(NULL == stream->closed_prev); - CU_ASSERT(NULL == stream->closed_next); - CU_ASSERT(1 == session->num_idle_streams); - CU_ASSERT(session->idle_stream_head == stream); - CU_ASSERT(session->idle_stream_tail == stream); - - opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); - - CU_ASSERT(stream == opened_stream); - CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state); - CU_ASSERT(0 == session->num_idle_streams); - CU_ASSERT(NULL == session->idle_stream_head); - CU_ASSERT(NULL == session->idle_stream_tail); - - nghttp2_frame_priority_free(&frame.priority); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_cancel_reserved_remote(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_stream *stream; - nghttp2_frame frame; - nghttp2_nv *nva; - size_t nvlen; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - nghttp2_bufs bufs; - ssize_t rv; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); - - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL); - - CU_ASSERT(NGHTTP2_STREAM_CLOSING == stream->state); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nvlen = ARRLEN(resnv); - nghttp2_nv_array_copy(&nva, resnv, nvlen, mem); - - nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2, - NGHTTP2_HCAT_PUSH_RESPONSE, NULL, nva, nvlen); - rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); - - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - /* stream is not dangling, so assign NULL */ - stream = NULL; - - /* No RST_STREAM or GOAWAY is generated since stream should be in - NGHTTP2_STREAM_CLOSING and push response should be ignored. */ - CU_ASSERT(0 == nghttp2_outbound_queue_size(&session->ob_reg)); - - /* Check that we can receive push response HEADERS while RST_STREAM - is just queued. */ - open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED); - - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL); - - nghttp2_bufs_reset(&bufs); - - frame.hd.stream_id = 4; - rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); - - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_reg)); - - nghttp2_frame_headers_free(&frame.headers, mem); - - nghttp2_hd_deflate_free(&deflater); - - nghttp2_session_del(session); - - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_session_reset_pending_headers(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_stream *stream; - int32_t stream_id; - my_user_data ud; - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - callbacks.on_frame_send_callback = on_frame_send_callback; - callbacks.on_frame_not_send_callback = on_frame_not_send_callback; - callbacks.on_stream_close_callback = on_stream_close_callback; - - nghttp2_session_client_new(&session, &callbacks, &ud); - - stream_id = nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL); - CU_ASSERT(stream_id >= 1); - - nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id, - NGHTTP2_CANCEL); - - session->remote_settings.max_concurrent_streams = 0; - - /* RST_STREAM cancels pending HEADERS and is not actually sent. */ - ud.frame_send_cb_called = 0; - CU_ASSERT(0 == nghttp2_session_send(session)); - - CU_ASSERT(0 == ud.frame_send_cb_called); - - stream = nghttp2_session_get_stream(session, stream_id); - - CU_ASSERT(NULL == stream); - - /* See HEADERS is not sent. on_stream_close is called just like - transmission failure. */ - session->remote_settings.max_concurrent_streams = 1; - - ud.frame_not_send_cb_called = 0; - ud.stream_close_error_code = 0; - CU_ASSERT(0 == nghttp2_session_send(session)); - - CU_ASSERT(1 == ud.frame_not_send_cb_called); - CU_ASSERT(NGHTTP2_HEADERS == ud.not_sent_frame_type); - CU_ASSERT(NGHTTP2_CANCEL == ud.stream_close_error_code); - - stream = nghttp2_session_get_stream(session, stream_id); - - CU_ASSERT(NULL == stream); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_send_data_callback(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_data_provider data_prd; - my_user_data ud; - accumulator acc; - nghttp2_frame_hd hd; - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = accumulator_send_callback; - callbacks.send_data_callback = send_data_callback; - - data_prd.read_callback = no_copy_data_source_read_callback; - - acc.length = 0; - ud.acc = &acc; - - ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2; - - nghttp2_session_client_new(&session, &callbacks, &ud); - - open_sent_stream(session, 1); - - nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - CU_ASSERT((NGHTTP2_FRAME_HDLEN + NGHTTP2_DATA_PAYLOADLEN) * 2 == acc.length); - - nghttp2_frame_unpack_frame_hd(&hd, acc.buf); - - CU_ASSERT(16384 == hd.length); - CU_ASSERT(NGHTTP2_DATA == hd.type); - CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags); - - nghttp2_frame_unpack_frame_hd(&hd, acc.buf + NGHTTP2_FRAME_HDLEN + hd.length); - - CU_ASSERT(16384 == hd.length); - CU_ASSERT(NGHTTP2_DATA == hd.type); - CU_ASSERT(NGHTTP2_FLAG_END_STREAM == hd.flags); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_on_begin_headers_temporal_failure(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - my_user_data ud; - nghttp2_bufs bufs; - nghttp2_mem *mem; - ssize_t rv; - nghttp2_hd_deflater deflater; - nghttp2_outbound_item *item; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - nghttp2_hd_deflate_init(&deflater, mem); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.on_begin_headers_callback = - temporal_failure_on_begin_headers_callback; - callbacks.on_header_callback = on_header_callback; - callbacks.on_frame_recv_callback = on_frame_recv_callback; - callbacks.send_callback = null_send_callback; - nghttp2_session_server_new(&session, &callbacks, &ud); - - rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv, - ARRLEN(reqnv), mem); - CU_ASSERT(0 == rv); - - ud.header_cb_called = 0; - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_bufs_len(&bufs)); - CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv); - CU_ASSERT(0 == ud.header_cb_called); - CU_ASSERT(0 == ud.frame_recv_cb_called); - - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(1 == item->frame.hd.stream_id); - CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code); - - nghttp2_session_del(session); - nghttp2_hd_deflate_free(&deflater); - - nghttp2_bufs_reset(&bufs); - /* check for PUSH_PROMISE */ - nghttp2_hd_deflate_init(&deflater, mem); - nghttp2_session_client_new(&session, &callbacks, &ud); - - open_sent_stream(session, 1); - - rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, - reqnv, ARRLEN(reqnv), mem); - CU_ASSERT(0 == rv); - - ud.header_cb_called = 0; - ud.frame_recv_cb_called = 0; - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_bufs_len(&bufs)); - CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == rv); - CU_ASSERT(0 == ud.header_cb_called); - CU_ASSERT(0 == ud.frame_recv_cb_called); - - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(2 == item->frame.hd.stream_id); - CU_ASSERT(NGHTTP2_INTERNAL_ERROR == item->frame.rst_stream.error_code); - - nghttp2_session_del(session); - nghttp2_hd_deflate_free(&deflater); - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_session_defer_then_close(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_data_provider prd; - int rv; - const uint8_t *datap; - ssize_t datalen; - nghttp2_frame frame; - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - - prd.read_callback = defer_data_source_read_callback; - - rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL); - CU_ASSERT(rv > 0); - - /* This sends HEADERS */ - datalen = nghttp2_session_mem_send(session, &datap); - - CU_ASSERT(datalen > 0); - - /* This makes DATA item deferred */ - datalen = nghttp2_session_mem_send(session, &datap); - - CU_ASSERT(datalen == 0); - - nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL); - - /* Assertion failure; GH-264 */ - rv = nghttp2_session_on_rst_stream_received(session, &frame); - - CU_ASSERT(rv == 0); - - nghttp2_session_del(session); -} - -static int submit_response_on_stream_close(nghttp2_session *session, - int32_t stream_id, - uint32_t error_code _U_, - void *user_data _U_) { - nghttp2_data_provider data_prd; - data_prd.read_callback = temporal_failure_data_source_read_callback; - - // Attempt to submit response or data to the stream being closed - switch (stream_id) { - case 1: - CU_ASSERT(0 == nghttp2_submit_response(session, stream_id, resnv, - ARRLEN(resnv), &data_prd)); - break; - case 3: - CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, stream_id, - &data_prd)); - break; - } - - return 0; -} - -void test_nghttp2_session_detach_item_from_closed_stream(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - - memset(&callbacks, 0, sizeof(callbacks)); - - callbacks.send_callback = null_send_callback; - callbacks.on_stream_close_callback = submit_response_on_stream_close; - - nghttp2_session_server_new(&session, &callbacks, NULL); - - open_recv_stream(session, 1); - open_recv_stream(session, 3); - - nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR); - nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_flooding(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_bufs bufs; - nghttp2_buf *buf; - nghttp2_frame frame; - nghttp2_mem *mem; - size_t i; - - mem = nghttp2_mem_default(); - - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(callbacks)); - - /* PING ACK */ - nghttp2_session_server_new(&session, &callbacks, NULL); - - nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL); - nghttp2_frame_pack_ping(&bufs, &frame.ping); - nghttp2_frame_ping_free(&frame.ping); - - buf = &bufs.head->buf; - - for (i = 0; i < NGHTTP2_MAX_OBQ_FLOOD_ITEM; ++i) { - CU_ASSERT( - (ssize_t)nghttp2_buf_len(buf) == - nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf))); - } - - CU_ASSERT(NGHTTP2_ERR_FLOODED == - nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf))); - - nghttp2_session_del(session); - - /* SETTINGS ACK */ - nghttp2_bufs_reset(&bufs); - - nghttp2_session_server_new(&session, &callbacks, NULL); - - nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0); - nghttp2_frame_pack_settings(&bufs, &frame.settings); - nghttp2_frame_settings_free(&frame.settings, mem); - - buf = &bufs.head->buf; - - for (i = 0; i < NGHTTP2_MAX_OBQ_FLOOD_ITEM; ++i) { - CU_ASSERT( - (ssize_t)nghttp2_buf_len(buf) == - nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf))); - } - - CU_ASSERT(NGHTTP2_ERR_FLOODED == - nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf))); - - nghttp2_session_del(session); - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_session_change_stream_priority(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_stream *stream1, *stream2, *stream3, *stream5; - nghttp2_priority_spec pri_spec; - int rv; - - memset(&callbacks, 0, sizeof(callbacks)); - - nghttp2_session_server_new(&session, &callbacks, NULL); - - stream1 = open_recv_stream(session, 1); - stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1); - stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3); - - nghttp2_priority_spec_init(&pri_spec, 1, 256, 0); - - rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec); - - CU_ASSERT(0 == rv); - - CU_ASSERT(stream1 == stream2->dep_prev); - CU_ASSERT(256 == stream2->weight); - - /* Cannot change stream which does not exist */ - rv = nghttp2_session_change_stream_priority(session, 5, &pri_spec); - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv); - - /* It is an error to depend on itself */ - rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec); - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv); - - /* It is an error to change priority of root stream (0) */ - rv = nghttp2_session_change_stream_priority(session, 0, &pri_spec); - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv); - - /* Depends on the non-existing idle stream. This creates that idle - stream. */ - nghttp2_priority_spec_init(&pri_spec, 5, 9, 1); - - rv = nghttp2_session_change_stream_priority(session, 2, &pri_spec); - - CU_ASSERT(0 == rv); - - stream5 = nghttp2_session_get_stream_raw(session, 5); - - CU_ASSERT(NULL != stream5); - CU_ASSERT(&session->root == stream5->dep_prev); - CU_ASSERT(stream5 == stream2->dep_prev); - CU_ASSERT(9 == stream2->weight); - - nghttp2_session_del(session); - - /* Check that this works in client session too */ - nghttp2_session_client_new(&session, &callbacks, NULL); - - stream1 = open_sent_stream(session, 1); - - nghttp2_priority_spec_init(&pri_spec, 5, 9, 1); - - rv = nghttp2_session_change_stream_priority(session, 1, &pri_spec); - - CU_ASSERT(0 == rv); - - stream5 = nghttp2_session_get_stream_raw(session, 5); - - CU_ASSERT(NULL != stream5); - CU_ASSERT(&session->root == stream5->dep_prev); - CU_ASSERT(stream5 == stream1->dep_prev); - CU_ASSERT(9 == stream1->weight); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_create_idle_stream(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_stream *stream2, *stream4, *stream8, *stream10; - nghttp2_priority_spec pri_spec; - int rv; - int i; - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_server_new(&session, &callbacks, NULL); - - stream2 = open_sent_stream(session, 2); - - nghttp2_priority_spec_init(&pri_spec, 2, 111, 1); - - rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec); - - CU_ASSERT(0 == rv); - - stream4 = nghttp2_session_get_stream_raw(session, 4); - - CU_ASSERT(4 == stream4->stream_id); - CU_ASSERT(111 == stream4->weight); - CU_ASSERT(stream2 == stream4->dep_prev); - CU_ASSERT(stream4 == stream2->dep_next); - - /* If pri_spec->stream_id does not exist, and it is idle stream, it - is created too */ - nghttp2_priority_spec_init(&pri_spec, 8, 109, 0); - - rv = nghttp2_session_create_idle_stream(session, 8, &pri_spec); - - CU_ASSERT(0 == rv); - - stream8 = nghttp2_session_get_stream_raw(session, 8); - stream10 = nghttp2_session_get_stream_raw(session, 10); - - CU_ASSERT(8 == stream8->stream_id); - CU_ASSERT(109 == stream8->weight); - CU_ASSERT(10 == stream10->stream_id); - CU_ASSERT(16 == stream10->weight); - CU_ASSERT(stream10 == stream8->dep_prev); - CU_ASSERT(&session->root == stream10->dep_prev); - - /* It is an error to attempt to create already existing idle - stream */ - rv = nghttp2_session_create_idle_stream(session, 4, &pri_spec); - - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv); - - /* It is an error to depend on itself */ - pri_spec.stream_id = 6; - - rv = nghttp2_session_create_idle_stream(session, 6, &pri_spec); - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv); - - /* It is an error to create root stream (0) as idle stream */ - rv = nghttp2_session_create_idle_stream(session, 0, &pri_spec); - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv); - - /* It is an error to create non-idle stream */ - session->next_stream_id = 20; - pri_spec.stream_id = 2; - - rv = nghttp2_session_create_idle_stream(session, 18, &pri_spec); - - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == rv); - - nghttp2_session_del(session); - - /* Check that this works in client session too */ - nghttp2_session_client_new(&session, &callbacks, NULL); - - nghttp2_priority_spec_init(&pri_spec, 4, 99, 1); - - rv = nghttp2_session_create_idle_stream(session, 2, &pri_spec); - - CU_ASSERT(0 == rv); - - stream4 = nghttp2_session_get_stream_raw(session, 4); - stream2 = nghttp2_session_get_stream_raw(session, 2); - - CU_ASSERT(NULL != stream4); - CU_ASSERT(NULL != stream2); - CU_ASSERT(&session->root == stream4->dep_prev); - CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream4->weight); - CU_ASSERT(stream4 == stream2->dep_prev); - CU_ASSERT(99 == stream2->weight); - - nghttp2_session_del(session); - - /* Check that idle stream is reduced when nghttp2_session_send() is - called. */ - nghttp2_session_server_new(&session, &callbacks, NULL); - - session->local_settings.max_concurrent_streams = 30; - - nghttp2_priority_spec_init(&pri_spec, 0, 16, 0); - for (i = 0; i < 100; ++i) { - rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec); - - CU_ASSERT(0 == rv); - - nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0); - } - - CU_ASSERT(100 == session->num_idle_streams); - CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(30 == session->num_idle_streams); - CU_ASSERT(141 == session->idle_stream_head->stream_id); - - nghttp2_session_del(session); - - /* Check that idle stream is reduced when nghttp2_session_mem_recv() is - called. */ - nghttp2_session_client_new(&session, &callbacks, NULL); - - session->local_settings.max_concurrent_streams = 30; - - nghttp2_priority_spec_init(&pri_spec, 0, 16, 0); - for (i = 0; i < 100; ++i) { - rv = nghttp2_session_create_idle_stream(session, i * 2 + 1, &pri_spec); - - CU_ASSERT(0 == rv); - - nghttp2_priority_spec_init(&pri_spec, i * 2 + 1, 16, 0); - } - - CU_ASSERT(100 == session->num_idle_streams); - CU_ASSERT(0 == nghttp2_session_mem_recv(session, NULL, 0)); - CU_ASSERT(30 == session->num_idle_streams); - CU_ASSERT(141 == session->idle_stream_head->stream_id); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_repeated_priority_change(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_frame frame; - nghttp2_priority_spec pri_spec; - int32_t stream_id, last_stream_id; - int32_t max_streams = 20; - - memset(&callbacks, 0, sizeof(callbacks)); - - nghttp2_session_server_new(&session, &callbacks, NULL); - - session->local_settings.max_concurrent_streams = (uint32_t)max_streams; - - /* 1 -> 0 */ - nghttp2_priority_spec_init(&pri_spec, 0, 16, 0); - nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec); - - CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame)); - - nghttp2_frame_priority_free(&frame.priority); - - last_stream_id = max_streams * 2 + 1; - - for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) { - /* 1 -> stream_id */ - nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0); - nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec); - - CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame)); - - nghttp2_frame_priority_free(&frame.priority); - } - - CU_ASSERT(20 == session->num_idle_streams); - CU_ASSERT(1 == session->idle_stream_head->stream_id); - - /* 1 -> last_stream_id */ - nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0); - nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec); - - CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame)); - - nghttp2_frame_priority_free(&frame.priority); - - CU_ASSERT(20 == session->num_idle_streams); - CU_ASSERT(3 == session->idle_stream_head->stream_id); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_repeated_priority_submission(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_priority_spec pri_spec; - int32_t stream_id, last_stream_id; - uint32_t max_streams = NGHTTP2_MIN_IDLE_STREAMS; - - memset(&callbacks, 0, sizeof(callbacks)); - - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - - session->local_settings.max_concurrent_streams = max_streams; - - /* 1 -> 0 */ - nghttp2_priority_spec_init(&pri_spec, 0, 16, 0); - - CU_ASSERT(0 == - nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec)); - - last_stream_id = (int32_t)(max_streams * 2 + 1); - - for (stream_id = 3; stream_id < last_stream_id; stream_id += 2) { - /* 1 -> stream_id */ - nghttp2_priority_spec_init(&pri_spec, stream_id, 16, 0); - - CU_ASSERT( - 0 == nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec)); - } - - CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(max_streams == session->num_idle_streams); - CU_ASSERT(1 == session->idle_stream_head->stream_id); - - /* 1 -> last_stream_id */ - nghttp2_priority_spec_init(&pri_spec, last_stream_id, 16, 0); - - CU_ASSERT(0 == - nghttp2_submit_priority(session, NGHTTP2_FLAG_NONE, 1, &pri_spec)); - - CU_ASSERT(0 == nghttp2_session_send(session)); - CU_ASSERT(max_streams == session->num_idle_streams); - CU_ASSERT(3 == session->idle_stream_head->stream_id); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_set_local_window_size(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_outbound_item *item; - nghttp2_stream *stream; - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - stream = open_sent_stream(session, 1); - stream->recv_window_size = 4096; - - CU_ASSERT(0 == nghttp2_session_set_local_window_size( - session, NGHTTP2_FLAG_NONE, 1, 65536)); - CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 == - stream->local_window_size); - CU_ASSERT(4096 == stream->recv_window_size); - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type); - CU_ASSERT(1 == item->frame.window_update.hd.stream_id); - CU_ASSERT(1 == item->frame.window_update.window_size_increment); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - /* Go decrement part */ - CU_ASSERT(0 == nghttp2_session_set_local_window_size( - session, NGHTTP2_FLAG_NONE, 1, 32768)); - CU_ASSERT(32768 == stream->local_window_size); - CU_ASSERT(-28672 == stream->recv_window_size); - CU_ASSERT(32768 == stream->recv_reduction); - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(item == NULL); - - /* Increase local window size */ - CU_ASSERT(0 == nghttp2_session_set_local_window_size( - session, NGHTTP2_FLAG_NONE, 1, 49152)); - CU_ASSERT(49152 == stream->local_window_size); - CU_ASSERT(-12288 == stream->recv_window_size); - CU_ASSERT(16384 == stream->recv_reduction); - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - - /* Increase local window again */ - CU_ASSERT(0 == nghttp2_session_set_local_window_size( - session, NGHTTP2_FLAG_NONE, 1, 65537)); - CU_ASSERT(65537 == stream->local_window_size); - CU_ASSERT(4096 == stream->recv_window_size); - CU_ASSERT(0 == stream->recv_reduction); - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(1 == item->frame.window_update.window_size_increment); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - /* Check connection-level flow control */ - session->recv_window_size = 4096; - CU_ASSERT(0 == nghttp2_session_set_local_window_size( - session, NGHTTP2_FLAG_NONE, 0, 65536)); - CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1 == - session->local_window_size); - CU_ASSERT(4096 == session->recv_window_size); - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type); - CU_ASSERT(0 == item->frame.window_update.hd.stream_id); - CU_ASSERT(1 == item->frame.window_update.window_size_increment); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - /* Go decrement part */ - CU_ASSERT(0 == nghttp2_session_set_local_window_size( - session, NGHTTP2_FLAG_NONE, 0, 32768)); - CU_ASSERT(32768 == session->local_window_size); - CU_ASSERT(-28672 == session->recv_window_size); - CU_ASSERT(32768 == session->recv_reduction); - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(item == NULL); - - /* Increase local window size */ - CU_ASSERT(0 == nghttp2_session_set_local_window_size( - session, NGHTTP2_FLAG_NONE, 0, 49152)); - CU_ASSERT(49152 == session->local_window_size); - CU_ASSERT(-12288 == session->recv_window_size); - CU_ASSERT(16384 == session->recv_reduction); - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - - /* Increase local window again */ - CU_ASSERT(0 == nghttp2_session_set_local_window_size( - session, NGHTTP2_FLAG_NONE, 0, 65537)); - CU_ASSERT(65537 == session->local_window_size); - CU_ASSERT(4096 == session->recv_window_size); - CU_ASSERT(0 == session->recv_reduction); - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(1 == item->frame.window_update.window_size_increment); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_session_del(session); -} - -void test_nghttp2_session_cancel_from_before_frame_send(void) { - int rv; - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - my_user_data ud; - nghttp2_settings_entry iv; - nghttp2_data_provider data_prd; - int32_t stream_id; - nghttp2_stream *stream; - - memset(&callbacks, 0, sizeof(callbacks)); - - callbacks.before_frame_send_callback = cancel_before_frame_send_callback; - callbacks.on_frame_not_send_callback = on_frame_not_send_callback; - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, &ud); - - iv.settings_id = 0; - iv.value = 1000000009; - - rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1); - - CU_ASSERT(0 == rv); - - ud.frame_send_cb_called = 0; - ud.before_frame_send_cb_called = 0; - ud.frame_not_send_cb_called = 0; - - rv = nghttp2_session_send(session); - - CU_ASSERT(0 == rv); - CU_ASSERT(0 == ud.frame_send_cb_called); - CU_ASSERT(1 == ud.before_frame_send_cb_called); - CU_ASSERT(1 == ud.frame_not_send_cb_called); - - data_prd.source.ptr = NULL; - data_prd.read_callback = temporal_failure_data_source_read_callback; - - stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), - &data_prd, NULL); - - CU_ASSERT(stream_id > 0); - - ud.frame_send_cb_called = 0; - ud.before_frame_send_cb_called = 0; - ud.frame_not_send_cb_called = 0; - - rv = nghttp2_session_send(session); - - CU_ASSERT(0 == rv); - CU_ASSERT(0 == ud.frame_send_cb_called); - CU_ASSERT(1 == ud.before_frame_send_cb_called); - CU_ASSERT(1 == ud.frame_not_send_cb_called); - - stream = nghttp2_session_get_stream_raw(session, stream_id); - - CU_ASSERT(NULL == stream); - - nghttp2_session_del(session); - - nghttp2_session_server_new(&session, &callbacks, &ud); - - open_recv_stream(session, 1); - - stream_id = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv, - ARRLEN(reqnv), NULL); - - CU_ASSERT(stream_id > 0); - - ud.frame_send_cb_called = 0; - ud.before_frame_send_cb_called = 0; - ud.frame_not_send_cb_called = 0; - - rv = nghttp2_session_send(session); - - CU_ASSERT(0 == rv); - CU_ASSERT(0 == ud.frame_send_cb_called); - CU_ASSERT(1 == ud.before_frame_send_cb_called); - CU_ASSERT(1 == ud.frame_not_send_cb_called); - - stream = nghttp2_session_get_stream_raw(session, stream_id); - - CU_ASSERT(NULL == stream); - - nghttp2_session_del(session); -} - -static void check_nghttp2_http_recv_headers_fail( - nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id, - int stream_state, const nghttp2_nv *nva, size_t nvlen) { - nghttp2_mem *mem; - ssize_t rv; - nghttp2_outbound_item *item; - nghttp2_bufs bufs; - my_user_data *ud; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - ud = session->user_data; - - if (stream_state != -1) { - if (nghttp2_session_is_my_stream_id(session, stream_id)) { - open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state); - } else { - open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state); - } - } - - rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva, - nvlen, mem); - CU_ASSERT(0 == rv); - - ud->invalid_frame_recv_cb_called = 0; - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - item = nghttp2_session_get_next_ob_item(session); - - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(1 == ud->invalid_frame_recv_cb_called); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_bufs_free(&bufs); -} - -static void check_nghttp2_http_recv_headers_ok( - nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id, - int stream_state, const nghttp2_nv *nva, size_t nvlen) { - nghttp2_mem *mem; - ssize_t rv; - nghttp2_bufs bufs; - my_user_data *ud; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - ud = session->user_data; - - if (stream_state != -1) { - if (nghttp2_session_is_my_stream_id(session, stream_id)) { - open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state); - } else { - open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state); - } - } - - rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva, - nvlen, mem); - CU_ASSERT(0 == rv); - - ud->frame_recv_cb_called = 0; - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - CU_ASSERT(1 == ud->frame_recv_cb_called); - - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_http_mandatory_headers(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - my_user_data ud; - /* test case for response */ - const nghttp2_nv nostatus_resnv[] = {MAKE_NV("server", "foo")}; - const nghttp2_nv dupstatus_resnv[] = {MAKE_NV(":status", "200"), - MAKE_NV(":status", "200")}; - const nghttp2_nv badpseudo_resnv[] = {MAKE_NV(":status", "200"), - MAKE_NV(":scheme", "https")}; - const nghttp2_nv latepseudo_resnv[] = {MAKE_NV("server", "foo"), - MAKE_NV(":status", "200")}; - const nghttp2_nv badstatus_resnv[] = {MAKE_NV(":status", "2000")}; - const nghttp2_nv badcl_resnv[] = {MAKE_NV(":status", "200"), - MAKE_NV("content-length", "-1")}; - const nghttp2_nv dupcl_resnv[] = {MAKE_NV(":status", "200"), - MAKE_NV("content-length", "0"), - MAKE_NV("content-length", "0")}; - const nghttp2_nv badhd_resnv[] = {MAKE_NV(":status", "200"), - MAKE_NV("connection", "close")}; - - /* test case for request */ - const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"), - MAKE_NV(":method", "GET"), - MAKE_NV(":authority", "localhost")}; - const nghttp2_nv earlyconnect_reqnv[] = { - MAKE_NV(":method", "CONNECT"), MAKE_NV(":scheme", "https"), - MAKE_NV(":path", "/"), MAKE_NV(":authority", "localhost")}; - const nghttp2_nv lateconnect_reqnv[] = { - MAKE_NV(":scheme", "https"), MAKE_NV(":path", "/"), - MAKE_NV(":method", "CONNECT"), MAKE_NV(":authority", "localhost")}; - const nghttp2_nv duppath_reqnv[] = { - MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"), - MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"), - MAKE_NV(":path", "/")}; - const nghttp2_nv badcl_reqnv[] = { - MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"), - MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"), - MAKE_NV("content-length", "-1")}; - const nghttp2_nv dupcl_reqnv[] = { - MAKE_NV(":scheme", "https"), MAKE_NV(":method", "POST"), - MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"), - MAKE_NV("content-length", "0"), MAKE_NV("content-length", "0")}; - const nghttp2_nv badhd_reqnv[] = { - MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"), - MAKE_NV(":authority", "localhost"), MAKE_NV(":path", "/"), - MAKE_NV("connection", "close")}; - const nghttp2_nv badauthority_reqnv[] = { - MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"), - MAKE_NV(":authority", "\x0d\x0alocalhost"), MAKE_NV(":path", "/")}; - const nghttp2_nv badhdbtw_reqnv[] = { - MAKE_NV(":scheme", "https"), MAKE_NV(":method", "GET"), - MAKE_NV("foo", "\x0d\x0a"), MAKE_NV(":authority", "localhost"), - MAKE_NV(":path", "/")}; - const nghttp2_nv asteriskget1_reqnv[] = { - MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"), - MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "GET")}; - const nghttp2_nv asteriskget2_reqnv[] = { - MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"), - MAKE_NV(":method", "GET"), MAKE_NV(":path", "*")}; - const nghttp2_nv asteriskoptions1_reqnv[] = { - MAKE_NV(":path", "*"), MAKE_NV(":scheme", "https"), - MAKE_NV(":authority", "localhost"), MAKE_NV(":method", "OPTIONS")}; - const nghttp2_nv asteriskoptions2_reqnv[] = { - MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "localhost"), - MAKE_NV(":method", "OPTIONS"), MAKE_NV(":path", "*")}; - - mem = nghttp2_mem_default(); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - callbacks.on_frame_recv_callback = on_frame_recv_callback; - callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; - - nghttp2_session_client_new(&session, &callbacks, &ud); - - nghttp2_hd_deflate_init(&deflater, mem); - - /* response header lacks :status */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 1, - NGHTTP2_STREAM_OPENING, nostatus_resnv, - ARRLEN(nostatus_resnv)); - - /* response header has 2 :status */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 3, - NGHTTP2_STREAM_OPENING, dupstatus_resnv, - ARRLEN(dupstatus_resnv)); - - /* response header has bad pseudo header :scheme */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 5, - NGHTTP2_STREAM_OPENING, badpseudo_resnv, - ARRLEN(badpseudo_resnv)); - - /* response header has :status after regular header field */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 7, - NGHTTP2_STREAM_OPENING, latepseudo_resnv, - ARRLEN(latepseudo_resnv)); - - /* response header has bad status code */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 9, - NGHTTP2_STREAM_OPENING, badstatus_resnv, - ARRLEN(badstatus_resnv)); - - /* response header has bad content-length */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 11, - NGHTTP2_STREAM_OPENING, badcl_resnv, - ARRLEN(badcl_resnv)); - - /* response header has multiple content-length */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 13, - NGHTTP2_STREAM_OPENING, dupcl_resnv, - ARRLEN(dupcl_resnv)); - - /* response header has disallowed header field */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 15, - NGHTTP2_STREAM_OPENING, badhd_resnv, - ARRLEN(badhd_resnv)); - - nghttp2_hd_deflate_free(&deflater); - - nghttp2_session_del(session); - - /* check server side */ - nghttp2_session_server_new(&session, &callbacks, &ud); - - nghttp2_hd_deflate_init(&deflater, mem); - - /* request header has no :path */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 1, -1, nopath_reqnv, - ARRLEN(nopath_reqnv)); - - /* request header has CONNECT method, but followed by :path */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 3, -1, - earlyconnect_reqnv, - ARRLEN(earlyconnect_reqnv)); - - /* request header has CONNECT method following :path */ - check_nghttp2_http_recv_headers_fail( - session, &deflater, 5, -1, lateconnect_reqnv, ARRLEN(lateconnect_reqnv)); - - /* request header has multiple :path */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 7, -1, duppath_reqnv, - ARRLEN(duppath_reqnv)); - - /* request header has bad content-length */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 9, -1, badcl_reqnv, - ARRLEN(badcl_reqnv)); - - /* request header has multiple content-length */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 11, -1, dupcl_reqnv, - ARRLEN(dupcl_reqnv)); - - /* request header has disallowed header field */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 13, -1, badhd_reqnv, - ARRLEN(badhd_reqnv)); - - /* request header has :authority header field containing illegal - characters */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 15, -1, - badauthority_reqnv, - ARRLEN(badauthority_reqnv)); - - /* request header has regular header field containing illegal - character before all mandatory header fields are seen. */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 17, -1, - badhdbtw_reqnv, ARRLEN(badhdbtw_reqnv)); - - /* request header has "*" in :path header field while method is GET. - :path is received before :method */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 19, -1, - asteriskget1_reqnv, - ARRLEN(asteriskget1_reqnv)); - - /* request header has "*" in :path header field while method is GET. - :method is received before :path */ - check_nghttp2_http_recv_headers_fail(session, &deflater, 21, -1, - asteriskget2_reqnv, - ARRLEN(asteriskget2_reqnv)); - - /* OPTIONS method can include "*" in :path header field. :path is - received before :method. */ - check_nghttp2_http_recv_headers_ok(session, &deflater, 23, -1, - asteriskoptions1_reqnv, - ARRLEN(asteriskoptions1_reqnv)); - - /* OPTIONS method can include "*" in :path header field. :method is - received before :path. */ - check_nghttp2_http_recv_headers_ok(session, &deflater, 25, -1, - asteriskoptions2_reqnv, - ARRLEN(asteriskoptions2_reqnv)); - - nghttp2_hd_deflate_free(&deflater); - - nghttp2_session_del(session); -} - -void test_nghttp2_http_content_length(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - nghttp2_bufs bufs; - ssize_t rv; - nghttp2_stream *stream; - const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"), - MAKE_NV("te", "trailers"), - MAKE_NV("content-length", "9000000000")}; - const nghttp2_nv cl_reqnv[] = { - MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"), - MAKE_NV(":scheme", "https"), MAKE_NV("te", "trailers"), - MAKE_NV("host", "localhost"), MAKE_NV("content-length", "9000000000")}; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING); - - rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv, - ARRLEN(cl_resnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - CU_ASSERT(9000000000LL == stream->content_length); - CU_ASSERT(200 == stream->status_code); - - nghttp2_hd_deflate_free(&deflater); - - nghttp2_session_del(session); - - nghttp2_bufs_reset(&bufs); - - /* check server side */ - nghttp2_session_server_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_reqnv, - ARRLEN(cl_reqnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - stream = nghttp2_session_get_stream(session, 1); - - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - CU_ASSERT(9000000000LL == stream->content_length); - - nghttp2_hd_deflate_free(&deflater); - - nghttp2_session_del(session); - - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_http_content_length_mismatch(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - nghttp2_bufs bufs; - ssize_t rv; - const nghttp2_nv cl_reqnv[] = { - MAKE_NV(":path", "/"), MAKE_NV(":method", "PUT"), - MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"), - MAKE_NV("content-length", "20")}; - nghttp2_outbound_item *item; - nghttp2_frame_hd hd; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_server_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - /* header says content-length: 20, but HEADERS has END_STREAM flag set */ - rv = pack_headers(&bufs, &deflater, 1, - NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, - cl_reqnv, ARRLEN(cl_reqnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_bufs_reset(&bufs); - - /* header says content-length: 20, but DATA has 0 byte */ - rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, cl_reqnv, - ARRLEN(cl_reqnv), mem); - CU_ASSERT(0 == rv); - - nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3); - nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd); - bufs.head->buf.last += NGHTTP2_FRAME_HDLEN; - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_bufs_reset(&bufs); - - /* header says content-length: 20, but DATA has 21 bytes */ - rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, cl_reqnv, - ARRLEN(cl_reqnv), mem); - CU_ASSERT(0 == rv); - - nghttp2_frame_hd_init(&hd, 21, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 5); - nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd); - bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 21; - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_bufs_reset(&bufs); - - nghttp2_hd_deflate_free(&deflater); - - nghttp2_session_del(session); - - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_http_non_final_response(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - nghttp2_bufs bufs; - ssize_t rv; - const nghttp2_nv nonfinal_resnv[] = { - MAKE_NV(":status", "100"), - }; - nghttp2_outbound_item *item; - nghttp2_frame_hd hd; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - /* non-final HEADERS with END_STREAM is illegal */ - open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING); - - rv = pack_headers(&bufs, &deflater, 1, - NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, - nonfinal_resnv, ARRLEN(nonfinal_resnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_bufs_reset(&bufs); - - /* non-final HEADERS followed by non-empty DATA is illegal */ - open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING); - - rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, - nonfinal_resnv, ARRLEN(nonfinal_resnv), mem); - CU_ASSERT(0 == rv); - - nghttp2_frame_hd_init(&hd, 10, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 3); - nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd); - bufs.head->buf.last += NGHTTP2_FRAME_HDLEN + 10; - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - item = nghttp2_session_get_next_ob_item(session); - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_bufs_reset(&bufs); - - /* non-final HEADERS followed by empty DATA (without END_STREAM) is - ok */ - open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING); - - rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, - nonfinal_resnv, ARRLEN(nonfinal_resnv), mem); - CU_ASSERT(0 == rv); - - nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 5); - nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd); - bufs.head->buf.last += NGHTTP2_FRAME_HDLEN; - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - - nghttp2_bufs_reset(&bufs); - - /* non-final HEADERS followed by empty DATA (with END_STREAM) is - illegal */ - open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING); - - rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS, - nonfinal_resnv, ARRLEN(nonfinal_resnv), mem); - CU_ASSERT(0 == rv); - - nghttp2_frame_hd_init(&hd, 0, NGHTTP2_DATA, NGHTTP2_FLAG_END_STREAM, 7); - nghttp2_frame_pack_frame_hd(bufs.head->buf.last, &hd); - bufs.head->buf.last += NGHTTP2_FRAME_HDLEN; - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - item = nghttp2_session_get_next_ob_item(session); - - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_bufs_reset(&bufs); - - /* non-final HEADERS followed by final HEADERS is OK */ - open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING); - - rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, - nonfinal_resnv, ARRLEN(nonfinal_resnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - nghttp2_bufs_reset(&bufs); - - rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, resnv, - ARRLEN(resnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - - nghttp2_bufs_reset(&bufs); - - nghttp2_hd_deflate_free(&deflater); - - nghttp2_session_del(session); - - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_http_trailer_headers(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - nghttp2_bufs bufs; - ssize_t rv; - const nghttp2_nv trailer_reqnv[] = { - MAKE_NV("foo", "bar"), - }; - nghttp2_outbound_item *item; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_server_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - /* good trailer header */ - rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, reqnv, - ARRLEN(reqnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - nghttp2_bufs_reset(&bufs); - - rv = pack_headers(&bufs, &deflater, 1, - NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, - trailer_reqnv, ARRLEN(trailer_reqnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - - nghttp2_bufs_reset(&bufs); - - /* trailer header without END_STREAM is illegal */ - rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, reqnv, - ARRLEN(reqnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - nghttp2_bufs_reset(&bufs); - - rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, - trailer_reqnv, ARRLEN(trailer_reqnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - item = nghttp2_session_get_next_ob_item(session); - - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_bufs_reset(&bufs); - - /* trailer header including pseudo header field is illegal */ - rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv, - ARRLEN(reqnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - nghttp2_bufs_reset(&bufs); - - rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, reqnv, - ARRLEN(reqnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - item = nghttp2_session_get_next_ob_item(session); - - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - nghttp2_bufs_reset(&bufs); - - nghttp2_hd_deflate_free(&deflater); - - nghttp2_session_del(session); - - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_http_ignore_regular_header(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - nghttp2_bufs bufs; - ssize_t rv; - my_user_data ud; - const nghttp2_nv bad_reqnv[] = { - MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"), - MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), - MAKE_NV("foo", "\x0zzz"), MAKE_NV("bar", "buzz"), - }; - const nghttp2_nv bad_ansnv[] = { - MAKE_NV(":authority", "localhost"), MAKE_NV(":scheme", "https"), - MAKE_NV(":path", "/"), MAKE_NV(":method", "GET"), MAKE_NV("bar", "buzz")}; - size_t proclen; - size_t i; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - callbacks.on_header_callback = pause_on_header_callback; - - nghttp2_session_server_new(&session, &callbacks, &ud); - nghttp2_hd_deflate_init(&deflater, mem); - - rv = pack_headers(&bufs, &deflater, 1, - NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, - bad_reqnv, ARRLEN(bad_reqnv), mem); - - CU_ASSERT_FATAL(0 == rv); - - proclen = 0; - - for (i = 0; i < 4; ++i) { - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen, - nghttp2_buf_len(&bufs.head->buf) - proclen); - CU_ASSERT_FATAL(rv > 0); - proclen += (size_t)rv; - CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[i], &ud.nv)); - } - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos + proclen, - nghttp2_buf_len(&bufs.head->buf) - proclen); - CU_ASSERT_FATAL(rv > 0); - /* header field "foo" must be ignored because it has illegal value. - So we have "bar" header field for 5th header. */ - CU_ASSERT(nghttp2_nv_equal(&bad_ansnv[4], &ud.nv)); - proclen += (size_t)rv; - - CU_ASSERT(nghttp2_buf_len(&bufs.head->buf) == proclen); - - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_http_ignore_content_length(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - nghttp2_bufs bufs; - ssize_t rv; - const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "304"), - MAKE_NV("content-length", "20")}; - const nghttp2_nv conn_reqnv[] = {MAKE_NV(":authority", "localhost"), - MAKE_NV(":method", "CONNECT"), - MAKE_NV("content-length", "999999")}; - nghttp2_stream *stream; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - /* If status 304, content-length must be ignored */ - open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING); - - rv = pack_headers(&bufs, &deflater, 1, - NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, - cl_resnv, ARRLEN(cl_resnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - - nghttp2_bufs_reset(&bufs); - - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); - - /* If request method is CONNECT, content-length must be ignored */ - nghttp2_session_server_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_reqnv, - ARRLEN(conn_reqnv), mem); - - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - - stream = nghttp2_session_get_stream(session, 1); - - CU_ASSERT(-1 == stream->content_length); - CU_ASSERT((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) > 0); - - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_http_record_request_method(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - const nghttp2_nv conn_reqnv[] = {MAKE_NV(":method", "CONNECT"), - MAKE_NV(":authority", "localhost")}; - const nghttp2_nv conn_resnv[] = {MAKE_NV(":status", "200"), - MAKE_NV("content-length", "9999")}; - nghttp2_stream *stream; - ssize_t rv; - nghttp2_bufs bufs; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - CU_ASSERT(1 == nghttp2_submit_request(session, NULL, conn_reqnv, - ARRLEN(conn_reqnv), NULL, NULL)); - - CU_ASSERT(0 == nghttp2_session_send(session)); - - stream = nghttp2_session_get_stream(session, 1); - - CU_ASSERT(NGHTTP2_HTTP_FLAG_METH_CONNECT == stream->http_flags); - - rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, conn_resnv, - ARRLEN(conn_resnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - CU_ASSERT((NGHTTP2_HTTP_FLAG_METH_CONNECT & stream->http_flags) > 0); - CU_ASSERT(-1 == stream->content_length); - - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_http_push_promise(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - nghttp2_bufs bufs; - ssize_t rv; - nghttp2_stream *stream; - const nghttp2_nv bad_reqnv[] = {MAKE_NV(":method", "GET")}; - nghttp2_outbound_item *item; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - /* good PUSH_PROMISE case */ - nghttp2_session_client_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING); - - rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, - reqnv, ARRLEN(reqnv), mem); - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - - stream = nghttp2_session_get_stream(session, 2); - CU_ASSERT(NULL != stream); - - nghttp2_bufs_reset(&bufs); - - rv = pack_headers(&bufs, &deflater, 2, NGHTTP2_FLAG_END_HEADERS, resnv, - ARRLEN(resnv), mem); - - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); - - CU_ASSERT(200 == stream->status_code); - - nghttp2_bufs_reset(&bufs); - - /* PUSH_PROMISE lacks mandatory header */ - rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 4, - bad_reqnv, ARRLEN(bad_reqnv), mem); - - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - item = nghttp2_session_get_next_ob_item(session); - - CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type); - CU_ASSERT(4 == item->frame.hd.stream_id); - - nghttp2_bufs_reset(&bufs); - - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); - nghttp2_bufs_free(&bufs); -} - -void test_nghttp2_http_head_method_upgrade_workaround(void) { - nghttp2_session *session; - nghttp2_session_callbacks callbacks; - const nghttp2_nv cl_resnv[] = {MAKE_NV(":status", "200"), - MAKE_NV("content-length", "1000000007")}; - nghttp2_bufs bufs; - nghttp2_hd_deflater deflater; - nghttp2_mem *mem; - ssize_t rv; - nghttp2_stream *stream; - - mem = nghttp2_mem_default(); - frame_pack_bufs_init(&bufs); - - memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); - callbacks.send_callback = null_send_callback; - - nghttp2_session_client_new(&session, &callbacks, NULL); - - nghttp2_hd_deflate_init(&deflater, mem); - - nghttp2_session_upgrade(session, NULL, 0, NULL); - - rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv, - ARRLEN(cl_resnv), mem); - - CU_ASSERT(0 == rv); - - rv = nghttp2_session_mem_recv(session, bufs.head->buf.pos, - nghttp2_buf_len(&bufs.head->buf)); - - CU_ASSERT((ssize_t)nghttp2_buf_len(&bufs.head->buf) == rv); - - stream = nghttp2_session_get_stream(session, 1); - - CU_ASSERT(-1 == stream->content_length); - - nghttp2_hd_deflate_free(&deflater); - nghttp2_session_del(session); - nghttp2_bufs_free(&bufs); -} diff -Nru nghttp2-1.13.0/tests/nghttp2_session_test.h nghttp2-0.6.7/tests/nghttp2_session_test.h --- nghttp2-1.13.0/tests/nghttp2_session_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_session_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,27 +25,19 @@ #ifndef NGHTTP2_SESSION_TEST_H #define NGHTTP2_SESSION_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - void test_nghttp2_session_recv(void); void test_nghttp2_session_recv_invalid_stream_id(void); void test_nghttp2_session_recv_invalid_frame(void); void test_nghttp2_session_recv_eof(void); void test_nghttp2_session_recv_data(void); -void test_nghttp2_session_recv_data_no_auto_flow_control(void); void test_nghttp2_session_recv_continuation(void); void test_nghttp2_session_recv_headers_with_priority(void); -void test_nghttp2_session_recv_headers_early_response(void); -void test_nghttp2_session_server_recv_push_response(void); void test_nghttp2_session_recv_premature_headers(void); +void test_nghttp2_session_recv_altsvc(void); void test_nghttp2_session_recv_unknown_frame(void); void test_nghttp2_session_recv_unexpected_continuation(void); void test_nghttp2_session_recv_settings_header_table_size(void); void test_nghttp2_session_recv_too_large_frame_length(void); -void test_nghttp2_session_recv_extension(void); -void test_nghttp2_session_recv_altsvc(void); void test_nghttp2_session_continue(void); void test_nghttp2_session_add_frame(void); void test_nghttp2_session_on_request_headers_received(void); @@ -60,8 +52,6 @@ void test_nghttp2_session_on_goaway_received(void); void test_nghttp2_session_on_window_update_received(void); void test_nghttp2_session_on_data_received(void); -void test_nghttp2_session_on_data_received_fail_fast(void); -void test_nghttp2_session_on_altsvc_received(void); void test_nghttp2_session_send_headers_start_stream(void); void test_nghttp2_session_send_headers_reply(void); void test_nghttp2_session_send_headers_frame_size_error(void); @@ -69,9 +59,9 @@ void test_nghttp2_session_send_rst_stream(void); void test_nghttp2_session_send_push_promise(void); void test_nghttp2_session_is_my_stream_id(void); -void test_nghttp2_session_upgrade2(void); +void test_nghttp2_session_upgrade(void); void test_nghttp2_session_reprioritize_stream(void); -void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void); +void test_nghttp2_session_reprioritize_stream_with_closed_stream_limit(void); void test_nghttp2_submit_data(void); void test_nghttp2_submit_data_read_length_too_large(void); void test_nghttp2_submit_data_read_length_smallest(void); @@ -80,31 +70,26 @@ void test_nghttp2_submit_request_without_data(void); void test_nghttp2_submit_response_with_data(void); void test_nghttp2_submit_response_without_data(void); -void test_nghttp2_submit_response_push_response(void); -void test_nghttp2_submit_trailer(void); void test_nghttp2_submit_headers_start_stream(void); void test_nghttp2_submit_headers_reply(void); void test_nghttp2_submit_headers_push_reply(void); void test_nghttp2_submit_headers(void); void test_nghttp2_submit_headers_continuation(void); -void test_nghttp2_submit_headers_continuation_extra_large(void); void test_nghttp2_submit_priority(void); void test_nghttp2_submit_settings(void); void test_nghttp2_submit_settings_update_local_window_size(void); -void test_nghttp2_submit_settings_multiple_times(void); void test_nghttp2_submit_push_promise(void); void test_nghttp2_submit_window_update(void); void test_nghttp2_submit_window_update_local_window_size(void); -void test_nghttp2_submit_shutdown_notice(void); -void test_nghttp2_submit_invalid_nv(void); -void test_nghttp2_submit_extension(void); void test_nghttp2_submit_altsvc(void); +void test_nghttp2_submit_invalid_nv(void); void test_nghttp2_session_open_stream(void); -void test_nghttp2_session_open_stream_with_idle_stream_dep(void); +void test_nghttp2_session_open_stream_with_closed_stream_limit(void); void test_nghttp2_session_get_next_ob_item(void); void test_nghttp2_session_pop_next_ob_item(void); void test_nghttp2_session_reply_fail(void); void test_nghttp2_session_max_concurrent_streams(void); +void test_nghttp2_session_stream_close_on_headers_push(void); void test_nghttp2_session_stop_data_with_rst_stream(void); void test_nghttp2_session_defer_data(void); void test_nghttp2_session_flow_control(void); @@ -125,42 +110,15 @@ void test_nghttp2_session_stream_dep_add_subtree(void); void test_nghttp2_session_stream_dep_remove_subtree(void); void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void); -void test_nghttp2_session_stream_attach_item(void); -void test_nghttp2_session_stream_attach_item_subtree(void); -void test_nghttp2_session_stream_get_state(void); -void test_nghttp2_session_stream_get_something(void); -void test_nghttp2_session_find_stream(void); +void test_nghttp2_session_stream_attach_data(void); +void test_nghttp2_session_stream_attach_data_subtree(void); void test_nghttp2_session_keep_closed_stream(void); -void test_nghttp2_session_keep_idle_stream(void); -void test_nghttp2_session_detach_idle_stream(void); +void test_nghttp2_session_detach_closed_stream(void); void test_nghttp2_session_large_dep_tree(void); void test_nghttp2_session_graceful_shutdown(void); void test_nghttp2_session_on_header_temporal_failure(void); -void test_nghttp2_session_recv_client_magic(void); +void test_nghttp2_session_recv_client_preface(void); void test_nghttp2_session_delete_data_item(void); void test_nghttp2_session_open_idle_stream(void); -void test_nghttp2_session_cancel_reserved_remote(void); -void test_nghttp2_session_reset_pending_headers(void); -void test_nghttp2_session_send_data_callback(void); -void test_nghttp2_session_on_begin_headers_temporal_failure(void); -void test_nghttp2_session_defer_then_close(void); -void test_nghttp2_session_detach_item_from_closed_stream(void); -void test_nghttp2_session_flooding(void); -void test_nghttp2_session_change_stream_priority(void); -void test_nghttp2_session_create_idle_stream(void); -void test_nghttp2_session_repeated_priority_change(void); -void test_nghttp2_session_repeated_priority_submission(void); -void test_nghttp2_session_set_local_window_size(void); -void test_nghttp2_session_cancel_from_before_frame_send(void); -void test_nghttp2_http_mandatory_headers(void); -void test_nghttp2_http_content_length(void); -void test_nghttp2_http_content_length_mismatch(void); -void test_nghttp2_http_non_final_response(void); -void test_nghttp2_http_trailer_headers(void); -void test_nghttp2_http_ignore_regular_header(void); -void test_nghttp2_http_ignore_content_length(void); -void test_nghttp2_http_record_request_method(void); -void test_nghttp2_http_push_promise(void); -void test_nghttp2_http_head_method_upgrade_workaround(void); #endif /* NGHTTP2_SESSION_TEST_H */ diff -Nru nghttp2-1.13.0/tests/nghttp2_stream_test.h nghttp2-0.6.7/tests/nghttp2_stream_test.h --- nghttp2-1.13.0/tests/nghttp2_stream_test.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_stream_test.h 2014-11-30 14:15:07.000000000 +0000 @@ -25,8 +25,4 @@ #ifndef NGHTTP2_STREAM_TEST_H #define NGHTTP2_STREAM_TEST_H -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - #endif /* NGHTTP2_STREAM_TEST_H */ diff -Nru nghttp2-1.13.0/tests/nghttp2_test_helper.c nghttp2-0.6.7/tests/nghttp2_test_helper.c --- nghttp2-1.13.0/tests/nghttp2_test_helper.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_test_helper.c 2014-11-30 14:15:07.000000000 +0000 @@ -45,9 +45,8 @@ const uint8_t *payload = in + NGHTTP2_FRAME_HDLEN; size_t payloadlen = len - NGHTTP2_FRAME_HDLEN; size_t payloadoff; - nghttp2_mem *mem; - - mem = nghttp2_mem_default(); + uint8_t *gift_payload; + size_t gift_payloadlen; nghttp2_frame_unpack_frame_hd(&frame->hd, in); switch (frame->hd.type) { @@ -66,7 +65,7 @@ break; case NGHTTP2_SETTINGS: rv = nghttp2_frame_unpack_settings_payload2( - &frame->settings.iv, &frame->settings.niv, payload, payloadlen, mem); + &frame->settings.iv, &frame->settings.niv, payload, payloadlen); break; case NGHTTP2_PUSH_PROMISE: rv = nghttp2_frame_unpack_push_promise_payload(&frame->push_promise, @@ -76,16 +75,23 @@ nghttp2_frame_unpack_ping_payload(&frame->ping, payload, payloadlen); break; case NGHTTP2_GOAWAY: - nghttp2_frame_unpack_goaway_payload2(&frame->goaway, payload, payloadlen, - mem); + nghttp2_frame_unpack_goaway_payload2(&frame->goaway, payload, payloadlen); break; case NGHTTP2_WINDOW_UPDATE: nghttp2_frame_unpack_window_update_payload(&frame->window_update, payload, payloadlen); break; - case NGHTTP2_ALTSVC: - assert(payloadlen > 2); - nghttp2_frame_unpack_altsvc_payload2(&frame->ext, payload, payloadlen, mem); + case NGHTTP2_EXT_ALTSVC: + gift_payloadlen = payloadlen - NGHTTP2_ALTSVC_FIXED_PARTLEN; + gift_payload = malloc(gift_payloadlen); + + memcpy(gift_payload, payload + NGHTTP2_ALTSVC_FIXED_PARTLEN, + gift_payloadlen); + + payloadlen -= NGHTTP2_ALTSVC_FIXED_PARTLEN; + + rv = nghttp2_frame_unpack_altsvc_payload(&frame->ext, payload, payloadlen, + gift_payload, gift_payloadlen); break; default: /* Must not be reachable */ @@ -118,26 +124,26 @@ out->nvlen = 0; } -void nva_out_reset(nva_out *out, nghttp2_mem *mem) { +void nva_out_reset(nva_out *out) { size_t i; for (i = 0; i < out->nvlen; ++i) { - mem->free(out->nva[i].name, NULL); - mem->free(out->nva[i].value, NULL); + free(out->nva[i].name); + free(out->nva[i].value); } memset(out->nva, 0, sizeof(out->nva)); out->nvlen = 0; } -void add_out(nva_out *out, nghttp2_nv *nv, nghttp2_mem *mem) { +void add_out(nva_out *out, nghttp2_nv *nv) { nghttp2_nv *onv = &out->nva[out->nvlen]; if (nv->namelen) { - onv->name = mem->malloc(nv->namelen, NULL); + onv->name = malloc(nv->namelen); memcpy(onv->name, nv->name, nv->namelen); } else { onv->name = NULL; } if (nv->valuelen) { - onv->value = mem->malloc(nv->valuelen, NULL); + onv->value = malloc(nv->valuelen); memcpy(onv->value, nv->value, nv->valuelen); } else { onv->value = NULL; @@ -151,7 +157,7 @@ } ssize_t inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out, - nghttp2_bufs *bufs, size_t offset, nghttp2_mem *mem) { + nghttp2_bufs *bufs, size_t offset) { ssize_t rv; nghttp2_nv nv; int inflate_flags; @@ -169,92 +175,49 @@ bp = *buf; if (offset) { - size_t n; + ssize_t n; - n = nghttp2_min(offset, nghttp2_buf_len(&bp)); + n = nghttp2_min((ssize_t)offset, nghttp2_buf_len(&bp)); bp.pos += n; offset -= n; } for (;;) { inflate_flags = 0; - rv = nghttp2_hd_inflate_hd2(inflater, &nv, &inflate_flags, bp.pos, - nghttp2_buf_len(&bp), final); + rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, bp.pos, + nghttp2_buf_len(&bp), final); if (rv < 0) { return rv; } bp.pos += rv; - processed += (size_t)rv; + processed += rv; if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { if (out) { - add_out(out, &nv, mem); + add_out(out, &nv); } } if (inflate_flags & NGHTTP2_HD_INFLATE_FINAL) { break; } - if ((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && - nghttp2_buf_len(&bp) == 0) { - break; - } } } nghttp2_hd_inflate_end_headers(inflater); - return (ssize_t)processed; -} - -int pack_headers(nghttp2_bufs *bufs, nghttp2_hd_deflater *deflater, - int32_t stream_id, uint8_t flags, const nghttp2_nv *nva, - size_t nvlen, nghttp2_mem *mem) { - nghttp2_nv *dnva; - nghttp2_frame frame; - int rv; - - nghttp2_nv_array_copy(&dnva, nva, nvlen, mem); - - nghttp2_frame_headers_init(&frame.headers, flags, stream_id, - NGHTTP2_HCAT_HEADERS, NULL, dnva, nvlen); - rv = nghttp2_frame_pack_headers(bufs, &frame.headers, deflater); - - nghttp2_frame_headers_free(&frame.headers, mem); - - return rv; -} - -int pack_push_promise(nghttp2_bufs *bufs, nghttp2_hd_deflater *deflater, - int32_t stream_id, uint8_t flags, - int32_t promised_stream_id, const nghttp2_nv *nva, - size_t nvlen, nghttp2_mem *mem) { - nghttp2_nv *dnva; - nghttp2_frame frame; - int rv; - - nghttp2_nv_array_copy(&dnva, nva, nvlen, mem); - - nghttp2_frame_push_promise_init(&frame.push_promise, flags, stream_id, - promised_stream_id, dnva, nvlen); - rv = nghttp2_frame_pack_push_promise(bufs, &frame.push_promise, deflater); - - nghttp2_frame_push_promise_free(&frame.push_promise, mem); - - return rv; + return processed; } int frame_pack_bufs_init(nghttp2_bufs *bufs) { /* 1 for Pad Length */ - return nghttp2_bufs_init2(bufs, 4096, 16, NGHTTP2_FRAME_HDLEN + 1, - nghttp2_mem_default()); + return nghttp2_bufs_init2(bufs, 4096, 16, NGHTTP2_FRAME_HDLEN + 1); } void bufs_large_init(nghttp2_bufs *bufs, size_t chunk_size) { /* 1 for Pad Length */ - nghttp2_bufs_init2(bufs, chunk_size, 16, NGHTTP2_FRAME_HDLEN + 1, - nghttp2_mem_default()); + nghttp2_bufs_init2(bufs, chunk_size, 16, NGHTTP2_FRAME_HDLEN + 1); } static nghttp2_stream *open_stream_with_all(nghttp2_session *session, @@ -302,129 +265,11 @@ dep_stream); } -nghttp2_outbound_item *create_data_ob_item(nghttp2_mem *mem) { +nghttp2_outbound_item *create_data_ob_item(void) { nghttp2_outbound_item *item; - item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); + item = malloc(sizeof(nghttp2_outbound_item)); memset(item, 0, sizeof(nghttp2_outbound_item)); return item; } - -nghttp2_stream *open_sent_stream(nghttp2_session *session, int32_t stream_id) { - nghttp2_priority_spec pri_spec; - - nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_DEFAULT_WEIGHT, 0); - return open_sent_stream3(session, stream_id, NGHTTP2_FLAG_NONE, &pri_spec, - NGHTTP2_STREAM_OPENED, NULL); -} - -nghttp2_stream *open_sent_stream2(nghttp2_session *session, int32_t stream_id, - nghttp2_stream_state initial_state) { - nghttp2_priority_spec pri_spec; - - nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_DEFAULT_WEIGHT, 0); - return open_sent_stream3(session, stream_id, NGHTTP2_FLAG_NONE, &pri_spec, - initial_state, NULL); -} - -nghttp2_stream *open_sent_stream3(nghttp2_session *session, int32_t stream_id, - uint8_t flags, - nghttp2_priority_spec *pri_spec_in, - nghttp2_stream_state initial_state, - void *stream_user_data) { - nghttp2_stream *stream; - - assert(nghttp2_session_is_my_stream_id(session, stream_id)); - - stream = nghttp2_session_open_stream(session, stream_id, flags, pri_spec_in, - initial_state, stream_user_data); - session->last_sent_stream_id = - nghttp2_max(session->last_sent_stream_id, stream_id); - session->next_stream_id = - nghttp2_max(session->next_stream_id, (uint32_t)stream_id + 2); - - return stream; -} - -nghttp2_stream *open_sent_stream_with_dep(nghttp2_session *session, - int32_t stream_id, - nghttp2_stream *dep_stream) { - return open_sent_stream_with_dep_weight(session, stream_id, - NGHTTP2_DEFAULT_WEIGHT, dep_stream); -} - -nghttp2_stream *open_sent_stream_with_dep_weight(nghttp2_session *session, - int32_t stream_id, - int32_t weight, - nghttp2_stream *dep_stream) { - nghttp2_stream *stream; - - assert(nghttp2_session_is_my_stream_id(session, stream_id)); - - stream = open_stream_with_all(session, stream_id, weight, 0, dep_stream); - - session->last_sent_stream_id = - nghttp2_max(session->last_sent_stream_id, stream_id); - session->next_stream_id = - nghttp2_max(session->next_stream_id, (uint32_t)stream_id + 2); - - return stream; -} - -nghttp2_stream *open_recv_stream(nghttp2_session *session, int32_t stream_id) { - nghttp2_priority_spec pri_spec; - - nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_DEFAULT_WEIGHT, 0); - return open_recv_stream3(session, stream_id, NGHTTP2_FLAG_NONE, &pri_spec, - NGHTTP2_STREAM_OPENED, NULL); -} - -nghttp2_stream *open_recv_stream2(nghttp2_session *session, int32_t stream_id, - nghttp2_stream_state initial_state) { - nghttp2_priority_spec pri_spec; - - nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_DEFAULT_WEIGHT, 0); - return open_recv_stream3(session, stream_id, NGHTTP2_FLAG_NONE, &pri_spec, - initial_state, NULL); -} - -nghttp2_stream *open_recv_stream3(nghttp2_session *session, int32_t stream_id, - uint8_t flags, - nghttp2_priority_spec *pri_spec_in, - nghttp2_stream_state initial_state, - void *stream_user_data) { - nghttp2_stream *stream; - - assert(!nghttp2_session_is_my_stream_id(session, stream_id)); - - stream = nghttp2_session_open_stream(session, stream_id, flags, pri_spec_in, - initial_state, stream_user_data); - session->last_recv_stream_id = - nghttp2_max(session->last_recv_stream_id, stream_id); - - return stream; -} - -nghttp2_stream *open_recv_stream_with_dep(nghttp2_session *session, - int32_t stream_id, - nghttp2_stream *dep_stream) { - return open_recv_stream_with_dep_weight(session, stream_id, - NGHTTP2_DEFAULT_WEIGHT, dep_stream); -} - -nghttp2_stream *open_recv_stream_with_dep_weight(nghttp2_session *session, - int32_t stream_id, - int32_t weight, - nghttp2_stream *dep_stream) { - nghttp2_stream *stream; - - assert(!nghttp2_session_is_my_stream_id(session, stream_id)); - - stream = open_stream_with_all(session, stream_id, weight, 0, dep_stream); - - session->last_recv_stream_id = - nghttp2_max(session->last_recv_stream_id, stream_id); - - return stream; -} diff -Nru nghttp2-1.13.0/tests/nghttp2_test_helper.h nghttp2-0.6.7/tests/nghttp2_test_helper.h --- nghttp2-1.13.0/tests/nghttp2_test_helper.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/tests/nghttp2_test_helper.h 2014-11-30 14:15:07.000000000 +0000 @@ -35,17 +35,17 @@ #define MAKE_NV(NAME, VALUE) \ { \ - (uint8_t *)(NAME), (uint8_t *)(VALUE), sizeof((NAME)) - 1, \ - sizeof((VALUE)) - 1, NGHTTP2_NV_FLAG_NONE \ + (uint8_t *) NAME, (uint8_t *)VALUE, strlen(NAME), strlen(VALUE), \ + NGHTTP2_NV_FLAG_NONE \ } #define ARRLEN(ARR) (sizeof(ARR) / sizeof(ARR[0])) -#define assert_nv_equal(A, B, len, mem) \ +#define assert_nv_equal(A, B, len) \ do { \ size_t alloclen = sizeof(nghttp2_nv) * len; \ - const nghttp2_nv *sa = A, *sb = B; \ - nghttp2_nv *a = mem->malloc(alloclen, NULL); \ - nghttp2_nv *b = mem->malloc(alloclen, NULL); \ + nghttp2_nv *sa = A, *sb = B; \ + nghttp2_nv *a = malloc(alloclen); \ + nghttp2_nv *b = malloc(alloclen); \ ssize_t i_; \ memcpy(a, sa, alloclen); \ memcpy(b, sb, alloclen); \ @@ -54,8 +54,8 @@ for (i_ = 0; i_ < (ssize_t)len; ++i_) { \ CU_ASSERT(nghttp2_nv_equal(&a[i_], &b[i_])); \ } \ - mem->free(b, NULL); \ - mem->free(a, NULL); \ + free(b); \ + free(a); \ } while (0); int unpack_framebuf(nghttp2_frame *frame, nghttp2_bufs *bufs); @@ -74,21 +74,12 @@ } nva_out; void nva_out_init(nva_out *out); -void nva_out_reset(nva_out *out, nghttp2_mem *mem); +void nva_out_reset(nva_out *out); -void add_out(nva_out *out, nghttp2_nv *nv, nghttp2_mem *mem); +void add_out(nva_out *out, nghttp2_nv *nv); ssize_t inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out, - nghttp2_bufs *bufs, size_t offset, nghttp2_mem *mem); - -int pack_headers(nghttp2_bufs *bufs, nghttp2_hd_deflater *deflater, - int32_t stream_id, uint8_t flags, const nghttp2_nv *nva, - size_t nvlen, nghttp2_mem *mem); - -int pack_push_promise(nghttp2_bufs *bufs, nghttp2_hd_deflater *deflater, - int32_t stream_id, uint8_t flags, - int32_t promised_stream_id, const nghttp2_nv *nva, - size_t nvlen, nghttp2_mem *mem); + nghttp2_bufs *bufs, size_t offset); int frame_pack_bufs_init(nghttp2_bufs *bufs); @@ -108,51 +99,6 @@ int32_t stream_id, nghttp2_stream *dep_stream); -nghttp2_outbound_item *create_data_ob_item(nghttp2_mem *mem); - -/* Opens stream. This stream is assumed to be sent from |session|, - and session->last_sent_stream_id and session->next_stream_id will - be adjusted accordingly. */ -nghttp2_stream *open_sent_stream(nghttp2_session *session, int32_t stream_id); - -nghttp2_stream *open_sent_stream2(nghttp2_session *session, int32_t stream_id, - nghttp2_stream_state initial_state); - -nghttp2_stream *open_sent_stream3(nghttp2_session *session, int32_t stream_id, - uint8_t flags, - nghttp2_priority_spec *pri_spec_in, - nghttp2_stream_state initial_state, - void *stream_user_data); - -nghttp2_stream *open_sent_stream_with_dep(nghttp2_session *session, - int32_t stream_id, - nghttp2_stream *dep_stream); - -nghttp2_stream *open_sent_stream_with_dep_weight(nghttp2_session *session, - int32_t stream_id, - int32_t weight, - nghttp2_stream *dep_stream); - -/* Opens stream. This stream is assumed to be received by |session|, - and session->last_recv_stream_id will be adjusted accordingly. */ -nghttp2_stream *open_recv_stream(nghttp2_session *session, int32_t stream_id); - -nghttp2_stream *open_recv_stream2(nghttp2_session *session, int32_t stream_id, - nghttp2_stream_state initial_state); - -nghttp2_stream *open_recv_stream3(nghttp2_session *session, int32_t stream_id, - uint8_t flags, - nghttp2_priority_spec *pri_spec_in, - nghttp2_stream_state initial_state, - void *stream_user_data); - -nghttp2_stream *open_recv_stream_with_dep(nghttp2_session *session, - int32_t stream_id, - nghttp2_stream *dep_stream); - -nghttp2_stream *open_recv_stream_with_dep_weight(nghttp2_session *session, - int32_t stream_id, - int32_t weight, - nghttp2_stream *dep_stream); +nghttp2_outbound_item *create_data_ob_item(void); #endif /* NGHTTP2_TEST_HELPER_H */ diff -Nru nghttp2-1.13.0/tests/testdata/Makefile.in nghttp2-0.6.7/tests/testdata/Makefile.in --- nghttp2-1.13.0/tests/testdata/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/tests/testdata/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -29,17 +29,7 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -104,6 +94,7 @@ host_triplet = @host@ target_triplet = @target@ subdir = tests/testdata +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -113,13 +104,11 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -144,12 +133,10 @@ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -168,7 +155,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -184,7 +170,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -200,10 +185,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -215,7 +196,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -253,11 +233,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -312,7 +291,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -349,6 +327,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/testdata/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu tests/testdata/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -523,8 +502,6 @@ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am -.PRECIOUS: Makefile - # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru nghttp2-1.13.0/third-party/build_config.rb nghttp2-0.6.7/third-party/build_config.rb --- nghttp2-1.13.0/third-party/build_config.rb 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/third-party/build_config.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -MRuby::Build.new do |conf| - # TODO use same compilers configured in configure script - toolchain :clang - - # C++ project needs this. Without this, mruby exception does not - # properly destory C++ object allocated on stack. - conf.enable_cxx_abi - - conf.build_dir = ENV['BUILD_DIR'] - - # include the default GEMs - conf.gembox 'default' - conf.gem :core => 'mruby-eval' -end diff -Nru nghttp2-1.13.0/third-party/CMakeLists.txt nghttp2-0.6.7/third-party/CMakeLists.txt --- nghttp2-1.13.0/third-party/CMakeLists.txt 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/third-party/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -if(ENABLE_THIRD_PARTY) - set(LIBHTTP_PARSER_SOURCES - http-parser/http_parser.c - ) - add_library(http-parser OBJECT ${LIBHTTP_PARSER_SOURCES}) - set_target_properties(http-parser PROPERTIES - POSITION_INDEPENDENT_CODE ON) - - if(HAVE_NEVERBLEED) - set(NEVERBLEED_SOURCES - neverbleed/neverbleed.c - ) - add_library(neverbleed ${NEVERBLEED_SOURCES}) - target_include_directories(neverbleed PRIVATE ${OPENSSL_INCLUDE_DIRS}) - target_include_directories(neverbleed INTERFACE - "${CMAKE_SOURCE_DIR}/third-party/neverbleed" - ) - target_link_libraries(neverbleed ${OPENSSL_LIBRARIES}) - endif() - - if(HAVE_MRUBY) - # EXTRA_DIST = build_config.rb mruby/* - - set(MRUBY_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/mruby/build") - set(MRUBY_LIBRARY - "${CMAKE_STATIC_LIBRARY_PREFIX}mruby${CMAKE_STATIC_LIBRARY_SUFFIX}" - ) - - # The mruby build needs some env vars. Alternatively, look at cmake -P - if(CMAKE_VERSION VERSION_LESS "3.1") - # XXX works only for Unixes? - set(ENV_COMMAND env) - else() - set(ENV_COMMAND ${CMAKE_COMMAND} -E env) - endif() - # Required for the Ninja generator. For older CMake, you first have to - # invoke 'ninja mruby' before building dependents. - if(CMAKE_VERSION VERSION_LESS "3.2") - set(_byproducts) - else() - set(_byproducts BYPRODUCTS "mruby/build/lib/${MRUBY_LIBRARY}") - endif() - add_custom_target(mruby - COMMAND ${ENV_COMMAND} - "MRUBY_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/build_config.rb" - "BUILD_DIR=${MRUBY_BUILD_DIR}" - "INSTALL_DIR=${MRUBY_BUILD_DIR}/install/bin" - "CC=${CMAKE_C_COMPILER}" "CXX=${CMAKE_CXX_COMPILER}" - "${CMAKE_CURRENT_SOURCE_DIR}/mruby/minirake" - -f "${CMAKE_CURRENT_SOURCE_DIR}/mruby/Rakefile" - ${_byproducts} - VERBATIM - ) - - # Make the mruby library available to others in this project without them - # having to worry about include dirs and the mruby location. - add_library(mruby-lib STATIC IMPORTED GLOBAL) - set_target_properties(mruby-lib PROPERTIES - IMPORTED_LOCATION "${MRUBY_BUILD_DIR}/lib/${MRUBY_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/mruby/include" - ) - add_dependencies(mruby-lib mruby) - - set_directory_properties(PROPERTIES - ADDITIONAL_MAKE_CLEAN_FILES mruby/build - ) - endif() -endif() diff -Nru nghttp2-1.13.0/third-party/http-parser/http_parser.c nghttp2-0.6.7/third-party/http-parser/http_parser.c --- nghttp2-1.13.0/third-party/http-parser/http_parser.c 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/third-party/http-parser/http_parser.c 2014-11-30 14:15:07.000000000 +0000 @@ -56,40 +56,19 @@ parser->http_errno = (e); \ } while(0) -#define CURRENT_STATE() p_state -#define UPDATE_STATE(V) p_state = (enum state) (V); -#define RETURN(V) \ -do { \ - parser->state = CURRENT_STATE(); \ - return (V); \ -} while (0); -#define REEXECUTE() \ - goto reexecute; \ - - -#ifdef __GNUC__ -# define LIKELY(X) __builtin_expect(!!(X), 1) -# define UNLIKELY(X) __builtin_expect(!!(X), 0) -#else -# define LIKELY(X) (X) -# define UNLIKELY(X) (X) -#endif - /* Run the notify callback FOR, returning ER if it fails */ #define CALLBACK_NOTIFY_(FOR, ER) \ do { \ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ \ - if (LIKELY(settings->on_##FOR)) { \ - parser->state = CURRENT_STATE(); \ - if (UNLIKELY(0 != settings->on_##FOR(parser))) { \ + if (settings->on_##FOR) { \ + if (0 != settings->on_##FOR(parser)) { \ SET_ERRNO(HPE_CB_##FOR); \ } \ - UPDATE_STATE(parser->state); \ \ /* We either errored above or got paused; get out */ \ - if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ + if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ return (ER); \ } \ } \ @@ -107,23 +86,20 @@ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ \ if (FOR##_mark) { \ - if (LIKELY(settings->on_##FOR)) { \ - parser->state = CURRENT_STATE(); \ - if (UNLIKELY(0 != \ - settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \ + if (settings->on_##FOR) { \ + if (0 != settings->on_##FOR(parser, FOR##_mark, (LEN))) { \ SET_ERRNO(HPE_CB_##FOR); \ } \ - UPDATE_STATE(parser->state); \ \ /* We either errored above or got paused; get out */ \ - if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ + if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \ return (ER); \ } \ } \ FOR##_mark = NULL; \ } \ } while (0) - + /* Run the data callback FOR and consume the current byte */ #define CALLBACK_DATA(FOR) \ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) @@ -140,26 +116,6 @@ } \ } while (0) -/* Don't allow the total size of the HTTP headers (including the status - * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect - * embedders against denial-of-service attacks where the attacker feeds - * us a never-ending header that the embedder keeps buffering. - * - * This check is arguably the responsibility of embedders but we're doing - * it on the embedder's behalf because most won't bother and this way we - * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger - * than any reasonable request or response so this should never affect - * day-to-day operation. - */ -#define COUNT_HEADER_SIZE(V) \ -do { \ - parser->nread += (V); \ - if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \ - SET_ERRNO(HPE_HEADER_OVERFLOW); \ - goto error; \ - } \ -} while (0) - #define PROXY_CONNECTION "proxy-connection" #define CONNECTION "connection" @@ -378,16 +334,12 @@ , h_upgrade , h_matching_transfer_encoding_chunked - , h_matching_connection_token_start , h_matching_connection_keep_alive , h_matching_connection_close - , h_matching_connection_upgrade - , h_matching_connection_token , h_transfer_encoding_chunked , h_connection_keep_alive , h_connection_close - , h_connection_upgrade }; enum http_host_state @@ -400,8 +352,6 @@ , s_http_host , s_http_host_v6 , s_http_host_v6_end - , s_http_host_v6_zone_start - , s_http_host_v6_zone , s_http_host_port_start , s_http_host_port }; @@ -421,8 +371,6 @@ (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ (c) == '$' || (c) == ',') -#define STRICT_TOKEN(c) (tokens[(unsigned char)c]) - #if HTTP_PARSER_STRICT #define TOKEN(c) (tokens[(unsigned char)c]) #define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) @@ -435,12 +383,6 @@ (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') #endif -/** - * Verify that a char is a valid visible (printable) US-ASCII - * character or %x80-FF - **/ -#define IS_HEADER_CHAR(ch) \ - (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) @@ -644,8 +586,6 @@ const char *url_mark = 0; const char *body_mark = 0; const char *status_mark = 0; - enum state p_state = (enum state) parser->state; - const unsigned int lenient = parser->lenient_http_headers; /* We're in an error state. Don't bother doing anything. */ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { @@ -653,7 +593,7 @@ } if (len == 0) { - switch (CURRENT_STATE()) { + switch (parser->state) { case s_body_identity_eof: /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if * we got paused. @@ -674,11 +614,11 @@ } - if (CURRENT_STATE() == s_header_field) + if (parser->state == s_header_field) header_field_mark = data; - if (CURRENT_STATE() == s_header_value) + if (parser->state == s_header_value) header_value_mark = data; - switch (CURRENT_STATE()) { + switch (parser->state) { case s_req_path: case s_req_schema: case s_req_schema_slash: @@ -695,24 +635,38 @@ case s_res_status: status_mark = data; break; - default: - break; } for (p=data; p != data + len; p++) { ch = *p; - if (PARSING_HEADER(CURRENT_STATE())) - COUNT_HEADER_SIZE(1); + if (PARSING_HEADER(parser->state)) { + ++parser->nread; + /* Don't allow the total size of the HTTP headers (including the status + * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect + * embedders against denial-of-service attacks where the attacker feeds + * us a never-ending header that the embedder keeps buffering. + * + * This check is arguably the responsibility of embedders but we're doing + * it on the embedder's behalf because most won't bother and this way we + * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger + * than any reasonable request or response so this should never affect + * day-to-day operation. + */ + if (parser->nread > (HTTP_MAX_HEADER_SIZE)) { + SET_ERRNO(HPE_HEADER_OVERFLOW); + goto error; + } + } -reexecute: - switch (CURRENT_STATE()) { + reexecute_byte: + switch (parser->state) { case s_dead: /* this state is used after a 'Connection: close' message * the parser will error out if it reads another message */ - if (LIKELY(ch == CR || ch == LF)) + if (ch == CR || ch == LF) break; SET_ERRNO(HPE_CLOSED_CONNECTION); @@ -726,13 +680,13 @@ parser->content_length = ULLONG_MAX; if (ch == 'H') { - UPDATE_STATE(s_res_or_resp_H); + parser->state = s_res_or_resp_H; CALLBACK_NOTIFY(message_begin); } else { parser->type = HTTP_REQUEST; - UPDATE_STATE(s_start_req); - REEXECUTE(); + parser->state = s_start_req; + goto reexecute_byte; } break; @@ -741,9 +695,9 @@ case s_res_or_resp_H: if (ch == 'T') { parser->type = HTTP_RESPONSE; - UPDATE_STATE(s_res_HT); + parser->state = s_res_HT; } else { - if (UNLIKELY(ch != 'E')) { + if (ch != 'E') { SET_ERRNO(HPE_INVALID_CONSTANT); goto error; } @@ -751,7 +705,7 @@ parser->type = HTTP_REQUEST; parser->method = HTTP_HEAD; parser->index = 2; - UPDATE_STATE(s_req_method); + parser->state = s_req_method; } break; @@ -762,7 +716,7 @@ switch (ch) { case 'H': - UPDATE_STATE(s_res_H); + parser->state = s_res_H; break; case CR: @@ -780,39 +734,39 @@ case s_res_H: STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_res_HT); + parser->state = s_res_HT; break; case s_res_HT: STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_res_HTT); + parser->state = s_res_HTT; break; case s_res_HTT: STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_res_HTTP); + parser->state = s_res_HTTP; break; case s_res_HTTP: STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_res_first_http_major); + parser->state = s_res_first_http_major; break; case s_res_first_http_major: - if (UNLIKELY(ch < '0' || ch > '9')) { + if (ch < '0' || ch > '9') { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_major = ch - '0'; - UPDATE_STATE(s_res_http_major); + parser->state = s_res_http_major; break; /* major HTTP version or dot */ case s_res_http_major: { if (ch == '.') { - UPDATE_STATE(s_res_first_http_minor); + parser->state = s_res_first_http_minor; break; } @@ -824,7 +778,7 @@ parser->http_major *= 10; parser->http_major += ch - '0'; - if (UNLIKELY(parser->http_major > 999)) { + if (parser->http_major > 999) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -834,24 +788,24 @@ /* first digit of minor HTTP version */ case s_res_first_http_minor: - if (UNLIKELY(!IS_NUM(ch))) { + if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_minor = ch - '0'; - UPDATE_STATE(s_res_http_minor); + parser->state = s_res_http_minor; break; /* minor HTTP version or end of request line */ case s_res_http_minor: { if (ch == ' ') { - UPDATE_STATE(s_res_first_status_code); + parser->state = s_res_first_status_code; break; } - if (UNLIKELY(!IS_NUM(ch))) { + if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -859,7 +813,7 @@ parser->http_minor *= 10; parser->http_minor += ch - '0'; - if (UNLIKELY(parser->http_minor > 999)) { + if (parser->http_minor > 999) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -878,7 +832,7 @@ goto error; } parser->status_code = ch - '0'; - UPDATE_STATE(s_res_status_code); + parser->state = s_res_status_code; break; } @@ -887,13 +841,13 @@ if (!IS_NUM(ch)) { switch (ch) { case ' ': - UPDATE_STATE(s_res_status_start); + parser->state = s_res_status_start; break; case CR: - UPDATE_STATE(s_res_line_almost_done); + parser->state = s_res_line_almost_done; break; case LF: - UPDATE_STATE(s_header_field_start); + parser->state = s_header_field_start; break; default: SET_ERRNO(HPE_INVALID_STATUS); @@ -905,7 +859,7 @@ parser->status_code *= 10; parser->status_code += ch - '0'; - if (UNLIKELY(parser->status_code > 999)) { + if (parser->status_code > 999) { SET_ERRNO(HPE_INVALID_STATUS); goto error; } @@ -916,30 +870,30 @@ case s_res_status_start: { if (ch == CR) { - UPDATE_STATE(s_res_line_almost_done); + parser->state = s_res_line_almost_done; break; } if (ch == LF) { - UPDATE_STATE(s_header_field_start); + parser->state = s_header_field_start; break; } MARK(status); - UPDATE_STATE(s_res_status); + parser->state = s_res_status; parser->index = 0; break; } case s_res_status: if (ch == CR) { - UPDATE_STATE(s_res_line_almost_done); + parser->state = s_res_line_almost_done; CALLBACK_DATA(status); break; } if (ch == LF) { - UPDATE_STATE(s_header_field_start); + parser->state = s_header_field_start; CALLBACK_DATA(status); break; } @@ -948,7 +902,7 @@ case s_res_line_almost_done: STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_field_start); + parser->state = s_header_field_start; break; case s_start_req: @@ -958,7 +912,7 @@ parser->flags = 0; parser->content_length = ULLONG_MAX; - if (UNLIKELY(!IS_ALPHA(ch))) { + if (!IS_ALPHA(ch)) { SET_ERRNO(HPE_INVALID_METHOD); goto error; } @@ -966,28 +920,26 @@ parser->method = (enum http_method) 0; parser->index = 1; switch (ch) { - case 'A': parser->method = HTTP_ACL; break; - case 'B': parser->method = HTTP_BIND; break; case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; case 'D': parser->method = HTTP_DELETE; break; case 'G': parser->method = HTTP_GET; break; case 'H': parser->method = HTTP_HEAD; break; - case 'L': parser->method = HTTP_LOCK; /* or LINK */ break; + case 'L': parser->method = HTTP_LOCK; break; case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break; case 'N': parser->method = HTTP_NOTIFY; break; case 'O': parser->method = HTTP_OPTIONS; break; case 'P': parser->method = HTTP_POST; /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ break; - case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break; + case 'R': parser->method = HTTP_REPORT; break; case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break; case 'T': parser->method = HTTP_TRACE; break; - case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break; + case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE */ break; default: SET_ERRNO(HPE_INVALID_METHOD); goto error; } - UPDATE_STATE(s_req_method); + parser->state = s_req_method; CALLBACK_NOTIFY(message_begin); @@ -997,50 +949,79 @@ case s_req_method: { const char *matcher; - if (UNLIKELY(ch == '\0')) { + if (ch == '\0') { SET_ERRNO(HPE_INVALID_METHOD); goto error; } matcher = method_strings[parser->method]; if (ch == ' ' && matcher[parser->index] == '\0') { - UPDATE_STATE(s_req_spaces_before_url); + parser->state = s_req_spaces_before_url; } else if (ch == matcher[parser->index]) { ; /* nada */ - } else if (IS_ALPHA(ch)) { - - switch (parser->method << 16 | parser->index << 8 | ch) { -#define XX(meth, pos, ch, new_meth) \ - case (HTTP_##meth << 16 | pos << 8 | ch): \ - parser->method = HTTP_##new_meth; break; - - XX(POST, 1, 'U', PUT) - XX(POST, 1, 'A', PATCH) - XX(CONNECT, 1, 'H', CHECKOUT) - XX(CONNECT, 2, 'P', COPY) - XX(MKCOL, 1, 'O', MOVE) - XX(MKCOL, 1, 'E', MERGE) - XX(MKCOL, 2, 'A', MKACTIVITY) - XX(MKCOL, 3, 'A', MKCALENDAR) - XX(SUBSCRIBE, 1, 'E', SEARCH) - XX(REPORT, 2, 'B', REBIND) - XX(POST, 1, 'R', PROPFIND) - XX(PROPFIND, 4, 'P', PROPPATCH) - XX(PUT, 2, 'R', PURGE) - XX(LOCK, 1, 'I', LINK) - XX(UNLOCK, 2, 'S', UNSUBSCRIBE) - XX(UNLOCK, 2, 'B', UNBIND) - XX(UNLOCK, 3, 'I', UNLINK) -#undef XX - - default: + } else if (parser->method == HTTP_CONNECT) { + if (parser->index == 1 && ch == 'H') { + parser->method = HTTP_CHECKOUT; + } else if (parser->index == 2 && ch == 'P') { + parser->method = HTTP_COPY; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->method == HTTP_MKCOL) { + if (parser->index == 1 && ch == 'O') { + parser->method = HTTP_MOVE; + } else if (parser->index == 1 && ch == 'E') { + parser->method = HTTP_MERGE; + } else if (parser->index == 1 && ch == '-') { + parser->method = HTTP_MSEARCH; + } else if (parser->index == 2 && ch == 'A') { + parser->method = HTTP_MKACTIVITY; + } else if (parser->index == 3 && ch == 'A') { + parser->method = HTTP_MKCALENDAR; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->method == HTTP_SUBSCRIBE) { + if (parser->index == 1 && ch == 'E') { + parser->method = HTTP_SEARCH; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->index == 1 && parser->method == HTTP_POST) { + if (ch == 'R') { + parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */ + } else if (ch == 'U') { + parser->method = HTTP_PUT; /* or HTTP_PURGE */ + } else if (ch == 'A') { + parser->method = HTTP_PATCH; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->index == 2) { + if (parser->method == HTTP_PUT) { + if (ch == 'R') { + parser->method = HTTP_PURGE; + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else if (parser->method == HTTP_UNLOCK) { + if (ch == 'S') { + parser->method = HTTP_UNSUBSCRIBE; + } else { SET_ERRNO(HPE_INVALID_METHOD); goto error; + } + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; } - } else if (ch == '-' && - parser->index == 1 && - parser->method == HTTP_MKCOL) { - parser->method = HTTP_MSEARCH; + } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') { + parser->method = HTTP_PROPPATCH; } else { SET_ERRNO(HPE_INVALID_METHOD); goto error; @@ -1056,11 +1037,11 @@ MARK(url); if (parser->method == HTTP_CONNECT) { - UPDATE_STATE(s_req_server_start); + parser->state = s_req_server_start; } - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { + parser->state = parse_url_char((enum state)parser->state, ch); + if (parser->state == s_dead) { SET_ERRNO(HPE_INVALID_URL); goto error; } @@ -1081,8 +1062,8 @@ SET_ERRNO(HPE_INVALID_URL); goto error; default: - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { + parser->state = parse_url_char((enum state)parser->state, ch); + if (parser->state == s_dead) { SET_ERRNO(HPE_INVALID_URL); goto error; } @@ -1101,21 +1082,21 @@ { switch (ch) { case ' ': - UPDATE_STATE(s_req_http_start); + parser->state = s_req_http_start; CALLBACK_DATA(url); break; case CR: case LF: parser->http_major = 0; parser->http_minor = 9; - UPDATE_STATE((ch == CR) ? + parser->state = (ch == CR) ? s_req_line_almost_done : - s_header_field_start); + s_header_field_start; CALLBACK_DATA(url); break; default: - UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); - if (UNLIKELY(CURRENT_STATE() == s_dead)) { + parser->state = parse_url_char((enum state)parser->state, ch); + if (parser->state == s_dead) { SET_ERRNO(HPE_INVALID_URL); goto error; } @@ -1126,7 +1107,7 @@ case s_req_http_start: switch (ch) { case 'H': - UPDATE_STATE(s_req_http_H); + parser->state = s_req_http_H; break; case ' ': break; @@ -1138,44 +1119,44 @@ case s_req_http_H: STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_req_http_HT); + parser->state = s_req_http_HT; break; case s_req_http_HT: STRICT_CHECK(ch != 'T'); - UPDATE_STATE(s_req_http_HTT); + parser->state = s_req_http_HTT; break; case s_req_http_HTT: STRICT_CHECK(ch != 'P'); - UPDATE_STATE(s_req_http_HTTP); + parser->state = s_req_http_HTTP; break; case s_req_http_HTTP: STRICT_CHECK(ch != '/'); - UPDATE_STATE(s_req_first_http_major); + parser->state = s_req_first_http_major; break; /* first digit of major HTTP version */ case s_req_first_http_major: - if (UNLIKELY(ch < '1' || ch > '9')) { + if (ch < '1' || ch > '9') { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_major = ch - '0'; - UPDATE_STATE(s_req_http_major); + parser->state = s_req_http_major; break; /* major HTTP version or dot */ case s_req_http_major: { if (ch == '.') { - UPDATE_STATE(s_req_first_http_minor); + parser->state = s_req_first_http_minor; break; } - if (UNLIKELY(!IS_NUM(ch))) { + if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1183,7 +1164,7 @@ parser->http_major *= 10; parser->http_major += ch - '0'; - if (UNLIKELY(parser->http_major > 999)) { + if (parser->http_major > 999) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1193,31 +1174,31 @@ /* first digit of minor HTTP version */ case s_req_first_http_minor: - if (UNLIKELY(!IS_NUM(ch))) { + if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } parser->http_minor = ch - '0'; - UPDATE_STATE(s_req_http_minor); + parser->state = s_req_http_minor; break; /* minor HTTP version or end of request line */ case s_req_http_minor: { if (ch == CR) { - UPDATE_STATE(s_req_line_almost_done); + parser->state = s_req_line_almost_done; break; } if (ch == LF) { - UPDATE_STATE(s_header_field_start); + parser->state = s_header_field_start; break; } /* XXX allow spaces after digit? */ - if (UNLIKELY(!IS_NUM(ch))) { + if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1225,7 +1206,7 @@ parser->http_minor *= 10; parser->http_minor += ch - '0'; - if (UNLIKELY(parser->http_minor > 999)) { + if (parser->http_minor > 999) { SET_ERRNO(HPE_INVALID_VERSION); goto error; } @@ -1236,32 +1217,32 @@ /* end of request line */ case s_req_line_almost_done: { - if (UNLIKELY(ch != LF)) { + if (ch != LF) { SET_ERRNO(HPE_LF_EXPECTED); goto error; } - UPDATE_STATE(s_header_field_start); + parser->state = s_header_field_start; break; } case s_header_field_start: { if (ch == CR) { - UPDATE_STATE(s_headers_almost_done); + parser->state = s_headers_almost_done; break; } if (ch == LF) { /* they might be just sending \n instead of \r\n so this would be * the second \n to denote the end of headers*/ - UPDATE_STATE(s_headers_almost_done); - REEXECUTE(); + parser->state = s_headers_almost_done; + goto reexecute_byte; } c = TOKEN(ch); - if (UNLIKELY(!c)) { + if (!c) { SET_ERRNO(HPE_INVALID_HEADER_TOKEN); goto error; } @@ -1269,7 +1250,7 @@ MARK(header_field); parser->index = 0; - UPDATE_STATE(s_header_field); + parser->state = s_header_field; switch (c) { case 'c': @@ -1297,14 +1278,9 @@ case s_header_field: { - const char* start = p; - for (; p != data + len; p++) { - ch = *p; - c = TOKEN(ch); - - if (!c) - break; + c = TOKEN(ch); + if (c) { switch (parser->header_state) { case h_general: break; @@ -1366,12 +1342,7 @@ || c != CONTENT_LENGTH[parser->index]) { parser->header_state = h_general; } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { - if (parser->flags & F_CONTENTLENGTH) { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } parser->header_state = h_content_length; - parser->flags |= F_CONTENTLENGTH; } break; @@ -1410,17 +1381,11 @@ assert(0 && "Unknown header_state"); break; } - } - - COUNT_HEADER_SIZE(p - start); - - if (p == data + len) { - --p; break; } if (ch == ':') { - UPDATE_STATE(s_header_value_discard_ws); + parser->state = s_header_value_discard_ws; CALLBACK_DATA(header_field); break; } @@ -1433,12 +1398,12 @@ if (ch == ' ' || ch == '\t') break; if (ch == CR) { - UPDATE_STATE(s_header_value_discard_ws_almost_done); + parser->state = s_header_value_discard_ws_almost_done; break; } if (ch == LF) { - UPDATE_STATE(s_header_value_discard_lws); + parser->state = s_header_value_discard_lws; break; } @@ -1448,7 +1413,7 @@ { MARK(header_value); - UPDATE_STATE(s_header_value); + parser->state = s_header_value; parser->index = 0; c = LOWER(ch); @@ -1469,7 +1434,7 @@ break; case h_content_length: - if (UNLIKELY(!IS_NUM(ch))) { + if (!IS_NUM(ch)) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } @@ -1484,17 +1449,11 @@ /* looking for 'Connection: close' */ } else if (c == 'c') { parser->header_state = h_matching_connection_close; - } else if (c == 'u') { - parser->header_state = h_matching_connection_upgrade; } else { - parser->header_state = h_matching_connection_token; + parser->header_state = h_general; } break; - /* Multi-value `Connection` header */ - case h_matching_connection_token_start: - break; - default: parser->header_state = h_general; break; @@ -1504,211 +1463,114 @@ case s_header_value: { - const char* start = p; - enum header_states h_state = (enum header_states) parser->header_state; - for (; p != data + len; p++) { - ch = *p; - if (ch == CR) { - UPDATE_STATE(s_header_almost_done); - parser->header_state = h_state; - CALLBACK_DATA(header_value); - break; - } - - if (ch == LF) { - UPDATE_STATE(s_header_almost_done); - COUNT_HEADER_SIZE(p - start); - parser->header_state = h_state; - CALLBACK_DATA_NOADVANCE(header_value); - REEXECUTE(); - } - - if (!lenient && !IS_HEADER_CHAR(ch)) { - SET_ERRNO(HPE_INVALID_HEADER_TOKEN); - goto error; - } - - c = LOWER(ch); - switch (h_state) { - case h_general: - { - const char* p_cr; - const char* p_lf; - size_t limit = data + len - p; - - limit = MIN(limit, HTTP_MAX_HEADER_SIZE); - - p_cr = (const char*) memchr(p, CR, limit); - p_lf = (const char*) memchr(p, LF, limit); - if (p_cr != NULL) { - if (p_lf != NULL && p_cr >= p_lf) - p = p_lf; - else - p = p_cr; - } else if (UNLIKELY(p_lf != NULL)) { - p = p_lf; - } else { - p = data + len; - } - --p; + if (ch == CR) { + parser->state = s_header_almost_done; + CALLBACK_DATA(header_value); + break; + } - break; - } + if (ch == LF) { + parser->state = s_header_almost_done; + CALLBACK_DATA_NOADVANCE(header_value); + goto reexecute_byte; + } - case h_connection: - case h_transfer_encoding: - assert(0 && "Shouldn't get here."); - break; + c = LOWER(ch); - case h_content_length: - { - uint64_t t; + switch (parser->header_state) { + case h_general: + break; - if (ch == ' ') break; + case h_connection: + case h_transfer_encoding: + assert(0 && "Shouldn't get here."); + break; - if (UNLIKELY(!IS_NUM(ch))) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - } + case h_content_length: + { + uint64_t t; - t = parser->content_length; - t *= 10; - t += ch - '0'; - - /* Overflow? Test against a conservative limit for simplicity. */ - if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) { - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); - parser->header_state = h_state; - goto error; - } + if (ch == ' ') break; - parser->content_length = t; - break; + if (!IS_NUM(ch)) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + goto error; } - /* Transfer-Encoding: chunked */ - case h_matching_transfer_encoding_chunked: - parser->index++; - if (parser->index > sizeof(CHUNKED)-1 - || c != CHUNKED[parser->index]) { - h_state = h_general; - } else if (parser->index == sizeof(CHUNKED)-2) { - h_state = h_transfer_encoding_chunked; - } - break; - - case h_matching_connection_token_start: - /* looking for 'Connection: keep-alive' */ - if (c == 'k') { - h_state = h_matching_connection_keep_alive; - /* looking for 'Connection: close' */ - } else if (c == 'c') { - h_state = h_matching_connection_close; - } else if (c == 'u') { - h_state = h_matching_connection_upgrade; - } else if (STRICT_TOKEN(c)) { - h_state = h_matching_connection_token; - } else if (c == ' ' || c == '\t') { - /* Skip lws */ - } else { - h_state = h_general; - } - break; + t = parser->content_length; + t *= 10; + t += ch - '0'; - /* looking for 'Connection: keep-alive' */ - case h_matching_connection_keep_alive: - parser->index++; - if (parser->index > sizeof(KEEP_ALIVE)-1 - || c != KEEP_ALIVE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(KEEP_ALIVE)-2) { - h_state = h_connection_keep_alive; - } - break; + /* Overflow? Test against a conservative limit for simplicity. */ + if ((ULLONG_MAX - 10) / 10 < parser->content_length) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + goto error; + } - /* looking for 'Connection: close' */ - case h_matching_connection_close: - parser->index++; - if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(CLOSE)-2) { - h_state = h_connection_close; - } - break; + parser->content_length = t; + break; + } - /* looking for 'Connection: upgrade' */ - case h_matching_connection_upgrade: - parser->index++; - if (parser->index > sizeof(UPGRADE) - 1 || - c != UPGRADE[parser->index]) { - h_state = h_matching_connection_token; - } else if (parser->index == sizeof(UPGRADE)-2) { - h_state = h_connection_upgrade; - } - break; + /* Transfer-Encoding: chunked */ + case h_matching_transfer_encoding_chunked: + parser->index++; + if (parser->index > sizeof(CHUNKED)-1 + || c != CHUNKED[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(CHUNKED)-2) { + parser->header_state = h_transfer_encoding_chunked; + } + break; - case h_matching_connection_token: - if (ch == ',') { - h_state = h_matching_connection_token_start; - parser->index = 0; - } - break; + /* looking for 'Connection: keep-alive' */ + case h_matching_connection_keep_alive: + parser->index++; + if (parser->index > sizeof(KEEP_ALIVE)-1 + || c != KEEP_ALIVE[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(KEEP_ALIVE)-2) { + parser->header_state = h_connection_keep_alive; + } + break; - case h_transfer_encoding_chunked: - if (ch != ' ') h_state = h_general; - break; + /* looking for 'Connection: close' */ + case h_matching_connection_close: + parser->index++; + if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(CLOSE)-2) { + parser->header_state = h_connection_close; + } + break; - case h_connection_keep_alive: - case h_connection_close: - case h_connection_upgrade: - if (ch == ',') { - if (h_state == h_connection_keep_alive) { - parser->flags |= F_CONNECTION_KEEP_ALIVE; - } else if (h_state == h_connection_close) { - parser->flags |= F_CONNECTION_CLOSE; - } else if (h_state == h_connection_upgrade) { - parser->flags |= F_CONNECTION_UPGRADE; - } - h_state = h_matching_connection_token_start; - parser->index = 0; - } else if (ch != ' ') { - h_state = h_matching_connection_token; - } - break; + case h_transfer_encoding_chunked: + case h_connection_keep_alive: + case h_connection_close: + if (ch != ' ') parser->header_state = h_general; + break; - default: - UPDATE_STATE(s_header_value); - h_state = h_general; - break; - } + default: + parser->state = s_header_value; + parser->header_state = h_general; + break; } - parser->header_state = h_state; - - COUNT_HEADER_SIZE(p - start); - - if (p == data + len) - --p; break; } case s_header_almost_done: { - if (UNLIKELY(ch != LF)) { - SET_ERRNO(HPE_LF_EXPECTED); - goto error; - } + STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_value_lws); + parser->state = s_header_value_lws; break; } case s_header_value_lws: { if (ch == ' ' || ch == '\t') { - UPDATE_STATE(s_header_value_start); - REEXECUTE(); + parser->state = s_header_value_start; + goto reexecute_byte; } /* finished the header */ @@ -1722,52 +1584,32 @@ case h_transfer_encoding_chunked: parser->flags |= F_CHUNKED; break; - case h_connection_upgrade: - parser->flags |= F_CONNECTION_UPGRADE; - break; default: break; } - UPDATE_STATE(s_header_field_start); - REEXECUTE(); + parser->state = s_header_field_start; + goto reexecute_byte; } case s_header_value_discard_ws_almost_done: { STRICT_CHECK(ch != LF); - UPDATE_STATE(s_header_value_discard_lws); + parser->state = s_header_value_discard_lws; break; } case s_header_value_discard_lws: { if (ch == ' ' || ch == '\t') { - UPDATE_STATE(s_header_value_discard_ws); + parser->state = s_header_value_discard_ws; break; } else { - switch (parser->header_state) { - case h_connection_keep_alive: - parser->flags |= F_CONNECTION_KEEP_ALIVE; - break; - case h_connection_close: - parser->flags |= F_CONNECTION_CLOSE; - break; - case h_connection_upgrade: - parser->flags |= F_CONNECTION_UPGRADE; - break; - case h_transfer_encoding_chunked: - parser->flags |= F_CHUNKED; - break; - default: - break; - } - /* header value was empty */ MARK(header_value); - UPDATE_STATE(s_header_field_start); + parser->state = s_header_field_start; CALLBACK_DATA_NOADVANCE(header_value); - REEXECUTE(); + goto reexecute_byte; } } @@ -1777,26 +1619,16 @@ if (parser->flags & F_TRAILING) { /* End of a chunked request */ - UPDATE_STATE(s_message_done); - CALLBACK_NOTIFY_NOADVANCE(chunk_complete); - REEXECUTE(); - } - - /* Cannot use chunked encoding and a content-length header together - per the HTTP specification. */ - if ((parser->flags & F_CHUNKED) && - (parser->flags & F_CONTENTLENGTH)) { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; + parser->state = NEW_MESSAGE(); + CALLBACK_NOTIFY(message_complete); + break; } - UPDATE_STATE(s_headers_done); + parser->state = s_headers_done; /* Set this here so that on_headers_complete() callbacks can see it */ parser->upgrade = - ((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) == - (F_UPGRADE | F_CONNECTION_UPGRADE) || - parser->method == HTTP_CONNECT); + (parser->flags & F_UPGRADE || parser->method == HTTP_CONNECT); /* Here we call the headers_complete callback. This is somewhat * different than other callbacks because if the user returns 1, we @@ -1812,65 +1644,59 @@ case 0: break; - case 2: - parser->upgrade = 1; - case 1: parser->flags |= F_SKIPBODY; break; default: SET_ERRNO(HPE_CB_headers_complete); - RETURN(p - data); /* Error */ + return p - data; /* Error */ } } if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { - RETURN(p - data); + return p - data; } - REEXECUTE(); + goto reexecute_byte; } case s_headers_done: { - int hasBody; STRICT_CHECK(ch != LF); parser->nread = 0; - hasBody = parser->flags & F_CHUNKED || - (parser->content_length > 0 && parser->content_length != ULLONG_MAX); - if (parser->upgrade && (parser->method == HTTP_CONNECT || - (parser->flags & F_SKIPBODY) || !hasBody)) { - /* Exit, the rest of the message is in a different protocol. */ - UPDATE_STATE(NEW_MESSAGE()); + /* Exit, the rest of the connect is in a different protocol. */ + if (parser->upgrade) { + parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); - RETURN((p - data) + 1); + return (p - data) + 1; } if (parser->flags & F_SKIPBODY) { - UPDATE_STATE(NEW_MESSAGE()); + parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); } else if (parser->flags & F_CHUNKED) { /* chunked encoding - ignore Content-Length header */ - UPDATE_STATE(s_chunk_size_start); + parser->state = s_chunk_size_start; } else { if (parser->content_length == 0) { /* Content-Length header given but zero: Content-Length: 0\r\n */ - UPDATE_STATE(NEW_MESSAGE()); + parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); } else if (parser->content_length != ULLONG_MAX) { /* Content-Length header given and non-zero */ - UPDATE_STATE(s_body_identity); + parser->state = s_body_identity; } else { - if (!http_message_needs_eof(parser)) { + if (parser->type == HTTP_REQUEST || + !http_message_needs_eof(parser)) { /* Assume content-length 0 - read the next */ - UPDATE_STATE(NEW_MESSAGE()); + parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); } else { /* Read body until EOF */ - UPDATE_STATE(s_body_identity_eof); + parser->state = s_body_identity_eof; } } } @@ -1896,7 +1722,7 @@ p += to_read - 1; if (parser->content_length == 0) { - UPDATE_STATE(s_message_done); + parser->state = s_message_done; /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. * @@ -1908,7 +1734,7 @@ * important for applications, but let's keep it for now. */ CALLBACK_DATA_(body, p - body_mark + 1, p - data); - REEXECUTE(); + goto reexecute_byte; } break; @@ -1922,12 +1748,8 @@ break; case s_message_done: - UPDATE_STATE(NEW_MESSAGE()); + parser->state = NEW_MESSAGE(); CALLBACK_NOTIFY(message_complete); - if (parser->upgrade) { - /* Exit, the rest of the message is in a different protocol. */ - RETURN((p - data) + 1); - } break; case s_chunk_size_start: @@ -1936,13 +1758,13 @@ assert(parser->flags & F_CHUNKED); unhex_val = unhex[(unsigned char)ch]; - if (UNLIKELY(unhex_val == -1)) { + if (unhex_val == -1) { SET_ERRNO(HPE_INVALID_CHUNK_SIZE); goto error; } parser->content_length = unhex_val; - UPDATE_STATE(s_chunk_size); + parser->state = s_chunk_size; break; } @@ -1953,7 +1775,7 @@ assert(parser->flags & F_CHUNKED); if (ch == CR) { - UPDATE_STATE(s_chunk_size_almost_done); + parser->state = s_chunk_size_almost_done; break; } @@ -1961,7 +1783,7 @@ if (unhex_val == -1) { if (ch == ';' || ch == ' ') { - UPDATE_STATE(s_chunk_parameters); + parser->state = s_chunk_parameters; break; } @@ -1974,7 +1796,7 @@ t += unhex_val; /* Overflow? Test against a conservative limit for simplicity. */ - if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) { + if ((ULLONG_MAX - 16) / 16 < parser->content_length) { SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); goto error; } @@ -1988,7 +1810,7 @@ assert(parser->flags & F_CHUNKED); /* just ignore this shit. TODO check for overflow */ if (ch == CR) { - UPDATE_STATE(s_chunk_size_almost_done); + parser->state = s_chunk_size_almost_done; break; } break; @@ -2003,11 +1825,10 @@ if (parser->content_length == 0) { parser->flags |= F_TRAILING; - UPDATE_STATE(s_header_field_start); + parser->state = s_header_field_start; } else { - UPDATE_STATE(s_chunk_data); + parser->state = s_chunk_data; } - CALLBACK_NOTIFY(chunk_header); break; } @@ -2028,7 +1849,7 @@ p += to_read - 1; if (parser->content_length == 0) { - UPDATE_STATE(s_chunk_data_almost_done); + parser->state = s_chunk_data_almost_done; } break; @@ -2038,7 +1859,7 @@ assert(parser->flags & F_CHUNKED); assert(parser->content_length == 0); STRICT_CHECK(ch != CR); - UPDATE_STATE(s_chunk_data_done); + parser->state = s_chunk_data_done; CALLBACK_DATA(body); break; @@ -2046,8 +1867,7 @@ assert(parser->flags & F_CHUNKED); STRICT_CHECK(ch != LF); parser->nread = 0; - UPDATE_STATE(s_chunk_size_start); - CALLBACK_NOTIFY(chunk_complete); + parser->state = s_chunk_size_start; break; default: @@ -2079,14 +1899,14 @@ CALLBACK_DATA_NOADVANCE(body); CALLBACK_DATA_NOADVANCE(status); - RETURN(len); + return len; error: if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { SET_ERRNO(HPE_UNKNOWN); } - RETURN(p - data); + return (p - data); } @@ -2151,21 +1971,15 @@ parser->http_errno = HPE_OK; } -void -http_parser_settings_init(http_parser_settings *settings) -{ - memset(settings, 0, sizeof(*settings)); -} - const char * http_errno_name(enum http_errno err) { - assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); + assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0]))); return http_strerror_tab[err].name; } const char * http_errno_description(enum http_errno err) { - assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); + assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0]))); return http_strerror_tab[err].description; } @@ -2218,23 +2032,6 @@ return s_http_host_v6; } - if (s == s_http_host_v6 && ch == '%') { - return s_http_host_v6_zone_start; - } - break; - - case s_http_host_v6_zone: - if (ch == ']') { - return s_http_host_v6_end; - } - - /* FALLTHROUGH */ - case s_http_host_v6_zone_start: - /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */ - if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' || - ch == '~') { - return s_http_host_v6_zone; - } break; case s_http_host_port: @@ -2258,8 +2055,6 @@ const char *p; size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; - assert(u->field_set & (1 << UF_HOST)); - u->field_data[UF_HOST].len = 0; s = found_at ? s_http_userinfo_start : s_http_host_start; @@ -2286,11 +2081,6 @@ u->field_data[UF_HOST].len++; break; - case s_http_host_v6_zone_start: - case s_http_host_v6_zone: - u->field_data[UF_HOST].len++; - break; - case s_http_host_port: if (s != s_http_host_port) { u->field_data[UF_PORT].off = p - buf; @@ -2320,8 +2110,6 @@ case s_http_host_start: case s_http_host_v6_start: case s_http_host_v6: - case s_http_host_v6_zone_start: - case s_http_host_v6_zone: case s_http_host_port_start: case s_http_userinfo: case s_http_userinfo_start: @@ -2333,11 +2121,6 @@ return 0; } -void -http_parser_url_init(struct http_parser_url *u) { - memset(u, 0, sizeof(*u)); -} - int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, struct http_parser_url *u) @@ -2411,12 +2194,7 @@ /* host must be present if there is a schema */ /* parsing http:///toto will fail */ - if ((u->field_set & (1 << UF_SCHEMA)) && - (u->field_set & (1 << UF_HOST)) == 0) { - return 1; - } - - if (u->field_set & (1 << UF_HOST)) { + if ((u->field_set & ((1 << UF_SCHEMA) | (1 << UF_HOST))) != 0) { if (http_parse_host(buf, u, found_at) != 0) { return 1; } diff -Nru nghttp2-1.13.0/third-party/http-parser/http_parser.h nghttp2-0.6.7/third-party/http-parser/http_parser.h --- nghttp2-1.13.0/third-party/http-parser/http_parser.h 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/third-party/http-parser/http_parser.h 2014-11-30 14:15:07.000000000 +0000 @@ -26,12 +26,11 @@ /* Also update SONAME in the Makefile whenever you change these. */ #define HTTP_PARSER_VERSION_MAJOR 2 -#define HTTP_PARSER_VERSION_MINOR 7 +#define HTTP_PARSER_VERSION_MINOR 3 #define HTTP_PARSER_VERSION_PATCH 0 #include -#if defined(_WIN32) && !defined(__MINGW32__) && \ - (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) +#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600) #include #include typedef __int8 int8_t; @@ -77,11 +76,6 @@ * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: * chunked' headers that indicate the presence of a body. * - * Returning `2` from on_headers_complete will tell parser that it should not - * expect neither a body nor any futher responses on this connection. This is - * useful for handling responses to a CONNECT request which may not contain - * `Upgrade` or `Connection: upgrade` headers. - * * http_data_cb does not return data chunks. It will be called arbitrarily * many times for each string. E.G. you might get 10 callbacks for "on_url" * each providing just a few characters more data. @@ -101,7 +95,7 @@ XX(5, CONNECT, CONNECT) \ XX(6, OPTIONS, OPTIONS) \ XX(7, TRACE, TRACE) \ - /* WebDAV */ \ + /* webdav */ \ XX(8, COPY, COPY) \ XX(9, LOCK, LOCK) \ XX(10, MKCOL, MKCOL) \ @@ -110,28 +104,21 @@ XX(13, PROPPATCH, PROPPATCH) \ XX(14, SEARCH, SEARCH) \ XX(15, UNLOCK, UNLOCK) \ - XX(16, BIND, BIND) \ - XX(17, REBIND, REBIND) \ - XX(18, UNBIND, UNBIND) \ - XX(19, ACL, ACL) \ /* subversion */ \ - XX(20, REPORT, REPORT) \ - XX(21, MKACTIVITY, MKACTIVITY) \ - XX(22, CHECKOUT, CHECKOUT) \ - XX(23, MERGE, MERGE) \ + XX(16, REPORT, REPORT) \ + XX(17, MKACTIVITY, MKACTIVITY) \ + XX(18, CHECKOUT, CHECKOUT) \ + XX(19, MERGE, MERGE) \ /* upnp */ \ - XX(24, MSEARCH, M-SEARCH) \ - XX(25, NOTIFY, NOTIFY) \ - XX(26, SUBSCRIBE, SUBSCRIBE) \ - XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ + XX(20, MSEARCH, M-SEARCH) \ + XX(21, NOTIFY, NOTIFY) \ + XX(22, SUBSCRIBE, SUBSCRIBE) \ + XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \ /* RFC-5789 */ \ - XX(28, PATCH, PATCH) \ - XX(29, PURGE, PURGE) \ + XX(24, PATCH, PATCH) \ + XX(25, PURGE, PURGE) \ /* CalDAV */ \ - XX(30, MKCALENDAR, MKCALENDAR) \ - /* RFC-2068, section 19.6.1.2 */ \ - XX(31, LINK, LINK) \ - XX(32, UNLINK, UNLINK) \ + XX(26, MKCALENDAR, MKCALENDAR) \ enum http_method { @@ -149,16 +136,14 @@ { F_CHUNKED = 1 << 0 , F_CONNECTION_KEEP_ALIVE = 1 << 1 , F_CONNECTION_CLOSE = 1 << 2 - , F_CONNECTION_UPGRADE = 1 << 3 - , F_TRAILING = 1 << 4 - , F_UPGRADE = 1 << 5 - , F_SKIPBODY = 1 << 6 - , F_CONTENTLENGTH = 1 << 7 + , F_TRAILING = 1 << 3 + , F_UPGRADE = 1 << 4 + , F_SKIPBODY = 1 << 5 }; /* Map for errno-related constants - * + * * The provided argument should be a macro that takes 2 arguments. */ #define HTTP_ERRNO_MAP(XX) \ @@ -174,8 +159,6 @@ XX(CB_body, "the on_body callback failed") \ XX(CB_message_complete, "the on_message_complete callback failed") \ XX(CB_status, "the on_status callback failed") \ - XX(CB_chunk_header, "the on_chunk_header callback failed") \ - XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ \ /* Parsing-related errors */ \ XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ @@ -196,8 +179,6 @@ XX(INVALID_HEADER_TOKEN, "invalid character in header") \ XX(INVALID_CONTENT_LENGTH, \ "invalid character in content-length header") \ - XX(UNEXPECTED_CONTENT_LENGTH, \ - "unexpected content-length header") \ XX(INVALID_CHUNK_SIZE, \ "invalid character in chunk size header") \ XX(INVALID_CONSTANT, "invalid constant string") \ @@ -222,11 +203,10 @@ struct http_parser { /** PRIVATE **/ unsigned int type : 2; /* enum http_parser_type */ - unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ - unsigned int state : 7; /* enum state from http_parser.c */ - unsigned int header_state : 7; /* enum header_state from http_parser.c */ - unsigned int index : 7; /* index into current matcher */ - unsigned int lenient_http_headers : 1; + unsigned int flags : 6; /* F_* values from 'flags' enum; semi-public */ + unsigned int state : 8; /* enum state from http_parser.c */ + unsigned int header_state : 8; /* enum header_state from http_parser.c */ + unsigned int index : 8; /* index into current matcher */ uint32_t nread; /* # bytes read in various scenarios */ uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ @@ -259,11 +239,6 @@ http_cb on_headers_complete; http_data_cb on_body; http_cb on_message_complete; - /* When on_chunk_header is called, the current chunk length is stored - * in parser->content_length. - */ - http_cb on_chunk_header; - http_cb on_chunk_complete; }; @@ -312,11 +287,6 @@ void http_parser_init(http_parser *parser, enum http_parser_type type); -/* Initialize http_parser_settings members to 0 - */ -void http_parser_settings_init(http_parser_settings *settings); - - /* Executes the parser. Returns number of parsed bytes. Sets * `parser->http_errno` on error. */ size_t http_parser_execute(http_parser *parser, @@ -342,9 +312,6 @@ /* Return a string description of the given error */ const char *http_errno_description(enum http_errno err); -/* Initialize all http_parser_url members to 0 */ -void http_parser_url_init(struct http_parser_url *u); - /* Parse a URL; return nonzero on failure */ int http_parser_parse_url(const char *buf, size_t buflen, int is_connect, diff -Nru nghttp2-1.13.0/third-party/Makefile.am nghttp2-0.6.7/third-party/Makefile.am --- nghttp2-1.13.0/third-party/Makefile.am 2016-07-21 13:47:26.000000000 +0000 +++ nghttp2-0.6.7/third-party/Makefile.am 2014-11-30 14:15:07.000000000 +0000 @@ -21,46 +21,9 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -AM_CPPFLAGS = @DEFS@ - -EXTRA_DIST = CMakeLists.txt - -if ENABLE_THIRD_PARTY +AM_CPPFLAGS = -Wall @DEFS@ noinst_LTLIBRARIES = libhttp-parser.la libhttp_parser_la_SOURCES = \ http-parser/http_parser.c \ http-parser/http_parser.h - -if HAVE_NEVERBLEED -noinst_LTLIBRARIES += libneverbleed.la -libneverbleed_la_CPPFLAGS = @OPENSSL_CFLAGS@ -libneverbleed_la_LIBADD = @OPENSSL_LIBS@ -libneverbleed_la_SOURCES = neverbleed/neverbleed.c neverbleed/neverbleed.h -endif # HAVE_NEVERBLEED - -if HAVE_MRUBY - -EXTRA_DIST += build_config.rb mruby/* - -.PHONY: all-local clean mruby - -mruby: - MRUBY_CONFIG="${srcdir}/build_config.rb" \ - BUILD_DIR="${abs_builddir}/mruby/build" \ - INSTALL_DIR="${abs_builddir}/mruby/build/install/bin" \ - CC="${CC}" CXX="${CXX}" LD="${LD}" \ - CFLAGS="${CPPFLAGS} ${CFLAGS}" CXXFLAGS="${CPPFLAGS} ${CXXFLAGS}" \ - LDFLAGS="${LDFLAGS}" \ - "${srcdir}/mruby/minirake" -f "${srcdir}/mruby/Rakefile" - -all-local: mruby - -clean-local: - MRUBY_CONFIG="${srcdir}/build_config.rb" \ - BUILD_DIR="${abs_builddir}/mruby/build" \ - "${srcdir}/mruby/minirake" -f "${srcdir}/mruby/Rakefile" clean - -endif # HAVE_MRUBY - -endif # ENABLE_THIRD_PARTY diff -Nru nghttp2-1.13.0/third-party/Makefile.in nghttp2-0.6.7/third-party/Makefile.in --- nghttp2-1.13.0/third-party/Makefile.in 2016-07-21 13:48:01.000000000 +0000 +++ nghttp2-0.6.7/third-party/Makefile.in 2014-11-30 14:15:35.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -38,17 +38,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. VPATH = @srcdir@ -am__is_gnu_make = { \ - if test -z '$(MAKELEVEL)'; then \ - false; \ - elif test -n '$(MAKE_HOST)'; then \ - true; \ - elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ - true; \ - else \ - false; \ - fi; \ -} +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -112,9 +102,9 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@am__append_1 = libneverbleed.la -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@am__append_2 = build_config.rb mruby/* subdir = third-party +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \ $(top_srcdir)/m4/ax_boost_base.m4 \ @@ -124,36 +114,24 @@ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/m4/ax_have_epoll.m4 \ $(top_srcdir)/m4/ax_python_devel.m4 \ - $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libxml2.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libhttp_parser_la_LIBADD = -am__libhttp_parser_la_SOURCES_DIST = http-parser/http_parser.c \ - http-parser/http_parser.h am__dirstamp = $(am__leading_dot)dirstamp -@ENABLE_THIRD_PARTY_TRUE@am_libhttp_parser_la_OBJECTS = \ -@ENABLE_THIRD_PARTY_TRUE@ http-parser/http_parser.lo +am_libhttp_parser_la_OBJECTS = http-parser/http_parser.lo libhttp_parser_la_OBJECTS = $(am_libhttp_parser_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -@ENABLE_THIRD_PARTY_TRUE@am_libhttp_parser_la_rpath = -libneverbleed_la_DEPENDENCIES = -am__libneverbleed_la_SOURCES_DIST = neverbleed/neverbleed.c \ - neverbleed/neverbleed.h -@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@am_libneverbleed_la_OBJECTS = neverbleed/libneverbleed_la-neverbleed.lo -libneverbleed_la_OBJECTS = $(am_libneverbleed_la_OBJECTS) -@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@am_libneverbleed_la_rpath = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -188,9 +166,8 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(libhttp_parser_la_SOURCES) $(libneverbleed_la_SOURCES) -DIST_SOURCES = $(am__libhttp_parser_la_SOURCES_DIST) \ - $(am__libneverbleed_la_SOURCES_DIST) +SOURCES = $(libhttp_parser_la_SOURCES) +DIST_SOURCES = $(libhttp_parser_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -215,12 +192,10 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -APPLDFLAGS = @APPLDFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -239,7 +214,6 @@ CUNIT_CFLAGS = @CUNIT_CFLAGS@ CUNIT_LIBS = @CUNIT_LIBS@ CXX = @CXX@ -CXX1XCXXFLAGS = @CXX1XCXXFLAGS@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ @@ -255,7 +229,6 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRACFLAG = @EXTRACFLAG@ FGREP = @FGREP@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -271,10 +244,6 @@ LDFLAGS = @LDFLAGS@ LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@ LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@ -LIBEV_CFLAGS = @LIBEV_CFLAGS@ -LIBEV_LIBS = @LIBEV_LIBS@ -LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@ -LIBMRUBY_LIBS = @LIBMRUBY_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSPDYLAY_CFLAGS = @LIBSPDYLAY_CFLAGS@ @@ -286,7 +255,6 @@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ -LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -324,11 +292,10 @@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SRC_LIBS = @SRC_LIBS@ STRIP = @STRIP@ -TESTLDADD = @TESTLDADD@ +TESTS_LIBS = @TESTS_LIBS@ VERSION = @VERSION@ -WARNCFLAGS = @WARNCFLAGS@ -WARNCXXFLAGS = @WARNCXXFLAGS@ XML2_CONFIG = @XML2_CONFIG@ XML_CPPFLAGS = @XML_CPPFLAGS@ XML_LIBS = @XML_LIBS@ @@ -383,7 +350,6 @@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -396,17 +362,12 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -AM_CPPFLAGS = @DEFS@ -EXTRA_DIST = CMakeLists.txt $(am__append_2) -@ENABLE_THIRD_PARTY_TRUE@noinst_LTLIBRARIES = libhttp-parser.la \ -@ENABLE_THIRD_PARTY_TRUE@ $(am__append_1) -@ENABLE_THIRD_PARTY_TRUE@libhttp_parser_la_SOURCES = \ -@ENABLE_THIRD_PARTY_TRUE@ http-parser/http_parser.c \ -@ENABLE_THIRD_PARTY_TRUE@ http-parser/http_parser.h - -@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@libneverbleed_la_CPPFLAGS = @OPENSSL_CFLAGS@ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@libneverbleed_la_LIBADD = @OPENSSL_LIBS@ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@libneverbleed_la_SOURCES = neverbleed/neverbleed.c neverbleed/neverbleed.h +AM_CPPFLAGS = -Wall @DEFS@ +noinst_LTLIBRARIES = libhttp-parser.la +libhttp_parser_la_SOURCES = \ + http-parser/http_parser.c \ + http-parser/http_parser.h + all: all-am .SUFFIXES: @@ -423,6 +384,7 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu third-party/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu third-party/Makefile +.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -461,31 +423,17 @@ http-parser/$(DEPDIR)/$(am__dirstamp) libhttp-parser.la: $(libhttp_parser_la_OBJECTS) $(libhttp_parser_la_DEPENDENCIES) $(EXTRA_libhttp_parser_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(am_libhttp_parser_la_rpath) $(libhttp_parser_la_OBJECTS) $(libhttp_parser_la_LIBADD) $(LIBS) -neverbleed/$(am__dirstamp): - @$(MKDIR_P) neverbleed - @: > neverbleed/$(am__dirstamp) -neverbleed/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) neverbleed/$(DEPDIR) - @: > neverbleed/$(DEPDIR)/$(am__dirstamp) -neverbleed/libneverbleed_la-neverbleed.lo: neverbleed/$(am__dirstamp) \ - neverbleed/$(DEPDIR)/$(am__dirstamp) - -libneverbleed.la: $(libneverbleed_la_OBJECTS) $(libneverbleed_la_DEPENDENCIES) $(EXTRA_libneverbleed_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(am_libneverbleed_la_rpath) $(libneverbleed_la_OBJECTS) $(libneverbleed_la_LIBADD) $(LIBS) + $(AM_V_CCLD)$(LINK) $(libhttp_parser_la_OBJECTS) $(libhttp_parser_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f http-parser/*.$(OBJEXT) -rm -f http-parser/*.lo - -rm -f neverbleed/*.$(OBJEXT) - -rm -f neverbleed/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@http-parser/$(DEPDIR)/http_parser.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -511,20 +459,12 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< -neverbleed/libneverbleed_la-neverbleed.lo: neverbleed/neverbleed.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libneverbleed_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT neverbleed/libneverbleed_la-neverbleed.lo -MD -MP -MF neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Tpo -c -o neverbleed/libneverbleed_la-neverbleed.lo `test -f 'neverbleed/neverbleed.c' || echo '$(srcdir)/'`neverbleed/neverbleed.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Tpo neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='neverbleed/neverbleed.c' object='neverbleed/libneverbleed_la-neverbleed.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libneverbleed_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o neverbleed/libneverbleed_la-neverbleed.lo `test -f 'neverbleed/neverbleed.c' || echo '$(srcdir)/'`neverbleed/neverbleed.c - mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf http-parser/.libs http-parser/_libs - -rm -rf neverbleed/.libs neverbleed/_libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique @@ -610,9 +550,7 @@ done check-am: all-am check: check-am -@ENABLE_THIRD_PARTY_FALSE@all-local: -@HAVE_MRUBY_FALSE@all-local: -all-am: Makefile $(LTLIBRARIES) all-local +all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am @@ -642,21 +580,17 @@ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f http-parser/$(DEPDIR)/$(am__dirstamp) -rm -f http-parser/$(am__dirstamp) - -rm -f neverbleed/$(DEPDIR)/$(am__dirstamp) - -rm -f neverbleed/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -@ENABLE_THIRD_PARTY_FALSE@clean-local: -@HAVE_MRUBY_FALSE@clean-local: clean: clean-am -clean-am: clean-generic clean-libtool clean-local \ - clean-noinstLTLIBRARIES mostlyclean-am +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am distclean: distclean-am - -rm -rf http-parser/$(DEPDIR) neverbleed/$(DEPDIR) + -rm -rf http-parser/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -702,7 +636,7 @@ installcheck-am: maintainer-clean: maintainer-clean-am - -rm -rf http-parser/$(DEPDIR) neverbleed/$(DEPDIR) + -rm -rf http-parser/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -723,40 +657,20 @@ .MAKE: install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ - clean-generic clean-libtool clean-local \ - clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am - -.PRECIOUS: Makefile - - -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@.PHONY: all-local clean mruby +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@mruby: -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ MRUBY_CONFIG="${srcdir}/build_config.rb" \ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ BUILD_DIR="${abs_builddir}/mruby/build" \ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ INSTALL_DIR="${abs_builddir}/mruby/build/install/bin" \ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ CC="${CC}" CXX="${CXX}" LD="${LD}" \ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ CFLAGS="${CPPFLAGS} ${CFLAGS}" CXXFLAGS="${CPPFLAGS} ${CXXFLAGS}" \ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ LDFLAGS="${LDFLAGS}" \ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ "${srcdir}/mruby/minirake" -f "${srcdir}/mruby/Rakefile" - -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@all-local: mruby - -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@clean-local: -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ MRUBY_CONFIG="${srcdir}/build_config.rb" \ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ BUILD_DIR="${abs_builddir}/mruby/build" \ -@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ "${srcdir}/mruby/minirake" -f "${srcdir}/mruby/Rakefile" clean # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru nghttp2-1.13.0/third-party/mruby/AUTHORS nghttp2-0.6.7/third-party/mruby/AUTHORS --- nghttp2-1.13.0/third-party/mruby/AUTHORS 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/AUTHORS 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -Original Authors "mruby developers" are: - Yukihiro Matsumoto - SCSK KYUSHU CORPORATION - Kyushu Institute of Technology - Network Applied Communication Laboratory, Inc. - Daniel Bovensiepen - Jon Maken - Bjorn De Meyer - Yuichiro MASUI - Masamitsu MURASE - Masaki Muranaka - Internet Initiative Japan Inc. - Tadashi FUKUZAWA - MATSUMOTO Ryosuke - Yasuhiro Matsumoto - Koji Yoshioka - Jun Hiroe - Narihiro Nakamura - Yuichi Nishiwaki - Tatsuhiko Kubo - Takeshi Watanabe - Yuki Kurihara - specified non-profit corporation mruby Forum - Kazuaki Tanaka - Hiromasa Ishii - Hiroshi Mimaki - Satoshi Odawara - Mitsubishi Electric Micro-Computer Application Software Co.,Ltd. - Ralph Desir(Mav7) - Hiroyuki Matsuzaki - Yuhei Okazaki - Manycolors, Inc. - Shota Nakano - Yuichi Osawa - Terence Lee - Zachary Scott diff -Nru nghttp2-1.13.0/third-party/mruby/benchmark/bm_ao_render.rb nghttp2-0.6.7/third-party/mruby/benchmark/bm_ao_render.rb --- nghttp2-1.13.0/third-party/mruby/benchmark/bm_ao_render.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/benchmark/bm_ao_render.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,314 +0,0 @@ -# AO render benchmark -# Original program (C) Syoyo Fujita in Javascript (and other languages) -# https://code.google.com/p/aobench/ -# Ruby(yarv2llvm) version by Hideki Miura -# mruby version by Hideki Miura -# - -IMAGE_WIDTH = 64 -IMAGE_HEIGHT = 64 -NSUBSAMPLES = 2 -NAO_SAMPLES = 8 - -module Rand - # Use xorshift - @@x = 123456789 - @@y = 362436069 - @@z = 521288629 - @@w = 88675123 - BNUM = 1 << 29 - BNUMF = BNUM.to_f - def self.rand - x = @@x - t = x ^ ((x & 0xfffff) << 11) - w = @@w - @@x, @@y, @@z = @@y, @@z, w - w = @@w = (w ^ (w >> 19) ^ (t ^ (t >> 8))) - (w % BNUM) / BNUMF - end -end - -class Vec - def initialize(x, y, z) - @x = x - @y = y - @z = z - end - - def x=(v); @x = v; end - def y=(v); @y = v; end - def z=(v); @z = v; end - def x; @x; end - def y; @y; end - def z; @z; end - - def vadd(b) - Vec.new(@x + b.x, @y + b.y, @z + b.z) - end - - def vsub(b) - Vec.new(@x - b.x, @y - b.y, @z - b.z) - end - - def vcross(b) - Vec.new(@y * b.z - @z * b.y, - @z * b.x - @x * b.z, - @x * b.y - @y * b.x) - end - - def vdot(b) - r = @x * b.x + @y * b.y + @z * b.z - r - end - - def vlength - Math.sqrt(@x * @x + @y * @y + @z * @z) - end - - def vnormalize - len = vlength - v = Vec.new(@x, @y, @z) - if len > 1.0e-17 then - v.x = v.x / len - v.y = v.y / len - v.z = v.z / len - end - v - end -end - - -class Sphere - def initialize(center, radius) - @center = center - @radius = radius - end - - def center; @center; end - def radius; @radius; end - - def intersect(ray, isect) - rs = ray.org.vsub(@center) - b = rs.vdot(ray.dir) - c = rs.vdot(rs) - (@radius * @radius) - d = b * b - c - if d > 0.0 then - t = - b - Math.sqrt(d) - - if t > 0.0 and t < isect.t then - isect.t = t - isect.hit = true - isect.pl = Vec.new(ray.org.x + ray.dir.x * t, - ray.org.y + ray.dir.y * t, - ray.org.z + ray.dir.z * t) - n = isect.pl.vsub(@center) - isect.n = n.vnormalize - end - end - end -end - -class Plane - def initialize(p, n) - @p = p - @n = n - end - - def intersect(ray, isect) - d = -@p.vdot(@n) - v = ray.dir.vdot(@n) - v0 = v - if v < 0.0 then - v0 = -v - end - if v0 < 1.0e-17 then - return - end - - t = -(ray.org.vdot(@n) + d) / v - - if t > 0.0 and t < isect.t then - isect.hit = true - isect.t = t - isect.n = @n - isect.pl = Vec.new(ray.org.x + t * ray.dir.x, - ray.org.y + t * ray.dir.y, - ray.org.z + t * ray.dir.z) - end - end -end - -class Ray - def initialize(org, dir) - @org = org - @dir = dir - end - - def org; @org; end - def org=(v); @org = v; end - def dir; @dir; end - def dir=(v); @dir = v; end -end - -class Isect - def initialize - @t = 10000000.0 - @hit = false - @pl = Vec.new(0.0, 0.0, 0.0) - @n = Vec.new(0.0, 0.0, 0.0) - end - - def t; @t; end - def t=(v); @t = v; end - def hit; @hit; end - def hit=(v); @hit = v; end - def pl; @pl; end - def pl=(v); @pl = v; end - def n; @n; end - def n=(v); @n = v; end -end - -def clamp(f) - i = f * 255.5 - if i > 255.0 then - i = 255.0 - end - if i < 0.0 then - i = 0.0 - end - i.to_i -end - -def otherBasis(basis, n) - basis[2] = Vec.new(n.x, n.y, n.z) - basis[1] = Vec.new(0.0, 0.0, 0.0) - - if n.x < 0.6 and n.x > -0.6 then - basis[1].x = 1.0 - elsif n.y < 0.6 and n.y > -0.6 then - basis[1].y = 1.0 - elsif n.z < 0.6 and n.z > -0.6 then - basis[1].z = 1.0 - else - basis[1].x = 1.0 - end - - basis[0] = basis[1].vcross(basis[2]) - basis[0] = basis[0].vnormalize - - basis[1] = basis[2].vcross(basis[0]) - basis[1] = basis[1].vnormalize -end - -class Scene - def initialize - @spheres = Array.new - @spheres[0] = Sphere.new(Vec.new(-2.0, 0.0, -3.5), 0.5) - @spheres[1] = Sphere.new(Vec.new(-0.5, 0.0, -3.0), 0.5) - @spheres[2] = Sphere.new(Vec.new(1.0, 0.0, -2.2), 0.5) - @plane = Plane.new(Vec.new(0.0, -0.5, 0.0), Vec.new(0.0, 1.0, 0.0)) - end - - def ambient_occlusion(isect) - basis = Array.new(3) - otherBasis(basis, isect.n) - - ntheta = NAO_SAMPLES - nphi = NAO_SAMPLES - eps = 0.0001 - occlusion = 0.0 - - p0 = Vec.new(isect.pl.x + eps * isect.n.x, - isect.pl.y + eps * isect.n.y, - isect.pl.z + eps * isect.n.z) - nphi.times do |j| - ntheta.times do |i| - r = Rand::rand - phi = 2.0 * 3.14159265 * Rand::rand - x = Math.cos(phi) * Math.sqrt(1.0 - r) - y = Math.sin(phi) * Math.sqrt(1.0 - r) - z = Math.sqrt(r) - - rx = x * basis[0].x + y * basis[1].x + z * basis[2].x - ry = x * basis[0].y + y * basis[1].y + z * basis[2].y - rz = x * basis[0].z + y * basis[1].z + z * basis[2].z - - raydir = Vec.new(rx, ry, rz) - ray = Ray.new(p0, raydir) - - occisect = Isect.new - @spheres[0].intersect(ray, occisect) - @spheres[1].intersect(ray, occisect) - @spheres[2].intersect(ray, occisect) - @plane.intersect(ray, occisect) - if occisect.hit then - occlusion = occlusion + 1.0 - else - 0.0 - end - end - end - - occlusion = (ntheta.to_f * nphi.to_f - occlusion) / (ntheta.to_f * nphi.to_f) - Vec.new(occlusion, occlusion, occlusion) - end - - def render(w, h, nsubsamples) - cnt = 0 - nsf = nsubsamples.to_f - h.times do |y| - w.times do |x| - rad = Vec.new(0.0, 0.0, 0.0) - - # Subsmpling - nsubsamples.times do |v| - nsubsamples.times do |u| - cnt = cnt + 1 - wf = w.to_f - hf = h.to_f - xf = x.to_f - yf = y.to_f - uf = u.to_f - vf = v.to_f - - px = (xf + (uf / nsf) - (wf / 2.0)) / (wf / 2.0) - py = -(yf + (vf / nsf) - (hf / 2.0)) / (hf / 2.0) - - eye = Vec.new(px, py, -1.0).vnormalize - - ray = Ray.new(Vec.new(0.0, 0.0, 0.0), eye) - - isect = Isect.new - @spheres[0].intersect(ray, isect) - @spheres[1].intersect(ray, isect) - @spheres[2].intersect(ray, isect) - @plane.intersect(ray, isect) - if isect.hit then - col = ambient_occlusion(isect) - rad.x = rad.x + col.x - rad.y = rad.y + col.y - rad.z = rad.z + col.z - else - 0.0 - end - end - end - - r = rad.x / (nsf * nsf) - g = rad.y / (nsf * nsf) - b = rad.z / (nsf * nsf) - printf("%c", clamp(r)) - printf("%c", clamp(g)) - printf("%c", clamp(b)) - end - end - end -end - -# File.open("ao.ppm", "w") do |fp| - printf("P6\n") - printf("%d %d\n", IMAGE_WIDTH, IMAGE_HEIGHT) - printf("255\n", IMAGE_WIDTH, IMAGE_HEIGHT) - Scene.new.render(IMAGE_WIDTH, IMAGE_HEIGHT, NSUBSAMPLES) -# Scene.new.render(256, 256, 2) -# end diff -Nru nghttp2-1.13.0/third-party/mruby/benchmark/bm_app_lc_fizzbuzz.rb nghttp2-0.6.7/third-party/mruby/benchmark/bm_app_lc_fizzbuzz.rb --- nghttp2-1.13.0/third-party/mruby/benchmark/bm_app_lc_fizzbuzz.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/benchmark/bm_app_lc_fizzbuzz.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -# -# FizzBuzz program using only lambda calculus -# -# This program is quoted from -# "Understanding Computation" by Tom Stuart -# http://computationbook.com/ -# -# You can understand why this program works fine by reading this book. -# - -solution = -> k { -> f { -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> l { -> x { -> g { -> b { b }[-> p { p[-> x { -> y { x } }] }[l]][x][-> y { g[f[-> l { -> p { p[-> x { -> y { y } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][x][g]][-> l { -> p { p[-> x { -> y { x } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][y] }] } } } }][k][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> l { -> x { -> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[l][f[x]] } }] } }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[m][n]][-> x { -> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[f[-> n { -> p { -> x { p[n[p][x]] } } }[m]][n]][m][x] }][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]] } } }][-> p { -> x { p[x] } }][-> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] } }]][-> n { -> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[x]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> n { -> l { -> x { -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> l { -> x { -> g { -> b { b }[-> p { p[-> x { -> y { x } }] }[l]][x][-> y { g[f[-> l { -> p { p[-> x { -> y { y } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][x][g]][-> l { -> p { p[-> x { -> y { x } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][y] }] } } } }][l][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][x]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }] } }[-> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> x { f[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { -> n { -> p { -> x { p[n[p][x]] } } }[f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n]][x] }][-> p { -> x { x } }] } } }][n][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][x] }]][-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]] } }][n]]]] }] - -FIRST = -> l { LEFT[RIGHT[l]] } -IF = -> b { b } -LEFT = -> p { p[-> x { -> y { x } } ] } -RIGHT = -> p { p[-> x { -> y { y } } ] } -IS_EMPTY = LEFT -REST = -> l { RIGHT[RIGHT[l]] } - -def to_integer(proc) - proc[-> n { n + 1 }][0] -end - -def to_boolean(proc) - IF[proc][true][false] -end - -def to_array(proc) - array = [] - - until to_boolean(IS_EMPTY[proc]) - array.push(FIRST[proc]) - proc = REST[proc] - end - - array -end - -def to_char(c) - '0123456789BFiuz'.slice(to_integer(c)) -end - -def to_string(s) - to_array(s).map { |c| to_char(c) }.join -end - -answer = to_array(solution).map do |p| - to_string(p) -end - -answer_str = answer.to_a -# puts answer_str diff -Nru nghttp2-1.13.0/third-party/mruby/benchmark/bm_fib.rb nghttp2-0.6.7/third-party/mruby/benchmark/bm_fib.rb --- nghttp2-1.13.0/third-party/mruby/benchmark/bm_fib.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/benchmark/bm_fib.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ - -def fib n - return n if n < 2 - fib(n-2) + fib(n-1) -end - -puts fib(37) diff -Nru nghttp2-1.13.0/third-party/mruby/benchmark/bm_so_lists.rb nghttp2-0.6.7/third-party/mruby/benchmark/bm_so_lists.rb --- nghttp2-1.13.0/third-party/mruby/benchmark/bm_so_lists.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/benchmark/bm_so_lists.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -#from http://www.bagley.org/~doug/shootout/bench/lists/lists.ruby - -NUM = 300 -SIZE = 10000 - -def test_lists() - # create a list of integers (Li1) from 1 to SIZE - li1 = (1..SIZE).to_a - # copy the list to li2 (not by individual items) - li2 = li1.dup - # remove each individual item from left side of li2 and - # append to right side of li3 (preserving order) - li3 = Array.new - while (not li2.empty?) - li3.push(li2.shift) - end - # li2 must now be empty - # remove each individual item from right side of li3 and - # append to right side of li2 (reversing list) - while (not li3.empty?) - li2.push(li3.pop) - end - # li3 must now be empty - # reverse li1 in place - li1.reverse! - # check that first item is now SIZE - if li1[0] != SIZE then - p "not SIZE" - 0 - else - # compare li1 and li2 for equality - if li1 != li2 then - return(0) - else - # return the length of the list - li1.length - end - end -end - -i = 0 -while i 'masuidrive/mrbgems-example', :checksum_hash => '76518e8aecd131d047378448ac8055fa29d974a9' - # conf.gem :git => 'git@github.com:masuidrive/mrbgems-example.git', :branch => 'master', :options => '-v' - - # include the default GEMs - conf.gembox 'default' - # C compiler settings - # conf.cc do |cc| - # cc.command = ENV['CC'] || 'gcc' - # cc.flags = [ENV['CFLAGS'] || %w()] - # cc.include_paths = ["#{root}/include"] - # cc.defines = %w(DISABLE_GEMS) - # cc.option_include_path = '-I%s' - # cc.option_define = '-D%s' - # cc.compile_options = "%{flags} -MMD -o %{outfile} -c %{infile}" - # end - - # mrbc settings - # conf.mrbc do |mrbc| - # mrbc.compile_options = "-g -B%{funcname} -o-" # The -g option is required for line numbers - # end - - # Linker settings - # conf.linker do |linker| - # linker.command = ENV['LD'] || 'gcc' - # linker.flags = [ENV['LDFLAGS'] || []] - # linker.flags_before_libraries = [] - # linker.libraries = %w() - # linker.flags_after_libraries = [] - # linker.library_paths = [] - # linker.option_library = '-l%s' - # linker.option_library_path = '-L%s' - # linker.link_options = "%{flags} -o %{outfile} %{objs} %{libs}" - # end - - # Archiver settings - # conf.archiver do |archiver| - # archiver.command = ENV['AR'] || 'ar' - # archiver.archive_options = 'rs %{outfile} %{objs}' - # end - - # Parser generator settings - # conf.yacc do |yacc| - # yacc.command = ENV['YACC'] || 'bison' - # yacc.compile_options = '-o %{outfile} %{infile}' - # end - - # gperf settings - # conf.gperf do |gperf| - # gperf.command = 'gperf' - # gperf.compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}' - # end - - # file extensions - # conf.exts do |exts| - # exts.object = '.o' - # exts.executable = '' # '.exe' if Windows - # exts.library = '.a' - # end - - # file separetor - # conf.file_separator = '/' - - # bintest - # conf.enable_bintest -end - -MRuby::Build.new('host-debug') do |conf| - # load specific toolchain settings - - # Gets set by the VS command prompts. - if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] - toolchain :visualcpp - else - toolchain :gcc - end - - enable_debug - - # include the default GEMs - conf.gembox 'default' - - # C compiler settings - conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK) - - # Generate mruby debugger command (require mruby-eval) - conf.gem :core => "mruby-bin-debugger" - - # bintest - # conf.enable_bintest -end - -MRuby::Build.new('test') do |conf| - # Gets set by the VS command prompts. - if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] - toolchain :visualcpp - else - toolchain :gcc - end - - enable_debug - conf.enable_bintest - conf.enable_test - - conf.gembox 'default' -end - -# Define cross build settings -# MRuby::CrossBuild.new('32bit') do |conf| -# toolchain :gcc -# -# conf.cc.flags << "-m32" -# conf.linker.flags << "-m32" -# -# conf.build_mrbtest_lib_only -# -# conf.gem 'examples/mrbgems/c_and_ruby_extension_example' -# -# conf.test_runner.command = 'env' -# -# end diff -Nru nghttp2-1.13.0/third-party/mruby/ChangeLog nghttp2-0.6.7/third-party/mruby/ChangeLog --- nghttp2-1.13.0/third-party/mruby/ChangeLog 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/ChangeLog 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -Thu Apl 19 17:25:18 2012 Yukihiro Matsumoto - - * first release version 1.0.0 released. - -Local variables: -add-log-time-format: (lambda () - (let* ((time (current-time)) - (system-time-locale "C") - (diff (+ (cadr time) 32400)) - (lo (% diff 65536)) - (hi (+ (car time) (/ diff 65536)))) - (format-time-string "%a %b %e %H:%M:%S %Y" (list hi lo) t))) -indent-tabs-mode: t -tab-width: 8 -end: diff -Nru nghttp2-1.13.0/third-party/mruby/CONTRIBUTING.md nghttp2-0.6.7/third-party/mruby/CONTRIBUTING.md --- nghttp2-1.13.0/third-party/mruby/CONTRIBUTING.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/CONTRIBUTING.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -# How to contribute - -mruby is an open-source project which is looking forward to each contribution. - -## Your Pull Request - -To make it easy to review and understand your change please keep the following -things in mind before submitting your pull request: - -* Work on the latest possible state of **mruby/master** -* Create a branch which is dedicated to your change -* Test your changes before creating a pull request (```./minirake test```) -* If possible write a test case which confirms your change -* Don't mix several features or bug-fixes in one pull request -* Create a meaningful commit message -* Explain your change (i.e. with a link to the issue you are fixing) -* Use mrbgem to provide non ISO features (classes, modules and methods) unless - you have a special reason to implement them in the core - -## Coding conventions - -How to style your C and Ruby code which you want to submit. - -### C code - -The core part (parser, bytecode-interpreter, core-lib, etc.) of mruby is -written in the C programming language. Please note the following hints for your -C code: - -#### Comply with C99 (ISO/IEC 9899:1999) - -mruby should be highly portable to other systems and compilers. For this it is -recommended to keep your code as close as possible to the C99 standard -(http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf). - -Although we target C99, Visual C++ is also an important target for mruby. For -this reason a declaration of a local variable has to be at the beginning of a -scope block. - -#### Reduce library dependencies to a minimum - -The dependencies to libraries should be kept to an absolute minimum. This -increases the portability but makes it also easier to cut away parts of mruby -on-demand. - -#### Don't use C++ style comments - - /* This is the preferred comment style */ - -Use C++ style comments only for temporary comment e.g. commenting out some code lines. - -#### Insert a break after the method return value: - - int - main(void) - { - ... - } - -### Ruby code - -Parts of the standard library of mruby are written in the Ruby programming -language itself. Please note the following hints for your Ruby code: - -#### Comply with the Ruby standard (ISO/IEC 30170:2012) - -mruby is currently targeting to execute Ruby code which complies to ISO/IEC -30170:2012 (http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579). diff -Nru nghttp2-1.13.0/third-party/mruby/doc/guides/compile.md nghttp2-0.6.7/third-party/mruby/doc/guides/compile.md --- nghttp2-1.13.0/third-party/mruby/doc/guides/compile.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/doc/guides/compile.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,481 +0,0 @@ -# Compile - -mruby uses Rake to compile and cross-compile all libraries and -binaries. - -## Prerequisites - -To compile mruby out of the source code you need the following tools: -* C Compiler (i.e. ```gcc```) -* Linker (i.e. ```gcc```) -* Archive utility (i.e. ```ar```) -* Parser generator (i.e. ```bison```) -* Ruby 1.8 or 1.9 (i.e. ```ruby``` or ```jruby```) - -Optional: -* GIT (to update mruby source and integrate mrbgems easier) -* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc) -* Assembler (to use GEMs which include \*.asm) - -## Usage - -Inside of the root directory of the mruby source a file exists -called *build_config.rb*. This file contains the build configuration -of mruby and looks like this for example: -```ruby -MRuby::Build.new do |conf| - toolchain :gcc -end -``` - -All tools necessary to compile mruby can be set or modified here. In case -you want to maintain an additional *build_config.rb* you can define a -customized path using the *$MRUBY_CONFIG* environment variable. - -To compile just call ```./minirake``` inside of the mruby source root. To -generate and execute the test tools call ```./minirake test```. To clean -all build files call ```./minirake clean```. To see full command line on -build, call ```./minirake -v```. - -## Build Configuration - -Inside of the *build_config.rb* the following options can be configured -based on your environment. - -### Toolchains - -The mruby build system already contains a set of toolchain templates which -configure the build environment for specific compiler infrastructures. - -#### GCC - -Toolchain configuration for the GNU C Compiler. -```ruby -toolchain :gcc -``` - -#### clang - -Toolchain configuration for the LLVM C Compiler clang. Mainly equal to the -GCC toolchain. -```ruby -toolchain :clang -``` - -#### Visual Studio 2010, 2012 and 2013 - -Toolchain configuration for Visual Studio on Windows. If you use the -[Visual Studio Command Prompt](http://msdn.microsoft.com/en-us/library/ms229859\(v=vs.110\).aspx), -you normally do not have to specify this manually, since it gets automatically detected by our build process. -``` -toolchain :visualcpp -``` - -#### Android - -Toolchain configuration for Android. -```ruby -toolchain :android -``` - -Requires the custom standalone Android NDK and the toolchain path -in ```ANDROID_STANDALONE_TOOLCHAIN```. - -### Binaries - -It is possible to select which tools should be compiled during the compilation -process. The following tools can be selected: -* mruby (mruby interpreter) -* mirb (mruby interactive shell) - -To select them declare conf.gem as follows: -```ruby -conf.gem "#{root}/mrbgems/mruby-bin-mruby" -conf.gem "#{root}/mrbgems/mruby-bin-mirb" -``` - -### File Separator - -Some environments require a different file separator character. It is possible to -set the character via ```conf.file_separator```. -```ruby -conf.file_separator = '/' -``` - -### C Compiler - -Configuration of the C compiler binary, flags and include paths. -```ruby -conf.cc do |cc| - cc.command = ... - cc.flags = ... - cc.include_paths = ... - cc.defines = ... - cc.option_include_path = ... - cc.option_define = ... - cc.compile_options = ... -end -``` - -C Compiler has header searcher to detect installed library. - -If you need a include path of header file use ```search_header_path```: -```ruby -# Searches ```iconv.h```. -# If found it will return include path of the header file. -# Otherwise it will return nil . -fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h' -``` - -If you need a full file name of header file use ```search_header```: -```ruby -# Searches ```iconv.h```. -# If found it will return full path of the header file. -# Otherwise it will return nil . -iconv_h = conf.cc.search_header 'iconv.h' -print "iconv.h found: #{iconv_h}\n" -``` - -Header searcher uses compiler's ```include_paths``` by default. -When you are using GCC toolchain (including clang toolchain since its base is gcc toolchain) -it will use compiler specific include paths too. (For example ```/usr/local/include```, ```/usr/include```) - -If you need a special header search paths define a singleton method ```header_search_paths``` to C compiler: -```ruby -def conf.cc.header_search_paths - ['/opt/local/include'] + include_paths -end -``` - -### Linker - -Configuration of the Linker binary, flags and library paths. -```ruby -conf.linker do |linker| - linker.command = ... - linker.flags = ... - linker.flags_before_libraries = ... - linker.libraries = ... - linker.flags_after_libraries = ... - linker.library_paths = .... - linker.option_library = ... - linker.option_library_path = ... - linker.link_options = ... -end -``` - -### Archiver - -Configuration of the Archiver binary and flags. -```ruby -conf.archiver do |archiver| - archiver.command = ... - archiver.archive_options = ... -end -``` - -### Parser Generator - -Configuration of the Parser Generator binary and flags. -```ruby -conf.yacc do |yacc| - yacc.command = ... - yacc.compile_options = ... -end -``` - -### GPerf - -Configuration of the GPerf binary and flags. -```ruby -conf.gperf do |gperf| - gperf.command = ... - gperf.compile_options = ... -end -``` - -### File Extensions -```ruby -conf.exts do |exts| - exts.object = ... - exts.executable = ... - exts.library = ... -end -``` - -### Mrbgems - -Integrate GEMs in the build process. -```ruby -# Integrate GEM with additional configuration -conf.gem 'path/to/gem' do |g| - g.cc.flags << ... -end - -# Integrate GEM without additional configuration -conf.gem 'path/to/another/gem' -``` - -See doc/mrbgems/README.md for more option about mrbgems. - -### Mrbtest - -Configuration Mrbtest build process. - -If you want mrbtest.a only, You should set ```conf.build_mrbtest_lib_only``` -```ruby -conf.build_mrbtest_lib_only -``` - -### Bintest - -Tests for mrbgem tools using CRuby. -To have bintests place \*.rb scripts to ```bintest/``` directory of mrbgems. -See ```mruby-bin-*/bintest/*.rb``` if you need examples. -If you want a temporary files use `tempfile` module of CRuby instead of ```/tmp/```. - -You can enable it with following: -```ruby -conf.enable_bintest -``` - -### C++ ABI - -mruby can use C++ exception to raise exception internally. -It is called C++ ABI mode. -By using C++ exception it can release C++ stack object correctly. -Whenever you mix C++ code C++ ABI mode would be enabled automatically. -If you need to enable C++ ABI mode explicitly add the following: -```ruby -conf.enable_cxx_abi -``` - -#### C++ exception disabling. - -If you need to force C++ exception disable -(For example using a compiler option to disable C++ exception) -add following: -```ruby -conf.disable_cxx_exception -``` - -Note that it must be called before ```enable_cxx_abi``` or ```gem``` method. - -### Debugging mode - -To enable debugging mode add the following: -```ruby -conf.enable_debug -``` - -When debugging mode is enabled -* Macro ```MRB_DEBUG``` would be defined. - * Which means ```mrb_assert()``` macro is enabled. -* Debug information of irep would be generated by ```mrbc```. - * Because ```-g``` flag would be added to ```mrbc``` runner. - * You can have better backtrace of mruby scripts with this. - -## Cross-Compilation - -mruby can also be cross-compiled from one platform to another. To -achieve this the *build_config.rb* needs to contain an instance of -```MRuby::CrossBuild```. This instance defines the compilation -tools and flags for the target platform. An example could look -like this: -```ruby -MRuby::CrossBuild.new('32bit') do |conf| - toolchain :gcc - - conf.cc.flags << "-m32" - conf.linker.flags << "-m32" -end -``` - -All configuration options of ```MRuby::Build``` can also be used -in ```MRuby::CrossBuild```. - -### Mrbtest in Cross-Compilation - -In cross compilation, you can run ```mrbtest``` on emulator if -you have it by changing configuration of test runner. -```ruby -conf.test_runner do |t| - t.command = ... # set emulator. this value must be non nil or false - t.flags = ... # set flags of emulator - - def t.run(bin) # override `run` if you need to change the behavior of it - ... # `bin` is the full path of mrbtest - end -end -``` - -## Build process - -During the build process the directory *build* will be created in the -root directory. The structure of this directory will look like this: - - +- build - | - +- host - | - +- bin <- Binaries (mirb, mrbc and mruby) - | - +- lib <- Libraries (libmruby.a and libmruby_core.a) - | - +- mrblib - | - +- src - | - +- test <- mrbtest tool - | - +- tools - | - +- mirb - | - +- mrbc - | - +- mruby - -The compilation workflow will look like this: -* compile all files under *src* (object files will be stored -in *build/host/src*) -* generate parser grammar out of *src/parse.y* (generated -result will be stored in *build/host/src/y.tab.c*) -* compile *build/host/src/y.tab.c* to *build/host/src/y.tab.o* -* create *build/host/lib/libmruby_core.a* out of all object files (C only) -* create ```build/host/bin/mrbc``` by compiling *tools/mrbc/mrbc.c* and -linking with *build/host/lib/libmruby_core.a* -* create *build/host/mrblib/mrblib.c* by compiling all \*.rb files -under *mrblib* with ```build/host/bin/mrbc``` -* compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o* -* create *build/host/lib/libmruby.a* out of all object files (C and Ruby) -* create ```build/host/bin/mruby``` by compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and -linking with *build/host/lib/libmruby.a* -* create ```build/host/bin/mirb``` by compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and -linking with *build/host/lib/libmruby.a* - -``` - _____ _____ ______ ____ ____ _____ _____ ____ -| CC |->|GEN |->|AR |->|CC |->|CC |->|AR |->|CC |->|CC | -| *.c | |y.tab| |core.a| |mrbc| |*.rb| |lib.a| |mruby| |mirb| - ----- ----- ------ ---- ---- ----- ----- ---- -``` - -### Cross-Compilation - -In case of a cross-compilation to *i386* the *build* directory structure looks -like this: - - +- build - | - +- host - | | - | +- bin <- Native Binaries - | | - | +- lib <- Native Libraries - | | - | +- mrblib - | | - | +- src - | | - | +- test <- Native mrbtest tool - | | - | +- tools - | | - | +- mirb - | | - | +- mrbc - | | - | +- mruby - +- i386 - | - +- bin <- Cross-compiled Binaries - | - +- lib <- Cross-compiled Libraries - | - +- mrblib - | - +- src - | - +- test <- Cross-compiled mrbtest tool - | - +- tools - | - +- mirb - | - +- mrbc - | - +- mruby - -An extra directory is created for the target platform. In case you -compile for *i386* a directory called *i386* is created under the -build directory. - -The cross compilation workflow starts in the same way as the normal -compilation by compiling all *native* libraries and binaries. -Afterwards the cross compilation process proceeds like this: -* cross-compile all files under *src* (object files will be stored -in *build/i386/src*) -* generate parser grammar out of *src/parse.y* (generated -result will be stored in *build/i386/src/y.tab.c*) -* cross-compile *build/i386/src/y.tab.c* to *build/i386/src/y.tab.o* -* create *build/i386/mrblib/mrblib.c* by compiling all \*.rb files -under *mrblib* with the native ```build/host/bin/mrbc``` -* cross-compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o* -* create *build/i386/lib/libmruby.a* out of all object files (C and Ruby) -* create ```build/i386/bin/mruby``` by cross-compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and -linking with *build/i386/lib/libmruby.a* -* create ```build/i386/bin/mirb``` by cross-compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and -linking with *build/i386/lib/libmruby.a* -* create *build/i386/lib/libmruby_core.a* out of all object files (C only) -* create ```build/i386/bin/mrbc``` by cross-compiling *tools/mrbc/mrbc.c* and -linking with *build/i386/lib/libmruby_core.a* - -``` - _______________________________________________________________ -| Native Compilation for Host System | -| _____ ______ _____ ____ ____ _____ | -| | CC | -> |AR | -> |GEN | -> |CC | -> |CC | -> |AR | | -| | *.c | |core.a| |y.tab| |mrbc| |*.rb| |lib.a| | -| ----- ------ ----- ---- ---- ----- | - --------------------------------------------------------------- - || - \||/ - \/ - ________________________________________________________________ -| Cross Compilation for Target System | -| _____ _____ _____ ____ ______ _____ | -| | CC | -> |AR | -> |CC | -> |CC | -> |AR | -> |CC | | -| | *.c | |lib.a| |mruby| |mirb| |core.a| |mrbc | | -| ----- ----- ----- ---- ------ ----- | - ---------------------------------------------------------------- -``` - -## Build Configuration Examples - -### Minimal Library - -To build a minimal mruby library you need to use the Cross Compiling -feature due to the reason that there are functions (i.e. stdio) which -can't be disabled for the main build. - -```ruby -MRuby::CrossBuild.new('Minimal') do |conf| - toolchain :gcc - - conf.cc.defines = %w(MRB_DISABLE_STDIO) - conf.bins = [] -end -``` - -This configuration defines a cross compile build called 'Minimal' which -is using the GCC and compiles for the host machine. It also disables -all usages of stdio and doesn't compile any binaries (i.e. mrbc). - -## Test Environment - -mruby's build process includes a test environment. In case you start the testing -of mruby, a native binary called ```mrbtest``` will be generated and executed. -This binary contains all test cases which are defined under *test/t*. In case -of a cross-compilation an additional cross-compiled *mrbtest* binary is -generated. You can copy this binary and run on your target system. diff -Nru nghttp2-1.13.0/third-party/mruby/doc/guides/debugger.md nghttp2-0.6.7/third-party/mruby/doc/guides/debugger.md --- nghttp2-1.13.0/third-party/mruby/doc/guides/debugger.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/doc/guides/debugger.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,370 +0,0 @@ -# How to Use the mruby Debugger - -copyright (c) 2014 Specified Non-Profit Corporation mruby Forum - -## 1. Summary - -This file documents the mruby debugger ('mrdb') methods. - -## 2 Debugging with mrdb - -## 2.1 Building mrdb - -The trunk of the mruby source tree, with the most recent mrdb, can be checked out with the following command: - -```bash -$ git clone https://github.com/mruby/mruby.git -``` - -To run the `make` command: - -```bash -$ cd mruby -$ make -``` - -By default, the `make` command will install the debugger files into mruby/bin. - -You can add the path for mrdb on your host environment with the following command: - -```bash -$ echo "export PATH=\$PATH:MRUBY_ROOT/bin" >> ~/.bashrc -$ source ~/.bashrc -``` - -`*MRUBY_ROOT` is the directory in which mruby source code will be installed. - -To confirm mrdb was installed properly, run mrdb with the `--version` option: - -```bash -$ mrdb --version -mruby 1.2.0 (2014-11-17) -``` - -## 2.2 Basic Operation - -### 2.2.1 Debugging mruby Script Files (rb file) with mrdb - -To invoke the mruby debugger, just type `mrdb`. - -To specify the script file: - -```bash -$ mrdb [option] file name -``` - -For example: Debugging sample.rb - -```bash -$ mrdb sample.rb -``` - -You can execute the shell commands listed below: - -|command|description| -|:-:|:--| -|run|execute programs| -|step|execute stepping| -|continue|execute continuing program| -|break|configure the breaking point| -|delete|deleting the breaking points| -|disable|disabling the breaking points| -|enable|enabling the breaking points| -|info breakpoints|showing list of the breaking points| -|print|evaluating and printing the values of the mruby expressions in the script| -|list|displaying the source cords| -|help|showing help| -|quit|terminating the mruby debugger| - -### 2.2.2 Debugging mruby Binary Files (mrb file) with mrdb - -You can debug the mruby binary files. - -#### 2.2.2.1 Debugging the binary files - -* notice -To debug mruby binary files, you need to compile mruby files with option `-g`. - -```bash -$ mrbc -g sample.rb -``` - -You can debug the mruby binary files with following command and the option `-b`. - -```bash -$ mrdb -b sample.mrb -``` - -Then you can execute all debugger shell commands. - -#### Break Command - -You can use any breakpoint to stop the program by specifying the line number and method name. -The breakpoint list will be displayed after you have set the breakpoint successfully. - -Usage: - -``` -break [file:]linenum -b [file:]linenum -break [class:]method -b [class:]method -``` - -The breakpoint will be ordered in serial from 1. -The number, which was given to the deleted breakpoint, will never be given to another breakpoint again. - -You can give multiple breakpoints to specified the line number and method. -Be ware that breakpoint command will not check the validity of the class name and method name. - -You can get the current breakpoint information by the following options. - -breakpoint breakpoint number : file name. line number - -breakpoint breakpoint number : [class name,] method name - -#### Continue Command - -Usage: - -``` -continue [N] -c [N] -``` - -N: the next breakpoint number - -When resuming the program, it will stop at breakpoint N (N-1 breakpoint will be ignored). - -When you run the `continue` command without specifying N, the program will be stopped at the next breakpoint. - -Example: - -``` -(foo.rb:1) continue 3 -``` - -This will resume the program and stop it at the third breakpoint. - -#### Delete Command - -This will delete the specified breakpoint. - -Usage: - -``` -delete [breakpoint-no] -d [breakpoint-no] -``` - -breakpoint-no: breakpoint number - -Example: - -``` -(foo.rb:1) delete -``` - -This will delete all of the breakpoints. - -``` -(foo.rb:1) delete 1 3 -``` - -This will delete the breakpoint at 1 and 3. - -#### Disable Command - -This will disable the specified breakpoint. - -Usage: - -``` -disable [breakpoint-no] -dis [breakpoint-no] -``` - -reappointing: breakpoint number - -Example: - -``` -(foo.rb:1) disable -``` - -Use `disable` if you would like to disable all of the breakpoints. - -``` -(foo.rb:1) disable 1 3 -``` - -This will disable the breakpoints at 1 and 3. - -#### Enable Command - -This will enable the specified breakpoints. - -Usage: - -``` -enable [breakpoint-no] -e [breakpoint-no] -``` - -breakpoint-no: breakpoint number - -Example: - -``` -(foo.rb:1) enable -``` - -Enabling all breakpoints -``` -(foo.rb:1) enable 1 3 -``` - -Enabling the breakpoint 1 and 3 - -#### eval command - -Evaluating the string as source code and printing the value. - -Same as print command, please see print command. - -#### help command - -Displaying the help message. - -Usage: - -``` -help [command] -h [command] -``` - -Typing `help` without any options will display the command list. - -#### Info Breakpoints Command - -Displaying the specified breakpoint information. - -Usage: - -``` -info breakpoints [breakpoint-no] -i b [breakpoint-no] -``` - -breakpoint-no: breakpoint number - -Typing "info breakpoints" without ant option will display all breakpoint information. -Example: - -``` -(sample.rb:1) info breakpoints -Num Type Enb What -1 breakpoint y at sample.rb:3 -> file name,line number -2 breakpoint n in Sample_class:sample_class_method -> [class:]method name -3 breakpoint y in sample_global_method -``` - -Displaying the specified breakpoint number: - -``` -(foo.rb:1) info breakpoints 1 3 -Num Type Enb What -1 breakpoint y at sample.rb:3 -3 breakpoint y in sample_global_method -``` - -#### List Command - -To display the code of the source file. - -Usage: - -``` -list [filename:]first[,last] -l [filename]:first[,last] -``` - -first: the opening row number -last : the closing row number - -When you specify the `first`, but not the `last` option, you will receive 10 rows. -When you do not specify both the `first` and `last` options, you will receive the next 10 rows. - -Example: - -``` -Specifying file name and first row number -sample.rb:1) list sample2.rb:5 -``` - -Specifying the file name and the first and last row number: - -``` -(sample.rb:1) list sample2.rb:6,7 -``` - -#### Print Command - -Evaluating the string as source code and printing the value. - -Usage: - -``` -print [expr] -p [expr] -``` - -expr: expression - -The expression is mandatory. -The displayed expressions will be serially ordered from 1. -If an exception occurs, the exception information will be displayed and the debugging will be continued. - -Example: - -``` -(sample.rb:1) print 1+2 -$1 = 3 -(sample.rb:1) print self -$2 = main -``` - -Below is the case of the exception: - -``` -(sample.rb:1) print (1+2 -$1 = SyntaxError: line 1: syntax error, unexpected $end, expecting ')' -``` - -#### Quit Command - -Quitting the debugger. - -Usage: - -``` -quit -q -``` - -#### Run Command - -Running the program and stopping at the first breakpoint. - -Usage: - -``` -run -r -``` - -#### Step Command - -This will run the program step by step. -When the method and the block are invoked, the program will be stop at the first row. -The program, which is developed in C, will be ignored. diff -Nru nghttp2-1.13.0/third-party/mruby/doc/guides/gc-arena-howto.md nghttp2-0.6.7/third-party/mruby/doc/guides/gc-arena-howto.md --- nghttp2-1.13.0/third-party/mruby/doc/guides/gc-arena-howto.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/doc/guides/gc-arena-howto.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,171 +0,0 @@ -# How to use `mrb_gc_arena_save()`/`mrb_gc_arena_restore()` - -This is basically English translation of [Matz's blog post](http://www.rubyist.net/~matz/20130731.html) written in Japanese. -Some parts are updated to reflect recent changes. - -When you are extending mruby using C language, you may encounter -mysterious "arena overflow error" or memory leak or very slow -execution speed. This is an error indicating overflow of "GC arena" -implementing "conservative GC". - -GC (garbage collector) must ensure that object is "alive", in other -words, that it is referenced by somewhere from program. This can be -determined by checking that that object can be directly or indirectly -referenced by root. The local variables, global variables and -constants etc are root. - -If program execution is performed inside mruby VM, there is nothing to -worry about because GC can access all roots owned by VM. - -The problem arises when executing C functions. The object referenced -by C variable is also "alive", but mruby GC cannot aware of this, so -it might mistakenly recognize the objects referenced by only C -variables as dead. - -It is a fatal bug for GC to collect live objects. - -In CRuby, we scan C stack area, and use C variable as root to check -whether object is alive or not. Of course, because we are accessing C -stack just as memory region, we never know it is an integer or a -pointer. We workaround this by assuming that if it looks like a -pointer, then assume it as a pointer. We call it "conservative". - -By the way, CRuby's "conservative GC" has some problems. - -Its biggest problem is we have no way to access to the stack area in -portable way. Therefore, we cannot use this method if we'd like to -implement highly portable runtime, like mruby. - -So we came up an another plan to implement "conservative GC" in mruby. - -Again, the problem is that there is an object which was created in C -function, and is not referenced by Ruby world, and cannot be treated -as garbage. - -In mruby, we recognize all objects created in C function are alive. -Then we have no problem such as recognizing live object as dead. - -This means that because we cannot collect truly dead object, we may -get a little bit less efficiency, but GC itself is highly portable. -We can say goodbye to the problem that GC deletes live objects due to -optimization which sometimes occurs in CRuby. - -According to this idea, we have a table, called "GC arena", which -remembers objects created in C function. The arena is stack -structure, when C function execution is returned to mruby VM, all -objects registered in the arena are popped. - -This works very well, but GC arena causes another problem. "arena -overflow error" or memory leak. - -As of this writing, mruby automatically extend arena to remember -objects (See `MRB_GC_FIXED_ARENA` and `MRB_GC_ARENA_SIZE` in -doc/mrbconf/README.md). If you keep creating objects in C functions, -it increases memory usage, since GC never kick in. This memory usage -may look like memory leak, and also makes execution slower. - -With the build time configuration, you can limit the maximum size of -arena (e.g., 100). Then if you create many objects, arena overflows, -thus you will get "arena overflow error". - -To workaround these problems, we have `mrb_gc_arena_save()` and -`mrb_gc_arena_restore()` functions. - -`int mrb_gc_arena_save(mrb)` returns the current position of the stack -top of GC arena, and `void mrb_gc_arena_restore(mrb, idx)` sets the -stack top position to back to given idx. We uses them like so: - -```c -int arena_idx = mrb_gc_arena_save(mrb); - -...create objects... -mrb_gc_arena_restore(mrb, arena_idx); - -``` - -In mruby, C function call are surrounded by this save/restore, but we -can further optimize memory usage by surrounding save/restore, and can -avoid arena overflow. - -Let's take a real example. Here is the source code of `Array#inspect`: - -```c -static mrb_value -inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) -{ - mrb_int i; - mrb_value s, arystr; - char head[] = { '[' }; - char sep[] = { ',', ' ' }; - char tail[] = { ']' }; - - /* check recursive */ - for(i=0; i 0) { - mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep)); - } - if (mrb_array_p(RARRAY_PTR(ary)[i])) { - s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list); - } - else { - s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]); - } - mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s)); - mrb_gc_arena_restore(mrb, ai); - } - - mrb_str_buf_cat(mrb, arystr, tail, sizeof(tail)); - mrb_ary_pop(mrb, list); - - return arystr; -} -``` - -This is a real example, so a little bit complicated, so bear with me. -The essence of `Array#inspect` is that after stringifying each element -of array using `inspect` method, we join them together so that we can -get `inspect` representation of entire array. - -After the `inspect` representation of entire array is created, we no -longer require the individual string representation. That means that -we don't have to register these temporal objects into GC arena. - -Therefore, in `ary_inspect()` function, we do: - -* save the position of the stack top using `mrb_gc_arena_save()`. -* get `inspect` representation of each element. -* append it to the constructing entire `inspect` representation of array. -* restore stack top position using `mrb_gc_arena_restore()`. - -to keep the arena size small. - -Please note that the final `inspect` representation of entire array -was created before the call of `mrb_gc_arena_restore()`. Otherwise, -required temporal object may be deleted by GC. - -We may have a usecase that after creating many temporal objects, we'd -like to keep some of them. In this case, we cannot use the same idea -in `ary_inspect()` like appending objects to existing one. Instead, -after `mrb_gc_arena_restore()`, we register back the objects we'd like -to keep to the arena using `mrb_gc_protect(mrb, obj)`. Use -`mrb_gc_protect()` with caution because its usage could lead to arena -overflow error. - -We also have to mention that when `mrb_funcall` is called in top -level, its return value is also registered to GC arena, so calling -them repeatedly eventually lead to arena overflow error. Use -`mrb_gc_arena_save()` and `mrb_gc_arena_restore()` or possible use of -`mrb_gc_protect()` to workaround this. diff -Nru nghttp2-1.13.0/third-party/mruby/doc/guides/mrbconf.md nghttp2-0.6.7/third-party/mruby/doc/guides/mrbconf.md --- nghttp2-1.13.0/third-party/mruby/doc/guides/mrbconf.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/doc/guides/mrbconf.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,157 +0,0 @@ -# mruby configuration macros. - -## How to use these macros. -You can use mrbconfs with following ways: -* Write them in `mrbconf.h`. - * Using compiler flags is preferred when building a cross binaries or multiple mruby binaries - since it's easier to use different mrbconf per each `MRuby::Build`. - * Most flags can be enabled by just commenting in. -* Pass them as compiler flags. - * Make sure you pass the same flags to all compilers since some mrbconf(e.g., `MRB_GC_FIXED_ARENA`) - changes `struct` layout and cause memory access error when C and other language(e.g., C++) is mixed. - -## stdio setting. -`MRB_DISABLE_STDIO` -* When defined `` functions won't be used. -* Some features will be disabled when this is enabled: - * `mrb_irep` load/dump from/to file. - * Compiling mruby script from file. - * Printing features in **src/print.c**. - -## Debug macros. -`MRB_ENABLE_DEBUG_HOOK` -* When defined code fetch hook and debug OP hook will be enabled. -* When using any of the hook set function pointer `code_fetch_hook` and/or `debug_op_hook` of `mrb_state`. -* Fetch hook will be called before any OP. -* Debug OP hook will be called when dispatching `OP_DEBUG`. - -`MRB_DEBUG` -* When defined `mrb_assert*` macro will be defined with macros from ``. -* Could be enabled via `enable_debug` method of `MRuby::Build`. - -## Stack configuration - -`MRB_STACK_EXTEND_DOUBLING` -* If defined doubles the stack size when extending it. -* Else extends stack with `MRB_STACK_GROWTH`. - -`MRB_STACK_GROWTH` -* Default value is `128`. -* Used in stack extending. -* Ignored when `MRB_STACK_EXTEND_DOUBLING` is defined. - -`MRB_STACK_MAX` -* Default value is `0x40000 - MRB_STACK_GROWTH`. -* Raises `RuntimeError` when stack size exceeds this value. - -## Primitive type configuration. - -`MRB_USE_FLOAT` -* When defined single precision floating point type(C type `float`) is used as `mrb_float`. -* Else double precision floating point type(C type `double`) is used as `mrb_float`. - -`MRB_INT16` -* When defined `int16_t` will be defined as `mrb_int`. -* Conflicts with `MRB_INT64`. - -`MRB_INT64` -* When defined `int64_t` will be defined as `mrb_int`. -* Conflicts with `MRB_INT16`. -* When `MRB_INT16` or `MRB_INT64` isn't defined `int`(most of the times 32-bit integer) -will be defined as `mrb_int`. - -## Garbage collector configuration. - -`MRB_GC_STRESS` -* When defined full GC is emitted per each `RBasic` allocation. -* Mainly used in memory manager debugging. - -`MRB_GC_TURN_OFF_GENERATIONAL` -* When defined turns generational GC by default. - -`MRB_GC_FIXED_ARENA` -* When defined used fixed size GC arena. -* Raises `RuntimeError` when this is defined and GC arena size exceeds `MRB_GC_ARENA_SIZE`. -* Useful tracking unnecessary mruby object allocation. - -`MRB_GC_ARENA_SIZE` -* Default value is `100`. -* Ignored when `MRB_GC_FIXED_ARENA` isn't defined. -* Defines fixed GC arena size. - -`MRB_HEAP_PAGE_SIZE` -* Defines value is `1024`. -* Specifies number of `RBasic` per each heap page. - -## Memory pool configuration. - -`POOL_ALIGNMENT` -* Default value is `4`. -* If you're allocating data types that requires alignment more than default value define the -largest value of required alignment. - -`POOL_PAGE_SIZE` -* Default value is `16000`. -* Specifies page size of pool page. -* Smaller the value is increases memory overhead. - -## State atexit configuration. - -`MRB_FIXED_STATE_ATEXIT_STACK` -* If defined enables fixed size `mrb_state` atexit stack. -* Raises `RuntimeError` when `mrb_state_atexit` call count to same `mrb_state` exceeds -`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`'s value. - -`MRB_FIXED_STATE_ATEXIT_STACK_SIZE` -* Default value is `5`. -* If `MRB_FIXED_STATE_ATEXIT_STACK` isn't defined this macro is ignored. - -## `mrb_value` configuration. - -`MRB_ENDIAN_BIG` -* If defined compiles mruby for big endian machines. -* Used in `MRB_NAN_BOXING`. -* Some mrbgem use this mrbconf. - -`MRB_NAN_BOXING` -* If defined represent `mrb_value` in boxed `double`. -* Conflicts with `MRB_USE_FLOAT`. - -`MRB_WORD_BOXING` -* If defined represent `mrb_value` as a word. -* If defined `Float` will be a mruby object with `RBasic`. - -## Instance variable configuration. -`MRB_USE_IV_SEGLIST` -* If defined enable segmented list in instance variable table instead of khash. -* Segmented list is a linked list of key and value segments. -* It will linear search instead of hash search. - -`MRB_SEGMENT_SIZE` -* Default value is `4`. -* Specifies size of each segment in segment list. -* Ignored when `MRB_USE_IV_SEGLIST` isn't defined. - -`MRB_IVHASH_INIT_SIZE` -* Default value is `8`. -* Specifies initial size for instance variable table. -* Ignored when `MRB_USE_IV_SEGLIST` is defined. - -## Other configuration. -`MRB_UTF8_STRING` -* Adds UTF-8 encoding support to character-oriented String instance methods. -* If it isn't defined, they only support the US-ASCII encoding. - -`MRB_FUNCALL_ARGC_MAX` -* Default value is `16`. -* Specifies 4th argument(`argc`) max value of `mrb_funcall`. -* Raises `ArgumentError` when the `argc` argument is bigger then this value `mrb_funcall`. - -`KHASH_DEFAULT_SIZE` -* Default value is `32`. -* Specifies default size of khash table bucket. -* Used in `kh_init_ ## name` function. - -`MRB_STR_BUF_MIN_SIZE` -* Default value is `128`. -* Specifies initial capacity of `RString` created by `mrb_str_buf_new` function.. diff -Nru nghttp2-1.13.0/third-party/mruby/doc/guides/mrbgems.md nghttp2-0.6.7/third-party/mruby/doc/guides/mrbgems.md --- nghttp2-1.13.0/third-party/mruby/doc/guides/mrbgems.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/doc/guides/mrbgems.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,337 +0,0 @@ -# mrbgems - -mrbgems is a library manager to integrate C and Ruby extension in an easy and -standardised way into mruby. - -## Usage - -By default mrbgems is currently deactivated. As soon as you add a GEM to your -build configuration (i.e. *build_config.rb*), mrbgems will be activated and the -extension integrated. - -To add a GEM into the *build_config.rb* add the following line for example: -```ruby -conf.gem '/path/to/your/gem/dir' -``` - -You can also use a relative path which would be relative from the mruby root: -```ruby -conf.gem 'examples/mrbgems/ruby_extension_example' -``` - -A remote GIT repository location for a GEM is also supported: -```ruby -conf.gem :git => 'https://github.com/masuidrive/mrbgems-example.git', :branch => 'master' -conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master' -conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master' -``` - -To use mrbgem from [mgem-list](https://github.com/mruby/mgem-list) use `:mgem` option: -```ruby -conf.gem :mgem => 'mruby-yaml' -conf.gem :mgem => 'yaml' # 'mruby-' prefix could be omitted -``` - -If there is missing dependencies, mrbgem dependencies solver will reference -mrbgem from core or mgem-list. - -To pull all gems from remote GIT repository on build, call ```./minirake -p```, -or ```./minirake --pull-gems```. - -NOTE: `:bitbucket` option supports only git. Hg is unsupported in this version. - -## GemBox - -There are instances when you wish to add a collection of mrbgems into mruby at -once, or be able to substitute mrbgems based on configuration, without having to -add each gem to the *build_config.rb* file. A packaged collection of mrbgems -is called a GemBox. A GemBox is a file that contains a list of mrbgems to load -into mruby, in the same format as if you were adding them to *build_config.rb* -via `config.gem`, but wrapped in an `MRuby::GemBox` object. GemBoxes are -loaded into mruby via `config.gembox 'boxname'`. - -Below we have created a GemBox containing *mruby-time* and *mrbgems-example*: -```ruby -MRuby::GemBox.new do |conf| - conf.gem "#{root}/mrbgems/mruby-time" - conf.gem :github => 'masuidrive/mrbgems-example' -end -``` - -As mentioned, the GemBox uses the same conventions as `MRuby::Build`. The GemBox -must be saved with a *.gembox* extension inside the *mrbgems* directory to to be -picked up by mruby. - -To use this example GemBox, we save it as `custom.gembox` inside the *mrbgems* -directory in mruby, and add the following to our *build_config.rb* file inside -the build block: -```ruby -conf.gembox 'custom' -``` -This will cause the *custom* GemBox to be read in during the build process, -adding *mruby-time* and *mrbgems-example* to the build. - -If you want, you can put GemBox outside of mruby directory. In that case you must -specify an absolute path like below. -```ruby -conf.gembox "#{ENV["HOME"]}/mygemboxes/custom" -``` - -There are two GemBoxes that ship with mruby: [default](../../mrbgems/default.gembox) -and [full-core](../../mrbgems/full-core.gembox). The [default](../../mrbgems/default.gembox) GemBox -contains several core components of mruby, and [full-core](../../mrbgems/full-core.gembox) -contains every gem found in the *mrbgems* directory. - -## GEM Structure - -The maximal GEM structure looks like this: - - +- GEM_NAME <- Name of GEM - | - +- include/ <- Header for Ruby extension (will exported) - | - +- mrblib/ <- Source for Ruby extension - | - +- src/ <- Source for C extension - | - +- test/ <- Test code (Ruby) - | - +- mrbgem.rake <- GEM Specification - | - +- README.md <- Readme for GEM - -The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src* -contains C/C++ files to extend mruby. The folder *include* contains C/C++ header -files. The folder *test* contains C/C++ and pure Ruby files for testing purposes -which will be used by `mrbtest`. *mrbgem.rake* contains the specification -to compile C and Ruby files. *README.md* is a short description of your GEM. - -## Build process - -mrbgems expects a specification file called *mrbgem.rake* inside of your -GEM directory. A typical GEM specification could look like this for example: -```ruby -MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Example mrbgem using C and ruby' -end -``` - -The mrbgems build process will use this specification to compile Object and Ruby -files. The compilation results will be added to *lib/libmruby.a*. This file exposes -the GEM functionality to tools like `mruby` and `mirb`. - -The following properties can be set inside of your `MRuby::Gem::Specification` for -information purpose: - -* `spec.license` or `spec.licenses` (A single license or a list of them under which this GEM is licensed) -* `spec.author` or `spec.authors` (Developer name or a list of them) -* `spec.version` (Current version) -* `spec.description` (Detailed description) -* `spec.summary` - * One line short description of mrbgem. - * Printed in build summary of rake when set. -* `spec.homepage` (Homepage) -* `spec.requirements` (External requirements as information for user) - -The `license` and `author` properties are required in every GEM! - -In case your GEM is depending on other GEMs please use -`spec.add_dependency(gem, *requirements[, default_get_info])` like: -```ruby -MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - - # Add GEM dependency mruby-parser. - # The version must be between 1.0.0 and 1.5.2 . - spec.add_dependency('mruby-parser', '>= 1.0.0', '<= 1.5.2') - - # Use any version of mruby-uv from github. - spec.add_dependency('mruby-uv', '>= 0.0.0', :github => 'mattn/mruby-uv') - - # Use latest mruby-onig-regexp from github. (version requirements can be omitted) - spec.add_dependency('mruby-onig-regexp', :github => 'mattn/mruby-onig-regexp') -end -``` - -The version requirements and default gem information are optional. - -Version requirement supports following operators: -* '=': is equal -* '!=': is not equal -* '>': is greater -* '<': is lesser -* '>=': is equal or greater -* '<=': is equal or lesser -* '~>': is equal or greater and is lesser than the next major version - * example 1: '~> 2.2.2' means '>= 2.2.2' and '< 2.3.0' - * example 2: '~> 2.2' means '>= 2.2.0' and '< 3.0.0' - -When more than one version requirements is passed, the dependency must satisfy all of it. - -You can have default gem to use as depedency when it's not defined in *build_config.rb*. -When the last argument of `add_dependency` call is `Hash`, it will be treated as default gem information. -Its format is same as argument of method `MRuby::Build#gem`, expect that it can't be treated as path gem location. - -When a special version of depedency is required, -use `MRuby::Build#gem` in *build_config.rb* to override default gem. - -If you have conflicting GEMs use the following method: -* `spec.add_conflict(gem, *requirements)` - * The `requirements` argument is same as in `add_dependency` method. - -like following code: -```ruby -MRuby::Gem::Specification.new 'some-regexp-binding' do |spec| - spec.license = 'BSD' - spec.author = 'John Doe' - - spec.add_conflict 'mruby-onig-regexp', '> 0.0.0' - spec.add_conflict 'mruby-hs-regexp' - spec.add_conflict 'mruby-pcre-regexp' - spec.add_conflict 'mruby-regexp-pcre' -end -``` - -In case your GEM has more complex build requirements you can use -the following options additionally inside of your GEM specification: - -* `spec.cc.flags` (C compiler flags) -* `spec.cc.defines` (C compiler defines) -* `spec.cc.include_paths` (C compiler include paths) -* `spec.linker.flags` (Linker flags) -* `spec.linker.libraries` (Linker libraries) -* `spec.linker.library_paths` (Linker additional library path) -* `spec.bins` (Generate binary file) -* `spec.rbfiles` (Ruby files to compile) -* `spec.objs` (Object files to compile) -* `spec.test_rbfiles` (Ruby test files for integration into mrbtest) -* `spec.test_objs` (Object test files for integration into mrbtest) -* `spec.test_preload` (Initialization files for mrbtest) - -You also can use `spec.mruby.cc` and `spec.mruby.linker` to add extra global parameters for compiler and linker. - -### include_paths and dependency - -Your GEM can export include paths to another GEMs that depends on your GEM. -By default, `/...absolute path.../{GEM_NAME}/include` will be exported. -So it is recommended not to put GEM's local header files on include/. - -These exports are retroactive. -For example: when B depends to C and A depends to B, A will get include paths exported by C. - -Exported include_paths are automatically appended to GEM local include_paths by Minirake. -You can use `spec.export_include_paths` accessor if you want more complex build. - - -## C Extension - -mruby can be extended with C. This is possible by using the C API to -integrate C libraries into mruby. - -### Preconditions - -mrbgems expects that you have implemented a C method called -`mrb_YOURGEMNAME_gem_init(mrb_state)`. `YOURGEMNAME` will be replaced -by the name of your GEM. If you call your GEM *c_extension_example*, your -initialisation method could look like this: -```C -void -mrb_c_extension_example_gem_init(mrb_state* mrb) { - struct RClass *class_cextension = mrb_define_module(mrb, "CExtension"); - mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE()); -} -``` - -### Finalize - -mrbgems expects that you have implemented a C method called -`mrb_YOURGEMNAME_gem_final(mrb_state)`. `YOURGEMNAME` will be replaced -by the name of your GEM. If you call your GEM *c_extension_example*, your -finalizer method could look like this: - -```C -void -mrb_c_extension_example_gem_final(mrb_state* mrb) { - free(someone); -} -``` - -### Example - - +- c_extension_example/ - | - +- src/ - | | - | +- example.c <- C extension source - | - +- test/ - | | - | +- example.rb <- Test code for C extension - | - +- mrbgem.rake <- GEM specification - | - +- README.md - -## Ruby Extension - -mruby can be extended with pure Ruby. It is possible to override existing -classes or add new ones in this way. Put all Ruby files into the *mrblib* -folder. - - -### Pre-Conditions - -none - -### Example - - +- ruby_extension_example/ - | - +- mrblib/ - | | - | +- example.rb <- Ruby extension source - | - +- test/ - | | - | +- example.rb <- Test code for Ruby extension - | - +- mrbgem.rake <- GEM specification - | - +- README.md - -## C and Ruby Extension - -mruby can be extended with C and Ruby at the same time. It is possible to -override existing classes or add new ones in this way. Put all Ruby files -into the *mrblib* folder and all C files into the *src* folder. - -mruby codes under *mrblib* directory would be executed after gem init C -function is called. Make sure *mruby script* depends on *C code* and -*C code* doesn't depend on *mruby script*. - -### Pre-Conditions - -See C and Ruby example. - -### Example - - +- c_and_ruby_extension_example/ - | - +- mrblib/ - | | - | +- example.rb <- Ruby extension source - | - +- src/ - | | - | +- example.c <- C extension source - | - +- test/ - | | - | +- example.rb <- Test code for C and Ruby extension - | - +- mrbgem.rake <- GEM specification - | - +- README.md diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - - # Add compile flags - # spec.cc.flags << '' - - # Add cflags to all - # spec.mruby.cc.flags << '-g' - - # Add libraries - # spec.linker.libraries << 'external_lib' - - # Default build files - # spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb") - # spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) } - # spec.test_rbfiles = Dir.glob("#{dir}/test/*.rb") - # spec.test_objs = Dir.glob("#{dir}/test/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) } - # spec.test_preload = 'test/assert.rb' - - # Values accessible as TEST_ARGS inside test scripts - # spec.test_args = {'tmp_dir' => Dir::tmpdir} -end diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -module CRubyExtension - def CRubyExtension.ruby_method - puts "A Ruby Extension" - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/README.md nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/README.md --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/README.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -C and Ruby Extension Example -========= - -This is an example gem which implements a C and Ruby extension. diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#include -#include - -static mrb_value -mrb_c_method(mrb_state *mrb, mrb_value self) -{ - puts("A C Extension"); - return self; -} - -void -mrb_c_and_ruby_extension_example_gem_init(mrb_state* mrb) { - struct RClass *class_cextension = mrb_define_module(mrb, "CRubyExtension"); - mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE()); -} - -void -mrb_c_and_ruby_extension_example_gem_final(mrb_state* mrb) { - /* finalizer */ -} diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -assert('C and Ruby Extension Example 1') do - CRubyExtension.respond_to? :c_method -end - -assert('C and Ruby Extension Example 2') do - CRubyExtension.respond_to? :ruby_method -end diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_extension_example/mrbgem.rake nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_extension_example/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_extension_example/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_extension_example/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -MRuby::Gem::Specification.new('c_extension_example') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - - # Add compile flags - # spec.cc.flags << '-g' - - # Add cflags to all - # spec.mruby.cc.flags << '-g' - - # Add libraries - # spec.linker.libraries << 'external_lib' - - # Default build files - # spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb") - # spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) } - # spec.test_rbfiles = Dir.glob("#{dir}/test/*.rb") - # spec.test_objs = Dir.glob("#{dir}/test/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) } - # spec.test_preload = 'test/assert.rb' - - # Values accessible as TEST_ARGS inside test scripts - # spec.test_args = {'tmp_dir' => Dir::tmpdir} -end diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_extension_example/README.md nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_extension_example/README.md --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_extension_example/README.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_extension_example/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -C Extension Example -========= - -This is an example gem which implements a C extension. diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_extension_example/src/example.c nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_extension_example/src/example.c --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_extension_example/src/example.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_extension_example/src/example.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -#include -#include - -static mrb_value -mrb_c_method(mrb_state *mrb, mrb_value self) -{ - puts("A C Extension"); - return self; -} - -void -mrb_c_extension_example_gem_init(mrb_state* mrb) { - struct RClass *class_cextension = mrb_define_module(mrb, "CExtension"); - mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE()); -} - -void -mrb_c_extension_example_gem_final(mrb_state* mrb) { - /* finalizer */ -} diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_extension_example/test/example.c nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_extension_example/test/example.c --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_extension_example/test/example.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_extension_example/test/example.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#include - -void -mrb_c_extension_example_gem_test(mrb_state *mrb) -{ - /* test initializer in C */ -} diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_extension_example/test/example.rb nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_extension_example/test/example.rb --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/c_extension_example/test/example.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/c_extension_example/test/example.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -assert('C Extension Example') do - CExtension.respond_to? :c_method -end diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/ruby_extension_example/mrbgem.rake nghttp2-0.6.7/third-party/mruby/examples/mrbgems/ruby_extension_example/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/ruby_extension_example/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/ruby_extension_example/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -MRuby::Gem::Specification.new('ruby_extension_example') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - - # Add compile flags - # spec.cc.flags << '' - - # Add cflags to all - # spec.mruby.cc.flags << '-g' - - # Add libraries - # spec.linker.libraries << 'external_lib' - - # Default build files - # spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb") - # spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) } - # spec.test_rbfiles = Dir.glob("#{dir}/test/*.rb") - # spec.test_objs = Dir.glob("#{dir}/test/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) } - # spec.test_preload = 'test/assert.rb' - - # Values accessible as TEST_ARGS inside test scripts - # spec.test_args = {'tmp_dir' => Dir::tmpdir} -end diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb nghttp2-0.6.7/third-party/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -class RubyExtension - def RubyExtension.ruby_method - puts "A Ruby Extension" - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/ruby_extension_example/README.md nghttp2-0.6.7/third-party/mruby/examples/mrbgems/ruby_extension_example/README.md --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/ruby_extension_example/README.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/ruby_extension_example/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -Pure Ruby Extension Example -========= - -This is an example gem which implements a pure Ruby extension. diff -Nru nghttp2-1.13.0/third-party/mruby/examples/mrbgems/ruby_extension_example/test/example.rb nghttp2-0.6.7/third-party/mruby/examples/mrbgems/ruby_extension_example/test/example.rb --- nghttp2-1.13.0/third-party/mruby/examples/mrbgems/ruby_extension_example/test/example.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/mrbgems/ruby_extension_example/test/example.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -assert('Ruby Extension Example') do - RubyExtension.respond_to? :ruby_method -end diff -Nru nghttp2-1.13.0/third-party/mruby/examples/targets/build_config_ArduinoDue.rb nghttp2-0.6.7/third-party/mruby/examples/targets/build_config_ArduinoDue.rb --- nghttp2-1.13.0/third-party/mruby/examples/targets/build_config_ArduinoDue.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/targets/build_config_ArduinoDue.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -MRuby::Build.new do |conf| - - # Gets set by the VS command prompts. - if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] - toolchain :visualcpp - else - toolchain :gcc - end - - enable_debug - - # include the default GEMs - conf.gembox 'default' - -end - -# Cross Compiling configuration for Arduino Due -# http://arduino.cc/en/Main/ArduinoBoardDue -# -# Requires Arduino IDE >= 1.5 -MRuby::CrossBuild.new("ArduinoDue") do |conf| - toolchain :gcc - - # Mac OS X, Arduino IDE <= 1.5.6 - # ARDUINO_PATH = '/Applications/Arduino.app/Contents/Resources/Java' - # Mac OS X, Arduino IDE >= 1.5.7 - # ARDUINO_PATH = '/Applications/Arduino.app/Contents/Java' - # GNU Linux - ARDUINO_PATH = '/opt/arduino' - # Arduino IDE <= 1.5.6 - BIN_PATH = "#{ARDUINO_PATH}/hardware/tools/g++_arm_none_eabi/bin" - # Arduino IDE >= 1.5.7 - # BIN_PATH = "#{ARDUINO_PATH}/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin" - SAM_PATH = "#{ARDUINO_PATH}/hardware/arduino/sam" - TARGET_PATH = "#{SAM_PATH}/variants/arduino_due_x" - - conf.cc do |cc| - cc.command = "#{BIN_PATH}/arm-none-eabi-gcc" - cc.include_paths << ["#{SAM_PATH}/system/libsam", "#{SAM_PATH}/system/CMSIS/CMSIS/Include/", - "#{SAM_PATH}/system/CMSIS/Device/ATMEL/", - "#{SAM_PATH}/cores/arduino", "#{SAM_PATH}/libraries","#{TARGET_PATH}"] - cc.flags = %w(-g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 - -Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=156 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM - -D__SAM3X8E__ -mthumb -DUSB_PID=0x003e -DUSB_VID=0x2341 -DUSBCON -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Due") - cc.compile_options = "%{flags} -o %{outfile} -c %{infile}" - - #configuration for low memory environment - cc.defines << %w(MRB_HEAP_PAGE_SIZE=64) - cc.defines << %w(MRB_USE_IV_SEGLIST) - cc.defines << %w(KHASH_DEFAULT_SIZE=8) - cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) - cc.defines << %w(MRB_GC_STRESS) - #cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio. - #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval - end - - conf.cxx do |cxx| - cxx.command = conf.cc.command.dup - cxx.include_paths = conf.cc.include_paths.dup - cxx.flags = conf.cc.flags.dup - cxx.flags << %w(-fno-rtti -fno-exceptions) - cxx.defines = conf.cc.defines.dup - cxx.compile_options = conf.cc.compile_options.dup - end - - conf.archiver do |archiver| - archiver.command = "#{BIN_PATH}/arm-none-eabi-ar" - archiver.archive_options = 'rcs %{outfile} %{objs}' - end - - #no executables - conf.bins = [] - - #do not build executable test - conf.build_mrbtest_lib_only - - #disable C++ exception - conf.disable_cxx_exception - - #gems from core - conf.gem :core => "mruby-print" - conf.gem :core => "mruby-math" - conf.gem :core => "mruby-enum-ext" - - #light-weight regular expression - conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master" - - #Arduino API - #conf.gem :github =>"kyab/mruby-arduino", :branch => "master" - -end diff -Nru nghttp2-1.13.0/third-party/mruby/examples/targets/build_config_chipKITMax32.rb nghttp2-0.6.7/third-party/mruby/examples/targets/build_config_chipKITMax32.rb --- nghttp2-1.13.0/third-party/mruby/examples/targets/build_config_chipKITMax32.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/targets/build_config_chipKITMax32.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -MRuby::Build.new do |conf| - - # Gets set by the VS command prompts. - if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] - toolchain :visualcpp - else - toolchain :gcc - end - - enable_debug - - # include the default GEMs - conf.gembox 'default' - -end - -# Cross Compiling configuration for Digilent chipKIT Max32 -# http://www.digilentinc.com/Products/Detail.cfm?Prod=CHIPKIT-MAX32 -# -# Requires MPIDE (https://github.com/chipKIT32/chipKIT32-MAX) -# -# This configuration is based on @kyab's version -# http://d.hatena.ne.jp/kyab/20130201 -MRuby::CrossBuild.new("chipKITMax32") do |conf| - toolchain :gcc - - # Mac OS X - # MPIDE_PATH = '/Applications/Mpide.app/Contents/Resources/Java' - # GNU Linux - MPIDE_PATH = '/opt/mpide-0023-linux-20120903' - - PIC32_PATH = "#{MPIDE_PATH}/hardware/pic32" - - conf.cc do |cc| - cc.command = "#{PIC32_PATH}/compiler/pic32-tools/bin/pic32-gcc" - cc.include_paths << ["#{PIC32_PATH}/cores/pic32", - "#{PIC32_PATH}/variants/Max32", - "#{PIC32_PATH}/libraries"] - cc.flags = %w(-O2 -mno-smart-io -w -ffunction-sections -fdata-sections -g -mdebugger -Wcast-align - -fno-short-double -mprocessor=32MX795F512L -DF_CPU=80000000L -DARDUINO=23 -D_BOARD_MEGA_ - -DMPIDEVER=0x01000202 -DMPIDE=23) - cc.compile_options = "%{flags} -o %{outfile} -c %{infile}" - - #configuration for low memory environment - cc.defines << %w(MRB_HEAP_PAGE_SIZE=64) - cc.defines << %w(MRB_USE_IV_SEGLIST) - cc.defines << %w(KHASH_DEFAULT_SIZE=8) - cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) - cc.defines << %w(MRB_GC_STRESS) - #cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio. - #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval - end - - conf.cxx do |cxx| - cxx.command = conf.cc.command.dup - cxx.include_paths = conf.cc.include_paths.dup - cxx.flags = conf.cc.flags.dup - cxx.defines = conf.cc.defines.dup - cxx.compile_options = conf.cc.compile_options.dup - end - - conf.archiver do |archiver| - archiver.command = "#{PIC32_PATH}/compiler/pic32-tools/bin/pic32-ar" - archiver.archive_options = 'rcs %{outfile} %{objs}' - end - - #no executables - conf.bins = [] - - #do not build test executable - conf.build_mrbtest_lib_only - - #disable C++ exception - conf.disable_cxx_exception - - #gems from core - conf.gem :core => "mruby-print" - conf.gem :core => "mruby-math" - conf.gem :core => "mruby-enum-ext" - - #light-weight regular expression - conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master" - - #Arduino API - #conf.gem :github =>"kyab/mruby-arduino", :branch => "master" - -end diff -Nru nghttp2-1.13.0/third-party/mruby/examples/targets/build_config_IntelGalileo.rb nghttp2-0.6.7/third-party/mruby/examples/targets/build_config_IntelGalileo.rb --- nghttp2-1.13.0/third-party/mruby/examples/targets/build_config_IntelGalileo.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/examples/targets/build_config_IntelGalileo.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -MRuby::Build.new do |conf| - - # Gets set by the VS command prompts. - if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] - toolchain :visualcpp - else - toolchain :gcc - end - - enable_debug - - # include the default GEMs - conf.gembox 'default' - -end - - -# Cross Compiling configuration for Intel Galileo on Arduino environment -# http://arduino.cc/en/ArduinoCertified/IntelGalileo -# -# Requires Arduino IDE for Intel Galileo -MRuby::CrossBuild.new("Galileo") do |conf| - toolchain :gcc - - # Mac OS X - # Assume you renamed Arduino.app to Arduino_Galileo.app - GALILEO_ARDUINO_PATH = '/Applications/Arduino_Galileo.app/Contents/Resources/Java' - # GNU Linux - #ARDUINO_GALILEO_PATH = '/opt/arduino' - - GALILEO_BIN_PATH = "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i386-pokysdk-darwin/usr/bin/i586-poky-linux-uclibc" - GALILEO_SYSROOT = "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i586-poky-linux-uclibc" - GALILEO_X86_PATH = "#{GALILEO_ARDUINO_PATH}/hardware/arduino/x86" - - - conf.cc do |cc| - cc.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-gcc" - cc.include_paths << ["#{GALILEO_X86_PATH}/cores/arduino", "#{GALILEO_X86_PATH}/variants/galileo_fab_d"] - cc.flags = %w(-m32 -march=i586 -c -g -Os -w - -ffunction-sections -fdata-sections -MMD -DARDUINO=153) - cc.flags << "--sysroot=#{GALILEO_SYSROOT}" - cc.compile_options = "%{flags} -o %{outfile} -c %{infile}" - end - - conf.cxx do |cxx| - cxx.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-g++" - cxx.include_paths = conf.cc.include_paths.dup - cxx.include_paths << "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i586-poky-linux-uclibc/usr/include/c++" - cxx.include_paths << "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i586-poky-linux-uclibc/usr/include/c++/i586-poky-linux-uclibc" - cxx.flags = conf.cc.flags.dup - cxx.defines = conf.cc.defines.dup - cxx.compile_options = conf.cc.compile_options.dup - end - - conf.archiver do |archiver| - archiver.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-ar" - archiver.archive_options = 'rcs %{outfile} %{objs}' - end - - conf.linker do |linker| - linker.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-g++" - linker.flags = %w(-m32 -march=i586) - linker.flags << "--sysroot=#{GALILEO_SYSROOT}" - linker.flags << %w(-Os -Wl,--gc-sections) - linker.libraries = %w(m pthread) - end - - #no executables - conf.bins = [] - - #do not build executable test - conf.build_mrbtest_lib_only - - #official mrbgems - conf.gem :core => "mruby-sprintf" - conf.gem :core => "mruby-print" - conf.gem :core => "mruby-math" - conf.gem :core => "mruby-time" - conf.gem :core => "mruby-struct" - conf.gem :core => "mruby-enum-ext" - conf.gem :core => "mruby-string-ext" - conf.gem :core => "mruby-numeric-ext" - conf.gem :core => "mruby-array-ext" - conf.gem :core => "mruby-hash-ext" - conf.gem :core => "mruby-range-ext" - conf.gem :core => "mruby-proc-ext" - conf.gem :core => "mruby-symbol-ext" - conf.gem :core => "mruby-random" - conf.gem :core => "mruby-object-ext" - conf.gem :core => "mruby-objectspace" - conf.gem :core => "mruby-fiber" - conf.gem :core => "mruby-toplevel-ext" - - #lightweigh regular expression - conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master" - - #Arduino API - #conf.gem :github =>"kyab/mruby-arduino", :branch => "master" do |g| - # g.cxx.include_paths << "#{GALILEO_X86_PATH}/libraries/Wire" - # g.cxx.include_paths << "#{GALILEO_X86_PATH}/libraries/Servo" - - #enable unsupported Servo class - # g.cxx.defines << "MRUBY_ARDUINO_GALILEO_ENABLE_SERVO" - #end - -end diff -Nru nghttp2-1.13.0/third-party/mruby/include/mrbconf.h nghttp2-0.6.7/third-party/mruby/include/mrbconf.h --- nghttp2-1.13.0/third-party/mruby/include/mrbconf.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mrbconf.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -/* -** mrbconf.h - mruby core configuration -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBYCONF_H -#define MRUBYCONF_H - -/* configuration options: */ -/* add -DMRB_USE_FLOAT to use float instead of double for floating point numbers */ -//#define MRB_USE_FLOAT - -/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT64 */ -//#define MRB_INT16 - -/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 */ -//#define MRB_INT64 - -/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT */ -//#define MRB_NAN_BOXING - -/* define on big endian machines; used by MRB_NAN_BOXING */ -//#define MRB_ENDIAN_BIG - -/* represent mrb_value as a word (natural unit of data for the processor) */ -//#define MRB_WORD_BOXING - -/* string class to handle UTF-8 encoding */ -//#define MRB_UTF8_STRING - -/* argv max size in mrb_funcall */ -//#define MRB_FUNCALL_ARGC_MAX 16 - -/* number of object per heap page */ -//#define MRB_HEAP_PAGE_SIZE 1024 - -/* use segmented list for IV table */ -//#define MRB_USE_IV_SEGLIST - -/* initial size for IV khash; ignored when MRB_USE_IV_SEGLIST is set */ -//#define MRB_IVHASH_INIT_SIZE 8 - -/* if _etext and _edata available, mruby can reduce memory used by symbols */ -//#define MRB_USE_ETEXT_EDATA - -/* do not use __init_array_start to determine readonly data section; - effective only when MRB_USE_ETEXT_EDATA is defined */ -//#define MRB_NO_INIT_ARRAY_START - -/* turn off generational GC by default */ -//#define MRB_GC_TURN_OFF_GENERATIONAL - -/* default size of khash table bucket */ -//#define KHASH_DEFAULT_SIZE 32 - -/* allocated memory address alignment */ -//#define POOL_ALIGNMENT 4 - -/* page size of memory pool */ -//#define POOL_PAGE_SIZE 16000 - -/* initial minimum size for string buffer */ -//#define MRB_STR_BUF_MIN_SIZE 128 - -/* arena size */ -//#define MRB_GC_ARENA_SIZE 100 - -/* fixed size GC arena */ -//#define MRB_GC_FIXED_ARENA - -/* state atexit stack size */ -//#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5 - -/* fixed size state atexit stack */ -//#define MRB_FIXED_STATE_ATEXIT_STACK - -/* -DMRB_DISABLE_XXXX to drop following features */ -//#define MRB_DISABLE_STDIO /* use of stdio */ - -/* -DMRB_ENABLE_XXXX to enable following features */ -//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */ - -/* end of configuration */ - -/* define MRB_DISABLE_XXXX from DISABLE_XXX (for compatibility) */ -#ifdef DISABLE_STDIO -#define MRB_DISABLE_STDIO -#endif - -/* define MRB_ENABLE_XXXX from ENABLE_XXX (for compatibility) */ -#ifdef ENABLE_DEBUG -#define MRB_ENABLE_DEBUG_HOOK -#endif - -#ifndef MRB_DISABLE_STDIO -# include -#endif - -#ifndef FALSE -# define FALSE 0 -#endif - -#ifndef TRUE -# define TRUE 1 -#endif - -#endif /* MRUBYCONF_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/array.h nghttp2-0.6.7/third-party/mruby/include/mruby/array.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/array.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/array.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,139 +0,0 @@ -/* -** mruby/array.h - Array class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_ARRAY_H -#define MRUBY_ARRAY_H - -#include "mruby/common.h" - -/* - * Array class - */ -MRB_BEGIN_DECL - - -typedef struct mrb_shared_array { - int refcnt; - mrb_int len; - mrb_value *ptr; -} mrb_shared_array; - -struct RArray { - MRB_OBJECT_HEADER; - mrb_int len; - union { - mrb_int capa; - mrb_shared_array *shared; - } aux; - mrb_value *ptr; -}; - -#define mrb_ary_ptr(v) ((struct RArray*)(mrb_ptr(v))) -#define mrb_ary_value(p) mrb_obj_value((void*)(p)) -#define RARRAY(v) ((struct RArray*)(mrb_ptr(v))) - -#define RARRAY_LEN(a) (RARRAY(a)->len) -#define RARRAY_PTR(a) ((const mrb_value*)RARRAY(a)->ptr) -#define MRB_ARY_SHARED 256 -#define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED) -#define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED) -#define ARY_UNSET_SHARED_FLAG(a) ((a)->flags &= ~MRB_ARY_SHARED) - -void mrb_ary_decref(mrb_state*, mrb_shared_array*); -MRB_API void mrb_ary_modify(mrb_state*, struct RArray*); -MRB_API mrb_value mrb_ary_new_capa(mrb_state*, mrb_int); - -/* - * Initializes a new array. - * - * Equivalent to: - * - * Array.new - * - * @param mrb The mruby state reference. - * @return The initialized array - */ -MRB_API mrb_value mrb_ary_new(mrb_state *mrb); - -MRB_API mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals); -MRB_API mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr); -MRB_API void mrb_ary_concat(mrb_state*, mrb_value, mrb_value); -MRB_API mrb_value mrb_ary_splat(mrb_state*, mrb_value); - -/* - * Pushes value into array. - * - * Equivalent to: - * - * ary << value - * - * @param mrb The mruby state reference. - * @param ary The array in which the value will be pushed - * @param value The value to be pushed into array - */ -MRB_API void mrb_ary_push(mrb_state *mrb, mrb_value array, mrb_value value); - -/* - * Pops the last element from the array. - * - * Equivalent to: - * - * ary.pop - * - * @param mrb The mruby state reference. - * @param ary The array from which the value will be poped. - * @return The poped value. - */ -MRB_API mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary); - -/* - * Returns a reference to an element of the array on the given index. - * - * Equivalent to: - * - * ary[n] - * - * @param mrb The mruby state reference. - * @param ary The target array. - * @param n The array index being referenced - * @return The referenced value. - */ -MRB_API mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n); - -/* - * Sets a value on an array at the given index - * - * Equivalent to: - * - * ary[n] = val - * - * @param mrb The mruby state reference. - * @param ary The target array. - * @param n The array index being referenced. - * @param val The value being setted. - */ -MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val); - -MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value a, mrb_value b); -MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); -MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item); -MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset); -MRB_API mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self); -MRB_API mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self); -MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep); -MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int len); - -static inline mrb_int -mrb_ary_len(mrb_state *mrb, mrb_value ary) -{ - (void)mrb; - mrb_assert(mrb_array_p(ary)); - return RARRAY_LEN(ary); -} - -MRB_END_DECL - -#endif /* MRUBY_ARRAY_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/boxing_nan.h nghttp2-0.6.7/third-party/mruby/include/mruby/boxing_nan.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/boxing_nan.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/boxing_nan.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -/* -** mruby/boxing_nan.h - nan boxing mrb_value definition -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_BOXING_NAN_H -#define MRUBY_BOXING_NAN_H - -#ifdef MRB_USE_FLOAT -# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<---- -#endif - -#ifdef MRB_INT64 -# error ---->> MRB_NAN_BOXING and MRB_INT64 conflict <<---- -#endif - -#define MRB_FIXNUM_SHIFT 0 -#define MRB_TT_HAS_BASIC MRB_TT_OBJECT - -#ifdef MRB_ENDIAN_BIG -#define MRB_ENDIAN_LOHI(a,b) a b -#else -#define MRB_ENDIAN_LOHI(a,b) b a -#endif - -/* value representation by nan-boxing: - * float : FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF - * object: 111111111111TTTT TTPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP - * int : 1111111111110001 0000000000000000 IIIIIIIIIIIIIIII IIIIIIIIIIIIIIII - * sym : 1111111111110001 0100000000000000 SSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSS - * In order to get enough bit size to save TT, all pointers are shifted 2 bits - * in the right direction. Also, TTTTTT is the mrb_vtype + 1; - */ -typedef struct mrb_value { - union { - mrb_float f; - union { - void *p; - struct { - MRB_ENDIAN_LOHI( - uint32_t ttt; - ,union { - mrb_int i; - mrb_sym sym; - }; - ) - }; - } value; - }; -} mrb_value; - -#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f) - -#define mrb_tt(o) ((enum mrb_vtype)(((o).value.ttt & 0xfc000)>>14)-1) -#define mrb_type(o) ((uint32_t)0xfff00000 < (o).value.ttt ? mrb_tt(o) : MRB_TT_FLOAT) -#define mrb_ptr(o) ((void*)((((uintptr_t)0x3fffffffffff)&((uintptr_t)((o).value.p)))<<2)) -#define mrb_float(o) (o).f -#define mrb_cptr(o) mrb_ptr(o) -#define mrb_fixnum(o) (o).value.i -#define mrb_symbol(o) (o).value.sym - -#define BOXNAN_SET_VALUE(o, tt, attr, v) do {\ - switch (tt) {\ - case MRB_TT_FALSE:\ - case MRB_TT_TRUE:\ - case MRB_TT_UNDEF:\ - case MRB_TT_FIXNUM:\ - case MRB_TT_SYMBOL: (o).attr = (v); break;\ - default: (o).value.i = 0; (o).value.p = (void*)((uintptr_t)(o).value.p | (((uintptr_t)(v))>>2)); break;\ - }\ - (o).value.ttt = (0xfff00000|(((tt)+1)<<14));\ -} while (0) - -#define SET_FLOAT_VALUE(mrb,r,v) do { \ - if (v != v) { \ - (r).value.ttt = 0x7ff80000; \ - (r).value.i = 0; \ - } else { \ - (r).f = v; \ - }} while(0) - -#define SET_NIL_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_FALSE, value.i, 0) -#define SET_FALSE_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_FALSE, value.i, 1) -#define SET_TRUE_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_TRUE, value.i, 1) -#define SET_BOOL_VALUE(r,b) BOXNAN_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1) -#define SET_INT_VALUE(r,n) BOXNAN_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n)) -#define SET_SYM_VALUE(r,v) BOXNAN_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v)) -#define SET_OBJ_VALUE(r,v) BOXNAN_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v)) -#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_VALUE(r, MRB_TT_CPTR, value.p, v) -#define SET_UNDEF_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0) - -#endif /* MRUBY_BOXING_NAN_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/boxing_no.h nghttp2-0.6.7/third-party/mruby/include/mruby/boxing_no.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/boxing_no.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/boxing_no.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -/* -** mruby/boxing_no.h - unboxed mrb_value definition -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_BOXING_NO_H -#define MRUBY_BOXING_NO_H - -#define MRB_FIXNUM_SHIFT 0 -#define MRB_TT_HAS_BASIC MRB_TT_OBJECT - -typedef struct mrb_value { - union { - mrb_float f; - void *p; - mrb_int i; - mrb_sym sym; - } value; - enum mrb_vtype tt; -} mrb_value; - -#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f) - -#define mrb_ptr(o) (o).value.p -#define mrb_cptr(o) mrb_ptr(o) -#define mrb_float(o) (o).value.f -#define mrb_fixnum(o) (o).value.i -#define mrb_symbol(o) (o).value.sym -#define mrb_type(o) (o).tt - -#define BOXNIX_SET_VALUE(o, ttt, attr, v) do {\ - (o).tt = ttt;\ - (o).attr = v;\ -} while (0) - -#define SET_NIL_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_FALSE, value.i, 0) -#define SET_FALSE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_FALSE, value.i, 1) -#define SET_TRUE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_TRUE, value.i, 1) -#define SET_BOOL_VALUE(r,b) BOXNIX_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1) -#define SET_INT_VALUE(r,n) BOXNIX_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n)) -#define SET_FLOAT_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v)) -#define SET_SYM_VALUE(r,v) BOXNIX_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v)) -#define SET_OBJ_VALUE(r,v) BOXNIX_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v)) -#define SET_CPTR_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_CPTR, value.p, v) -#define SET_UNDEF_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0) - -#endif /* MRUBY_BOXING_NO_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/boxing_word.h nghttp2-0.6.7/third-party/mruby/include/mruby/boxing_word.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/boxing_word.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/boxing_word.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -/* -** mruby/boxing_word.h - word boxing mrb_value definition -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_BOXING_WORD_H -#define MRUBY_BOXING_WORD_H - -#if defined(MRB_INT16) -# error MRB_INT16 is too small for MRB_WORD_BOXING. -#endif - -struct RFloat { - MRB_OBJECT_HEADER; - mrb_float f; -}; - -struct RCptr { - MRB_OBJECT_HEADER; - void *p; -}; - -#define MRB_FIXNUM_SHIFT 1 -#define MRB_TT_HAS_BASIC MRB_TT_FLOAT - -enum mrb_special_consts { - MRB_Qnil = 0, - MRB_Qfalse = 2, - MRB_Qtrue = 4, - MRB_Qundef = 6, -}; - -#define MRB_FIXNUM_FLAG 0x01 -#define MRB_SYMBOL_FLAG 0x0e -#define MRB_SPECIAL_SHIFT 8 - -typedef union mrb_value { - union { - void *p; - struct { - unsigned int i_flag : MRB_FIXNUM_SHIFT; - mrb_int i : (MRB_INT_BIT - MRB_FIXNUM_SHIFT); - }; - struct { - unsigned int sym_flag : MRB_SPECIAL_SHIFT; - mrb_sym sym : (sizeof(mrb_sym) * CHAR_BIT); - }; - struct RBasic *bp; - struct RFloat *fp; - struct RCptr *vp; - } value; - unsigned long w; -} mrb_value; - -MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*); -MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float); -MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float); - -#define mrb_float_pool(mrb,f) mrb_word_boxing_float_pool(mrb,f) - -#define mrb_ptr(o) (o).value.p -#define mrb_cptr(o) (o).value.vp->p -#define mrb_float(o) (o).value.fp->f -#define mrb_fixnum(o) (o).value.i -#define mrb_symbol(o) (o).value.sym - -static inline enum mrb_vtype -mrb_type(mrb_value o) -{ - switch (o.w) { - case MRB_Qfalse: - case MRB_Qnil: - return MRB_TT_FALSE; - case MRB_Qtrue: - return MRB_TT_TRUE; - case MRB_Qundef: - return MRB_TT_UNDEF; - } - if (o.value.i_flag == MRB_FIXNUM_FLAG) { - return MRB_TT_FIXNUM; - } - if (o.value.sym_flag == MRB_SYMBOL_FLAG) { - return MRB_TT_SYMBOL; - } - return o.value.bp->tt; -} - -#define mrb_bool(o) ((o).w != MRB_Qnil && (o).w != MRB_Qfalse) -#define mrb_fixnum_p(o) ((o).value.i_flag == MRB_FIXNUM_FLAG) -#define mrb_undef_p(o) ((o).w == MRB_Qundef) -#define mrb_nil_p(o) ((o).w == MRB_Qnil) - -#define BOXWORD_SET_VALUE(o, ttt, attr, v) do {\ - switch (ttt) {\ - case MRB_TT_FALSE: (o).w = (v) ? MRB_Qfalse : MRB_Qnil; break;\ - case MRB_TT_TRUE: (o).w = MRB_Qtrue; break;\ - case MRB_TT_UNDEF: (o).w = MRB_Qundef; break;\ - case MRB_TT_FIXNUM: (o).value.i_flag = MRB_FIXNUM_FLAG; (o).attr = (v); break;\ - case MRB_TT_SYMBOL: (o).value.sym_flag = MRB_SYMBOL_FLAG; (o).attr = (v); break;\ - default: (o).w = 0; (o).attr = (v); if ((o).value.bp) (o).value.bp->tt = ttt; break;\ - }\ -} while (0) - -#define SET_FLOAT_VALUE(mrb,r,v) r = mrb_word_boxing_float_value(mrb, v) -#define SET_CPTR_VALUE(mrb,r,v) r = mrb_word_boxing_cptr_value(mrb, v) -#define SET_NIL_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 0) -#define SET_FALSE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 1) -#define SET_TRUE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_TRUE, value.i, 1) -#define SET_BOOL_VALUE(r,b) BOXWORD_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1) -#define SET_INT_VALUE(r,n) BOXWORD_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n)) -#define SET_SYM_VALUE(r,v) BOXWORD_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v)) -#define SET_OBJ_VALUE(r,v) BOXWORD_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v)) -#define SET_UNDEF_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0) - -#endif /* MRUBY_BOXING_WORD_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/class.h nghttp2-0.6.7/third-party/mruby/include/mruby/class.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/class.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/class.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -/* -** mruby/class.h - Class class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_CLASS_H -#define MRUBY_CLASS_H - -#include "mruby/common.h" - -/** - * Class class - */ -MRB_BEGIN_DECL - -struct RClass { - MRB_OBJECT_HEADER; - struct iv_tbl *iv; - struct kh_mt *mt; - struct RClass *super; -}; - -#define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v))) -#define RCLASS_SUPER(v) (((struct RClass*)(mrb_ptr(v)))->super) -#define RCLASS_IV_TBL(v) (((struct RClass*)(mrb_ptr(v)))->iv) -#define RCLASS_M_TBL(v) (((struct RClass*)(mrb_ptr(v)))->mt) - -static inline struct RClass* -mrb_class(mrb_state *mrb, mrb_value v) -{ - switch (mrb_type(v)) { - case MRB_TT_FALSE: - if (mrb_fixnum(v)) - return mrb->false_class; - return mrb->nil_class; - case MRB_TT_TRUE: - return mrb->true_class; - case MRB_TT_SYMBOL: - return mrb->symbol_class; - case MRB_TT_FIXNUM: - return mrb->fixnum_class; - case MRB_TT_FLOAT: - return mrb->float_class; - case MRB_TT_CPTR: - return mrb->object_class; - case MRB_TT_ENV: - return NULL; - default: - return mrb_obj_ptr(v)->c; - } -} - -// TODO: figure out where to put user flags -#define MRB_FLAG_IS_PREPENDED (1 << 19) -#define MRB_FLAG_IS_ORIGIN (1 << 20) -#define MRB_CLASS_ORIGIN(c) do {\ - if (c->flags & MRB_FLAG_IS_PREPENDED) {\ - c = c->super;\ - while (!(c->flags & MRB_FLAG_IS_ORIGIN)) {\ - c = c->super;\ - }\ - }\ -} while (0) -#define MRB_INSTANCE_TT_MASK (0xFF) -#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~MRB_INSTANCE_TT_MASK) | (char)tt) -#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & MRB_INSTANCE_TT_MASK) - -MRB_API struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*); -MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym); -MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym); -MRB_API struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym); -MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *); -MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec); -MRB_API void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b); - -MRB_API struct RClass *mrb_class_outer_module(mrb_state*, struct RClass *); -MRB_API struct RProc *mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym); -MRB_API struct RProc *mrb_method_search(mrb_state*, struct RClass*, mrb_sym); - -MRB_API struct RClass* mrb_class_real(struct RClass* cl); - -void mrb_gc_mark_mt(mrb_state*, struct RClass*); -size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*); -void mrb_gc_free_mt(mrb_state*, struct RClass*); - -MRB_END_DECL - -#endif /* MRUBY_CLASS_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/common.h nghttp2-0.6.7/third-party/mruby/include/mruby/common.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/common.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/common.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -/* -** mruby/common.h - mruby common platform definitions -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_COMMON_H -#define MRUBY_COMMON_H - - -#ifdef __cplusplus -# define MRB_BEGIN_DECL extern "C" { -# define MRB_END_DECL } -#else -/** Start declarations in C mode */ -# define MRB_BEGIN_DECL -/** End declarations in C mode */ -# define MRB_END_DECL -#endif - -/** - * Shared compiler macros - */ -MRB_BEGIN_DECL - -/** Declare a function that never returns. */ -#if __STDC_VERSION__ >= 201112L -# define mrb_noreturn _Noreturn -#elif defined __GNUC__ && !defined __STRICT_ANSI__ -# define mrb_noreturn __attribute__((noreturn)) -#elif defined _MSC_VER -# define mrb_noreturn __declspec(noreturn) -#else -# define mrb_noreturn -#endif - -/** Mark a function as deprecated. */ -#if defined __GNUC__ && !defined __STRICT_ANSI__ -# define mrb_deprecated __attribute__((deprecated)) -#elif defined _MSC_VER -# define mrb_deprecated __declspec(deprecated) -#else -# define mrb_deprecated -#endif - -/** Declare a function as always inlined. */ -#if defined(_MSC_VER) -# define MRB_INLINE static __inline -#else -# define MRB_INLINE static inline -#endif - - -/** Declare a public MRuby API function. */ -#if defined(MRB_BUILD_AS_DLL) -#if defined(MRB_CORE) || defined(MRB_LIB) -# define MRB_API __declspec(dllexport) -#else -# define MRB_API __declspec(dllimport) -#endif -#else -# define MRB_API extern -#endif - -MRB_END_DECL - -#endif /* MRUBY_COMMON_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/compile.h nghttp2-0.6.7/third-party/mruby/include/mruby/compile.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/compile.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/compile.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,190 +0,0 @@ -/* -** mruby/compile.h - mruby parser -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_COMPILE_H -#define MRUBY_COMPILE_H - -#include "mruby/common.h" - -/** - * MRuby Compiler - */ -MRB_BEGIN_DECL - -#include "mruby.h" - -struct mrb_jmpbuf; - -struct mrb_parser_state; -/* load context */ -typedef struct mrbc_context { - mrb_sym *syms; - int slen; - char *filename; - short lineno; - int (*partial_hook)(struct mrb_parser_state*); - void *partial_data; - struct RClass *target_class; - mrb_bool capture_errors:1; - mrb_bool dump_result:1; - mrb_bool no_exec:1; - mrb_bool keep_lv:1; - mrb_bool no_optimize:1; -} mrbc_context; - -MRB_API mrbc_context* mrbc_context_new(mrb_state *mrb); -MRB_API void mrbc_context_free(mrb_state *mrb, mrbc_context *cxt); -MRB_API const char *mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s); -MRB_API void mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*partial_hook)(struct mrb_parser_state*), void*data); - -MRB_API mrb_value mrb_toplevel_run_keep(mrb_state*, struct RProc*, unsigned int); - -/* AST node structure */ -typedef struct mrb_ast_node { - struct mrb_ast_node *car, *cdr; - uint16_t lineno, filename_index; -} mrb_ast_node; - -/* lexer states */ -enum mrb_lex_state_enum { - EXPR_BEG, /* ignore newline, +/- is a sign. */ - EXPR_END, /* newline significant, +/- is an operator. */ - EXPR_ENDARG, /* ditto, and unbound braces. */ - EXPR_ENDFN, /* ditto, and unbound braces. */ - EXPR_ARG, /* newline significant, +/- is an operator. */ - EXPR_CMDARG, /* newline significant, +/- is an operator. */ - EXPR_MID, /* newline significant, +/- is an operator. */ - EXPR_FNAME, /* ignore newline, no reserved words. */ - EXPR_DOT, /* right after '.' or '::', no reserved words. */ - EXPR_CLASS, /* immediate after 'class', no here document. */ - EXPR_VALUE, /* alike EXPR_BEG but label is disallowed. */ - EXPR_MAX_STATE -}; - -/* saved error message */ -struct mrb_parser_message { - int lineno; - int column; - char* message; -}; - -#define STR_FUNC_PARSING 0x01 -#define STR_FUNC_EXPAND 0x02 -#define STR_FUNC_REGEXP 0x04 -#define STR_FUNC_WORD 0x08 -#define STR_FUNC_SYMBOL 0x10 -#define STR_FUNC_ARRAY 0x20 -#define STR_FUNC_HEREDOC 0x40 -#define STR_FUNC_XQUOTE 0x80 - -enum mrb_string_type { - str_not_parsing = (0), - str_squote = (STR_FUNC_PARSING), - str_dquote = (STR_FUNC_PARSING|STR_FUNC_EXPAND), - str_regexp = (STR_FUNC_PARSING|STR_FUNC_REGEXP|STR_FUNC_EXPAND), - str_sword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY), - str_dword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY|STR_FUNC_EXPAND), - str_ssym = (STR_FUNC_PARSING|STR_FUNC_SYMBOL), - str_ssymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY), - str_dsymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY|STR_FUNC_EXPAND), - str_heredoc = (STR_FUNC_PARSING|STR_FUNC_HEREDOC), - str_xquote = (STR_FUNC_PARSING|STR_FUNC_XQUOTE|STR_FUNC_EXPAND), -}; - -/* heredoc structure */ -struct mrb_parser_heredoc_info { - mrb_bool allow_indent:1; - mrb_bool line_head:1; - enum mrb_string_type type; - const char *term; - int term_len; - mrb_ast_node *doc; -}; - -#define MRB_PARSER_BUF_SIZE 1024 - -/* parser structure */ -struct mrb_parser_state { - mrb_state *mrb; - struct mrb_pool *pool; - mrb_ast_node *cells; - const char *s, *send; -#ifndef MRB_DISABLE_STDIO - FILE *f; -#endif - mrbc_context *cxt; - char const *filename; - int lineno; - int column; - - enum mrb_lex_state_enum lstate; - mrb_ast_node *lex_strterm; /* (type nest_level beg . end) */ - - unsigned int cond_stack; - unsigned int cmdarg_stack; - int paren_nest; - int lpar_beg; - int in_def, in_single; - mrb_bool cmd_start:1; - mrb_ast_node *locals; - - mrb_ast_node *pb; - char buf[MRB_PARSER_BUF_SIZE]; - int bidx; - - mrb_ast_node *all_heredocs; /* list of mrb_parser_heredoc_info* */ - mrb_ast_node *heredocs_from_nextline; - mrb_ast_node *parsing_heredoc; - mrb_ast_node *lex_strterm_before_heredoc; - mrb_bool heredoc_end_now:1; /* for mirb */ - - void *ylval; - - size_t nerr; - size_t nwarn; - mrb_ast_node *tree; - - mrb_bool no_optimize:1; - mrb_bool capture_errors:1; - struct mrb_parser_message error_buffer[10]; - struct mrb_parser_message warn_buffer[10]; - - mrb_sym* filename_table; - size_t filename_table_length; - int current_filename_index; - - struct mrb_jmpbuf* jmp; -}; - -MRB_API struct mrb_parser_state* mrb_parser_new(mrb_state*); -MRB_API void mrb_parser_free(struct mrb_parser_state*); -MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*); - -MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*); -MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx); - -/* utility functions */ -#ifndef MRB_DISABLE_STDIO -MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*); -#endif -MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*); -MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mrbc_context*); -MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*); - -/* program load functions */ -#ifndef MRB_DISABLE_STDIO -MRB_API mrb_value mrb_load_file(mrb_state*,FILE*); -MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt); -#endif -MRB_API mrb_value mrb_load_string(mrb_state *mrb, const char *s); -MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len); -MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt); -MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *cxt); - -/** @} */ -MRB_END_DECL - -#endif /* MRUBY_COMPILE_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/data.h nghttp2-0.6.7/third-party/mruby/include/mruby/data.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/data.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/data.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -/* -** mruby/data.h - Data class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_DATA_H -#define MRUBY_DATA_H - -#include "mruby/common.h" - -/** - * Custom C wrapped data. - * - * Defining Ruby wrappers around native objects. - */ -MRB_BEGIN_DECL - -/** - * Custom data type description. - */ -typedef struct mrb_data_type { - /** data type name */ - const char *struct_name; - - /** data type release function pointer */ - void (*dfree)(mrb_state *mrb, void*); -} mrb_data_type; - -struct RData { - MRB_OBJECT_HEADER; - struct iv_tbl *iv; - const mrb_data_type *type; - void *data; -}; - -MRB_API struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass, void *datap, const mrb_data_type *type); - -#define Data_Wrap_Struct(mrb,klass,type,ptr)\ - mrb_data_object_alloc(mrb,klass,ptr,type) - -#define Data_Make_Struct(mrb,klass,strct,type,sval,data) do { \ - sval = mrb_malloc(mrb, sizeof(strct)); \ - { static const strct zero = { 0 }; *sval = zero; };\ - data = Data_Wrap_Struct(mrb,klass,type,sval);\ -} while (0) - -#define RDATA(obj) ((struct RData *)(mrb_ptr(obj))) -#define DATA_PTR(d) (RDATA(d)->data) -#define DATA_TYPE(d) (RDATA(d)->type) -MRB_API void mrb_data_check_type(mrb_state *mrb, mrb_value, const mrb_data_type*); -MRB_API void *mrb_data_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*); -#define DATA_GET_PTR(mrb,obj,dtype,type) (type*)mrb_data_get_ptr(mrb,obj,dtype) -MRB_API void *mrb_data_check_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*); -#define DATA_CHECK_GET_PTR(mrb,obj,dtype,type) (type*)mrb_data_check_get_ptr(mrb,obj,dtype) - -/* obsolete functions and macros */ -#define mrb_data_check_and_get(mrb,obj,dtype) mrb_data_get_ptr(mrb,obj,dtype) -#define mrb_get_datatype(mrb,val,type) mrb_data_get_ptr(mrb, val, type) -#define mrb_check_datatype(mrb,val,type) mrb_data_get_ptr(mrb, val, type) -#define Data_Get_Struct(mrb,obj,type,sval) do {\ - *(void**)&sval = mrb_data_get_ptr(mrb, obj, type); \ -} while (0) - -static inline void -mrb_data_init(mrb_value v, void *ptr, const mrb_data_type *type) -{ - mrb_assert(mrb_type(v) == MRB_TT_DATA); - DATA_PTR(v) = ptr; - DATA_TYPE(v) = type; -} - -MRB_END_DECL - -#endif /* MRUBY_DATA_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/debug.h nghttp2-0.6.7/third-party/mruby/include/mruby/debug.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/debug.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/debug.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -/* -** mruby/debug.h - mruby debug info -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_DEBUG_H -#define MRUBY_DEBUG_H - -#include "mruby/common.h" - -/** - * MRuby Debugging. - */ -MRB_BEGIN_DECL - -typedef enum mrb_debug_line_type { - mrb_debug_line_ary = 0, - mrb_debug_line_flat_map = 1 -} mrb_debug_line_type; - -typedef struct mrb_irep_debug_info_line { - uint32_t start_pos; - uint16_t line; -} mrb_irep_debug_info_line; - -typedef struct mrb_irep_debug_info_file { - uint32_t start_pos; - const char *filename; - mrb_sym filename_sym; - uint32_t line_entry_count; - mrb_debug_line_type line_type; - union { - void *ptr; - mrb_irep_debug_info_line *flat_map; - uint16_t *ary; - } lines; -} mrb_irep_debug_info_file; - -typedef struct mrb_irep_debug_info { - uint32_t pc_count; - uint16_t flen; - mrb_irep_debug_info_file **files; -} mrb_irep_debug_info; - -/* - * get line from irep's debug info and program counter - * @return returns NULL if not found - */ -MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, uint32_t pc); - -/* - * get line from irep's debug info and program counter - * @return returns -1 if not found - */ -MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, uint32_t pc); - -MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file( - mrb_state *mrb, mrb_irep *irep, - uint32_t start_pos, uint32_t end_pos); -MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep); -MRB_API void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d); - -MRB_END_DECL - -#endif /* MRUBY_DEBUG_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/dump.h nghttp2-0.6.7/third-party/mruby/include/mruby/dump.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/dump.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/dump.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,196 +0,0 @@ -/* -** mruby/dump.h - mruby binary dumper (mrbc binary format) -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_DUMP_H -#define MRUBY_DUMP_H - -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/common.h" - -/** - * Dumping compiled mruby script. - */ -MRB_BEGIN_DECL - -#define DUMP_DEBUG_INFO 1 -#define DUMP_ENDIAN_BIG 2 -#define DUMP_ENDIAN_LIL 4 -#define DUMP_ENDIAN_NAT 6 -#define DUMP_ENDIAN_MASK 6 - -int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size); -#ifndef MRB_DISABLE_STDIO -int mrb_dump_irep_binary(mrb_state*, mrb_irep*, uint8_t, FILE*); -int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep*, uint8_t flags, FILE *f, const char *initname); -mrb_irep *mrb_read_irep_file(mrb_state*, FILE*); -MRB_API mrb_value mrb_load_irep_file(mrb_state*,FILE*); -MRB_API mrb_value mrb_load_irep_file_cxt(mrb_state*, FILE*, mrbc_context*); -#endif -MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*); - -/* dump/load error code - * - * NOTE: MRB_DUMP_GENERAL_FAILURE is caused by - * unspecified issues like malloc failed. - */ -#define MRB_DUMP_OK 0 -#define MRB_DUMP_GENERAL_FAILURE (-1) -#define MRB_DUMP_WRITE_FAULT (-2) -#define MRB_DUMP_READ_FAULT (-3) -#define MRB_DUMP_CRC_ERROR (-4) -#define MRB_DUMP_INVALID_FILE_HEADER (-5) -#define MRB_DUMP_INVALID_IREP (-6) -#define MRB_DUMP_INVALID_ARGUMENT (-7) - -/* null symbol length */ -#define MRB_DUMP_NULL_SYM_LEN 0xFFFF - -/* Rite Binary File header */ -#define RITE_BINARY_IDENT "RITE" -#define RITE_BINARY_IDENT_LIL "ETIR" -#define RITE_BINARY_FORMAT_VER "0003" -#define RITE_COMPILER_NAME "MATZ" -#define RITE_COMPILER_VERSION "0000" - -#define RITE_VM_VER "0000" - -#define RITE_BINARY_EOF "END\0" -#define RITE_SECTION_IREP_IDENT "IREP" -#define RITE_SECTION_LINENO_IDENT "LINE" -#define RITE_SECTION_DEBUG_IDENT "DBG\0" -#define RITE_SECTION_LV_IDENT "LVAR" - -#define MRB_DUMP_DEFAULT_STR_LEN 128 -#define MRB_DUMP_ALIGNMENT sizeof(uint32_t) - -/* binary header */ -struct rite_binary_header { - uint8_t binary_ident[4]; /* Binary Identifier */ - uint8_t binary_version[4]; /* Binary Format Version */ - uint8_t binary_crc[2]; /* Binary CRC */ - uint8_t binary_size[4]; /* Binary Size */ - uint8_t compiler_name[4]; /* Compiler name */ - uint8_t compiler_version[4]; -}; - -/* section header */ -#define RITE_SECTION_HEADER \ - uint8_t section_ident[4]; \ - uint8_t section_size[4] - -struct rite_section_header { - RITE_SECTION_HEADER; -}; - -struct rite_section_irep_header { - RITE_SECTION_HEADER; - - uint8_t rite_version[4]; /* Rite Instruction Specification Version */ -}; - -struct rite_section_lineno_header { - RITE_SECTION_HEADER; -}; - -struct rite_section_debug_header { - RITE_SECTION_HEADER; -}; - -struct rite_section_lv_header { - RITE_SECTION_HEADER; -}; - -#define RITE_LV_NULL_MARK UINT16_MAX - -struct rite_binary_footer { - RITE_SECTION_HEADER; -}; - -static inline int -bigendian_p() -{ - int i; - char *p; - - i = 1; - p = (char*)&i; - return p[0]?0:1; -} - -static inline size_t -uint8_to_bin(uint8_t s, uint8_t *bin) -{ - *bin = s; - return sizeof(uint8_t); -} - -static inline size_t -uint16_to_bin(uint16_t s, uint8_t *bin) -{ - *bin++ = (s >> 8) & 0xff; - *bin = s & 0xff; - return sizeof(uint16_t); -} - -static inline size_t -uint32_to_bin(uint32_t l, uint8_t *bin) -{ - *bin++ = (l >> 24) & 0xff; - *bin++ = (l >> 16) & 0xff; - *bin++ = (l >> 8) & 0xff; - *bin = l & 0xff; - return sizeof(uint32_t); -} - -static inline size_t -uint32l_to_bin(uint32_t l, uint8_t *bin) -{ - bin[3] = (l >> 24) & 0xff; - bin[2] = (l >> 16) & 0xff; - bin[1] = (l >> 8) & 0xff; - bin[0] = l & 0xff; - return sizeof(uint32_t); -} - -static inline uint32_t -bin_to_uint32(const uint8_t *bin) -{ - return (uint32_t)bin[0] << 24 | - (uint32_t)bin[1] << 16 | - (uint32_t)bin[2] << 8 | - (uint32_t)bin[3]; -} - -static inline uint32_t -bin_to_uint32l(const uint8_t *bin) -{ - return (uint32_t)bin[3] << 24 | - (uint32_t)bin[2] << 16 | - (uint32_t)bin[1] << 8 | - (uint32_t)bin[0]; -} - -static inline uint16_t -bin_to_uint16(const uint8_t *bin) -{ - return (uint16_t)bin[0] << 8 | - (uint16_t)bin[1]; -} - -static inline uint8_t -bin_to_uint8(const uint8_t *bin) -{ - return (uint8_t)bin[0]; -} - -MRB_END_DECL - -/** @internal crc.c */ -uint16_t -calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc); - -#endif /* MRUBY_DUMP_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/error.h nghttp2-0.6.7/third-party/mruby/include/mruby/error.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/error.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/error.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -/* -** mruby/error.h - Exception class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_ERROR_H -#define MRUBY_ERROR_H - -#include "mruby/common.h" - -/** - * MRuby error handling. - */ -MRB_BEGIN_DECL - -struct RException { - MRB_OBJECT_HEADER; - struct iv_tbl *iv; -}; - -#define mrb_exc_ptr(v) ((struct RException*)mrb_ptr(v)) - -MRB_API void mrb_sys_fail(mrb_state *mrb, const char *mesg); -MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str); -#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit)) -MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv); -MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc); -MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb); -MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...); - -/* declaration for fail method */ -MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value); - -/** - * Protect - * - * @mrbgem mruby-error - */ -MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state); - -/** - * Ensure - * - * @mrbgem mruby-error - */ -MRB_API mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, - mrb_func_t ensure, mrb_value e_data); - -/** - * Rescue - * - * @mrbgem mruby-error - */ -MRB_API mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data, - mrb_func_t rescue, mrb_value r_data); - -/** - * Rescue exception - * - * @mrbgem mruby-error - */ -MRB_API mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, - mrb_func_t rescue, mrb_value r_data, - mrb_int len, struct RClass **classes); - -MRB_END_DECL - -#endif /* MRUBY_ERROR_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/gc.h nghttp2-0.6.7/third-party/mruby/include/mruby/gc.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/gc.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/gc.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ -/* -** mruby/gc.h - garbage collector for mruby -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_GC_H -#define MRUBY_GC_H - -#include "mruby/common.h" - -/** - * Uncommon memory management stuffs. - */ -MRB_BEGIN_DECL - - -struct mrb_state; - -typedef void (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data); -void mrb_objspace_each_objects(struct mrb_state *mrb, mrb_each_object_callback *callback, void *data); -MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c); - -#ifndef MRB_GC_ARENA_SIZE -#define MRB_GC_ARENA_SIZE 100 -#endif - -typedef enum { - MRB_GC_STATE_ROOT = 0, - MRB_GC_STATE_MARK, - MRB_GC_STATE_SWEEP -} mrb_gc_state; - -typedef struct mrb_heap_page { - struct RBasic *freelist; - struct mrb_heap_page *prev; - struct mrb_heap_page *next; - struct mrb_heap_page *free_next; - struct mrb_heap_page *free_prev; - mrb_bool old:1; - void *objects[]; -} mrb_heap_page; - -typedef struct mrb_gc { - mrb_heap_page *heaps; /* heaps for GC */ - mrb_heap_page *sweeps; - mrb_heap_page *free_heaps; - size_t live; /* count of live objects */ -#ifdef MRB_GC_FIXED_ARENA - struct RBasic *arena[MRB_GC_ARENA_SIZE]; /* GC protection array */ -#else - struct RBasic **arena; /* GC protection array */ - int arena_capa; -#endif - int arena_idx; - - mrb_gc_state state; /* state of gc */ - int current_white_part; /* make white object by white_part */ - struct RBasic *gray_list; /* list of gray objects to be traversed incrementally */ - struct RBasic *atomic_gray_list; /* list of objects to be traversed atomically */ - size_t live_after_mark; - size_t threshold; - int interval_ratio; - int step_ratio; - mrb_bool disabled :1; - mrb_bool full :1; - mrb_bool generational :1; - mrb_bool out_of_memory :1; - size_t majorgc_old_threshold; -} mrb_gc; - -MRB_API mrb_bool -mrb_object_dead_p(struct mrb_state *mrb, struct RBasic *object); - -MRB_END_DECL - -#endif /* MRUBY_GC_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/hash.h nghttp2-0.6.7/third-party/mruby/include/mruby/hash.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/hash.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/hash.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -/* -** mruby/hash.h - Hash class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_HASH_H -#define MRUBY_HASH_H - -#include "mruby/common.h" - -/** - * Hash class - */ -MRB_BEGIN_DECL - -struct RHash { - MRB_OBJECT_HEADER; - struct iv_tbl *iv; - struct kh_ht *ht; -}; - -#define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v))) -#define mrb_hash_value(p) mrb_obj_value((void*)(p)) - -MRB_API mrb_value mrb_hash_new_capa(mrb_state*, int); - -/* - * Initializes a new hash. - */ -MRB_API mrb_value mrb_hash_new(mrb_state *mrb); - -/* - * Sets a keys and values to hashes. - */ -MRB_API void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val); - -/* - * Gets a value from a key. - */ -MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key); - -MRB_API mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def); - -/* - * Deletes hash key and value pair. - */ -MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key); - -/* - * Gets an array of keys. - */ -MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash); -MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); -MRB_API mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self); - -/* - * Clears the hash. - */ -MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash); - -/* RHASH_TBL allocates st_table if not available. */ -#define RHASH(obj) ((struct RHash*)(mrb_ptr(obj))) -#define RHASH_TBL(h) (RHASH(h)->ht) -#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern_lit(mrb, "ifnone")) -#define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h) -MRB_API struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash); - -#define MRB_HASH_PROC_DEFAULT 256 -#define MRB_RHASH_PROCDEFAULT_P(h) (RHASH(h)->flags & MRB_HASH_PROC_DEFAULT) - -/* GC functions */ -void mrb_gc_mark_hash(mrb_state*, struct RHash*); -size_t mrb_gc_mark_hash_size(mrb_state*, struct RHash*); -void mrb_gc_free_hash(mrb_state*, struct RHash*); - -MRB_END_DECL - -#endif /* MRUBY_HASH_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/irep.h nghttp2-0.6.7/third-party/mruby/include/mruby/irep.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/irep.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/irep.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -/* -** mruby/irep.h - mrb_irep structure -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_IREP_H -#define MRUBY_IREP_H - -#include "mruby/common.h" -#include "mruby/compile.h" - -/** - * Compiled mruby scripts. - */ -MRB_BEGIN_DECL - -enum irep_pool_type { - IREP_TT_STRING, - IREP_TT_FIXNUM, - IREP_TT_FLOAT, -}; - -struct mrb_locals { - mrb_sym name; - uint16_t r; -}; - -/* Program data array struct */ -typedef struct mrb_irep { - uint16_t nlocals; /* Number of local variables */ - uint16_t nregs; /* Number of register variables */ - uint8_t flags; - - mrb_code *iseq; - mrb_value *pool; - mrb_sym *syms; - struct mrb_irep **reps; - - struct mrb_locals *lv; - /* debug info */ - const char *filename; - uint16_t *lines; - struct mrb_irep_debug_info* debug_info; - - size_t ilen, plen, slen, rlen, refcnt; -} mrb_irep; - -#define MRB_ISEQ_NO_FREE 1 - -MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb); -MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*); -MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*); -void mrb_irep_free(mrb_state*, struct mrb_irep*); -void mrb_irep_incref(mrb_state*, struct mrb_irep*); -void mrb_irep_decref(mrb_state*, struct mrb_irep*); - -MRB_END_DECL - -#endif /* MRUBY_IREP_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/khash.h nghttp2-0.6.7/third-party/mruby/include/mruby/khash.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/khash.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/khash.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,274 +0,0 @@ -/* -** mruby/khash.c - Hash for mruby -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_KHASH_H -#define MRUBY_KHASH_H - -#include - -#include "mruby.h" -#include "mruby/common.h" - -/** - * khash definitions used in mruby's hash table. - */ -MRB_BEGIN_DECL - -typedef uint32_t khint_t; -typedef khint_t khiter_t; - -#ifndef KHASH_DEFAULT_SIZE -# define KHASH_DEFAULT_SIZE 32 -#endif -#define KHASH_MIN_SIZE 8 - -#define UPPER_BOUND(x) ((x)>>2|(x)>>1) - -/* extern uint8_t __m[]; */ - -/* mask for flags */ -static const uint8_t __m_empty[] = {0x02, 0x08, 0x20, 0x80}; -static const uint8_t __m_del[] = {0x01, 0x04, 0x10, 0x40}; -static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0}; - - -#define __ac_isempty(ed_flag, i) (ed_flag[(i)/4]&__m_empty[(i)%4]) -#define __ac_isdel(ed_flag, i) (ed_flag[(i)/4]&__m_del[(i)%4]) -#define __ac_iseither(ed_flag, i) (ed_flag[(i)/4]&__m_either[(i)%4]) -#define khash_power2(v) do { \ - v--;\ - v |= v >> 1;\ - v |= v >> 2;\ - v |= v >> 4;\ - v |= v >> 8;\ - v |= v >> 16;\ - v++;\ -} while (0) -#define khash_mask(h) ((h)->n_buckets-1) -#define khash_upper_bound(h) (UPPER_BOUND((h)->n_buckets)) - -/* declare struct kh_xxx and kh_xxx_funcs - - name: hash name - khkey_t: key data type - khval_t: value data type - kh_is_map: (0: hash set / 1: hash map) -*/ -#define KHASH_DECLARE(name, khkey_t, khval_t, kh_is_map) \ - typedef struct kh_##name { \ - khint_t n_buckets; \ - khint_t size; \ - khint_t n_occupied; \ - uint8_t *ed_flags; \ - khkey_t *keys; \ - khval_t *vals; \ - } kh_##name##_t; \ - void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h); \ - kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size); \ - kh_##name##_t *kh_init_##name(mrb_state *mrb); \ - void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h); \ - void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \ - khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \ - khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \ - void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \ - void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \ - kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h); - -static inline void -kh_fill_flags(uint8_t *p, uint8_t c, size_t len) -{ - while (len-- > 0) { - *p++ = c; - } -} - -/* define kh_xxx_funcs - - name: hash name - khkey_t: key data type - khval_t: value data type - kh_is_map: (0: hash set / 1: hash map) - __hash_func: hash function - __hash_equal: hash comparation function -*/ -#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \ - { \ - khint_t sz = h->n_buckets; \ - size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \ - uint8_t *p = (uint8_t*)mrb_malloc(mrb, sizeof(uint8_t)*sz/4+len*sz); \ - h->size = h->n_occupied = 0; \ - h->keys = (khkey_t *)p; \ - h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \ - h->ed_flags = p+len*sz; \ - kh_fill_flags(h->ed_flags, 0xaa, sz/4); \ - } \ - kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \ - kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \ - if (size < KHASH_MIN_SIZE) \ - size = KHASH_MIN_SIZE; \ - khash_power2(size); \ - h->n_buckets = size; \ - kh_alloc_##name(mrb, h); \ - return h; \ - } \ - kh_##name##_t *kh_init_##name(mrb_state *mrb) { \ - return kh_init_##name##_size(mrb, KHASH_DEFAULT_SIZE); \ - } \ - void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h) \ - { \ - if (h) { \ - mrb_free(mrb, h->keys); \ - mrb_free(mrb, h); \ - } \ - } \ - void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h) \ - { \ - (void)mrb; \ - if (h && h->ed_flags) { \ - kh_fill_flags(h->ed_flags, 0xaa, h->n_buckets/4); \ - h->size = h->n_occupied = 0; \ - } \ - } \ - khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key) \ - { \ - khint_t k = __hash_func(mrb,key) & khash_mask(h), step = 0; \ - (void)mrb; \ - while (!__ac_isempty(h->ed_flags, k)) { \ - if (!__ac_isdel(h->ed_flags, k)) { \ - if (__hash_equal(mrb,h->keys[k], key)) return k; \ - } \ - k = (k+(++step)) & khash_mask(h); \ - } \ - return kh_end(h); \ - } \ - void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets) \ - { \ - if (new_n_buckets < KHASH_MIN_SIZE) \ - new_n_buckets = KHASH_MIN_SIZE; \ - khash_power2(new_n_buckets); \ - { \ - kh_##name##_t hh; \ - uint8_t *old_ed_flags = h->ed_flags; \ - khkey_t *old_keys = h->keys; \ - khval_t *old_vals = h->vals; \ - khint_t old_n_buckets = h->n_buckets; \ - khint_t i; \ - hh.n_buckets = new_n_buckets; \ - kh_alloc_##name(mrb, &hh); \ - /* relocate */ \ - for (i=0 ; in_occupied >= khash_upper_bound(h)) { \ - kh_resize_##name(mrb, h, h->n_buckets*2); \ - } \ - k = __hash_func(mrb,key) & khash_mask(h); \ - del_k = kh_end(h); \ - while (!__ac_isempty(h->ed_flags, k)) { \ - if (!__ac_isdel(h->ed_flags, k)) { \ - if (__hash_equal(mrb,h->keys[k], key)) { \ - if (ret) *ret = 0; \ - return k; \ - } \ - } \ - else if (del_k == kh_end(h)) { \ - del_k = k; \ - } \ - k = (k+(++step)) & khash_mask(h); \ - } \ - if (del_k != kh_end(h)) { \ - /* put at del */ \ - h->keys[del_k] = key; \ - h->ed_flags[del_k/4] &= ~__m_del[del_k%4]; \ - h->size++; \ - if (ret) *ret = 2; \ - return del_k; \ - } \ - else { \ - /* put at empty */ \ - h->keys[k] = key; \ - h->ed_flags[k/4] &= ~__m_empty[k%4]; \ - h->size++; \ - h->n_occupied++; \ - if (ret) *ret = 1; \ - return k; \ - } \ - } \ - void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x) \ - { \ - (void)mrb; \ - mrb_assert(x != h->n_buckets && !__ac_iseither(h->ed_flags, x)); \ - h->ed_flags[x/4] |= __m_del[x%4]; \ - h->size--; \ - } \ - kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h) \ - { \ - kh_##name##_t *h2; \ - khiter_t k, k2; \ - \ - h2 = kh_init_##name(mrb); \ - for (k = kh_begin(h); k != kh_end(h); k++) { \ - if (kh_exist(h, k)) { \ - k2 = kh_put_##name(mrb, h2, kh_key(h, k), NULL); \ - if (kh_is_map) kh_value(h2, k2) = kh_value(h, k); \ - } \ - } \ - return h2; \ - } - - -#define khash_t(name) kh_##name##_t - -#define kh_init_size(name,mrb,size) kh_init_##name##_size(mrb,size) -#define kh_init(name,mrb) kh_init_##name(mrb) -#define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h) -#define kh_clear(name, mrb, h) kh_clear_##name(mrb, h) -#define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s) -#define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL) -#define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r) -#define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k) -#define kh_del(name, mrb, h, k) kh_del_##name(mrb, h, k) -#define kh_copy(name, mrb, h) kh_copy_##name(mrb, h) - -#define kh_exist(h, x) (!__ac_iseither((h)->ed_flags, (x))) -#define kh_key(h, x) ((h)->keys[x]) -#define kh_val(h, x) ((h)->vals[x]) -#define kh_value(h, x) ((h)->vals[x]) -#define kh_begin(h) (khint_t)(0) -#define kh_end(h) ((h)->n_buckets) -#define kh_size(h) ((h)->size) -#define kh_n_buckets(h) ((h)->n_buckets) - -#define kh_int_hash_func(mrb,key) (khint_t)((key)^((key)<<2)^((key)>>2)) -#define kh_int_hash_equal(mrb,a, b) (a == b) -#define kh_int64_hash_func(mrb,key) (khint_t)((key)>>33^(key)^(key)<<11) -#define kh_int64_hash_equal(mrb,a, b) (a == b) -static inline khint_t __ac_X31_hash_string(const char *s) -{ - khint_t h = *s; - if (h) for (++s ; *s; ++s) h = (h << 5) - h + *s; - return h; -} -#define kh_str_hash_func(mrb,key) __ac_X31_hash_string(key) -#define kh_str_hash_equal(mrb,a, b) (strcmp(a, b) == 0) - -typedef const char *kh_cstr_t; - -MRB_END_DECL - -#endif /* MRUBY_KHASH_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/numeric.h nghttp2-0.6.7/third-party/mruby/include/mruby/numeric.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/numeric.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/numeric.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -/* -** mruby/numeric.h - Numeric, Integer, Float, Fixnum class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_NUMERIC_H -#define MRUBY_NUMERIC_H - -#include "mruby/common.h" - -/** - * Numeric class and it's sub-classes. - * - * Integer, Float and Fixnum - */ -MRB_BEGIN_DECL - -#define POSFIXABLE(f) ((f) <= MRB_INT_MAX) -#define NEGFIXABLE(f) ((f) >= MRB_INT_MIN) -#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f)) - -MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val); -MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base); -/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */ -MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt); -MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x); - -mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y); -mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y); -mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y); -mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y); - -#define MRB_UINT_MAKE2(n) uint ## n ## _t -#define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n) -#define mrb_uint MRB_UINT_MAKE(MRB_INT_BIT) - -#define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT)) - -/* Idea from Potion: https://github.com/perl11/potion (MIT) */ -#if (defined(__clang__) && ((__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ >= 4))) \ - || (defined(__GNUC__) && __GNUC__ >= 5) - -static inline mrb_bool -mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum) -{ - mrb_bool of; - -#ifdef MRB_INT64 - long long val; - of = __builtin_saddll_overflow(augend, addend, &val) || -#else - int val; - of = __builtin_sadd_overflow(augend, addend, &val) || -#endif - (val > MRB_INT_MAX) || (val < MRB_INT_MIN); - - *sum = (mrb_int) val; - return of; -} - -static inline mrb_bool -mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference) -{ - mrb_bool of; - -#ifdef MRB_INT64 - long long val; - of = __builtin_ssubll_overflow(minuend, subtrahend, &val) || -#else - int val; - of = __builtin_ssub_overflow(minuend, subtrahend, &val) || -#endif - (val > MRB_INT_MAX) || (val < MRB_INT_MIN); - - *difference = (mrb_int) val; - return of; -} -#else - -static inline mrb_bool -mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum) -{ - mrb_uint x = (mrb_uint)augend; - mrb_uint y = (mrb_uint)addend; - mrb_uint z = (mrb_uint)(x + y); - *sum = (mrb_int)z; - return !!(((x ^ z) & (y ^ z)) & MRB_INT_OVERFLOW_MASK); -} - -static inline mrb_bool -mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference) -{ - mrb_uint x = (mrb_uint)minuend; - mrb_uint y = (mrb_uint)subtrahend; - mrb_uint z = (mrb_uint)(x - y); - *difference = (mrb_int)z; - return !!(((x ^ z) & (~y ^ z)) & MRB_INT_OVERFLOW_MASK); -} - -#endif - -#undef MRB_INT_OVERFLOW_MASK -#undef mrb_uint -#undef MRB_UINT_MAKE -#undef MRB_UINT_MAKE2 - -MRB_END_DECL - -#endif /* MRUBY_NUMERIC_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/object.h nghttp2-0.6.7/third-party/mruby/include/mruby/object.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/object.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/object.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* -** mruby/object.h - mruby object definition -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_OBJECT_H -#define MRUBY_OBJECT_H - -#define MRB_OBJECT_HEADER \ - enum mrb_vtype tt:8;\ - uint32_t color:3;\ - uint32_t flags:21;\ - struct RClass *c;\ - struct RBasic *gcnext - -#define MRB_FLAG_TEST(obj, flag) ((obj)->flags & flag) - - -struct RBasic { - MRB_OBJECT_HEADER; -}; -#define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v))) - -struct RObject { - MRB_OBJECT_HEADER; - struct iv_tbl *iv; -}; -#define mrb_obj_ptr(v) ((struct RObject*)(mrb_ptr(v))) - -#define mrb_immediate_p(x) (mrb_type(x) < MRB_TT_HAS_BASIC) -#define mrb_special_const_p(x) mrb_immediate_p(x) - -struct RFiber { - MRB_OBJECT_HEADER; - struct mrb_context *cxt; -}; - -#endif /* MRUBY_OBJECT_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/opcode.h nghttp2-0.6.7/third-party/mruby/include/mruby/opcode.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/opcode.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/opcode.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,160 +0,0 @@ -/* -** mruby/opcode.h - RiteVM operation codes -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_OPCODE_H -#define MRUBY_OPCODE_H - -#define MAXARG_Bx (0xffff) -#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */ - -/* instructions: packed 32 bit */ -/* ------------------------------- */ -/* A:B:C:OP = 9: 9: 7: 7 */ -/* A:Bx:OP = 9:16: 7 */ -/* Ax:OP = 25: 7 */ -/* A:Bz:Cz:OP = 9:14: 2: 7 */ - -#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f)) -#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff)) -#define GETARG_B(i) ((int)((((mrb_code)(i)) >> 14) & 0x1ff)) -#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f)) -#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff)) -#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx)) -#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff)) -#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1)))) -#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1)))) -#define GETARG_b(i) GETARG_UNPACK_b(i,14,2) -#define GETARG_c(i) GETARG_UNPACK_c(i,14,2) - -#define MKOPCODE(op) ((op) & 0x7f) -#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23) -#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14) -#define MKARG_C(c) (((c) & 0x7f) << 7) -#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7) -#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx) -#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7) -#define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<R(A+1) (Syms[B]=:>,C=1) */ - OP_GE,/* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1) */ - - OP_ARRAY,/* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */ - OP_ARYCAT,/* A B ary_cat(R(A),R(B)) */ - OP_ARYPUSH,/* A B ary_push(R(A),R(B)) */ - OP_AREF,/* A B C R(A) := R(B)[C] */ - OP_ASET,/* A B C R(B)[C] := R(A) */ - OP_APOST,/* A B C *R(A),R(A+1)..R(A+C) := R(A) */ - - OP_STRING,/* A Bx R(A) := str_dup(Lit(Bx)) */ - OP_STRCAT,/* A B str_cat(R(A),R(B)) */ - - OP_HASH,/* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */ - OP_LAMBDA,/* A Bz Cz R(A) := lambda(SEQ[Bz],Cz) */ - OP_RANGE,/* A B C R(A) := range_new(R(B),R(B+1),C) */ - - OP_OCLASS,/* A R(A) := ::Object */ - OP_CLASS,/* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */ - OP_MODULE,/* A B R(A) := newmodule(R(A),Syms(B)) */ - OP_EXEC,/* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */ - OP_METHOD,/* A B R(A).newmethod(Syms(B),R(A+1)) */ - OP_SCLASS,/* A B R(A) := R(B).singleton_class */ - OP_TCLASS,/* A R(A) := target_class */ - - OP_DEBUG,/* A B C print R(A),R(B),R(C) */ - OP_STOP,/* stop VM */ - OP_ERR,/* Bx raise RuntimeError with message Lit(Bx) */ - - OP_RSVD1,/* reserved instruction #1 */ - OP_RSVD2,/* reserved instruction #2 */ - OP_RSVD3,/* reserved instruction #3 */ - OP_RSVD4,/* reserved instruction #4 */ - OP_RSVD5,/* reserved instruction #5 */ -}; - -#define OP_L_STRICT 1 -#define OP_L_CAPTURE 2 -#define OP_L_METHOD OP_L_STRICT -#define OP_L_LAMBDA (OP_L_STRICT|OP_L_CAPTURE) -#define OP_L_BLOCK OP_L_CAPTURE - -#define OP_R_NORMAL 0 -#define OP_R_BREAK 1 -#define OP_R_RETURN 2 - -#endif /* MRUBY_OPCODE_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/proc.h nghttp2-0.6.7/third-party/mruby/include/mruby/proc.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/proc.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/proc.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -/* -** mruby/proc.h - Proc class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_PROC_H -#define MRUBY_PROC_H - -#include "mruby/common.h" -#include "mruby/irep.h" - -/** - * Proc class - */ -MRB_BEGIN_DECL - -struct REnv { - MRB_OBJECT_HEADER; - mrb_value *stack; - mrb_sym mid; - ptrdiff_t cioff; -}; - -#define MRB_SET_ENV_STACK_LEN(e,len) (e)->flags = (unsigned int)(len) -#define MRB_ENV_STACK_LEN(e) ((mrb_int)(e)->flags) -#define MRB_ENV_UNSHARE_STACK(e) ((e)->cioff = -1) -#define MRB_ENV_STACK_SHARED_P(e) ((e)->cioff >= 0) - -struct RProc { - MRB_OBJECT_HEADER; - union { - mrb_irep *irep; - mrb_func_t func; - } body; - struct RClass *target_class; - struct REnv *env; -}; - -/* aspec access */ -#define MRB_ASPEC_REQ(a) (((a) >> 18) & 0x1f) -#define MRB_ASPEC_OPT(a) (((a) >> 13) & 0x1f) -#define MRB_ASPEC_REST(a) (((a) >> 12) & 0x1) -#define MRB_ASPEC_POST(a) (((a) >> 7) & 0x1f) -#define MRB_ASPEC_KEY(a) (((a) >> 2) & 0x1f) -#define MRB_ASPEC_KDICT(a) ((a) & (1<<1)) -#define MRB_ASPEC_BLOCK(a) ((a) & 1) - -#define MRB_PROC_CFUNC 128 -#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC) != 0) -#define MRB_PROC_STRICT 256 -#define MRB_PROC_STRICT_P(p) (((p)->flags & MRB_PROC_STRICT) != 0) - -#define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v))) - -struct RProc *mrb_proc_new(mrb_state*, mrb_irep*); -struct RProc *mrb_closure_new(mrb_state*, mrb_irep*); -MRB_API struct RProc *mrb_proc_new_cfunc(mrb_state*, mrb_func_t); -MRB_API struct RProc *mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals); -void mrb_proc_copy(struct RProc *a, struct RProc *b); - -/* implementation of #send method */ -MRB_API mrb_value mrb_f_send(mrb_state *mrb, mrb_value self); - -/* following functions are defined in mruby-proc-ext so please include it when using */ -MRB_API struct RProc *mrb_proc_new_cfunc_with_env(mrb_state*, mrb_func_t, mrb_int, const mrb_value*); -MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state*, mrb_int); -/* old name */ -#define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx) - -#include "mruby/khash.h" -KHASH_DECLARE(mt, mrb_sym, struct RProc*, TRUE) - -MRB_END_DECL - -#endif /* MRUBY_PROC_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/range.h nghttp2-0.6.7/third-party/mruby/include/mruby/range.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/range.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/range.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -/* -** mruby/range.h - Range class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_RANGE_H -#define MRUBY_RANGE_H - -#include "mruby/common.h" - -/** - * Range class - */ -MRB_BEGIN_DECL - -typedef struct mrb_range_edges { - mrb_value beg; - mrb_value end; -} mrb_range_edges; - -struct RRange { - MRB_OBJECT_HEADER; - mrb_range_edges *edges; - mrb_bool excl : 1; -}; - -#define mrb_range_ptr(v) ((struct RRange*)(mrb_ptr(v))) -#define mrb_range_value(p) mrb_obj_value((void*)(p)) - -/* - * Initializes a Range. - * - * If the third parameter is FALSE then it includes the last value in the range. - * If the third parameter is TRUE then it excludes the last value in the range. - * - * @param start the beginning value. - * @param end the ending value. - * @param exclude represents the inclusion or exclusion of the last value. - */ -MRB_API mrb_value mrb_range_new(mrb_state *mrb, mrb_value start, mrb_value end, mrb_bool exclude); - -MRB_API mrb_bool mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len); -mrb_value mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int)); - -MRB_END_DECL - -#endif /* MRUBY_RANGE_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/re.h nghttp2-0.6.7/third-party/mruby/include/mruby/re.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/re.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/re.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -/* -** mruby/re.h - Regexp class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_RE_H -#define MRUBY_RE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define REGEXP_CLASS "Regexp" - -#ifdef __cplusplus -} -#endif - -#endif /* RE_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/string.h nghttp2-0.6.7/third-party/mruby/include/mruby/string.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/string.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/string.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,201 +0,0 @@ -/* -** mruby/string.h - String class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_STRING_H -#define MRUBY_STRING_H - -#include "mruby/common.h" - -/** - * String class - */ -MRB_BEGIN_DECL - -extern const char mrb_digitmap[]; - -#define RSTRING_EMBED_LEN_MAX ((mrb_int)(sizeof(void*) * 3 - 1)) - -struct RString { - MRB_OBJECT_HEADER; - union { - struct { - mrb_int len; - union { - mrb_int capa; - struct mrb_shared_string *shared; - } aux; - char *ptr; - } heap; - char ary[RSTRING_EMBED_LEN_MAX + 1]; - } as; -}; - -#define RSTR_EMBED_P(s) ((s)->flags & MRB_STR_EMBED) -#define RSTR_SET_EMBED_FLAG(s) ((s)->flags |= MRB_STR_EMBED) -#define RSTR_UNSET_EMBED_FLAG(s) ((s)->flags &= ~(MRB_STR_EMBED|MRB_STR_EMBED_LEN_MASK)) -#define RSTR_SET_EMBED_LEN(s, n) do {\ - size_t tmp_n = (n);\ - s->flags &= ~MRB_STR_EMBED_LEN_MASK;\ - s->flags |= (tmp_n) << MRB_STR_EMBED_LEN_SHIFT;\ -} while (0) -#define RSTR_SET_LEN(s, n) do {\ - if (RSTR_EMBED_P(s)) {\ - RSTR_SET_EMBED_LEN((s),(n));\ - } else {\ - s->as.heap.len = (mrb_int)(n);\ - }\ -} while (0) -#define RSTR_EMBED_LEN(s)\ - (mrb_int)(((s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT) -#define RSTR_PTR(s) ((RSTR_EMBED_P(s)) ? (s)->as.ary : (s)->as.heap.ptr) -#define RSTR_LEN(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_LEN(s) : (s)->as.heap.len) -#define RSTR_CAPA(s) (RSTR_EMBED_P(s) ? RSTRING_EMBED_LEN_MAX : (s)->as.heap.aux.capa) - -#define RSTR_SHARED_P(s) ((s)->flags & MRB_STR_SHARED) -#define RSTR_SET_SHARED_FLAG(s) ((s)->flags |= MRB_STR_SHARED) -#define RSTR_UNSET_SHARED_FLAG(s) ((s)->flags &= ~MRB_STR_SHARED) - -#define RSTR_NOFREE_P(s) ((s)->flags & MRB_STR_NOFREE) -#define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE) -#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE) - -#define RSTR_FROZEN_P(s) ((s)->flags & MRB_STR_FROZEN) -#define RSTR_SET_FROZEN_FLAG(s) ((s)->flags |= MRB_STR_FROZEN) -#define RSTR_UNSET_FROZEN_FLAG(s) ((s)->flags &= ~MRB_STR_FROZEN) - -/* - * Returns a pointer from a Ruby string - */ -#define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s))) -#define RSTRING(s) mrb_str_ptr(s) -#define RSTRING_PTR(s) RSTR_PTR(RSTRING(s)) -#define RSTRING_EMBED_LEN(s) RSTR_ENBED_LEN(RSTRING(s)) -#define RSTRING_LEN(s) RSTR_LEN(RSTRING(s)) -#define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s)) -#define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s)) -mrb_int mrb_str_strlen(mrb_state*, struct RString*); - -#define MRB_STR_SHARED 1 -#define MRB_STR_NOFREE 2 -#define MRB_STR_FROZEN 4 -#define MRB_STR_EMBED 8 -#define MRB_STR_EMBED_LEN_MASK 0x1f0 -#define MRB_STR_EMBED_LEN_SHIFT 4 - -void mrb_gc_free_str(mrb_state*, struct RString*); -MRB_API void mrb_str_modify(mrb_state*, struct RString*); -MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value); - -/* - * Adds two strings together. - */ -MRB_API mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value); - -/* - * Converts pointer into a Ruby string. - */ -MRB_API mrb_value mrb_ptr_to_str(mrb_state *, void*); - -/* - * Returns an object as a Ruby string. - */ -MRB_API mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj); - -/* - * Resizes the string's length. - */ -MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len); - -/* - * Returns a sub string. - */ -MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); - -/* - * Returns a Ruby string type. - */ -MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str); - -MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str); -MRB_API mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa); - -MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr); -MRB_API const char *mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr); - -/* - * Duplicates a string object. - */ -MRB_API mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str); - -/* - * Returns a symbol from a passed in string. - */ -MRB_API mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self); - -MRB_API mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck); -MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck); - -/* - * Returns a converted string type. - */ -MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str); - -/* - * Returns true if the strings match and false if the strings don't match. - */ -MRB_API mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2); - -/* - * Returns a concated string comprised of a Ruby string and a C string. - * - * @see mrb_str_cat_cstr - */ -MRB_API mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len); - -/* - * Returns a concated string comprised of a Ruby string and a C string. - * - * @see mrb_str_cat - */ -MRB_API mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr); -MRB_API mrb_value mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2); -#define mrb_str_cat_lit(mrb, str, lit) mrb_str_cat(mrb, str, lit, mrb_strlen_lit(lit)) - -/* - * Adds str2 to the end of str1. - */ -MRB_API mrb_value mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2); - -/* - * Returns 0 if both Ruby strings are equal. Returns a value < 0 if Ruby str1 is less than Ruby str2. Returns a value > 0 if Ruby str2 is greater than Ruby str1. - */ -MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2); - -/* - * Returns a C string from a Ruby string. - */ -MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str); - -mrb_value mrb_str_pool(mrb_state *mrb, mrb_value str); -mrb_int mrb_str_hash(mrb_state *mrb, mrb_value str); -mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str); - -/* - * Returns a printable version of str, surrounded by quote marks, with special characters escaped. - */ -mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str); - -void mrb_noregexp(mrb_state *mrb, mrb_value self); -void mrb_regexp_check(mrb_state *mrb, mrb_value obj); - -/* For backward compatibility */ -#define mrb_str_cat2(mrb, str, ptr) mrb_str_cat_cstr(mrb, str, ptr) -#define mrb_str_buf_cat(mrb, str, ptr, len) mrb_str_cat(mrb, str, ptr, len) -#define mrb_str_buf_append(mrb, str, str2) mrb_str_cat_str(mrb, str, str2) - -MRB_END_DECL - -#endif /* MRUBY_STRING_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/throw.h nghttp2-0.6.7/third-party/mruby/include/mruby/throw.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/throw.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/throw.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -/* -** mruby/throw.h - mruby exception throwing handler -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRB_THROW_H -#define MRB_THROW_H - -#ifdef MRB_ENABLE_CXX_EXCEPTION - -#define MRB_TRY(buf) do { try { -#define MRB_CATCH(buf) } catch(mrb_jmpbuf_impl e) { if (e != (buf)->impl) { throw e; } -#define MRB_END_EXC(buf) } } while(0) - -#define MRB_THROW(buf) throw((buf)->impl) -typedef mrb_int mrb_jmpbuf_impl; - -#else - -#include - -#define MRB_TRY(buf) do { if (setjmp((buf)->impl) == 0) { -#define MRB_CATCH(buf) } else { -#define MRB_END_EXC(buf) } } while(0) - -#define MRB_THROW(buf) longjmp((buf)->impl, 1); -#define mrb_jmpbuf_impl jmp_buf - -#endif - -struct mrb_jmpbuf { - mrb_jmpbuf_impl impl; - -#ifdef MRB_ENABLE_CXX_EXCEPTION - static mrb_int jmpbuf_id; - mrb_jmpbuf() : impl(jmpbuf_id++) {} -#endif -}; - -#endif /* MRB_THROW_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/value.h nghttp2-0.6.7/third-party/mruby/include/mruby/value.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/value.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/value.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,268 +0,0 @@ -/* -** mruby/value.h - mruby value definitions -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_VALUE_H -#define MRUBY_VALUE_H - -#include "mruby/common.h" - -/** - * MRuby Value definition functions and macros. - */ -MRB_BEGIN_DECL - -typedef uint32_t mrb_sym; -typedef uint8_t mrb_bool; -struct mrb_state; - -#if defined(MRB_INT16) && defined(MRB_INT64) -# error "You can't define MRB_INT16 and MRB_INT64 at the same time." -#endif - -#if defined(MRB_INT64) - typedef int64_t mrb_int; -# define MRB_INT_BIT 64 -# define MRB_INT_MIN (INT64_MIN>>MRB_FIXNUM_SHIFT) -# define MRB_INT_MAX (INT64_MAX>>MRB_FIXNUM_SHIFT) -#elif defined(MRB_INT16) - typedef int16_t mrb_int; -# define MRB_INT_BIT 16 -# define MRB_INT_MIN (INT16_MIN>>MRB_FIXNUM_SHIFT) -# define MRB_INT_MAX (INT16_MAX>>MRB_FIXNUM_SHIFT) -#else - typedef int32_t mrb_int; -# define MRB_INT_BIT 32 -# define MRB_INT_MIN (INT32_MIN>>MRB_FIXNUM_SHIFT) -# define MRB_INT_MAX (INT32_MAX>>MRB_FIXNUM_SHIFT) -#endif - -#ifdef MRB_USE_FLOAT - typedef float mrb_float; -# define str_to_mrb_float(buf) strtof(buf, NULL) -#else - typedef double mrb_float; -# define str_to_mrb_float(buf) strtod(buf, NULL) -#endif - -#if defined _MSC_VER && _MSC_VER < 1900 -# ifndef __cplusplus -# define inline __inline -# endif -# include -MRB_API int mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg); -MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...); -# define vsnprintf(s, n, format, arg) mrb_msvc_vsnprintf(s, n, format, arg) -# define snprintf(s, n, format, ...) mrb_msvc_snprintf(s, n, format, __VA_ARGS__) -# if _MSC_VER < 1800 -# include -# define isfinite(n) _finite(n) -# define isnan _isnan -# define isinf(n) (!_finite(n) && !_isnan(n)) -# define signbit(n) (_copysign(1.0, (n)) < 0.0) -# define strtof (float)strtod -static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000; -# define INFINITY (*(float *)&IEEE754_INFINITY_BITS_SINGLE) -# define NAN ((float)(INFINITY - INFINITY)) -# endif -#endif - -enum mrb_vtype { - MRB_TT_FALSE = 0, /* 0 */ - MRB_TT_FREE, /* 1 */ - MRB_TT_TRUE, /* 2 */ - MRB_TT_FIXNUM, /* 3 */ - MRB_TT_SYMBOL, /* 4 */ - MRB_TT_UNDEF, /* 5 */ - MRB_TT_FLOAT, /* 6 */ - MRB_TT_CPTR, /* 7 */ - MRB_TT_OBJECT, /* 8 */ - MRB_TT_CLASS, /* 9 */ - MRB_TT_MODULE, /* 10 */ - MRB_TT_ICLASS, /* 11 */ - MRB_TT_SCLASS, /* 12 */ - MRB_TT_PROC, /* 13 */ - MRB_TT_ARRAY, /* 14 */ - MRB_TT_HASH, /* 15 */ - MRB_TT_STRING, /* 16 */ - MRB_TT_RANGE, /* 17 */ - MRB_TT_EXCEPTION, /* 18 */ - MRB_TT_FILE, /* 19 */ - MRB_TT_ENV, /* 20 */ - MRB_TT_DATA, /* 21 */ - MRB_TT_FIBER, /* 22 */ - MRB_TT_MAXDEFINE /* 23 */ -}; - -#include "mruby/object.h" - -#ifdef MRB_DOCUMENTATION_BLOCK - -/** - * @abstract - * MRuby value boxing. - * - * Actual implementation depends on configured boxing type. - * - * @see mruby/boxing_no.h Default boxing representation - * @see mruby/boxing_word.h Word representation - * @see mruby/boxing_nan.h Boxed double representation - */ -typedef void mrb_value; - -#endif - -#if defined(MRB_NAN_BOXING) -#include "boxing_nan.h" -#elif defined(MRB_WORD_BOXING) -#include "boxing_word.h" -#else -#include "boxing_no.h" -#endif - -#ifndef mrb_fixnum_p -#define mrb_fixnum_p(o) (mrb_type(o) == MRB_TT_FIXNUM) -#endif -#ifndef mrb_undef_p -#define mrb_undef_p(o) (mrb_type(o) == MRB_TT_UNDEF) -#endif -#ifndef mrb_nil_p -#define mrb_nil_p(o) (mrb_type(o) == MRB_TT_FALSE && !mrb_fixnum(o)) -#endif -#ifndef mrb_bool -#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE) -#endif -#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT) -#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL) -#define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY) -#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING) -#define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH) -#define mrb_cptr_p(o) (mrb_type(o) == MRB_TT_CPTR) -#define mrb_exception_p(o) (mrb_type(o) == MRB_TT_EXCEPTION) -#define mrb_test(o) mrb_bool(o) -MRB_API mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value); - -/* - * Returns a float in Ruby. - */ -MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f) -{ - mrb_value v; - (void) mrb; - SET_FLOAT_VALUE(mrb, v, f); - return v; -} - -static inline mrb_value -mrb_cptr_value(struct mrb_state *mrb, void *p) -{ - mrb_value v; - (void) mrb; - SET_CPTR_VALUE(mrb,v,p); - return v; -} - -/* - * Returns a fixnum in Ruby. - */ -MRB_INLINE mrb_value mrb_fixnum_value(mrb_int i) -{ - mrb_value v; - SET_INT_VALUE(v, i); - return v; -} - -static inline mrb_value -mrb_symbol_value(mrb_sym i) -{ - mrb_value v; - SET_SYM_VALUE(v, i); - return v; -} - -static inline mrb_value -mrb_obj_value(void *p) -{ - mrb_value v; - SET_OBJ_VALUE(v, (struct RBasic*)p); - return v; -} - - -/* - * Get a nil mrb_value object. - * - * @return - * nil mrb_value object reference. - */ -MRB_INLINE mrb_value mrb_nil_value(void) -{ - mrb_value v; - SET_NIL_VALUE(v); - return v; -} - -/* - * Returns false in Ruby. - */ -MRB_INLINE mrb_value mrb_false_value(void) -{ - mrb_value v; - SET_FALSE_VALUE(v); - return v; -} - -/* - * Returns true in Ruby. - */ -MRB_INLINE mrb_value mrb_true_value(void) -{ - mrb_value v; - SET_TRUE_VALUE(v); - return v; -} - -static inline mrb_value -mrb_bool_value(mrb_bool boolean) -{ - mrb_value v; - SET_BOOL_VALUE(v, boolean); - return v; -} - -static inline mrb_value -mrb_undef_value(void) -{ - mrb_value v; - SET_UNDEF_VALUE(v); - return v; -} - -#ifdef MRB_USE_ETEXT_EDATA -extern char _etext[]; -#ifdef MRB_NO_INIT_ARRAY_START -extern char _edata[]; - -static inline mrb_bool -mrb_ro_data_p(const char *p) -{ - return _etext < p && p < _edata; -} -#else -extern char __init_array_start[]; - -static inline mrb_bool -mrb_ro_data_p(const char *p) -{ - return _etext < p && p < (char*)&__init_array_start; -} -#endif -#else -# define mrb_ro_data_p(p) FALSE -#endif - -MRB_END_DECL - -#endif /* MRUBY_VALUE_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/variable.h nghttp2-0.6.7/third-party/mruby/include/mruby/variable.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/variable.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/variable.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -/* -** mruby/variable.h - mruby variables -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_VARIABLE_H -#define MRUBY_VARIABLE_H - -#include "mruby/common.h" - -/** - * Functions to access mruby variables. - */ -MRB_BEGIN_DECL - -typedef struct global_variable { - int counter; - mrb_value *data; - mrb_value (*getter)(void); - void (*setter)(void); - /* void (*marker)(); */ - /* int block_trace; */ - /* struct trace_var *trace; */ -} global_variable; - -struct global_entry { - global_variable *var; - mrb_sym id; -}; - -mrb_value mrb_vm_special_get(mrb_state*, mrb_sym); -void mrb_vm_special_set(mrb_state*, mrb_sym, mrb_value); -mrb_value mrb_vm_iv_get(mrb_state*, mrb_sym); -void mrb_vm_iv_set(mrb_state*, mrb_sym, mrb_value); -mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym); -void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value); -mrb_value mrb_vm_const_get(mrb_state*, mrb_sym); -void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value); -MRB_API mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym); -MRB_API void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value); -MRB_API mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym); -MRB_API void mrb_const_remove(mrb_state*, mrb_value, mrb_sym); - -MRB_API mrb_bool mrb_iv_p(mrb_state *mrb, mrb_sym sym); -MRB_API void mrb_iv_check(mrb_state *mrb, mrb_sym sym); -MRB_API mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym); -MRB_API void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v); -MRB_API mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym); -MRB_API void mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v); -MRB_API mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym); -MRB_API void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v); -MRB_API mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym); -MRB_API mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym); -MRB_API void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src); -MRB_API mrb_bool mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id); -MRB_API mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym); -MRB_API void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val); -MRB_API void mrb_gv_remove(mrb_state *mrb, mrb_sym sym); -MRB_API mrb_value mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym); -MRB_API void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v); -MRB_API void mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v); -MRB_API mrb_bool mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym); -mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*); -mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod); -mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self); -mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value); -mrb_value mrb_mod_class_variables(mrb_state*, mrb_value); -mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym); -mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym); -mrb_sym mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer); - -/* GC functions */ -void mrb_gc_mark_gv(mrb_state*); -void mrb_gc_free_gv(mrb_state*); -void mrb_gc_mark_iv(mrb_state*, struct RObject*); -size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*); -void mrb_gc_free_iv(mrb_state*, struct RObject*); - -MRB_END_DECL - -#endif /* MRUBY_VARIABLE_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby/version.h nghttp2-0.6.7/third-party/mruby/include/mruby/version.h --- nghttp2-1.13.0/third-party/mruby/include/mruby/version.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby/version.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -/* -** mruby/version.h - mruby version definition -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_VERSION_H -#define MRUBY_VERSION_H - -#include "mruby/common.h" - -/** - * mruby version definition macros - */ -MRB_BEGIN_DECL - -/* - * A passed in expression. - */ -#define MRB_STRINGIZE0(expr) #expr - -/* - * Passes in an expression to MRB_STRINGIZE0. - */ -#define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr) - -/* - * The version of Ruby used by mruby. - */ -#define MRUBY_RUBY_VERSION "1.9" - -/* - * Ruby engine. - */ -#define MRUBY_RUBY_ENGINE "mruby" - -/* - * Major release version number. - */ -#define MRUBY_RELEASE_MAJOR 1 - -/* - * Minor release version number. - */ -#define MRUBY_RELEASE_MINOR 2 - -/* - * Tiny release version number. - */ -#define MRUBY_RELEASE_TEENY 0 - -/* - * The mruby version. - */ -#define MRUBY_VERSION MRB_STRINGIZE(MRUBY_RELEASE_MAJOR) "." MRB_STRINGIZE(MRUBY_RELEASE_MINOR) "." MRB_STRINGIZE(MRUBY_RELEASE_TEENY) - -/* - * Release number. - */ -#define MRUBY_RELEASE_NO (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY) - -/* - * Release year. - */ -#define MRUBY_RELEASE_YEAR 2015 - -/* - * Release month. - */ -#define MRUBY_RELEASE_MONTH 11 - -/* - * Release day. - */ -#define MRUBY_RELEASE_DAY 17 - -/* - * Release date as a string. - */ -#define MRUBY_RELEASE_DATE MRB_STRINGIZE(MRUBY_RELEASE_YEAR) "-" MRB_STRINGIZE(MRUBY_RELEASE_MONTH) "-" MRB_STRINGIZE(MRUBY_RELEASE_DAY) - -/* - * The year mruby was first created. - */ -#define MRUBY_BIRTH_YEAR 2010 - -/* - * MRuby's authors. - */ -#define MRUBY_AUTHOR "mruby developers" - -/* - * mruby's version, and release date. - */ -#define MRUBY_DESCRIPTION \ - "mruby " MRUBY_VERSION \ - " (" MRUBY_RELEASE_DATE ") " \ - -/* - * mruby's copyright information. - */ -#define MRUBY_COPYRIGHT \ - "mruby - Copyright (c) " \ - MRB_STRINGIZE(MRUBY_BIRTH_YEAR)"-" \ - MRB_STRINGIZE(MRUBY_RELEASE_YEAR)" " \ - MRUBY_AUTHOR \ - -MRB_END_DECL - -#endif /* MRUBY_VERSION_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/include/mruby.h nghttp2-0.6.7/third-party/mruby/include/mruby.h --- nghttp2-1.13.0/third-party/mruby/include/mruby.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/include/mruby.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,1071 +0,0 @@ -/* -** mruby - An embeddable Ruby implementation -** -** Copyright (c) mruby developers 2010-2015 -** -** 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. -** -** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] -*/ - -#ifndef MRUBY_H -#define MRUBY_H - -#include -#include -#include - -#include "mrbconf.h" -#include "mruby/common.h" -#include "mruby/value.h" -#include "mruby/gc.h" -#include "mruby/version.h" - -/** - * MRuby C API entry point - */ -MRB_BEGIN_DECL - -typedef uint32_t mrb_code; - -/** - * Required arguments signature type. - */ -typedef uint32_t mrb_aspec; - - -struct mrb_irep; -struct mrb_state; - -/** - * Function pointer type of custom allocator used in @see mrb_open_allocf. - * - * The function pointing it must behave similarly as realloc except: - * - If ptr is NULL it must allocate new space. - * - If s is NULL, ptr must be freed. - * - * See @see mrb_default_allocf for the default implementation. - */ -typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud); - -#ifndef MRB_FIXED_STATE_ATEXIT_STACK_SIZE -#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5 -#endif - -typedef struct { - mrb_sym mid; - struct RProc *proc; - mrb_value *stackent; - int nregs; - int ridx; - int eidx; - struct REnv *env; - mrb_code *pc; /* return address */ - mrb_code *err; /* error position */ - int argc; - int acc; - struct RClass *target_class; -} mrb_callinfo; - -enum mrb_fiber_state { - MRB_FIBER_CREATED = 0, - MRB_FIBER_RUNNING, - MRB_FIBER_RESUMING, - MRB_FIBER_SUSPENDED, - MRB_FIBER_TRANSFERRED, - MRB_FIBER_TERMINATED, -}; - -struct mrb_context { - struct mrb_context *prev; - - mrb_value *stack; /* stack of virtual machine */ - mrb_value *stbase, *stend; - - mrb_callinfo *ci; - mrb_callinfo *cibase, *ciend; - - mrb_code **rescue; /* exception handler stack */ - int rsize; - struct RProc **ensure; /* ensure handler stack */ - int esize; - - enum mrb_fiber_state status; - struct RFiber *fib; -}; - -struct mrb_jmpbuf; - -typedef void (*mrb_atexit_func)(struct mrb_state*); - -typedef struct mrb_state { - struct mrb_jmpbuf *jmp; - - mrb_allocf allocf; /* memory allocation function */ - void *allocf_ud; /* auxiliary data of allocf */ - - struct mrb_context *c; - struct mrb_context *root_c; - - struct RObject *exc; /* exception */ - struct iv_tbl *globals; /* global variable table */ - - struct RObject *top_self; - struct RClass *object_class; /* Object class */ - struct RClass *class_class; - struct RClass *module_class; - struct RClass *proc_class; - struct RClass *string_class; - struct RClass *array_class; - struct RClass *hash_class; - - struct RClass *float_class; - struct RClass *fixnum_class; - struct RClass *true_class; - struct RClass *false_class; - struct RClass *nil_class; - struct RClass *symbol_class; - struct RClass *kernel_module; - - struct alloca_header *mems; - mrb_gc gc; - - mrb_sym symidx; - struct kh_n2s *name2sym; /* symbol hash */ - struct symbol_name *symtbl; /* symbol table */ - size_t symcapa; - -#ifdef MRB_ENABLE_DEBUG_HOOK - void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs); - void (*debug_op_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs); -#endif - - struct RClass *eException_class; - struct RClass *eStandardError_class; - struct RObject *nomem_err; /* pre-allocated NoMemoryError */ - - void *ud; /* auxiliary data */ - -#ifdef MRB_FIXED_STATE_ATEXIT_STACK - mrb_atexit_func atexit_stack[MRB_FIXED_STATE_ATEXIT_STACK_SIZE]; -#else - mrb_atexit_func *atexit_stack; -#endif - mrb_int atexit_stack_len; -} mrb_state; - - -typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value); - -/** - * Defines a new class. - * - * If you're creating a gem it may look something like this: - * - * !!!c - * void mrb_example_gem_init(mrb_state* mrb) { - * struct RClass *example_class; - * example_class = mrb_define_class(mrb, "Example_Class", mrb->object_class); - * } - * - * void mrb_example_gem_final(mrb_state* mrb) { - * //free(TheAnimals); - * } - * - * @param [mrb_state *] mrb The current mruby state. - * @param [const char *] name The name of the defined class. - * @param [struct RClass *] super The new class parent. - * @return [struct RClass *] Reference to the newly defined class. - * @see mrb_define_class_under - */ -MRB_API struct RClass *mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super); - -/** - * Defines a new module. - * @param [mrb_state *] mrb_state* The current mruby state. - * @param [const char *] char* The name of the module. - * @return [struct RClass *] Reference to the newly defined module. - */ -MRB_API struct RClass *mrb_define_module(mrb_state *, const char*); -MRB_API mrb_value mrb_singleton_class(mrb_state*, mrb_value); - -/** - * Include a module in another class or module. - * Equivalent to: - * - * module B - * include A - * end - * @param [mrb_state *] mrb_state* The current mruby state. - * @param [struct RClass *] RClass* A reference to module or a class. - * @param [struct RClass *] RClass* A reference to the module to be included. - */ -MRB_API void mrb_include_module(mrb_state*, struct RClass*, struct RClass*); - -/** - * Prepends a module in another class or module. - * - * Equivalent to: - * module B - * prepend A - * end - * @param [mrb_state *] mrb_state* The current mruby state. - * @param [struct RClass *] RClass* A reference to module or a class. - * @param [struct RClass *] RClass* A reference to the module to be prepended. - */ -MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*); - -/** - * Defines a global function in ruby. - * - * If you're creating a gem it may look something like this - * - * Example: - * - * !!!c - * mrb_value example_method(mrb_state* mrb, mrb_value self) - * { - * puts("Executing example command!"); - * return self; - * } - * - * void mrb_example_gem_init(mrb_state* mrb) - * { - * mrb_define_method(mrb, mrb->kernel_module, "example_method", example_method, MRB_ARGS_NONE()); - * } - * - * @param [mrb_state *] mrb The MRuby state reference. - * @param [struct RClass *] cla The class pointer where the method will be defined. - * @param [const char *] name The name of the method being defined. - * @param [mrb_func_t] func The function pointer to the method definition. - * @param [mrb_aspec] aspec The method parameters declaration. - */ -MRB_API void mrb_define_method(mrb_state *mrb, struct RClass *cla, const char *name, mrb_func_t func, mrb_aspec aspec); - -/** - * Defines a class method. - * - * Example: - * # Ruby style - * class Foo - * - * def Foo.bar - * end - * - * end - * // C style - * mrb_value bar_method(mrb_state* mrb, mrb_value self){ - * - * return mrb_nil_value(); - * - * } - * void mrb_example_gem_init(mrb_state* mrb){ - * - * struct RClass *foo; - * - * foo = mrb_define_class(mrb, "Foo", mrb->object_class); - * - * mrb_define_class_method(mrb, foo, "bar", bar_method, MRB_ARGS_NONE()); - * - * } - * @param [mrb_state *] mrb_state* The MRuby state reference. - * @param [struct RClass *] RClass* The class where the class method will be defined. - * @param [const char *] char* The name of the class method being defined. - * @param [mrb_func_t] mrb_func_t The function pointer to the class method definition. - * @param [mrb_aspec] mrb_aspec The method parameters declaration. - */ -MRB_API void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec); -MRB_API void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec); - -/** - * Defines a module fuction. - * - * Example: - * # Ruby style - * module Foo - * - * def Foo.bar * end - * - * end - * // C style - * mrb_value bar_method(mrb_state* mrb, mrb_value self){ - * - * return mrb_nil_value(); * - * } - * void mrb_example_gem_init(mrb_state* mrb){ - * - * struct RClass *foo; - * - * foo = mrb_define_module(mrb, "Foo"); - * - * mrb_define_module_function(mrb, foo, "bar", bar_method, MRB_ARGS_NONE()); - * - * } - * @param [mrb_state *] mrb_state* The MRuby state reference. - * @param [struct RClass *] RClass* The module where the module function will be defined. - * @param [const char *] char* The name of the module function being defined. - * @param [mrb_func_t] mrb_func_t The function pointer to the module function definition. - * @param [mrb_aspec] mrb_aspec The method parameters declaration. - */ -MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); - -/** - * Defines a constant. - * - * Example: - * # Ruby style - * - * class ExampleClass - * - * AGE = 22 - * - * end - * - * // C style - * #include - * #include - * - * void - * mrb_example_gem_init(mrb_state* mrb){ - * - * mrb_define_const(mrb, mrb->kernel_module, "AGE", mrb_fixnum_value(22)); - * - * } - * - * mrb_value - * mrb_example_gem_final(mrb_state* mrb){ - * - * } - * @param [mrb_state *] mrb_state* The MRuby state reference. - * @param [struct RClass *] RClass* A class or module the constant is defined in. - * @param [const char *] name The name of the constant being defined. - * @param [mrb_value] mrb_value The value for the constant. - */ -MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value); - -/** - * Undefines a method. - * - * Example: - * # Ruby style - * - * class ExampleClassA - * - * def example_method - * "example" - * end - * - * end - * - * ExampleClassA.new.example_method # => example - * - * class ExampleClassB < ExampleClassA - * - * undef_method :example_method - * - * end - * - * ExampleClassB.new.example_method # => undefined method 'example_method' for ExampleClassB (NoMethodError) - * - * // C style - * #include - * #include - * - * mrb_value - * mrb_example_method(mrb_state *mrb){ - * - * return mrb_str_new_cstr(mrb, "example"); - * - * } - * - * void - * mrb_example_gem_init(mrb_state* mrb){ - * struct RClass *example_class_a; - * struct RClass *example_class_b; - * struct RClass *example_class_c; - * - * example_class_a = mrb_define_class(mrb, "ExampleClassA", mrb->object_class); - * - * mrb_define_method(mrb, example_class_a, "example_method", mrb_example_method, MRB_ARGS_NONE()); - * - * example_class_b = mrb_define_class(mrb, "ExampleClassB", example_class_a); - * - * example_class_c = mrb_define_class(mrb, "ExampleClassC", example_class_b); - * - * mrb_undef_method(mrb, example_class_c, "example_method"); - * - * } - * - * mrb_example_gem_final(mrb_state* mrb){ - * - * } - * - * @param [mrb_state*] mrb_state* The mruby state reference. - * @param [struct RClass*] RClass* A class the method will be undefined from. - * @param [const char*] constchar* The name of the method to be undefined. - */ -MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*); - -/** - * Undefine a class method. - * - * Example: - * # Ruby style - * - * class ExampleClass - * def self.example_method - * "example" - * end - * - * end - * - * ExampleClass.example_method - * - * // C style - * #include - * #include - * - * mrb_value - * mrb_example_method(mrb_state *mrb){ - * - * return mrb_str_new_cstr(mrb, "example"); - * - * } - * - * void - * mrb_example_gem_init(mrb_state* mrb){ - * - * struct RClass *example_class; - * - * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); - * - * mrb_define_class_method(mrb, example_class, "example_method", mrb_example_method, MRB_ARGS_NONE()); - * - * mrb_undef_class_method(mrb, example_class, "example_method"); - * - * } - * - * void - * mrb_example_gem_final(mrb_state* mrb){ - * - * } - * @param [mrb_state*] mrb_state* The mruby state reference. - * @param [RClass*] RClass* A class the class method will be undefined from. - * @param [constchar*] constchar* The name of the class method to be undefined. - */ -MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*); - -/** - * Initialize a new object instace of c class. - * - * Example: - * - * # Ruby style - * class ExampleClass - * end - * - * p ExampleClass # => # - * // C style - * #include - * #include - * - * void - * mrb_example_gem_init(mrb_state* mrb) { - * struct RClass *example_class; - * mrb_value obj; - * - * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); # => class ExampleClass; end - * obj = mrb_obj_new(mrb, example_class, 0, NULL); # => ExampleClass.new - * mrb_p(mrb, obj); // => Kernel#p - * } - * @param [mrb_state*] mrb The current mruby state. - * @param [RClass*] c Reference to the class of the new object. - * @param [mrb_int] argc Number of arguments in argv - * @param [const mrb_value *] argv Array of mrb_value to initialize the object - * @return [mrb_value] The newly initialized object - */ -MRB_API mrb_value mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv); - -/** @see mrb_obj_new */ -MRB_INLINE mrb_value mrb_class_new_instance(mrb_state *mrb, mrb_int argc, const mrb_value *argv, struct RClass *c) -{ - return mrb_obj_new(mrb,c,argc,argv); -} - -MRB_API mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv); - -/** - * Creates a new instance of Class, Class. - * - * Example: - * - * void - * mrb_example_gem_init(mrb_state* mrb) { - * struct RClass *example_class; - * mrb_value obj; - * - * example_class = mrb_class_new(mrb, mrb->object_class); - * obj = mrb_obj_new(mrb, example_class, 0, NULL); // => #<#:0x9a94588> - * mrb_p(mrb, obj); // => Kernel#p - * } - * - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] super The super class or parent. - * @return [struct RClass *] Reference to the new class. - */ -MRB_API struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super); - -/** - * Creates a new module, Module. - * - * Example: - * void - * mrb_example_gem_init(mrb_state* mrb) { - * struct RClass *example_module; - * - * example_module = mrb_module_new(mrb); - * } - * - * @param [mrb_state*] mrb The current mruby state. - * @return [struct RClass *] Reference to the new module. - */ -MRB_API struct RClass * mrb_module_new(mrb_state *mrb); - -/** - * Returns an mrb_bool. True if class was defined, and false if the class was not defined. - * - * Example: - * void - * mrb_example_gem_init(mrb_state* mrb) { - * struct RClass *example_class; - * mrb_bool cd; - * - * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); - * cd = mrb_class_defined(mrb, "ExampleClass"); - * - * // If mrb_class_defined returns 1 then puts "True" - * // If mrb_class_defined returns 0 then puts "False" - * if (cd == 1){ - * puts("True"); - * } - * else { - * puts("False"); - * } - * } - * - * @param [mrb_state*] mrb The current mruby state. - * @param [const char *] name A string representing the name of the class. - * @return [mrb_bool] A boolean value. - */ -MRB_API mrb_bool mrb_class_defined(mrb_state *mrb, const char *name); - -/** - * Gets a class. - * @param [mrb_state*] mrb The current mruby state. - * @param [const char *] name The name of the class. - * @return [struct RClass *] A reference to the class. -*/ -MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name); - -/** - * Gets a child class. - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] outer The name of the parent class. - * @param [const char *] name The name of the class. - * @return [struct RClass *] A reference to the class. -*/ -MRB_API struct RClass * mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name); - -/** - * Gets a module. - * @param [mrb_state*] mrb The current mruby state. - * @param [const char *] name The name of the module. - * @return [struct RClass *] A reference to the module. -*/ -MRB_API struct RClass * mrb_module_get(mrb_state *mrb, const char *name); - -/** - * Gets a module defined under another module. - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] outer The name of the outer module. - * @param [const char *] name The name of the module. - * @return [struct RClass *] A reference to the module. -*/ -MRB_API struct RClass * mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name); -MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value); - -/** - * Duplicate an object. - * - * Equivalent to: - * Object#dup - * @param [mrb_state*] mrb The current mruby state. - * @param [mrb_value] obj Object to be duplicate. - * @return [mrb_value] The newly duplicated object. - */ -MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj); -MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method); - -/** - * Returns true if obj responds to the given method. If the method was defined for that - * class it returns true, it returns false otherwise. - * - * Example: - * # Ruby style - * class ExampleClass - * def example_method - * end - * end - * - * ExampleClass.new.respond_to?(:example_method) # => true - * - * // C style - * void - * mrb_example_gem_init(mrb_state* mrb) { - * struct RClass *example_class; - * mrb_sym mid; - * mrb_bool obj_resp; - * - * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); - * mrb_define_method(mrb, example_class, "example_method", exampleMethod, MRB_ARGS_NONE()); - * mid = mrb_intern_str(mrb, mrb_str_new_cstr(mrb, "example_method" )); - * obj_resp = mrb_obj_respond_to(mrb, example_class, mid); // => 1(true in Ruby world) - * - * // If mrb_obj_respond_to returns 1 then puts "True" - * // If mrb_obj_respond_to returns 0 then puts "False" - * if (obj_resp == 1) { - * puts("True"); - * } - * else if (obj_resp == 0) { - * puts("False"); - * } - * } - * - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] c A reference to a class. - * @param [mrb_sym] mid A symbol referencing a method id. - * @return [mrb_bool] A boolean value. - */ -MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid); - -/** - * Defines a new class under a given module - * - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] outer Reference to the module under which the new class will be defined - * @param [const char *] name The name of the defined class - * @param [struct RClass *] super The new class parent - * @return [struct RClass *] Reference to the newly defined class - * @see mrb_define_class - */ -MRB_API struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super); - -MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name); - -/** - * Function requires n arguments. - * - * @param n - * The number of required arguments. - */ -#define MRB_ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 18) - -/** - * Funtion takes n optional arguments - * - * @param n - * The number of optional arguments. - */ -#define MRB_ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 13) - -/** - * Funtion takes n1 mandatory arguments and n2 optional arguments - * - * @param n1 - * The number of required arguments. - * @param n2 - * The number of optional arguments. - */ -#define MRB_ARGS_ARG(n1,n2) (MRB_ARGS_REQ(n1)|MRB_ARGS_OPT(n2)) - -/** rest argument */ -#define MRB_ARGS_REST() ((mrb_aspec)(1 << 12)) - -/** required arguments after rest */ -#define MRB_ARGS_POST(n) ((mrb_aspec)((n)&0x1f) << 7) - -/** keyword arguments (n of keys, kdict) */ -#define MRB_ARGS_KEY(n1,n2) ((mrb_aspec)((((n1)&0x1f) << 2) | ((n2)?(1<<1):0))) - -/** - * Function takes a block argument - */ -#define MRB_ARGS_BLOCK() ((mrb_aspec)1) - -/** - * Function accepts any number of arguments - */ -#define MRB_ARGS_ANY() MRB_ARGS_REST() - -/** - * Function accepts no arguments - */ -#define MRB_ARGS_NONE() ((mrb_aspec)0) - -/** - * Format specifiers for {mrb_get_args} function - * - * Must be a C string composed of the following format specifiers: - * - * | char | Ruby type | C types | Notes | - * |:----:|----------------|-------------------|----------------------------------------------------| - * | `o` | {Object} | {mrb_value} | Could be used to retrieve any type of argument | - * | `C` | {Class}/{Module} | {mrb_value} | | - * | `S` | {String} | {mrb_value} | when `!` follows, the value may be `nil` | - * | `A` | {Array} | {mrb_value} | when `!` follows, the value may be `nil` | - * | `H` | {Hash} | {mrb_value} | when `!` follows, the value may be `nil` | - * | `s` | {String} | char *, {mrb_int} | Receive two arguments; `s!` gives (`NULL`,`0`) for `nil` | - * | `z` | {String} | char * | `NULL` terminated string; `z!` gives `NULL` for `nil` | - * | `a` | {Array} | {mrb_value} *, {mrb_int} | Receive two arguments; `a!` gives (`NULL`,`0`) for `nil` | - * | `f` | {Float} | {mrb_float} | | - * | `i` | {Integer} | {mrb_int} | | - * | `b` | boolean | {mrb_bool} | | - * | `n` | {Symbol} | {mrb_sym} | | - * | `&` | block | {mrb_value} | | - * | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array. | - * | | | optional | | After this spec following specs would be optional. | - * | `?` | optional given | {mrb_bool} | `TRUE` if preceding argument is given. Used to check optional argument is given. | - * - * @see mrb_get_args - */ -typedef const char *mrb_args_format; - -/** - * Retrieve arguments from mrb_state. - * - * When applicable, implicit conversions (such as `to_str`, `to_ary`, `to_hash`) are - * applied to received arguments. - * Used inside a function of mrb_func_t type. - * - * @param mrb The current MRuby state. - * @param format [mrb_args_format] is a list of format specifiers - * @param ... The passing variadic arguments must be a pointer of retrieving type. - * @return the number of arguments retrieved. - * @see mrb_args_format - */ -MRB_API mrb_int mrb_get_args(mrb_state *mrb, mrb_args_format format, ...); - -static inline mrb_sym -mrb_get_mid(mrb_state *mrb) /* get method symbol */ -{ - return mrb->c->ci->mid; -} - -static inline int -mrb_get_argc(mrb_state *mrb) /* get argc */ -{ - return mrb->c->ci->argc; -} - -/* `strlen` for character string literals (use with caution or `strlen` instead) - Adjacent string literals are concatenated in C/C++ in translation phase 6. - If `lit` is not one, the compiler will report a syntax error: - MSVC: "error C2143: syntax error : missing ')' before 'string'" - GCC: "error: expected ')' before string constant" -*/ -#define mrb_strlen_lit(lit) (sizeof(lit "") - 1) - -/** - * Call existing ruby functions. - */ -MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...); -MRB_API mrb_value mrb_funcall_argv(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*); -MRB_API mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*, mrb_value); -MRB_API mrb_sym mrb_intern_cstr(mrb_state*,const char*); -MRB_API mrb_sym mrb_intern(mrb_state*,const char*,size_t); -MRB_API mrb_sym mrb_intern_static(mrb_state*,const char*,size_t); -#define mrb_intern_lit(mrb, lit) mrb_intern_static(mrb, lit, mrb_strlen_lit(lit)) -MRB_API mrb_sym mrb_intern_str(mrb_state*,mrb_value); -MRB_API mrb_value mrb_check_intern_cstr(mrb_state*,const char*); -MRB_API mrb_value mrb_check_intern(mrb_state*,const char*,size_t); -MRB_API mrb_value mrb_check_intern_str(mrb_state*,mrb_value); -MRB_API const char *mrb_sym2name(mrb_state*,mrb_sym); -MRB_API const char *mrb_sym2name_len(mrb_state*,mrb_sym,mrb_int*); -MRB_API mrb_value mrb_sym2str(mrb_state*,mrb_sym); - -MRB_API void *mrb_malloc(mrb_state*, size_t); /* raise RuntimeError if no mem */ -MRB_API void *mrb_calloc(mrb_state*, size_t, size_t); /* ditto */ -MRB_API void *mrb_realloc(mrb_state*, void*, size_t); /* ditto */ -MRB_API void *mrb_realloc_simple(mrb_state*, void*, size_t); /* return NULL if no memory available */ -MRB_API void *mrb_malloc_simple(mrb_state*, size_t); /* return NULL if no memory available */ -MRB_API struct RBasic *mrb_obj_alloc(mrb_state*, enum mrb_vtype, struct RClass*); -MRB_API void mrb_free(mrb_state*, void*); - -MRB_API mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len); - -/** - * Turns a C string into a Ruby string value. - */ -MRB_API mrb_value mrb_str_new_cstr(mrb_state*, const char*); -MRB_API mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, size_t len); -#define mrb_str_new_lit(mrb, lit) mrb_str_new_static(mrb, (lit), mrb_strlen_lit(lit)) - -#ifdef _WIN32 -char* mrb_utf8_from_locale(const char *p, size_t len); -char* mrb_locale_from_utf8(const char *p, size_t len); -#define mrb_locale_free(p) free(p) -#define mrb_utf8_free(p) free(p) -#else -#define mrb_utf8_from_locale(p, l) (p) -#define mrb_locale_from_utf8(p, l) (p) -#define mrb_locale_free(p) -#define mrb_utf8_free(p) -#endif - -/** - * Creates new mrb_state. - * - * @return - * Pointer to the newly created mrb_state. - */ -MRB_API mrb_state* mrb_open(void); - -/** - * Create new mrb_state with custom allocators. - * - * @param f - * Reference to the allocation function. - * @param ud - * User data will be passed to custom allocator f. - * If user data isn't required just pass NULL. - * @return - * Pointer to the newly created mrb_state. - */ -MRB_API mrb_state* mrb_open_allocf(mrb_allocf f, void *ud); - -/** - * Create new mrb_state with just the MRuby core - * - * @param f - * Reference to the allocation function. - * Use mrb_default_allocf for the default - * @param ud - * User data will be passed to custom allocator f. - * If user data isn't required just pass NULL. - * @return - * Pointer to the newly created mrb_state. - */ -MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud); - -/** - * Closes and frees a mrb_state. - * - * @param mrb - * Pointer to the mrb_state to be closed. - */ -MRB_API void mrb_close(mrb_state *mrb); - -/** - * The default allocation function. - * - * @see mrb_allocf - */ -MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*); - -MRB_API mrb_value mrb_top_self(mrb_state *); -MRB_API mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value); -MRB_API mrb_value mrb_toplevel_run(mrb_state*, struct RProc*); -MRB_API mrb_value mrb_context_run(mrb_state*, struct RProc*, mrb_value, unsigned int); - -MRB_API void mrb_p(mrb_state*, mrb_value); -MRB_API mrb_int mrb_obj_id(mrb_value obj); -MRB_API mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name); - -MRB_API mrb_bool mrb_obj_eq(mrb_state*, mrb_value, mrb_value); -MRB_API mrb_bool mrb_obj_equal(mrb_state*, mrb_value, mrb_value); -MRB_API mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2); -MRB_API mrb_value mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base); -MRB_API mrb_value mrb_Integer(mrb_state *mrb, mrb_value val); -MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val); -MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj); -MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2); - -MRB_API void mrb_garbage_collect(mrb_state*); -MRB_API void mrb_full_gc(mrb_state*); -MRB_API void mrb_incremental_gc(mrb_state *); -MRB_API int mrb_gc_arena_save(mrb_state*); -MRB_API void mrb_gc_arena_restore(mrb_state*,int); -MRB_API void mrb_gc_mark(mrb_state*,struct RBasic*); -#define mrb_gc_mark_value(mrb,val) do {\ - if (!mrb_immediate_p(val)) mrb_gc_mark((mrb), mrb_basic_ptr(val)); \ -} while (0) -MRB_API void mrb_field_write_barrier(mrb_state *, struct RBasic*, struct RBasic*); -#define mrb_field_write_barrier_value(mrb, obj, val) do{\ - if (!mrb_immediate_p(val)) mrb_field_write_barrier((mrb), (obj), mrb_basic_ptr(val)); \ -} while (0) -MRB_API void mrb_write_barrier(mrb_state *, struct RBasic*); - -MRB_API mrb_value mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method); -MRB_API mrb_value mrb_any_to_s(mrb_state *mrb, mrb_value obj); -MRB_API const char * mrb_obj_classname(mrb_state *mrb, mrb_value obj); -MRB_API struct RClass* mrb_obj_class(mrb_state *mrb, mrb_value obj); -MRB_API mrb_value mrb_class_path(mrb_state *mrb, struct RClass *c); -MRB_API mrb_value mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method); -MRB_API mrb_bool mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c); -MRB_API mrb_value mrb_obj_inspect(mrb_state *mrb, mrb_value self); -MRB_API mrb_value mrb_obj_clone(mrb_state *mrb, mrb_value self); - -#ifndef ISPRINT -#define ISASCII(c) ((unsigned)(c) <= 0x7f) -#define ISPRINT(c) (((unsigned)(c) - 0x20) < 0x5f) -#define ISSPACE(c) ((c) == ' ' || (unsigned)(c) - '\t' < 5) -#define ISUPPER(c) (((unsigned)(c) - 'A') < 26) -#define ISLOWER(c) (((unsigned)(c) - 'a') < 26) -#define ISALPHA(c) ((((unsigned)(c) | 0x20) - 'a') < 26) -#define ISDIGIT(c) (((unsigned)(c) - '0') < 10) -#define ISXDIGIT(c) (ISDIGIT(c) || ((unsigned)(c) | 0x20) - 'a' < 6) -#define ISALNUM(c) (ISALPHA(c) || ISDIGIT(c)) -#define ISBLANK(c) ((c) == ' ' || (c) == '\t') -#define ISCNTRL(c) ((unsigned)(c) < 0x20 || (c) == 0x7f) -#define TOUPPER(c) (ISLOWER(c) ? ((c) & 0x5f) : (c)) -#define TOLOWER(c) (ISUPPER(c) ? ((c) | 0x20) : (c)) -#endif - -MRB_API mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, size_t len); -MRB_API mrb_noreturn void mrb_exc_raise(mrb_state *mrb, mrb_value exc); - -MRB_API mrb_noreturn void mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg); -MRB_API mrb_noreturn void mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...); -MRB_API mrb_noreturn void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...); -MRB_API void mrb_warn(mrb_state *mrb, const char *fmt, ...); -MRB_API mrb_noreturn void mrb_bug(mrb_state *mrb, const char *fmt, ...); -MRB_API void mrb_print_backtrace(mrb_state *mrb); -MRB_API void mrb_print_error(mrb_state *mrb); - -/* macros to get typical exception objects - note: - + those E_* macros requires mrb_state* variable named mrb. - + exception objects obtained from those macros are local to mrb -*/ -#define E_RUNTIME_ERROR (mrb_class_get(mrb, "RuntimeError")) -#define E_TYPE_ERROR (mrb_class_get(mrb, "TypeError")) -#define E_ARGUMENT_ERROR (mrb_class_get(mrb, "ArgumentError")) -#define E_INDEX_ERROR (mrb_class_get(mrb, "IndexError")) -#define E_RANGE_ERROR (mrb_class_get(mrb, "RangeError")) -#define E_NAME_ERROR (mrb_class_get(mrb, "NameError")) -#define E_NOMETHOD_ERROR (mrb_class_get(mrb, "NoMethodError")) -#define E_SCRIPT_ERROR (mrb_class_get(mrb, "ScriptError")) -#define E_SYNTAX_ERROR (mrb_class_get(mrb, "SyntaxError")) -#define E_LOCALJUMP_ERROR (mrb_class_get(mrb, "LocalJumpError")) -#define E_REGEXP_ERROR (mrb_class_get(mrb, "RegexpError")) -#define E_SYSSTACK_ERROR (mrb_class_get(mrb, "SystemStackError")) - -#define E_NOTIMP_ERROR (mrb_class_get(mrb, "NotImplementedError")) -#define E_FLOATDOMAIN_ERROR (mrb_class_get(mrb, "FloatDomainError")) - -#define E_KEY_ERROR (mrb_class_get(mrb, "KeyError")) - -MRB_API mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg); -MRB_API mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv); -MRB_API mrb_value mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c); - -/* mrb_gc_protect() leaves the object in the arena */ -MRB_API void mrb_gc_protect(mrb_state *mrb, mrb_value obj); -/* mrb_gc_register() keeps the object from GC. */ -MRB_API void mrb_gc_register(mrb_state *mrb, mrb_value obj); -/* mrb_gc_unregister() removes the object from GC root. */ -MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj); - -MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val); -#define mrb_int(mrb, val) mrb_fixnum(mrb_to_int(mrb, val)) -MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t); - -typedef enum call_type { - CALL_PUBLIC, - CALL_FCALL, - CALL_VCALL, - CALL_TYPE_MAX -} call_type; - -MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2); -MRB_API const char *mrb_class_name(mrb_state *mrb, struct RClass* klass); -MRB_API void mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val); - -MRB_API mrb_value mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id); - -MRB_API mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid); -MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c); - - -/* - * Resume a Fiber - * - * @mrbgem mruby-fiber - */ -MRB_API mrb_value mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int argc, const mrb_value *argv); - -/* - * Yield a Fiber - * - * @mrbgem mruby-fiber - */ -MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv); - -/* - * FiberError reference - * - * @mrbgem mruby-fiber - */ -#define E_FIBER_ERROR (mrb_class_get(mrb, "FiberError")) - -/* memory pool implementation */ -typedef struct mrb_pool mrb_pool; -MRB_API struct mrb_pool* mrb_pool_open(mrb_state*); -MRB_API void mrb_pool_close(struct mrb_pool*); -MRB_API void* mrb_pool_alloc(struct mrb_pool*, size_t); -MRB_API void* mrb_pool_realloc(struct mrb_pool*, void*, size_t oldlen, size_t newlen); -MRB_API mrb_bool mrb_pool_can_realloc(struct mrb_pool*, void*, size_t); -MRB_API void* mrb_alloca(mrb_state *mrb, size_t); - -MRB_API void mrb_state_atexit(mrb_state *mrb, mrb_atexit_func func); - -MRB_API void mrb_show_version(mrb_state *mrb); -MRB_API void mrb_show_copyright(mrb_state *mrb); - -#ifdef MRB_DEBUG -#include -#define mrb_assert(p) assert(p) -#define mrb_assert_int_fit(t1,n,t2,max) assert((n)>=0 && ((sizeof(n)<=sizeof(t2))||(n<=(t1)(max)))) -#else -#define mrb_assert(p) ((void)0) -#define mrb_assert_int_fit(t1,n,t2,max) ((void)0) -#endif - -#if __STDC_VERSION__ >= 201112L -#define mrb_static_assert(exp, str) _Static_assert(exp, str) -#else -#define mrb_static_assert(exp, str) mrb_assert(exp) -#endif - -MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...); - -MRB_END_DECL - -#endif /* MRUBY_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/LEGAL nghttp2-0.6.7/third-party/mruby/LEGAL --- nghttp2-1.13.0/third-party/mruby/LEGAL 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/LEGAL 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -LEGAL NOTICE INFORMATION ------------------------- - -All the files in this distribution are covered under the MIT license -(see the file MITL) except some files mentioned below: - diff -Nru nghttp2-1.13.0/third-party/mruby/lib/mruby/source.rb nghttp2-0.6.7/third-party/mruby/lib/mruby/source.rb --- nghttp2-1.13.0/third-party/mruby/lib/mruby/source.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/lib/mruby/source.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -require "pathname" - -module MRuby - module Source - # MRuby's source root directory - ROOT = Pathname.new(File.expand_path('../../../',__FILE__)) - - # Reads a constant defined at version.h - MRUBY_READ_VERSION_CONSTANT = Proc.new { |name| ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?$/)[1] } - - MRUBY_RUBY_VERSION = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_VERSION'] - MRUBY_RUBY_ENGINE = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_ENGINE'] - - MRUBY_RELEASE_MAJOR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MAJOR']) - MRUBY_RELEASE_MINOR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MINOR']) - MRUBY_RELEASE_TEENY = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_TEENY']) - - MRUBY_VERSION = [MRUBY_RELEASE_MAJOR,MRUBY_RELEASE_MINOR,MRUBY_RELEASE_TEENY].join('.') - MRUBY_RELEASE_NO = (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY) - - MRUBY_RELEASE_YEAR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_YEAR']) - MRUBY_RELEASE_MONTH = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MONTH']) - MRUBY_RELEASE_DAY = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_DAY']) - MRUBY_RELEASE_DATE = [MRUBY_RELEASE_YEAR,MRUBY_RELEASE_MONTH,MRUBY_RELEASE_DAY].join('.') - - MRUBY_BIRTH_YEAR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_BIRTH_YEAR']) - - MRUBY_AUTHOR = MRUBY_READ_VERSION_CONSTANT['MRUBY_AUTHOR'] - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/Makefile nghttp2-0.6.7/third-party/mruby/Makefile --- nghttp2-1.13.0/third-party/mruby/Makefile 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/Makefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -# mruby is using Rake (http://rake.rubyforge.org) as a build tool. -# We provide a minimalistic version called minirake inside of our -# codebase. - -RAKE = ruby ./minirake - -all : - $(RAKE) -.PHONY : all - -test : all - $(RAKE) test -.PHONY : test - -clean : - $(RAKE) clean -.PHONY : clean diff -Nru nghttp2-1.13.0/third-party/mruby/minirake nghttp2-0.6.7/third-party/mruby/minirake --- nghttp2-1.13.0/third-party/mruby/minirake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/minirake 1970-01-01 00:00:00.000000000 +0000 @@ -1,484 +0,0 @@ -#!/usr/bin/env ruby - -# Original is https://github.com/jimweirich/rake/ -# Copyright (c) 2003 Jim Weirich -# License: MIT-LICENSE - -require 'getoptlong' -require 'fileutils' - -class String - def ext(newext='') - return self.dup if ['.', '..'].include? self - if newext != '' - newext = (newext =~ /^\./) ? newext : ("." + newext) - end - self.chomp(File.extname(self)) << newext - end - - def pathmap(spec=nil, &block) - return self if spec.nil? - result = '' - spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag| - case frag - when '%f' - result << File.basename(self) - when '%n' - result << File.basename(self).ext - when '%d' - result << File.dirname(self) - when '%x' - result << File.extname(self) - when '%X' - result << self.ext - when '%p' - result << self - when '%s' - result << (File::ALT_SEPARATOR || File::SEPARATOR) - when '%-' - # do nothing - when '%%' - result << "%" - when /%(-?\d+)d/ - result << pathmap_partial($1.to_i) - when /^%\{([^}]*)\}(\d*[dpfnxX])/ - patterns, operator = $1, $2 - result << pathmap('%' + operator).pathmap_replace(patterns, &block) - when /^%/ - fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'" - else - result << frag - end - end - result - end -end - -module MiniRake - class Task - TASKS = Hash.new - RULES = Array.new - - # List of prerequisites for a task. - attr_reader :prerequisites - - # Source dependency for rule synthesized tasks. Nil if task was not - # sythesized from a rule. - attr_accessor :source - - # Create a task named +task_name+ with no actions or prerequisites.. - # use +enhance+ to add actions and prerequisites. - def initialize(task_name) - @name = task_name - @prerequisites = [] - @actions = [] - end - - # Enhance a task with prerequisites or actions. Returns self. - def enhance(deps=nil, &block) - @prerequisites |= deps if deps - @actions << block if block_given? - self - end - - # Name of the task. - def name - @name.to_s - end - - # Invoke the task if it is needed. Prerequites are invoked first. - def invoke - puts "Invoke #{name} (already=[#{@already_invoked}], needed=[#{needed?}])" if $trace - return if @already_invoked - @already_invoked = true - prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten - prerequisites.each { |n| Task[n].invoke } - execute if needed? - end - - # Execute the actions associated with this task. - def execute - puts "Execute #{name}" if $trace - self.class.enhance_with_matching_rule(name) if @actions.empty? - unless $dryrun - @actions.each { |act| act.call(self) } - end - end - - # Is this task needed? - def needed? - true - end - - # Timestamp for this task. Basic tasks return the current time for - # their time stamp. Other tasks can be more sophisticated. - def timestamp - prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten - prerequisites.collect { |n| Task[n].timestamp }.max || Time.now - end - - # Class Methods ---------------------------------------------------- - - class << self - - # Clear the task list. This cause rake to immediately forget all - # the tasks that have been assigned. (Normally used in the unit - # tests.) - def clear - TASKS.clear - RULES.clear - end - - # List of all defined tasks. - def tasks - TASKS.keys.sort.collect { |tn| Task[tn] } - end - - # Return a task with the given name. If the task is not currently - # known, try to synthesize one from the defined rules. If no - # rules are found, but an existing file matches the task name, - # assume it is a file task with no dependencies or actions. - def [](task_name) - task_name = task_name.to_s - if task = TASKS[task_name] - return task - end - if task = enhance_with_matching_rule(task_name) - return task - end - if File.exist?(task_name) - return FileTask.define_task(task_name) - end - fail "Don't know how to rake #{task_name}" - end - - # Define a task given +args+ and an option block. If a rule with - # the given name already exists, the prerequisites and actions are - # added to the existing task. - def define_task(args, &block) - task_name, deps = resolve_args(args) - lookup(task_name).enhance([deps].flatten, &block) - end - - # Define a rule for synthesizing tasks. - def create_rule(args, &block) - pattern, deps = resolve_args(args) - pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern - RULES << [pattern, deps, block] - end - - - # Lookup a task. Return an existing task if found, otherwise - # create a task of the current type. - def lookup(task_name) - name = task_name.to_s - TASKS[name] ||= self.new(name) - end - - # If a rule can be found that matches the task name, enhance the - # task with the prerequisites and actions from the rule. Set the - # source attribute of the task appropriately for the rule. Return - # the enhanced task or nil of no rule was found. - def enhance_with_matching_rule(task_name) - RULES.each do |pattern, extensions, block| - if pattern.match(task_name) - ext = extensions.first - deps = extensions[1..-1] - case ext - when String - source = task_name.sub(/\.[^.]*$/, ext) - when Proc - source = ext.call(task_name) - else - fail "Don't know how to handle rule dependent: #{ext.inspect}" - end - if File.exist?(source) - task = FileTask.define_task({task_name => [source]+deps}, &block) - task.source = source - return task - end - end - end - nil - end - - private - - # Resolve the arguments for a task/rule. - def resolve_args(args) - case args - when Hash - fail "Too Many Task Names: #{args.keys.join(' ')}" if args.size > 1 - fail "No Task Name Given" if args.size < 1 - task_name = args.keys[0] - deps = args[task_name] - deps = [deps] if (String===deps) || (Regexp===deps) || (Proc===deps) - else - task_name = args - deps = [] - end - [task_name, deps] - end - end - end - - - ###################################################################### - class FileTask < Task - # Is this file task needed? Yes if it doesn't exist, or if its time - # stamp is out of date. - def needed? - return true unless File.exist?(name) - prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten - latest_prereq = prerequisites.collect{|n| Task[n].timestamp}.max - return false if latest_prereq.nil? - timestamp < latest_prereq - end - - # Time stamp for file task. - def timestamp - stat = File::stat(name.to_s) - stat.directory? ? Time.at(0) : stat.mtime - end - end - - module DSL - # Declare a basic task. - def task(args, &block) - MiniRake::Task.define_task(args, &block) - end - - # Declare a file task. - def file(args, &block) - MiniRake::FileTask.define_task(args, &block) - end - - # Declare a set of files tasks to create the given directories on - # demand. - def directory(args, &block) - MiniRake::FileTask.define_task(args) do |t| - block.call(t) unless block.nil? - dir = args.is_a?(Hash) ? args.keys.first : args - (dir.split(File::SEPARATOR) + ['']).inject do |acc, part| - (acc + File::SEPARATOR).tap do |d| - Dir.mkdir(d) unless File.exists? d - end + part - end - end - end - - # Declare a rule for auto-tasks. - def rule(args, &block) - MiniRake::Task.create_rule(args, &block) - end - - # Write a message to standard out if $verbose is enabled. - def log(msg) - print " " if $trace && $verbose - puts msg if $verbose - end - - # Run the system command +cmd+. - def sh(cmd) - puts cmd if $verbose - system(cmd) or fail "Command Failed: [#{cmd}]" - end - - def desc(text) - end - end -end - -Rake = MiniRake -extend MiniRake::DSL - - -###################################################################### -# Task Definition Functions ... - -###################################################################### -# Rake main application object. When invoking +rake+ from the command -# line, a RakeApp object is created and run. -# -class RakeApp - RAKEFILES = ['rakefile', 'Rakefile'] - - OPTIONS = [ - ['--dry-run', '-n', GetoptLong::NO_ARGUMENT, - "Do a dry run without executing actions."], - ['--help', '-H', GetoptLong::NO_ARGUMENT, - "Display this help message."], - ['--libdir', '-I', GetoptLong::REQUIRED_ARGUMENT, - "Include LIBDIR in the search path for required modules."], - ['--nosearch', '-N', GetoptLong::NO_ARGUMENT, - "Do not search parent directories for the Rakefile."], - ['--quiet', '-q', GetoptLong::NO_ARGUMENT, - "Do not log messages to standard output (default)."], - ['--rakefile', '-f', GetoptLong::REQUIRED_ARGUMENT, - "Use FILE as the rakefile."], - ['--require', '-r', GetoptLong::REQUIRED_ARGUMENT, - "Require MODULE before executing rakefile."], - ['--tasks', '-T', GetoptLong::NO_ARGUMENT, - "Display the tasks and dependencies, then exit."], - ['--pull-gems','-p', GetoptLong::NO_ARGUMENT, - "Pull all git mrbgems."], - ['--trace', '-t', GetoptLong::NO_ARGUMENT, - "Turn on invoke/execute tracing."], - ['--usage', '-h', GetoptLong::NO_ARGUMENT, - "Display usage."], - ['--verbose', '-v', GetoptLong::NO_ARGUMENT, - "Log message to standard output."], - ['--directory', '-C', GetoptLong::REQUIRED_ARGUMENT, - "Change executing directory of rakefiles."] - ] - - # Create a RakeApp object. - def initialize - @rakefile = nil - @nosearch = false - end - - # True if one of the files in RAKEFILES is in the current directory. - # If a match is found, it is copied into @rakefile. - def have_rakefile - RAKEFILES.each do |fn| - if File.exist?(fn) - @rakefile = fn - return true - end - end - return false - end - - # Display the program usage line. - def usage - puts "rake [-f rakefile] {options} targets..." - end - - # Display the rake command line help. - def help - usage - puts - puts "Options are ..." - puts - OPTIONS.sort.each do |long, short, mode, desc| - if mode == GetoptLong::REQUIRED_ARGUMENT - if desc =~ /\b([A-Z]{2,})\b/ - long = long + "=#{$1}" - end - end - printf " %-20s (%s)\n", long, short - printf " %s\n", desc - end - end - - # Display the tasks and dependencies. - def display_tasks - MiniRake::Task.tasks.each do |t| - puts "#{t.class} #{t.name}" - t.prerequisites.each { |pre| puts " #{pre}" } - end - end - - # Return a list of the command line options supported by the - # program. - def command_line_options - OPTIONS.collect { |lst| lst[0..-2] } - end - - # Do the option defined by +opt+ and +value+. - def do_option(opt, value) - case opt - when '--dry-run' - $dryrun = true - $trace = true - when '--help' - help - exit - when '--libdir' - $:.push(value) - when '--nosearch' - @nosearch = true - when '--quiet' - $verbose = false - when '--rakefile' - RAKEFILES.clear - RAKEFILES << value - when '--require' - require value - when '--tasks' - $show_tasks = true - when '--pull-gems' - $pull_gems = true - when '--trace' - $trace = true - when '--usage' - usage - exit - when '--verbose' - $verbose = true - when '--version' - puts "rake, version #{RAKEVERSION}" - exit - when '--directory' - Dir.chdir value - else - fail "Unknown option: #{opt}" - end - end - - # Read and handle the command line options. - def handle_options - $verbose = false - $pull_gems = false - opts = GetoptLong.new(*command_line_options) - opts.each { |opt, value| do_option(opt, value) } - end - - # Run the +rake+ application. - def run - handle_options - begin - here = Dir.pwd - while ! have_rakefile - Dir.chdir("..") - if Dir.pwd == here || @nosearch - fail "No Rakefile found (looking for: #{RAKEFILES.join(', ')})" - end - here = Dir.pwd - end - tasks = [] - ARGV.each do |task_name| - if /^(\w+)=(.*)/.match(task_name) - ENV[$1] = $2 - else - tasks << task_name - end - end - puts "(in #{Dir.pwd})" - $rakefile = @rakefile - load @rakefile - if $show_tasks - display_tasks - else - tasks.push("default") if tasks.size == 0 - tasks.each do |task_name| - MiniRake::Task[task_name].invoke - end - end - rescue Exception => ex - puts "rake aborted!" - puts ex.message - if $trace - puts ex.backtrace.join("\n") - else - puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || "" - end - exit 1 - end - end -end - -if __FILE__ == $0 then - RakeApp.new.run -end diff -Nru nghttp2-1.13.0/third-party/mruby/MITL nghttp2-0.6.7/third-party/mruby/MITL --- nghttp2-1.13.0/third-party/mruby/MITL 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/MITL 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -Copyright (c) 2015 mruby developers - -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. - diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/default.gembox nghttp2-0.6.7/third-party/mruby/mrbgems/default.gembox --- nghttp2-1.13.0/third-party/mruby/mrbgems/default.gembox 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/default.gembox 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -MRuby::GemBox.new do |conf| - # Use standard Kernel#sprintf method - conf.gem :core => "mruby-sprintf" - - # Use standard print/puts/p - conf.gem :core => "mruby-print" - - # Use standard Math module - conf.gem :core => "mruby-math" - - # Use standard Time class - conf.gem :core => "mruby-time" - - # Use standard Struct class - conf.gem :core => "mruby-struct" - - # Use Enumerable module extension - conf.gem :core => "mruby-enum-ext" - - # Use String class extension - conf.gem :core => "mruby-string-ext" - - # Use Numeric class extension - conf.gem :core => "mruby-numeric-ext" - - # Use Array class extension - conf.gem :core => "mruby-array-ext" - - # Use Hash class extension - conf.gem :core => "mruby-hash-ext" - - # Use Range class extension - conf.gem :core => "mruby-range-ext" - - # Use Proc class extension - conf.gem :core => "mruby-proc-ext" - - # Use Symbol class extension - conf.gem :core => "mruby-symbol-ext" - - # Use Random class - conf.gem :core => "mruby-random" - - # Use Object class extension - conf.gem :core => "mruby-object-ext" - - # Use ObjectSpace class - conf.gem :core => "mruby-objectspace" - - # Use Fiber class - conf.gem :core => "mruby-fiber" - - # Use Enumerator class (require mruby-fiber) - conf.gem :core => "mruby-enumerator" - - # Use Enumerable::Lazy class (require mruby-enumerator) - conf.gem :core => "mruby-enum-lazy" - - # Use toplevel object (main) methods extension - conf.gem :core => "mruby-toplevel-ext" - - # Generate mirb command - conf.gem :core => "mruby-bin-mirb" - - # Generate mruby command - conf.gem :core => "mruby-bin-mruby" - - # Generate mruby-strip command - conf.gem :core => "mruby-bin-strip" - - # Use Kernel module extension - conf.gem :core => "mruby-kernel-ext" - - # Use mruby-compiler to build other mrbgems - conf.gem :core => "mruby-compiler" -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/full-core.gembox nghttp2-0.6.7/third-party/mruby/mrbgems/full-core.gembox --- nghttp2-1.13.0/third-party/mruby/mrbgems/full-core.gembox 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/full-core.gembox 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -MRuby::GemBox.new do |conf| - conf.gem :core => "mruby-sprintf" - conf.gem :core => "mruby-print" - - Dir.glob("#{root}/mrbgems/mruby-*/mrbgem.rake") do |x| - g = File.basename File.dirname x - conf.gem :core => g unless g =~ /^mruby-(print|sprintf|bin-debugger|test)$/ - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-array-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-array-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-array-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-array-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-array-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Array class extension' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-array-ext/mrblib/array.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-array-ext/mrblib/array.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-array-ext/mrblib/array.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-array-ext/mrblib/array.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,712 +0,0 @@ -class Array - ## - # call-seq: - # ary.uniq! -> ary or nil - # ary.uniq! { |item| ... } -> ary or nil - # - # Removes duplicate elements from +self+. - # Returns nil if no changes are made (that is, no - # duplicates are found). - # - # a = [ "a", "a", "b", "b", "c" ] - # a.uniq! #=> ["a", "b", "c"] - # b = [ "a", "b", "c" ] - # b.uniq! #=> nil - # c = [["student","sam"], ["student","george"], ["teacher","matz"]] - # c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]] - # - def uniq!(&block) - ary = self.dup - result = [] - if block - hash = {} - while ary.size > 0 - val = ary.shift - key = block.call(val) - hash[key] = val unless hash.has_key?(key) - end - hash.each_value do |value| - result << value - end - else - while ary.size > 0 - result << ary.shift - ary.delete(result.last) - end - end - if result.size == self.size - nil - else - self.replace(result) - end - end - - ## - # call-seq: - # ary.uniq -> new_ary - # ary.uniq { |item| ... } -> new_ary - # - # Returns a new array by removing duplicate values in +self+. - # - # a = [ "a", "a", "b", "b", "c" ] - # a.uniq #=> ["a", "b", "c"] - # - # b = [["student","sam"], ["student","george"], ["teacher","matz"]] - # b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]] - # - def uniq(&block) - ary = self.dup - if block - ary.uniq!(&block) - else - ary.uniq! - end - ary - end - - ## - # call-seq: - # ary - other_ary -> new_ary - # - # Array Difference---Returns a new array that is a copy of - # the original array, removing any items that also appear in - # other_ary. (If you need set-like behavior, see the - # library class Set.) - # - # [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ] - # - def -(elem) - raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array - - hash = {} - array = [] - elem.each { |x| hash[x] = true } - self.each { |x| array << x unless hash[x] } - array - end - - ## - # call-seq: - # ary | other_ary -> new_ary - # - # Set Union---Returns a new array by joining this array with - # other_ary, removing duplicates. - # - # [ "a", "b", "c" ] | [ "c", "d", "a" ] - # #=> [ "a", "b", "c", "d" ] - # - def |(elem) - raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array - - ary = self + elem - ary.uniq! or ary - end - - ## - # call-seq: - # ary & other_ary -> new_ary - # - # Set Intersection---Returns a new array - # containing elements common to the two arrays, with no duplicates. - # - # [ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ] - # - def &(elem) - raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array - - hash = {} - array = [] - elem.each{|v| hash[v] = true } - self.each do |v| - if hash[v] - array << v - hash.delete v - end - end - array - end - - ## - # call-seq: - # ary.flatten -> new_ary - # ary.flatten(level) -> new_ary - # - # Returns a new array that is a one-dimensional flattening of this - # array (recursively). That is, for every element that is an array, - # extract its elements into the new array. If the optional - # level argument determines the level of recursion to flatten. - # - # s = [ 1, 2, 3 ] #=> [1, 2, 3] - # t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]] - # a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10] - # a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - # a = [ 1, 2, [3, [4, 5] ] ] - # a.flatten(1) #=> [1, 2, 3, [4, 5]] - # - def flatten(depth=nil) - ar = [] - self.each do |e| - if e.is_a?(Array) && (depth.nil? || depth > 0) - ar += e.flatten(depth.nil? ? nil : depth - 1) - else - ar << e - end - end - ar - end - - ## - # call-seq: - # ary.flatten! -> ary or nil - # ary.flatten!(level) -> array or nil - # - # Flattens +self+ in place. - # Returns nil if no modifications were made (i.e., - # ary contains no subarrays.) If the optional level - # argument determines the level of recursion to flatten. - # - # a = [ 1, 2, [3, [4, 5] ] ] - # a.flatten! #=> [1, 2, 3, 4, 5] - # a.flatten! #=> nil - # a #=> [1, 2, 3, 4, 5] - # a = [ 1, 2, [3, [4, 5] ] ] - # a.flatten!(1) #=> [1, 2, 3, [4, 5]] - # - def flatten!(depth=nil) - modified = false - ar = [] - self.each do |e| - if e.is_a?(Array) && (depth.nil? || depth > 0) - ar += e.flatten(depth.nil? ? nil : depth - 1) - modified = true - else - ar << e - end - end - if modified - self.replace(ar) - else - nil - end - end - - ## - # call-seq: - # ary.compact -> new_ary - # - # Returns a copy of +self+ with all +nil+ elements removed. - # - # [ "a", nil, "b", nil, "c", nil ].compact - # #=> [ "a", "b", "c" ] - # - def compact - result = self.dup - result.compact! - result - end - - ## - # call-seq: - # ary.compact! -> ary or nil - # - # Removes +nil+ elements from the array. - # Returns +nil+ if no changes were made, otherwise returns - # ary. - # - # [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ] - # [ "a", "b", "c" ].compact! #=> nil - # - def compact! - result = self.select { |e| !e.nil? } - if result.size == self.size - nil - else - self.replace(result) - end - end - - # for efficiency - def reverse_each(&block) - return to_enum :reverse_each unless block_given? - - i = self.size - 1 - while i>=0 - block.call(self[i]) - i -= 1 - end - self - end - - NONE=Object.new - ## - # call-seq: - # ary.fetch(index) -> obj - # ary.fetch(index, default) -> obj - # ary.fetch(index) { |index| block } -> obj - # - # Tries to return the element at position +index+, but throws an IndexError - # exception if the referenced +index+ lies outside of the array bounds. This - # error can be prevented by supplying a second argument, which will act as a - # +default+ value. - # - # Alternatively, if a block is given it will only be executed when an - # invalid +index+ is referenced. Negative values of +index+ count from the - # end of the array. - # - # a = [ 11, 22, 33, 44 ] - # a.fetch(1) #=> 22 - # a.fetch(-1) #=> 44 - # a.fetch(4, 'cat') #=> "cat" - # a.fetch(100) { |i| puts "#{i} is out of bounds" } - # #=> "100 is out of bounds" - # - - def fetch(n=nil, ifnone=NONE, &block) - warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block - - idx = n - if idx < 0 - idx += size - end - if idx < 0 || size <= idx - return block.call(n) if block - if ifnone == NONE - raise IndexError, "index #{n} outside of array bounds: #{-size}...#{size}" - end - return ifnone - end - self[idx] - end - - ## - # call-seq: - # ary.fill(obj) -> ary - # ary.fill(obj, start [, length]) -> ary - # ary.fill(obj, range ) -> ary - # ary.fill { |index| block } -> ary - # ary.fill(start [, length] ) { |index| block } -> ary - # ary.fill(range) { |index| block } -> ary - # - # The first three forms set the selected elements of +self+ (which - # may be the entire array) to +obj+. - # - # A +start+ of +nil+ is equivalent to zero. - # - # A +length+ of +nil+ is equivalent to the length of the array. - # - # The last three forms fill the array with the value of the given block, - # which is passed the absolute index of each element to be filled. - # - # Negative values of +start+ count from the end of the array, where +-1+ is - # the last element. - # - # a = [ "a", "b", "c", "d" ] - # a.fill("x") #=> ["x", "x", "x", "x"] - # a.fill("w", -1) #=> ["x", "x", "x", "w"] - # a.fill("z", 2, 2) #=> ["x", "x", "z", "z"] - # a.fill("y", 0..1) #=> ["y", "y", "z", "z"] - # a.fill { |i| i*i } #=> [0, 1, 4, 9] - # a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27] - # a.fill(1, 2) { |i| i+1 } #=> [0, 2, 3, 27] - # a.fill(0..1) { |i| i+1 } #=> [1, 2, 3, 27] - # - - def fill(arg0=nil, arg1=nil, arg2=nil, &block) - if arg0.nil? && arg1.nil? && arg2.nil? && !block - raise ArgumentError, "wrong number of arguments (0 for 1..3)" - end - - beg = len = 0 - ary = [] - if block - if arg0.nil? && arg1.nil? && arg2.nil? - # ary.fill { |index| block } -> ary - beg = 0 - len = self.size - elsif !arg0.nil? && arg0.kind_of?(Range) - # ary.fill(range) { |index| block } -> ary - beg = arg0.begin - beg += self.size if beg < 0 - len = arg0.end - len += self.size if len < 0 - len += 1 unless arg0.exclude_end? - elsif !arg0.nil? - # ary.fill(start [, length] ) { |index| block } -> ary - beg = arg0 - beg += self.size if beg < 0 - if arg1.nil? - len = self.size - else - len = arg0 + arg1 - end - end - else - if !arg0.nil? && arg1.nil? && arg2.nil? - # ary.fill(obj) -> ary - beg = 0 - len = self.size - elsif !arg0.nil? && !arg1.nil? && arg1.kind_of?(Range) - # ary.fill(obj, range ) -> ary - beg = arg1.begin - beg += self.size if beg < 0 - len = arg1.end - len += self.size if len < 0 - len += 1 unless arg1.exclude_end? - elsif !arg0.nil? && !arg1.nil? - # ary.fill(obj, start [, length]) -> ary - beg = arg1 - beg += self.size if beg < 0 - if arg2.nil? - len = self.size - else - len = beg + arg2 - end - end - end - - i = beg - if block - while i < len - self[i] = block.call(i) - i += 1 - end - else - while i < len - self[i] = arg0 - i += 1 - end - end - self - end - - ## - # call-seq: - # ary.rotate(count=1) -> new_ary - # - # Returns a new array by rotating +self+ so that the element at +count+ is - # the first element of the new array. - # - # If +count+ is negative then it rotates in the opposite direction, starting - # from the end of +self+ where +-1+ is the last element. - # - # a = [ "a", "b", "c", "d" ] - # a.rotate #=> ["b", "c", "d", "a"] - # a #=> ["a", "b", "c", "d"] - # a.rotate(2) #=> ["c", "d", "a", "b"] - # a.rotate(-3) #=> ["b", "c", "d", "a"] - - def rotate(count=1) - ary = [] - len = self.length - - if len > 0 - idx = (count < 0) ? (len - (~count % len) - 1) : (count % len) # rotate count - len.times do - ary << self[idx] - idx += 1 - idx = 0 if idx > len-1 - end - end - ary - end - - ## - # call-seq: - # ary.rotate!(count=1) -> ary - # - # Rotates +self+ in place so that the element at +count+ comes first, and - # returns +self+. - # - # If +count+ is negative then it rotates in the opposite direction, starting - # from the end of the array where +-1+ is the last element. - # - # a = [ "a", "b", "c", "d" ] - # a.rotate! #=> ["b", "c", "d", "a"] - # a #=> ["b", "c", "d", "a"] - # a.rotate!(2) #=> ["d", "a", "b", "c"] - # a.rotate!(-3) #=> ["a", "b", "c", "d"] - - def rotate!(count=1) - self.replace(self.rotate(count)) - end - - ## - # call-seq: - # ary.delete_if { |item| block } -> ary - # ary.delete_if -> Enumerator - # - # Deletes every element of +self+ for which block evaluates to +true+. - # - # The array is changed instantly every time the block is called, not after - # the iteration is over. - # - # See also Array#reject! - # - # If no block is given, an Enumerator is returned instead. - # - # scores = [ 97, 42, 75 ] - # scores.delete_if {|score| score < 80 } #=> [97] - - def delete_if(&block) - return to_enum :delete_if unless block_given? - - idx = 0 - while idx < self.size do - if block.call(self[idx]) - self.delete_at(idx) - else - idx += 1 - end - end - self - end - - ## - # call-seq: - # ary.reject! { |item| block } -> ary or nil - # ary.reject! -> Enumerator - # - # Equivalent to Array#delete_if, deleting elements from +self+ for which the - # block evaluates to +true+, but returns +nil+ if no changes were made. - # - # The array is changed instantly every time the block is called, not after - # the iteration is over. - # - # See also Enumerable#reject and Array#delete_if. - # - # If no block is given, an Enumerator is returned instead. - - def reject!(&block) - return to_enum :reject! unless block_given? - - len = self.size - idx = 0 - while idx < self.size do - if block.call(self[idx]) - self.delete_at(idx) - else - idx += 1 - end - end - if self.size == len - nil - else - self - end - end - - ## - # call-seq: - # ary.insert(index, obj...) -> ary - # - # Inserts the given values before the element with the given +index+. - # - # Negative indices count backwards from the end of the array, where +-1+ is - # the last element. - # - # a = %w{ a b c d } - # a.insert(2, 99) #=> ["a", "b", 99, "c", "d"] - # a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"] - - def insert(idx, *args) - idx += self.size + 1 if idx < 0 - self[idx, 0] = args - self - end - - ## - # call-seq: - # ary.bsearch {|x| block } -> elem - # - # By using binary search, finds a value from this array which meets - # the given condition in O(log n) where n is the size of the array. - # - # You can use this method in two use cases: a find-minimum mode and - # a find-any mode. In either case, the elements of the array must be - # monotone (or sorted) with respect to the block. - # - # In find-minimum mode (this is a good choice for typical use case), - # the block must return true or false, and there must be an index i - # (0 <= i <= ary.size) so that: - # - # - the block returns false for any element whose index is less than - # i, and - # - the block returns true for any element whose index is greater - # than or equal to i. - # - # This method returns the i-th element. If i is equal to ary.size, - # it returns nil. - # - # ary = [0, 4, 7, 10, 12] - # ary.bsearch {|x| x >= 4 } #=> 4 - # ary.bsearch {|x| x >= 6 } #=> 7 - # ary.bsearch {|x| x >= -1 } #=> 0 - # ary.bsearch {|x| x >= 100 } #=> nil - # - # In find-any mode (this behaves like libc's bsearch(3)), the block - # must return a number, and there must be two indices i and j - # (0 <= i <= j <= ary.size) so that: - # - # - the block returns a positive number for ary[k] if 0 <= k < i, - # - the block returns zero for ary[k] if i <= k < j, and - # - the block returns a negative number for ary[k] if - # j <= k < ary.size. - # - # Under this condition, this method returns any element whose index - # is within i...j. If i is equal to j (i.e., there is no element - # that satisfies the block), this method returns nil. - # - # ary = [0, 4, 7, 10, 12] - # # try to find v such that 4 <= v < 8 - # ary.bsearch {|x| 1 - (x / 4).truncate } #=> 4 or 7 - # # try to find v such that 8 <= v < 10 - # ary.bsearch {|x| 4 - (x / 2).truncate } #=> nil - # - # You must not mix the two modes at a time; the block must always - # return either true/false, or always return a number. It is - # undefined which value is actually picked up at each iteration. - - def bsearch(&block) - return to_enum :bsearch unless block_given? - - low = 0 - high = self.size - satisfied = false - while low < high - mid = low + ((high - low) / 2).truncate - val = self[mid] - v = block.call(val) - if v.is_a?(Integer) - return val if v == 0 - smaller = v < 0 - elsif v == true - satisfied = true - smaller = true - elsif v == false || v.nil? - smaller = false - end - if smaller - high = mid - else - low = mid + 1 - end - end - return nil if low == self.size - return nil unless satisfied - self[low] - end - - ## - # call-seq: - # ary.delete_if { |item| block } -> ary - # ary.delete_if -> Enumerator - # - # Deletes every element of +self+ for which block evaluates to +true+. - # - # The array is changed instantly every time the block is called, not after - # the iteration is over. - # - # See also Array#reject! - # - # If no block is given, an Enumerator is returned instead. - # - # scores = [ 97, 42, 75 ] - # scores.delete_if {|score| score < 80 } #=> [97] - - def delete_if(&block) - return to_enum :delete_if unless block_given? - - idx = 0 - while idx < self.size do - if block.call(self[idx]) - self.delete_at(idx) - else - idx += 1 - end - end - self - end - - ## - # call-seq: - # ary.keep_if { |item| block } -> ary - # ary.keep_if -> Enumerator - # - # Deletes every element of +self+ for which the given block evaluates to - # +false+. - # - # See also Array#select! - # - # If no block is given, an Enumerator is returned instead. - # - # a = [1, 2, 3, 4, 5] - # a.keep_if { |val| val > 3 } #=> [4, 5] - - def keep_if(&block) - return to_enum :keep_if unless block_given? - - idx = 0 - len = self.size - while idx < self.size do - if block.call(self[idx]) - idx += 1 - else - self.delete_at(idx) - end - end - self - end - - ## - # call-seq: - # ary.select! {|item| block } -> ary or nil - # ary.select! -> Enumerator - # - # Invokes the given block passing in successive elements from +self+, - # deleting elements for which the block returns a +false+ value. - # - # If changes were made, it will return +self+, otherwise it returns +nil+. - # - # See also Array#keep_if - # - # If no block is given, an Enumerator is returned instead. - - def select!(&block) - return to_enum :select! unless block_given? - - result = [] - self.each do |x| - result << x if block.call(x) - end - return nil if self.size == result.size - self.replace(result) - end - - ## - # call-seq: - # ary.index(val) -> int or nil - # ary.index {|item| block } -> int or nil - # - # Returns the _index_ of the first object in +ary+ such that the object is - # == to +obj+. - # - # If a block is given instead of an argument, returns the _index_ of the - # first object for which the block returns +true+. Returns +nil+ if no - # match is found. - # - # ISO 15.2.12.5.14 - def index(val=NONE, &block) - return to_enum(:find_index, val) if !block && val == NONE - - if block - idx = 0 - self.each do |*e| - return idx if block.call(*e) - idx += 1 - end - else - return self.__ary_index(val) - end - nil - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-array-ext/src/array.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-array-ext/src/array.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-array-ext/src/array.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-array-ext/src/array.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,167 +0,0 @@ -#include "mruby.h" -#include "mruby/value.h" -#include "mruby/array.h" -#include "mruby/range.h" -#include "mruby/hash.h" - -/* - * call-seq: - * ary.assoc(obj) -> new_ary or nil - * - * Searches through an array whose elements are also arrays - * comparing _obj_ with the first element of each contained array - * using obj.==. - * Returns the first contained array that matches (that - * is, the first associated array), - * or +nil+ if no match is found. - * See also Array#rassoc. - * - * s1 = [ "colors", "red", "blue", "green" ] - * s2 = [ "letters", "a", "b", "c" ] - * s3 = "foo" - * a = [ s1, s2, s3 ] - * a.assoc("letters") #=> [ "letters", "a", "b", "c" ] - * a.assoc("foo") #=> nil - */ - -static mrb_value -mrb_ary_assoc(mrb_state *mrb, mrb_value ary) -{ - mrb_int i; - mrb_value v, k; - - mrb_get_args(mrb, "o", &k); - - for (i = 0; i < RARRAY_LEN(ary); ++i) { - v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]); - if (!mrb_nil_p(v) && RARRAY_LEN(v) > 0 && - mrb_equal(mrb, RARRAY_PTR(v)[0], k)) - return v; - } - return mrb_nil_value(); -} - -/* - * call-seq: - * ary.rassoc(obj) -> new_ary or nil - * - * Searches through the array whose elements are also arrays. Compares - * _obj_ with the second element of each contained array using - * ==. Returns the first contained array that matches. See - * also Array#assoc. - * - * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ] - * a.rassoc("two") #=> [2, "two"] - * a.rassoc("four") #=> nil - */ - -static mrb_value -mrb_ary_rassoc(mrb_state *mrb, mrb_value ary) -{ - mrb_int i; - mrb_value v, value; - - mrb_get_args(mrb, "o", &value); - - for (i = 0; i < RARRAY_LEN(ary); ++i) { - v = RARRAY_PTR(ary)[i]; - if (mrb_type(v) == MRB_TT_ARRAY && - RARRAY_LEN(v) > 1 && - mrb_equal(mrb, RARRAY_PTR(v)[1], value)) - return v; - } - return mrb_nil_value(); -} - -/* - * call-seq: - * ary.at(index) -> obj or nil - * - * Returns the element at _index_. A - * negative index counts from the end of +self+. Returns +nil+ - * if the index is out of range. See also Array#[]. - * - * a = [ "a", "b", "c", "d", "e" ] - * a.at(0) #=> "a" - * a.at(-1) #=> "e" - */ - -static mrb_value -mrb_ary_at(mrb_state *mrb, mrb_value ary) -{ - mrb_int pos; - mrb_get_args(mrb, "i", &pos); - - return mrb_ary_entry(ary, pos); -} - -static mrb_value -mrb_ary_values_at(mrb_state *mrb, mrb_value self) -{ - mrb_int argc; - mrb_value *argv; - - mrb_get_args(mrb, "*", &argv, &argc); - - return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref); -} - -/* - * call-seq: - * ary.to_h -> Hash - * - * Returns the result of interpreting aray as an array of - * [key, value] paris. - * - * [[:foo, :bar], [1, 2]].to_h - * # => {:foo => :bar, 1 => 2} - * - */ - -static mrb_value -mrb_ary_to_h(mrb_state *mrb, mrb_value ary) -{ - mrb_int i; - mrb_value v, hash; - - hash = mrb_hash_new_capa(mrb, 0); - - for (i = 0; i < RARRAY_LEN(ary); ++i) { - v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]); - - if (mrb_nil_p(v)) { - mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)", - mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, RARRAY_PTR(ary)[i])), - mrb_fixnum_value(i) - ); - } - - if (RARRAY_LEN(v) != 2) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)", - mrb_fixnum_value(i), - mrb_fixnum_value(RARRAY_LEN(v)) - ); - } - - mrb_hash_set(mrb, hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]); - } - - return hash; -} - -void -mrb_mruby_array_ext_gem_init(mrb_state* mrb) -{ - struct RClass * a = mrb->array_class; - - mrb_define_method(mrb, a, "assoc", mrb_ary_assoc, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, a, "at", mrb_ary_at, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY()); - mrb_define_method(mrb, a, "to_h", mrb_ary_to_h, MRB_ARGS_REQ(0)); -} - -void -mrb_mruby_array_ext_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-array-ext/test/array.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-array-ext/test/array.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-array-ext/test/array.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-array-ext/test/array.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,300 +0,0 @@ -## -# Array(Ext) Test - -assert("Array#assoc") do - s1 = [ "colors", "red", "blue", "green" ] - s2 = [ "letters", "a", "b", "c" ] - s3 = "foo" - a = [ s1, s2, s3 ] - - assert_equal [ "letters", "a", "b", "c" ], a.assoc("letters") - assert_nil a.assoc("foo") -end - -assert("Array#at") do - a = [ "a", "b", "c", "d", "e" ] - assert_equal "a", a.at(0) - assert_equal "e", a.at(-1) -end - -assert("Array#rassoc") do - a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ] - - assert_equal [2, "two"], a.rassoc("two") - assert_nil a.rassoc("four") -end - -assert("Array#uniq!") do - a = [1, 2, 3, 1] - a.uniq! - assert_equal [1, 2, 3], a - - b = [ "a", "b", "c" ] - assert_nil b.uniq! - - c = [["student","sam"], ["student","george"], ["teacher","matz"]] - assert_equal [["student", "sam"], ["teacher", "matz"]], c.uniq! { |s| s.first } - - d = [["student","sam"], ["teacher","matz"]] - assert_nil d.uniq! { |s| s.first } -end - -assert("Array#uniq") do - a = [1, 2, 3, 1] - assert_equal [1, 2, 3], a.uniq - assert_equal [1, 2, 3, 1], a - - b = [["student","sam"], ["student","george"], ["teacher","matz"]] - assert_equal [["student", "sam"], ["teacher", "matz"]], b.uniq { |s| s.first } -end - -assert("Array#-") do - a = [1, 2, 3, 1] - b = [1] - c = 1 - - assert_raise(TypeError) { a - c } - assert_equal [2, 3], (a - b) - assert_equal [1, 2, 3, 1], a -end - -assert("Array#|") do - a = [1, 2, 3, 1] - b = [1, 4] - c = 1 - - assert_raise(TypeError) { a | c } - assert_equal [1, 2, 3, 4], (a | b) - assert_equal [1, 2, 3, 1], a -end - -assert("Array#&") do - a = [1, 2, 3, 1] - b = [1, 4] - c = 1 - - assert_raise(TypeError) { a & c } - assert_equal [1], (a & b) - assert_equal [1, 2, 3, 1], a -end - -assert("Array#flatten") do - assert_equal [1, 2, "3", {4=>5}, :'6'], [1, 2, "3", {4=>5}, :'6'].flatten - assert_equal [1, 2, 3, 4, 5, 6], [1, 2, [3, 4, 5], 6].flatten - assert_equal [1, 2, 3, 4, 5, 6], [1, 2, [3, [4, 5], 6]].flatten - assert_equal [1, [2, [3, [4, [5, [6]]]]]], [1, [2, [3, [4, [5, [6]]]]]].flatten(0) - assert_equal [1, 2, [3, [4, [5, [6]]]]], [1, [2, [3, [4, [5, [6]]]]]].flatten(1) - assert_equal [1, 2, 3, [4, [5, [6]]]], [1, [2, [3, [4, [5, [6]]]]]].flatten(2) - assert_equal [1, 2, 3, 4, [5, [6]]], [1, [2, [3, [4, [5, [6]]]]]].flatten(3) - assert_equal [1, 2, 3, 4, 5, [6]], [1, [2, [3, [4, [5, [6]]]]]].flatten(4) - assert_equal [1, 2, 3, 4, 5, 6], [1, [2, [3, [4, [5, [6]]]]]].flatten(5) -end - -assert("Array#flatten!") do - assert_equal [1, 2, 3, 4, 5, 6], [1, 2, [3, [4, 5], 6]].flatten! -end - -assert("Array#compact") do - a = [1, nil, "2", nil, :t, false, nil] - assert_equal [1, "2", :t, false], a.compact - assert_equal [1, nil, "2", nil, :t, false, nil], a -end - -assert("Array#compact!") do - a = [1, nil, "2", nil, :t, false, nil] - a.compact! - assert_equal [1, "2", :t, false], a -end - -assert("Array#fetch") do - a = [ 11, 22, 33, 44 ] - assert_equal 22, a.fetch(1) - assert_equal 44, a.fetch(-1) - assert_equal 'cat', a.fetch(4, 'cat') - ret = 0 - a.fetch(100) { |i| ret = i } - assert_equal 100, ret - assert_raise(IndexError) { a.fetch(100) } -end - -assert("Array#fill") do - a = [ "a", "b", "c", "d" ] - assert_equal ["x", "x", "x", "x"], a.fill("x") - assert_equal ["x", "x", "x", "w"], a.fill("w", -1) - assert_equal ["x", "x", "z", "z"], a.fill("z", 2, 2) - assert_equal ["y", "y", "z", "z"], a.fill("y", 0..1) - assert_equal [0, 1, 4, 9], a.fill { |i| i*i } - assert_equal [0, 1, 8, 27], a.fill(-2) { |i| i*i*i } - assert_equal [0, 2, 3, 27], a.fill(1, 2) { |i| i+1 } - assert_equal [1, 2, 3, 27], a.fill(0..1) { |i| i+1 } - assert_raise(ArgumentError) { a.fill } - - assert_equal([0, 1, 2, 3, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, -2, 1)) - assert_equal([0, 1, 2, 3, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1, -2, 3)) - assert_equal([0, 1, 2, -1, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, 3..4)) - assert_equal([0, 1, 2, -1, 4, 5], [0, 1, 2, 3, 4, 5].fill(-1, 3...4)) - assert_equal([0, 1, -1, -1, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, 2..-2)) - assert_equal([0, 1, -1, -1, 4, 5], [0, 1, 2, 3, 4, 5].fill(-1, 2...-2)) - assert_equal([0, 1, 2, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(3..4){|i| i+10}) - assert_equal([0, 1, 2, 13, 4, 5], [0, 1, 2, 3, 4, 5].fill(3...4){|i| i+10}) - assert_equal([0, 1, 12, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(2..-2){|i| i+10}) - assert_equal([0, 1, 12, 13, 4, 5], [0, 1, 2, 3, 4, 5].fill(2...-2){|i| i+10}) - - assert_equal [1, 2, 3, 4, 'x', 'x'], [1, 2, 3, 4, 5, 6].fill('x', -2..-1) - assert_equal [1, 2, 3, 4, 'x', 6], [1, 2, 3, 4, 5, 6].fill('x', -2...-1) - assert_equal [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6].fill('x', -2...-2) - assert_equal [1, 2, 3, 4, 'x', 6], [1, 2, 3, 4, 5, 6].fill('x', -2..-2) - assert_equal [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6].fill('x', -2..0) -end - -assert("Array#reverse_each") do - a = [ "a", "b", "c", "d" ] - b = [] - a.reverse_each do |i| - b << i - end - assert_equal [ "d", "c", "b", "a" ], b - - if Object.const_defined?(:Enumerator) - assert_equal [ "d", "c", "b", "a" ], a.reverse_each.to_a - else - true - end -end - -assert("Array#rotate") do - a = ["a", "b", "c", "d"] - assert_equal ["b", "c", "d", "a"], a.rotate - assert_equal ["a", "b", "c", "d"], a - assert_equal ["c", "d", "a", "b"], a.rotate(2) - assert_equal ["b", "c", "d", "a"], a.rotate(-3) - assert_equal ["c", "d", "a", "b"], a.rotate(10) - assert_equal [], [].rotate -end - -assert("Array#rotate!") do - a = ["a", "b", "c", "d"] - assert_equal ["b", "c", "d", "a"], a.rotate! - assert_equal ["b", "c", "d", "a"], a - assert_equal ["d", "a", "b", "c"], a.rotate!(2) - assert_equal ["a", "b", "c", "d"], a.rotate!(-3) - assert_equal ["c", "d", "a", "b"], a.rotate(10) - assert_equal [], [].rotate! -end - -assert("Array#delete_if") do - a = [1, 2, 3, 4, 5] - assert_equal [1, 2, 3, 4, 5], a.delete_if { false } - assert_equal [1, 2, 3, 4, 5], a - - a = [1, 2, 3, 4, 5] - assert_equal [], a.delete_if { true } - assert_equal [], a - - a = [1, 2, 3, 4, 5] - assert_equal [1, 2, 3], a.delete_if { |i| i > 3 } - assert_equal [1, 2, 3], a -end - -assert("Array#reject!") do - a = [1, 2, 3, 4, 5] - assert_nil a.reject! { false } - assert_equal [1, 2, 3, 4, 5], a - - a = [1, 2, 3, 4, 5] - assert_equal [], a.reject! { true } - assert_equal [], a - - a = [1, 2, 3, 4, 5] - assert_equal [1, 2, 3], a.reject! { |val| val > 3 } - assert_equal [1, 2, 3], a -end - -assert("Array#insert") do - a = ["a", "b", "c", "d"] - assert_equal ["a", "b", 99, "c", "d"], a.insert(2, 99) - assert_equal ["a", "b", 99, "c", 1, 2, 3, "d"], a.insert(-2, 1, 2, 3) - - b = ["a", "b", "c", "d"] - assert_equal ["a", "b", "c", "d", nil, nil, 99], b.insert(6, 99) -end - -assert("Array#bsearch") do - # Find minimum mode - a = [0, 4, 7, 10, 12] - assert_include [4, 7], a.bsearch {|x| x >= 4 } - assert_equal 7, a.bsearch {|x| x >= 6 } - assert_equal 0, a.bsearch {|x| x >= -1 } - assert_nil a.bsearch {|x| x >= 100 } - - # Find any mode - a = [0, 4, 7, 10, 12] - assert_include [4, 7], a.bsearch {|x| 1 - (x / 4).truncate } - assert_nil a.bsearch {|x| 4 - (x / 2).truncate } - assert_equal(nil, a.bsearch {|x| 1 }) - assert_equal(nil, a.bsearch {|x| -1 }) -end - -assert("Array#delete_if") do - a = [1, 2, 3, 4, 5] - assert_equal [1, 2, 3, 4, 5], a.delete_if { false } - assert_equal [1, 2, 3, 4, 5], a - - a = [1, 2, 3, 4, 5] - assert_equal [], a.delete_if { true } - assert_equal [], a - - a = [ 1, 2, 3, 4, 5 ] - assert_equal [1, 2, 3], a.delete_if { |val| val > 3 } -end - -assert("Array#keep_if") do - a = [1, 2, 3, 4, 5] - assert_equal [1, 2, 3, 4, 5], a.keep_if { true } - assert_equal [1, 2, 3, 4, 5], a - - a = [1, 2, 3, 4, 5] - assert_equal [], a.keep_if { false } - assert_equal [], a - - a = [1, 2, 3, 4, 5] - assert_equal [4, 5], a.keep_if { |val| val > 3 } - assert_equal [4, 5], a -end - -assert("Array#select!") do - a = [1, 2, 3, 4, 5] - assert_nil a.select! { true } - assert_equal [1, 2, 3, 4, 5], a - - a = [1, 2, 3, 4, 5] - assert_equal [], a.select! { false } - assert_equal [], a - - a = [1, 2, 3, 4, 5] - assert_equal [4, 5], a.select! { |val| val > 3 } - assert_equal [4, 5], a -end - -assert('Array#values_at') do - a = %w{red green purple white none} - - assert_equal %w{red purple none}, a.values_at(0, 2, 4) - assert_equal ['green', 'white', nil, nil], a.values_at(1, 3, 5, 7) - assert_equal ['none', 'white', 'white', nil], a.values_at(-1, -2, -2, -7) - assert_equal ['none', nil, nil, 'red', 'green', 'purple'], a.values_at(4..6, 0...3) - assert_raise(TypeError) { a.values_at 'tt' } -end - -assert('Array#to_h') do - assert_equal({}, [].to_h) - assert_equal({a: 1, b:2}, [[:a, 1], [:b, 2]].to_h) - - assert_raise(TypeError) { [1].to_h } - assert_raise(ArgumentError) { [[1]].to_h } -end - -assert("Array#index (block)") do - assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 } - assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 } -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,286 +0,0 @@ -require 'open3' -require 'tempfile' - -class BinTest_MrubyBinDebugger - @debug1=false - @debug2=true - @debug3=true - def self.test(rubysource, testcase) - script, bin = Tempfile.new(['test', '.rb']), Tempfile.new(['test', '.mrb']) - - # .rb - script.write rubysource - script.flush - - # compile - `./bin/mrbc -g -o "#{bin.path}" "#{script.path}"` - - # add mrdb quit - testcase << {:cmd=>"quit"} - - stdin_data = testcase.map{|t| t[:cmd]}.join("\n") << "\n" - - ["bin/mrdb #{script.path}","bin/mrdb -b #{bin.path}"].each do |cmd| - o, s = Open3.capture2(cmd, :stdin_data => stdin_data) - - exp_vals = testcase.map{|t| t.fetch(:exp, nil)} - unexp_vals = testcase.map{|t| t.fetch(:unexp, nil)} - -if @debug1 - o.split("\n").each_with_index do |i,actual| - p [i,actual] - end -end - # compare actual / expected - o.split("\n").each do |actual| - next if actual.empty? - exp = exp_vals.shift -if @debug2 - a = true - a = actual.include?(exp) unless exp.nil? - p [actual, exp] unless a -end - assert_true actual.include?(exp) unless exp.nil? - end - # compare actual / unexpected - o.split("\n").each do |actual| - next if actual.empty? - unexp = unexp_vals.shift -if @debug3 - a = false - a = actual.include?(unexp) unless unexp.nil? - p [actual, unexp] if a -end - assert_false actual.include?(unexp) unless unexp.nil? - end - end - end -end - -INVCMD = "invalid command" - -assert('mruby-bin-debugger(mrdb) command line') do - # ruby source - src = "foo = 'foo'\n" - - str = "" - 103.times { - str += "1234567890" - } - cmd = "p a=#{str}" - - # test case - BinTest_MrubyBinDebugger.test(src, [{:cmd=>cmd[0...1023], :unexp=>'command line too long.'}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>cmd[0...1024], :unexp=>'command line too long.'}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>cmd[0...1025], :exp=>'command line too long.'}]) -end - -assert('mruby-bin-debugger(mrdb) command: "break"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"b", :unexp=>INVCMD} - tc << {:cmd=>"br", :unexp=>INVCMD} - tc << {:cmd=>"brea", :unexp=>INVCMD} - tc << {:cmd=>"break", :unexp=>INVCMD} - BinTest_MrubyBinDebugger.test(src, tc) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"bl", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"breaka", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "continue"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"c", :unexp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"co", :unexp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"continu", :unexp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"continue", :unexp=>INVCMD}]) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"cn", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"continuee", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "delete"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"d 1", :unexp=>INVCMD} - tc << {:cmd=>"de 1", :unexp=>INVCMD} - tc << {:cmd=>"delet 1", :unexp=>INVCMD} - tc << {:cmd=>"delete 1", :unexp=>INVCMD} - BinTest_MrubyBinDebugger.test(src, tc) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"dd 1", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"deletee 1", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "disable"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"dis", :unexp=>INVCMD} - tc << {:cmd=>"disa", :unexp=>INVCMD} - tc << {:cmd=>"disabl", :unexp=>INVCMD} - tc << {:cmd=>"disable", :unexp=>INVCMD} - BinTest_MrubyBinDebugger.test(src, tc) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"di", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"disb", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"disablee", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "enable"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"en", :unexp=>INVCMD} - tc << {:cmd=>"ena", :unexp=>INVCMD} - tc << {:cmd=>"enabl", :unexp=>INVCMD} - tc << {:cmd=>"enable", :unexp=>INVCMD} - BinTest_MrubyBinDebugger.test(src, tc) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"e", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"enb", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"enablee", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "eval"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"ev", :unexp=>INVCMD} - tc << {:cmd=>"eva", :unexp=>INVCMD} - tc << {:cmd=>"eval", :unexp=>INVCMD} - BinTest_MrubyBinDebugger.test(src, tc) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"e", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"evl", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"evall", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "help"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"h", :unexp=>INVCMD} - tc << {:cmd=>"he", :unexp=>INVCMD} - tc << {:cmd=>"hel", :unexp=>INVCMD} - tc << {:cmd=>"help", :unexp=>INVCMD} - BinTest_MrubyBinDebugger.test(src, tc) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"hl", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"helpp", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "info breakpoints"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"i b", :unexp=>INVCMD} - tc << {:cmd=>"in b", :unexp=>INVCMD} - tc << {:cmd=>"i br", :unexp=>INVCMD} - tc << {:cmd=>"inf breakpoint", :unexp=>INVCMD} - tc << {:cmd=>"info breakpoints", :unexp=>INVCMD} - BinTest_MrubyBinDebugger.test(src, tc) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ii b", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"i bb", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"infoo breakpoints", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"info breakpointss", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "list"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"l", :unexp=>INVCMD} - tc << {:cmd=>"li", :unexp=>INVCMD} - tc << {:cmd=>"lis", :unexp=>INVCMD} - tc << {:cmd=>"list", :unexp=>INVCMD} - BinTest_MrubyBinDebugger.test(src, tc) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ll", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"listt", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "print"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"p", :unexp=>INVCMD} - tc << {:cmd=>"pr", :unexp=>INVCMD} - tc << {:cmd=>"prin", :unexp=>INVCMD} - tc << {:cmd=>"print", :unexp=>INVCMD} - BinTest_MrubyBinDebugger.test(src, tc) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"pp", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"printt", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "quit"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"q", :unexp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"qu", :unexp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"qui", :unexp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"quit", :unexp=>INVCMD}]) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"qq", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"quitt", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "run"') do - # ruby source - src = "foo = 'foo'\n" - - # test case - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"r", :unexp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ru", :unexp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"run", :unexp=>INVCMD}]) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"rr", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"runn", :exp=>INVCMD}]) -end - -assert('mruby-bin-debugger(mrdb) command: "step"') do - # ruby source - src = <<"SRC" -while true - foo = 'foo' -end -SRC - - # test case - tc = [] - tc << {:cmd=>"s", :unexp=>INVCMD} - tc << {:cmd=>"st", :unexp=>INVCMD} - tc << {:cmd=>"ste", :unexp=>INVCMD} - tc << {:cmd=>"step", :unexp=>INVCMD} - BinTest_MrubyBinDebugger.test(src, tc) - - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ss", :exp=>INVCMD}]) - BinTest_MrubyBinDebugger.test(src, [{:cmd=>"stepp", :exp=>INVCMD}]) -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,701 +0,0 @@ -require 'open3' -require 'tempfile' - -class BinTest_MrubyBinDebugger - @debug1=false - @debug2=true - def self.test(rubysource, testcase) - script, bin = Tempfile.new(['test', '.rb']), Tempfile.new(['test', '.mrb']) - - # .rb - script.write rubysource - script.flush - - # compile - `./bin/mrbc -g -o "#{bin.path}" "#{script.path}"` - - # add mrdb quit - testcase << {:cmd=>"quit"} - - stdin_data = testcase.map{|t| t[:cmd]}.join("\n") << "\n" - - ["bin/mrdb #{script.path}","bin/mrdb -b #{bin.path}"].each do |cmd| - o, s = Open3.capture2(cmd, :stdin_data => stdin_data) - - exp_vals = testcase.map{|t| t.fetch(:exp, nil)} -=begin -if @debug1 - o.split("\n").each_with_index do |i,actual| - p [i,actual] - end -end - # compare actual / expected - o.split("\n").each do |actual| - next if actual.empty? - exp = exp_vals.shift -if @debug2 - a = true - a = actual.include?(exp) unless exp.nil? - p [actual, exp] unless a -end - assert_true actual.include?(exp) unless exp.nil? - end -=end - idx = 0 - exp_vals.each do |exp| - next if exp.nil? - idx = o.index(exp, idx) - assert_false idx.nil? - break unless idx - idx += 1 - end - end - end -end - -assert('mruby-bin-debugger(print) invalid arguments') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"p", :exp=>"Parameter not specified."} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) nomal') do - # ruby source - src = <<"SRC" -foo = 'foo' -bar = foo -baz = bar -SRC - - # test case - tc = [] - tc << {:cmd=>"s"} - tc << {:cmd=>"p (1+2)", :exp=>'$1 = 3'} - tc << {:cmd=>"p foo", :exp=>'$2 = "foo"'} - tc << {:cmd=>"p foo*=2", :exp=>'$3 = "foofoo"'} - tc << {:cmd=>"s"} - tc << {:cmd=>"p bar", :exp=>'$4 = "foofoo"'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) error') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"p (1+2", :exp=>'$1 = SyntaxError'} - tc << {:cmd=>"p bar", :exp=>'$2 = NoMethodError'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -# Kernel#instance_eval(string) does't work multiple statements. -=begin -assert('mruby-bin-debugger(print) multiple statements') do - # ruby source - src = <<"SRC" -x = 0 -y = 0 -z = 0 -SRC - - # test case - tc = [] - tc << {:cmd=>"s",} - tc << {:cmd=>"p x=1;x+=2", :exp=>"3"} - tc << {:cmd=>"s",} - tc << {:cmd=>"p x", :exp=>"3"} - - BinTest_MrubyBinDebugger.test(src, tc) -end -=end - -assert('mruby-bin-debugger(print) scope:top') do - # ruby source (bp is break point) - src = "bp=nil\n" - - # test case - tc = [] - tc << {:cmd=>"p self", :exp=>'$1 = main'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) scope:class') do - # ruby source (bp is break point) - src = <<"SRC" -class TestClassScope - bp = nil -end -SRC - - # test case - tc = [] - tc << {:cmd=>"s"} - tc << {:cmd=>"p self", :exp=>'$1 = TestClassScope'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) scope:module') do - # ruby source (bp is break point) - src = <<"SRC" -class TestModuleScope - bp = nil -end -SRC - - # test case - tc = [] - tc << {:cmd=>"s"} - tc << {:cmd=>"p self", :exp=>'$1 = TestModuleScope'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) scope:instance method') do - # ruby source (bp is break point) - src = <<"SRC" -class TestMethodScope - def m - bp = nil - end -end -TestMethodScope.new.m -SRC - - tc = [] - tc << {:cmd=>"b 3"} - tc << {:cmd=>"r"} - tc << {:cmd=>"p self", :exp=>'$1 = #"b 3"} - tc << {:cmd=>"r"} - tc << {:cmd=>"p self", :exp=>'$1 = TestClassMethodScope'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) scope:block') do - # ruby source (bp is break point) - src = <<"SRC" -1.times do - bp = nil -end -class TestBlockScope - 1.times do - bp = nil - end - def m - 1.times do - bp = nil - end - end -end -TestBlockScope.new.m -SRC - - tc = [] - tc << {:cmd=>"b 2"} - tc << {:cmd=>"b 6"} - tc << {:cmd=>"b 10"} - tc << {:cmd=>"c"} - tc << {:cmd=>"p self", :exp=>'$1 = main'} - tc << {:cmd=>"c"} - tc << {:cmd=>"p self", :exp=>'$2 = TestBlockScope'} - tc << {:cmd=>"c"} - tc << {:cmd=>"p self", :exp=>'$3 = #"b 6"} - tc << {:cmd=>"b 8"} - tc << {:cmd=>"b 11"} - tc << {:cmd=>"r"} - tc << {:cmd=>"p lv", :exp=>'$1 = "class"'} - tc << {:cmd=>"c"} - tc << {:cmd=>"p lv", :exp=>'$2 = "instance method"'} - tc << {:cmd=>"c"} - tc << {:cmd=>"p lv", :exp=>'$3 = "top"'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) same name:instance variabe') do - # ruby source (bp is break point) - src = <<"SRC" -@iv = 'top' -class TestInstanceVariableName - def initialize(v) - @iv = v - end - def m - bp = nil - end -end -i1 = TestInstanceVariableName.new('instance1') -i2 = TestInstanceVariableName.new('instance2') -i1.m -i2.m -bp = nil -SRC - - tc = [] - tc << {:cmd=>"b 7"} - tc << {:cmd=>"b 14"} - tc << {:cmd=>"r"} - tc << {:cmd=>"p @iv", :exp=>'$1 = "instance1"'} - tc << {:cmd=>"c"} - tc << {:cmd=>"p @iv", :exp=>'$2 = "instance2"'} - tc << {:cmd=>"c"} - tc << {:cmd=>"p @iv", :exp=>'$3 = "top"'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -# Kernel#instance_eval(string) does't work const. -=begin -assert('mruby-bin-debugger(print) same name:const') do - # ruby source (bp is break point) - src = <<"SRC" -CONST='top' -class TestConstNameSuperClass - CONST='super class' - def m - bp = nil - end -end -class TestConstNameSubClass < TestConstNameSuperClass - CONST='sub class' - def m - bp = nil - end -end - -TestConstNameSuperClass.new.m() -TestConstNameSubClass.new.m() -bp = nil -SRC - - # todo: wait for 'break' to be implimented - tc = [] - 9.times { tc << {:cmd=>"s"} } - tc << {:cmd=>"p CONST", :exp=>"super class"} - 3.times { tc << {:cmd=>"s"} } - tc << {:cmd=>"p CONST", :exp=>"sub class"} - 1.times { tc << {:cmd=>"s"} } - tc << {:cmd=>"p CONST", :exp=>"top"} - - BinTest_MrubyBinDebugger.test(src, tc) -end -=end - -assert('mruby-bin-debugger(print) Literal:Numeric') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>"p 100", :exp=>'$1 = 100'} - tc << {:cmd=>"p -0b100", :exp=>'$2 = -4'} - tc << {:cmd=>"p +0100", :exp=>'$3 = 64'} - tc << {:cmd=>"p 0x100", :exp=>'$4 = 256'} - tc << {:cmd=>"p 1_234", :exp=>'$5 = 1234'} - tc << {:cmd=>"p 0b1000_0000", :exp=>"$6 = #{0b1000_0000.to_s}"} - tc << {:cmd=>"p 0x1000_0000", :exp=>"$7 = #{0x1000_0000.to_s}"} - - tc << {:cmd=>"p 3.14", :exp=>'$8 = 3.14'} - tc << {:cmd=>"p -12.3", :exp=>'$9 = -12.3'} - tc << {:cmd=>"p +12.000", :exp=>'$10 = 12.0'} - tc << {:cmd=>"p 1e4", :exp=>'$11 = 10000.0'} - tc << {:cmd=>"p -0.1e-2", :exp=>'$12 = -0.001'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Literal:String') do - # ruby source - src = <<"SRC" -foo = 'foo' -bar = "bar" -baz = "baz" -SRC - - # test case - tc = [] - tc << {:cmd=>"s"} - tc << {:cmd=>"s"} - - tc << {:cmd=>'p "str"', :exp=>'$1 = "str"'} - tc << {:cmd=>'p "s\tt\rr\n"', :exp=>'$2 = "s\\tt\\rr\\n"'} - tc << {:cmd=>'p "\C-a\C-z"', :exp=>'$3 = "\\001\\032"'} - tc << {:cmd=>'p "#{foo+bar}"', :exp=>'$4 = "foobar"'} - - tc << {:cmd=>'p \'str\'', :exp=>'$5 = "str"'} - tc << {:cmd=>'p \'s\\tt\\rr\\n\'', :exp=>'$6 = "s\\\\tt\\\\rr\\\\n"'} - tc << {:cmd=>'p \'\\C-a\\C-z\'', :exp=>'$7 = "\\\\C-a\\\\C-z"'} - tc << {:cmd=>'p \'#{foo+bar}\'', :exp=>'$8 = "#{foo+bar}"'} - - tc << {:cmd=>'p %!str!', :exp=>'$9 = "str"'} - tc << {:cmd=>'p %!s\tt\rr\n!', :exp=>'$10 = "s\\tt\\rr\\n"'} - tc << {:cmd=>'p %!\C-a\C-z!', :exp=>'$11 = "\\001\\032"'} - tc << {:cmd=>'p %!#{foo+bar}!', :exp=>'$12 = "foobar"'} - - tc << {:cmd=>'p %Q!str!', :exp=>'$13 = "str"'} - tc << {:cmd=>'p %Q!s\tt\rr\n!', :exp=>'$14 = "s\\tt\\rr\\n"'} - tc << {:cmd=>'p %Q!\C-a\C-z!', :exp=>'$15 = "\\001\\032"'} - tc << {:cmd=>'p %Q!#{foo+bar}!', :exp=>'$16 = "foobar"'} - - tc << {:cmd=>'p %q!str!', :exp=>'$17 = "str"'} - tc << {:cmd=>'p %q!s\\tt\\rr\\n!', :exp=>'$18 = "s\\\\tt\\\\rr\\\\n"'} - tc << {:cmd=>'p %q!\\C-a\\C-z!', :exp=>'$19 = "\\\\C-a\\\\C-z"'} - tc << {:cmd=>'p %q!#{foo+bar}!', :exp=>'$20 = "#{foo+bar}"'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Literal:Array') do - # ruby source - src = <<"SRC" -foo = 'foo' -bar = "bar" -baz = "baz" -SRC - - # test case - tc = [] - tc << {:cmd=>"s"} - tc << {:cmd=>"s"} - - tc << {:cmd=>'p []', :exp=>'$1 = []'} - tc << {:cmd=>'p [ 5, 12, 8, 10, ]', :exp=>'$2 = [5, 12, 8, 10]'} - tc << {:cmd=>'p [1,2.5,"#{foo+bar}"]', :exp=>'$3 = [1, 2.5, "foobar"]'} - tc << {:cmd=>'p %w[3.14 A\ &\ B #{foo}]', :exp=>'$4 = ["3.14", "A & B", "#{foo}"]'} - tc << {:cmd=>'p %W[3.14 A\ &\ B #{foo}]', :exp=>'$5 = ["3.14", "A & B", "foo"]'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Literal:Hash') do - # ruby source - src = <<"SRC" -foo = 'foo' -bar = "bar" -baz = "baz" -SRC - - # test case - tc = [] - tc << {:cmd=>"s"} - tc << {:cmd=>"s"} - - tc << {:cmd=>'p {}', :exp=>'$1 = {}'} - tc << {:cmd=>'p {"one"=>1,"two"=>2}', :exp=>'$2 = {"one"=>1, "two"=>2}'} - tc << {:cmd=>'p {:eins=>"1", :zwei=>"2", }', :exp=>'$3 = {:eins=>"1", :zwei=>"2"}'} - tc << {:cmd=>'p {uno:"one", dos: 2}', :exp=>'$4 = {:uno=>"one", :dos=>2}'} - tc << {:cmd=>'p {"one"=>1, :zwei=>2, tres:3}', :exp=>'$5 = {"one"=>1, :zwei=>2, :tres=>3}'} - tc << {:cmd=>'p {:foo=>"#{foo}",:bar=>"#{bar}"}', :exp=>'$6 = {:foo=>"foo", :bar=>"bar"}'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Literal:Range') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>'p 1..10', :exp=>'$1 = 1..10'} - tc << {:cmd=>'p 1...10', :exp=>'$2 = 1...10'} - tc << {:cmd=>'p 100..10', :exp=>'$3 = 100..10'} - tc << {:cmd=>'p 1 ... 10', :exp=>'$4 = 1...10'} - - tc << {:cmd=>'p "1" .. "9"', :exp=>'$5 = "1".."9"'} - tc << {:cmd=>'p "A" ... "Z"', :exp=>'$6 = "A"..."Z"'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Literal:Symbol') do - # ruby source - src = <<"SRC" -foo = 'foo' -bar = "bar" -baz = "baz" -SRC - - # test case - tc = [] - tc << {:cmd=>"s"} - tc << {:cmd=>"s"} - - tc << {:cmd=>'p :sym', :exp=>'$1 = :sym'} - tc << {:cmd=>'p :"sd"', :exp=>'$2 = :sd'} - tc << {:cmd=>"p :'ss'", :exp=>'$3 = :ss'} - tc << {:cmd=>'p :"123"', :exp=>'$4 = :"123"'} - tc << {:cmd=>'p :"#{foo} baz"', :exp=>'$5 = :"foo baz"'} - tc << {:cmd=>'p %s!symsym!', :exp=>'$6 = :symsym'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Unary operation') do - # ruby source - src = "foo = 'foo'\n" - - # test case - tc = [] - tc << {:cmd=>'p +10', :exp=>'$1 = 10'} - tc << {:cmd=>'p -100', :exp=>'$2 = -100'} - tc << {:cmd=>'p !true', :exp=>'$3 = false'} - tc << {:cmd=>'p !false', :exp=>'$4 = true'} - tc << {:cmd=>'p !nil', :exp=>'$5 = true'} - tc << {:cmd=>'p !1', :exp=>'$6 = false'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Binary operation') do - # ruby source - src = <<"SRC" -CONST = 100 -a,b,c = 1, 5, 8 -foo,bar,baz = 'foo','bar','baz' -ary = [] -SRC - - # test case - tc = [] - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - - tc << {:cmd=>'p a+1', :exp=>'$1 = 2'} - tc << {:cmd=>'p 2-b', :exp=>'$2 = -3'} - tc << {:cmd=>'p c * 3', :exp=>'$3 = 24'} - tc << {:cmd=>'p a/b', :exp=>'$4 = 0.2'} - tc << {:cmd=>'p c%b', :exp=>'$5 = 3'} - tc << {:cmd=>'p 2**10', :exp=>'$6 = 1024'} - tc << {:cmd=>'p ~3', :exp=>'$7 = -4'} - - tc << {:cmd=>'p 1<<2', :exp=>'$8 = 4'} - tc << {:cmd=>'p 64>>5', :exp=>'$9 = 2'} - - tc << {:cmd=>'p a|c', :exp=>'$10 = 9'} - tc << {:cmd=>'p a&b', :exp=>'$11 = 1'} - tc << {:cmd=>'p a^b', :exp=>'$12 = 4'} - - tc << {:cmd=>'p a>b', :exp=>'$13 = false'} - tc << {:cmd=>'p a'$14 = true'} - tc << {:cmd=>'p b>=5', :exp=>'$15 = true'} - tc << {:cmd=>'p b<=5', :exp=>'$16 = true'} - - tc << {:cmd=>'p "A"<=>"B"', :exp=>'$17 = -1'} - tc << {:cmd=>'p "A"=="B"', :exp=>'$18 = false'} - tc << {:cmd=>'p "A"==="B"', :exp=>'$19 = false'} - tc << {:cmd=>'p "A"!="B"', :exp=>'$20 = true'} - - tc << {:cmd=>'p false || true', :exp=>'$21 = true'} - tc << {:cmd=>'p false && true', :exp=>'$22 = false'} - - tc << {:cmd=>'p not nil', :exp=>'$23 = true'} - tc << {:cmd=>'p false or true', :exp=>'$24 = true'} - tc << {:cmd=>'p false and true', :exp=>'$25 = false'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Ternary operation') do - # ruby source - src = <<"SRC" -CONST = 100 -a,b,c = 1, 5, -10 -foo,bar,baz = 'foo','bar','baz' -ary = [] -SRC - - # test case - tc = [] - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - - tc << {:cmd=>'p (a < b) ? a : b', :exp=>'$1 = 1'} - tc << {:cmd=>'p (a > b) ? a : b', :exp=>'$2 = 5'} - tc << {:cmd=>'p true ? "true" : "false"', :exp=>'$3 = "true"'} - tc << {:cmd=>'p false ? "true" : "false"', :exp=>'$4 = "false"'} - tc << {:cmd=>'p nil ? "true" : "false"', :exp=>'$5 = "false"'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Substitution:simple') do - # ruby source - src = <<"SRC" -CONST = 100 -a,b,c = 1, 5, -10 -foo,bar,baz = 'foo','bar','baz' -ary = [] -SRC - - # test case - tc = [] - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - - tc << {:cmd=>'p a=2', :exp=>'$1 = 2'} - tc << {:cmd=>'p foo=[foo,bar,baz]', :exp=>'$2 = ["foo", "bar", "baz"]'} - - tc << {:cmd=>'p undefined=-1', :exp=>'$3 = -1'} - tc << {:cmd=>'p "#{undefined}"', :exp=>'$4 = NoMethodError'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Substitution:self') do - # ruby source - src = <<"SRC" -CONST = 100 -a,b,c = 1, 5, -10 -foo,bar,baz = 'foo','bar','baz' -ary = [] -SRC - - # test case - tc = [] - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - - tc << {:cmd=>'p a+=9', :exp=>'$1 = 10'} - tc << {:cmd=>'p b-=c', :exp=>'$2 = 15'} - tc << {:cmd=>'p bar*=2', :exp=>'$3 = "barbar"'} - tc << {:cmd=>'p a/=4', :exp=>'$4 = 2.5'} - tc << {:cmd=>'p c%=4', :exp=>'$5 = 2'} - - tc << {:cmd=>'p b&=0b0101', :exp=>'$6 = 5'} - tc << {:cmd=>'p c|=0x10', :exp=>'$7 = 18'} - - tc << {:cmd=>'p "#{a} #{b} #{c}"', :exp=>'$8 = "2.5 5 18"'} - tc << {:cmd=>'p "#{foo}#{bar}#{baz}"', :exp=>'$9 = "foobarbarbaz"'} - - tc << {:cmd=>'p a,b,c=[10,20,30]',:exp=>'$10 = [10, 20, 30]'} - tc << {:cmd=>'p [a,b,c]', :exp=>'$11 = [10, 20, 30]'} - tc << {:cmd=>'p a,b=b,a', :exp=>'$12 = [20, 10]'} - tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'} - - tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'} - tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = NoMethodError'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Substitution:multiple') do - # ruby source - src = <<"SRC" -CONST = 100 -a,b,c = 1, 5, -10 -foo,bar,baz = 'foo','bar','baz' -ary = [] -SRC - - # test case - tc = [] - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - - tc << {:cmd=>'p a,b=[10,20]', :exp=>'$1 = [10, 20]'} - tc << {:cmd=>'p [a,b,c]', :exp=>'$2 = [10, 20, -10]'} - - tc << {:cmd=>'p foo,bar=["FOO","BAR","BAZ"]', :exp=>'$3 = ["FOO", "BAR", "BAZ"]'} - tc << {:cmd=>'p [foo,bar,baz]', :exp=>'$4 = ["FOO", "BAR", "baz"]'} - - tc << {:cmd=>'p a,foo=foo,a', :exp=>'$5 = ["FOO", 10]'} - tc << {:cmd=>'p [a,foo]', :exp=>'$6 = ["FOO", 10]'} - -# tc << {:cmd=>'p a,*b=[123, 456, 789]'} -# tc << {:cmd=>'p [a,b]', :exp=>'[123, [456, 789]]'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - -assert('mruby-bin-debugger(print) Substitution:self') do - # ruby source - src = <<"SRC" -CONST = 100 -a,b,c = 1, 5, -10 -foo,bar,baz = 'foo','bar','baz' -ary = [] -SRC - - # test case - tc = [] - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - tc << {:cmd=>'s'} - - tc << {:cmd=>'p a+=9', :exp=>'$1 = 10'} - tc << {:cmd=>'p b-=c', :exp=>'$2 = 15'} - tc << {:cmd=>'p bar*=2', :exp=>'$3 = "barbar"'} - tc << {:cmd=>'p a/=4', :exp=>'$4 = 2.5'} - tc << {:cmd=>'p c%=4', :exp=>'$5 = 2'} - - tc << {:cmd=>'p b&=0b0101', :exp=>'$6 = 5'} - tc << {:cmd=>'p c|=0x10', :exp=>'$7 = 18'} - - tc << {:cmd=>'p "#{a} #{b} #{c}"', :exp=>'$8 = "2.5 5 18"'} - tc << {:cmd=>'p "#{foo}#{bar}#{baz}"', :exp=>'$9 = "foobarbarbaz"'} - - tc << {:cmd=>'p a,b,c=[10,20,30]',:exp=>'$10 = [10, 20, 30]'} - tc << {:cmd=>'p [a,b,c]', :exp=>'$11 = [10, 20, 30]'} - tc << {:cmd=>'p a,b=b,a', :exp=>'$12 = [20, 10]'} - tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'} - - tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'} - tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = NoMethodError'} - - BinTest_MrubyBinDebugger.test(src, tc) -end - diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -MRuby::Gem::Specification.new('mruby-bin-debugger') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'mruby debugger command' - - spec.add_dependency('mruby-eval', :core => 'mruby-eval') - - spec.bins = %w(mrdb) -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,516 +0,0 @@ -/* -** apibreak.c -** -*/ - -#include -#include "mruby.h" -#include "mruby/irep.h" -#include "mrdb.h" -#include "mruby/debug.h" -#include "mruby/opcode.h" -#include "mruby/class.h" -#include "mruby/proc.h" -#include "mruby/variable.h" -#include "mrdberror.h" -#include "apibreak.h" - -#define MAX_BREAKPOINTNO (MAX_BREAKPOINT * 1024) -#define MRB_DEBUG_BP_FILE_OK (0x0001) -#define MRB_DEBUG_BP_LINENO_OK (0x0002) - -static uint16_t -check_lineno( mrb_irep_debug_info_file *info_file, uint16_t lineno ) -{ - uint32_t count = info_file->line_entry_count; - uint16_t l_idx; - - if( info_file->line_type == mrb_debug_line_ary ) { - for (l_idx = 0; l_idx < count; ++l_idx) { - if(lineno == info_file->lines.ary[l_idx]) { - return lineno; - } - } - } else { - for (l_idx = 0; l_idx < count; ++l_idx) { - if(lineno == info_file->lines.flat_map[l_idx].line) { - return lineno; - } - } - } - - return 0; -} - -static int32_t -get_break_index( mrb_debug_context *dbg, int32_t bpno ) -{ - uint32_t i; - int32_t index; - char hit = FALSE; - - for(i = 0 ; i < dbg->bpnum; i++) { - if(dbg->bp[i].bpno == bpno) { - hit = TRUE; - index = i; - break; - } - } - - if(hit == FALSE) { - return MRB_DEBUG_BREAK_INVALID_NO; - } - - return index; -} - -static void -free_breakpoint( mrb_state *mrb, mrb_debug_breakpoint *bp ) -{ - switch(bp->type) { - case MRB_DEBUG_BPTYPE_LINE: - mrb_free(mrb, (void*)bp->point.linepoint.file); - break; - case MRB_DEBUG_BPTYPE_METHOD: - mrb_free(mrb, (void*)bp->point.methodpoint.method_name); - if(bp->point.methodpoint.class_name != NULL) { - mrb_free(mrb, (void*)bp->point.methodpoint.class_name); - } - break; - default: - break; - } -} - -static uint16_t -check_file_lineno( struct mrb_irep *irep, const char *file, uint16_t lineno ) -{ - mrb_irep_debug_info_file *info_file; - uint16_t result = 0; - uint16_t f_idx; - uint16_t fix_lineno; - uint16_t i; - - for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { - info_file = irep->debug_info->files[f_idx]; - if(!strcmp(info_file->filename, file)) { - result = MRB_DEBUG_BP_FILE_OK; - - fix_lineno = check_lineno( info_file, lineno ); - if(fix_lineno != 0) { - return result | MRB_DEBUG_BP_LINENO_OK; - } - } - for ( i=0; i < irep->rlen; ++i ) { - result |= check_file_lineno(irep->reps[i], file, lineno); - if(result == (MRB_DEBUG_BP_FILE_OK | MRB_DEBUG_BP_LINENO_OK)) { - return result; - } - } - } - return result; -} - -static const char* -get_class_name( mrb_state *mrb, struct RClass *class_obj ) -{ - struct RClass *outer; - mrb_sym class_sym; - - outer = mrb_class_outer_module(mrb, class_obj); - class_sym = mrb_class_sym(mrb, class_obj, outer); - return mrb_sym2name(mrb, class_sym); -} - -static int32_t -compare_break_method( mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc ) -{ - const char* class_name; - const char* method_name; - struct RProc* m; - struct RClass* sc; - const char* sn; - mrb_sym ssym; - mrb_debug_methodpoint *method_p; - mrb_bool is_defined; - - method_name = mrb_sym2name(mrb, method_sym); - - method_p = &bp->point.methodpoint; - if(strcmp(method_p->method_name, method_name) == 0) { - class_name = get_class_name(mrb, class_obj); - if(class_name == NULL) { - if(method_p->class_name == NULL) { - return bp->bpno; - } - } - else if(method_p->class_name != NULL) { - m = mrb_method_search_vm(mrb, &class_obj, method_sym); - if(m == NULL) { - return MRB_DEBUG_OK; - } - if(MRB_PROC_CFUNC_P(m)) { - *isCfunc = TRUE; - } - - is_defined = mrb_class_defined(mrb, method_p->class_name); - if(is_defined == FALSE) { - return MRB_DEBUG_OK; - } - - sc = mrb_class_get(mrb, method_p->class_name); - ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name)); - m = mrb_method_search_vm(mrb, &sc, ssym); - if(m == NULL) { - return MRB_DEBUG_OK; - } - - class_name = get_class_name(mrb, class_obj); - sn = get_class_name(mrb, sc); - if(strcmp(sn, class_name) == 0) { - return bp->bpno; - } - } - } - return MRB_DEBUG_OK; -} - -int32_t -mrb_debug_set_break_line( mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t lineno) -{ - int32_t index; - char* set_file; - uint16_t result; - - if((mrb == NULL)||(dbg == NULL)||(file == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - if(dbg->bpnum >= MAX_BREAKPOINT) { - return MRB_DEBUG_BREAK_NUM_OVER; - } - - if(dbg->next_bpno > MAX_BREAKPOINTNO) { - return MRB_DEBUG_BREAK_NO_OVER; - } - - /* file and lineno check (line type mrb_debug_line_ary only.) */ - result = check_file_lineno( dbg->root_irep, file, lineno ); - if(result == 0) { - return MRB_DEBUG_BREAK_INVALID_FILE; - }else if(result == MRB_DEBUG_BP_FILE_OK) { - return MRB_DEBUG_BREAK_INVALID_LINENO; - } - - set_file = mrb_malloc(mrb, strlen(file) + 1); - - index = dbg->bpnum; - dbg->bp[index].bpno = dbg->next_bpno; - dbg->next_bpno++; - dbg->bp[index].enable = TRUE; - dbg->bp[index].type = MRB_DEBUG_BPTYPE_LINE; - dbg->bp[index].point.linepoint.lineno = lineno; - dbg->bpnum++; - - strncpy(set_file, file, strlen(file) + 1); - - dbg->bp[index].point.linepoint.file = set_file; - - return dbg->bp[index].bpno; -} - -int32_t -mrb_debug_set_break_method( mrb_state *mrb, mrb_debug_context *dbg, const char *class_name, const char *method_name ) -{ - int32_t index; - char* set_class; - char* set_method; - - if((mrb == NULL) || (dbg == NULL) || (method_name == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - if(dbg->bpnum >= MAX_BREAKPOINT) { - return MRB_DEBUG_BREAK_NUM_OVER; - } - - if(dbg->next_bpno > MAX_BREAKPOINTNO) { - return MRB_DEBUG_BREAK_NO_OVER; - } - - if(class_name != NULL) { - set_class = mrb_malloc(mrb, strlen(class_name) + 1); - strncpy(set_class, class_name, strlen(class_name) + 1); - } - else { - set_class = NULL; - } - - set_method = mrb_malloc(mrb, strlen(method_name) + 1); - - strncpy(set_method, method_name, strlen(method_name) + 1); - - index = dbg->bpnum; - dbg->bp[index].bpno = dbg->next_bpno; - dbg->next_bpno++; - dbg->bp[index].enable = TRUE; - dbg->bp[index].type = MRB_DEBUG_BPTYPE_METHOD; - dbg->bp[index].point.methodpoint.method_name = set_method; - dbg->bp[index].point.methodpoint.class_name = set_class; - dbg->bpnum++; - - return dbg->bp[index].bpno; -} - -int32_t -mrb_debug_get_breaknum( mrb_state *mrb, mrb_debug_context *dbg ) -{ - if((mrb == NULL) || (dbg == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - return dbg->bpnum; -} - -int32_t -mrb_debug_get_break_all( mrb_state *mrb, mrb_debug_context *dbg, uint32_t size, mrb_debug_breakpoint *bp ) -{ - uint32_t get_size = 0; - - if((mrb == NULL) || (dbg == NULL) || (bp == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - if(dbg->bpnum >= size) { - get_size = size; - } - else { - get_size = dbg->bpnum; - } - - memcpy(bp, dbg->bp, sizeof(mrb_debug_breakpoint) * get_size); - - return get_size; -} - -int32_t -mrb_debug_get_break( mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno, mrb_debug_breakpoint *bp ) -{ - uint32_t index; - - if((mrb == NULL) || (dbg == NULL) || (bp == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - index = get_break_index(dbg, bpno); - if(index == MRB_DEBUG_BREAK_INVALID_NO) { - return MRB_DEBUG_BREAK_INVALID_NO; - } - - bp->bpno = dbg->bp[index].bpno; - bp->enable = dbg->bp[index].enable; - bp->point = dbg->bp[index].point; - bp->type = dbg->bp[index].type; - - return 0; -} - -int32_t -mrb_debug_delete_break( mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno ) -{ - uint32_t i; - int32_t index; - - if((mrb == NULL) ||(dbg == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - index = get_break_index(dbg, bpno); - if(index == MRB_DEBUG_BREAK_INVALID_NO) { - return MRB_DEBUG_BREAK_INVALID_NO; - } - - free_breakpoint(mrb, &dbg->bp[index]); - - for(i = index ; i < dbg->bpnum; i++) { - if((i + 1) == dbg->bpnum) { - memset(&dbg->bp[i], 0, sizeof(mrb_debug_breakpoint)); - } - else { - memcpy(&dbg->bp[i], &dbg->bp[i + 1], sizeof(mrb_debug_breakpoint)); - } - } - - dbg->bpnum--; - - return MRB_DEBUG_OK; -} - -int32_t -mrb_debug_delete_break_all( mrb_state *mrb, mrb_debug_context *dbg ) -{ - uint32_t i; - - if((mrb == NULL) || (dbg == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - for(i = 0 ; i < dbg->bpnum ; i++) { - free_breakpoint(mrb, &dbg->bp[i]); - } - - dbg->bpnum = 0; - - return MRB_DEBUG_OK; -} - -int32_t -mrb_debug_enable_break( mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno ) -{ - int32_t index = 0; - - if((mrb == NULL) || (dbg == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - index = get_break_index(dbg, bpno); - if(index == MRB_DEBUG_BREAK_INVALID_NO) { - return MRB_DEBUG_BREAK_INVALID_NO; - } - - dbg->bp[index].enable = TRUE; - - return MRB_DEBUG_OK; -} - -int32_t -mrb_debug_enable_break_all( mrb_state *mrb, mrb_debug_context *dbg ) -{ - uint32_t i; - - if((mrb == NULL) || (dbg == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - for(i = 0 ; i < dbg->bpnum; i++) { - dbg->bp[i].enable = TRUE; - } - - return MRB_DEBUG_OK; -} - -int32_t -mrb_debug_disable_break( mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno ) -{ - int32_t index = 0; - - if((mrb == NULL) || (dbg == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - index = get_break_index(dbg, bpno); - if(index == MRB_DEBUG_BREAK_INVALID_NO) { - return MRB_DEBUG_BREAK_INVALID_NO; - } - - dbg->bp[index].enable = FALSE; - - return MRB_DEBUG_OK; -} - -int32_t -mrb_debug_disable_break_all( mrb_state *mrb, mrb_debug_context *dbg ) -{ - uint32_t i; - - if((mrb == NULL) || (dbg == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - for(i = 0 ; i < dbg->bpnum; i++) { - dbg->bp[i].enable = FALSE; - } - - return MRB_DEBUG_OK; -} - -static mrb_bool -check_start_pc_for_line( mrb_irep *irep, mrb_code *pc, uint16_t line ) -{ - if( pc > irep->iseq ) { - if( line == mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq - 1))) { - return FALSE; - } - } - return TRUE; -} - -int32_t -mrb_debug_check_breakpoint_line( mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t line ) -{ - mrb_debug_breakpoint *bp; - mrb_debug_linepoint *line_p; - int i; - - if((mrb == NULL) || (dbg == NULL) || (file == NULL) || (line <= 0)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - if(!check_start_pc_for_line(dbg->irep, dbg->pc, line)) { - return MRB_DEBUG_OK; - } - - bp = dbg->bp; - for(i=0; ibpnum; i++) { - switch (bp->type) { - case MRB_DEBUG_BPTYPE_LINE: - if(bp->enable == TRUE) { - line_p = &bp->point.linepoint; - if((strcmp(line_p->file, file) == 0) && (line_p->lineno == line)) { - return bp->bpno; - } - } - break; - case MRB_DEBUG_BPTYPE_METHOD: - break; - case MRB_DEBUG_BPTYPE_NONE: - default: - return MRB_DEBUG_OK; - } - bp++; - } - return MRB_DEBUG_OK; -} - - -int32_t -mrb_debug_check_breakpoint_method( mrb_state *mrb, mrb_debug_context *dbg, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc ) -{ - mrb_debug_breakpoint *bp; - int32_t bpno; - int i; - - if((mrb == NULL) || (dbg == NULL) || (class_obj == NULL)) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - bp = dbg->bp; - for(i=0; ibpnum; i++) { - if(bp->type == MRB_DEBUG_BPTYPE_METHOD) { - if(bp->enable == TRUE) { - bpno = compare_break_method(mrb, bp, class_obj, method_sym, isCfunc); - if(bpno > 0) { - return bpno; - } - } - } - else if(bp->type == MRB_DEBUG_BPTYPE_NONE) { - break; - } - bp++; - } - - return 0; -} - - diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -/* -** apibreak.h -** -*/ - -#ifndef APIBREAK_H_ -#define APIBREAK_H_ - -#include "mruby.h" -#include "mrdb.h" - -int32_t mrb_debug_set_break_line( mrb_state *, mrb_debug_context *, const char *, uint16_t ); -int32_t mrb_debug_set_break_method( mrb_state *, mrb_debug_context *, const char *, const char * ); -int32_t mrb_debug_get_breaknum( mrb_state *, mrb_debug_context * ); -int32_t mrb_debug_get_break_all( mrb_state *, mrb_debug_context *, uint32_t, mrb_debug_breakpoint bp[]); -int32_t mrb_debug_get_break( mrb_state *, mrb_debug_context *, uint32_t, mrb_debug_breakpoint * ); -int32_t mrb_debug_delete_break( mrb_state *, mrb_debug_context *, uint32_t ); -int32_t mrb_debug_delete_break_all( mrb_state *, mrb_debug_context * ); -int32_t mrb_debug_enable_break( mrb_state *, mrb_debug_context *, uint32_t ); -int32_t mrb_debug_enable_break_all( mrb_state *, mrb_debug_context * ); -int32_t mrb_debug_disable_break( mrb_state *, mrb_debug_context *, uint32_t ); -int32_t mrb_debug_disable_break_all( mrb_state *, mrb_debug_context * ); -int32_t mrb_debug_check_breakpoint_line( mrb_state *, mrb_debug_context *, const char *, uint16_t ); -int32_t mrb_debug_check_breakpoint_method( mrb_state *, mrb_debug_context *, struct RClass *, mrb_sym, mrb_bool* ); - -#endif /* APIBREAK_H_ */ diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,235 +0,0 @@ -/* - * apilist.c - */ - -#include -#include -#include - -#include "mrdb.h" -#include "mrdberror.h" -#include "apilist.h" -#include "mruby/compile.h" -#include "mruby/irep.h" -#include "mruby/debug.h" - -#define LINE_BUF_SIZE MAX_COMMAND_LINE - -typedef struct source_file { - char *path; - uint16_t lineno; - FILE *fp; -} source_file; - -static void -source_file_free(mrb_state *mrb, source_file *file) -{ - if (file != NULL) { - if (file->path != NULL) { - mrb_free(mrb, file->path); - } - if (file->fp != NULL) { - fclose(file->fp); - file->fp = NULL; - } - mrb_free(mrb, file); - } -} - -static char* -build_path(mrb_state *mrb, const char *dir, const char *base) -{ - int len; - char *path = NULL; - - len = strlen(base) + 1; - - if (strcmp(dir, ".")) { - len += strlen(dir) + sizeof("/") - 1; - } - - path = mrb_malloc(mrb, len); - memset(path, 0, len); - - if (strcmp(dir, ".")) { - strcat(path, dir); - strcat(path, "/"); - } - strcat(path, base); - - return path; -} - -static char* -dirname(mrb_state *mrb, const char *path) -{ - size_t len; - char *p, *dir; - - if (path == NULL) { - return NULL; - } - - p = strrchr(path, '/'); - len = p != NULL ? p - path : strlen(path); - - dir = mrb_malloc(mrb, len + 1); - strncpy(dir, path, len); - dir[len] = '\0'; - - return dir; -} - -static source_file* -source_file_new(mrb_state *mrb, mrb_debug_context *dbg, char *filename) -{ - source_file *file = NULL; - - file = mrb_malloc(mrb, sizeof(source_file)); - - memset(file, '\0', sizeof(source_file)); - file->fp = fopen(filename, "rb"); - - if (file->fp == NULL) { - source_file_free(mrb, file); - return NULL; - } - - file->lineno = 1; - file->path = mrb_malloc(mrb, strlen(filename) + 1); - strcpy(file->path, filename); - return file; -} - -static mrb_bool -remove_newlines(char *s, FILE *fp) -{ - int c; - char *p; - size_t len; - - if ((len = strlen(s)) == 0) { - return FALSE; - } - - p = s + len - 1; - - if (*p != '\r' && *p != '\n') { - return FALSE; - } - - if (*p == '\r') { - /* peek the next character and skip '\n' */ - if ((c = fgetc(fp)) != '\n') { - ungetc(c, fp); - } - } - - /* remove trailing newline characters */ - while (s <= p && (*p == '\r' || *p == '\n')) { - *p-- = '\0'; - } - - return TRUE; -} - -static void -show_lines(source_file *file, uint16_t line_min, uint16_t line_max) -{ - char buf[LINE_BUF_SIZE]; - int show_lineno = 1, found_newline = 0, is_printed = 0; - - if (file->fp == NULL) { - return; - } - - while (fgets(buf, sizeof(buf), file->fp) != NULL) { - found_newline = remove_newlines(buf, file->fp); - - if (line_min <= file->lineno) { - if (show_lineno) { - printf("%-8d", file->lineno); - } - show_lineno = found_newline; - printf(found_newline ? "%s\n" : "%s", buf); - is_printed = 1; - } - - if (found_newline) { - if (line_max < ++file->lineno) { - break; - } - } - } - - if (is_printed && !found_newline) { - printf("\n"); - } -} - -char* -mrb_debug_get_source(mrb_state *mrb, mrdb_state *mrdb, const char *srcpath, const char *filename) -{ - int i; - FILE *fp; - const char *search_path[3]; - char *path = NULL; - - search_path[0] = srcpath; - search_path[1] = dirname(mrb, mrb_debug_get_filename(mrdb->dbg->root_irep, 0)); - search_path[2] = "."; - - for (i = 0; i < 3; i++) { - if (search_path[i] == NULL) { - continue; - } - - if ((path = build_path(mrb, search_path[i], filename)) == NULL) { - continue; - } - - if ((fp = fopen(path, "rb")) == NULL) { - mrb_free(mrb, path); - path = NULL; - continue; - } - fclose(fp); - break; - } - - mrb_free(mrb, (void *)search_path[1]); - - return path; -} - -int32_t -mrb_debug_list(mrb_state *mrb, mrb_debug_context *dbg, char *filename, uint16_t line_min, uint16_t line_max) -{ - char *ext; - source_file *file; - - if (mrb == NULL || dbg == NULL || filename == NULL) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - ext = strrchr(filename, '.'); - - if (ext == NULL || strcmp(ext, ".rb")) { - printf("List command only supports .rb file.\n"); - return MRB_DEBUG_INVALID_ARGUMENT; - } - - if (line_min > line_max) { - return MRB_DEBUG_INVALID_ARGUMENT; - } - - if ((file = source_file_new(mrb, dbg, filename)) != NULL) { - show_lines(file, line_min, line_max); - source_file_free(mrb, file); - return MRB_DEBUG_OK; - } - else { - printf("Invalid source file named %s.\n", filename); - return MRB_DEBUG_INVALID_ARGUMENT; - } -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -/* - * apilist.h - */ - -#ifndef APILIST_H_ -#define APILIST_H_ - -#include "mruby.h" -#include "mrdb.h" - -int32_t mrb_debug_list(mrb_state *, mrb_debug_context *, char *, uint16_t, uint16_t); -char* mrb_debug_get_source(mrb_state *, mrdb_state *, const char *, const char *); - -#endif /* APILIST_H_ */ diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -/* -** apiprint.c -** -*/ - -#include -#include "mrdb.h" -#include "mruby/value.h" -#include "mruby/class.h" -#include "mruby/compile.h" -#include "mruby/error.h" -#include "mruby/numeric.h" -#include "mruby/string.h" -#include "apiprint.h" - -static void -mrdb_check_syntax(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len) -{ - mrbc_context *c; - - c = mrbc_context_new(mrb); - c->no_exec = TRUE; - c->capture_errors = TRUE; - c->filename = (char*)dbg->prvfile; - c->lineno = dbg->prvline; - - /* Load program */ - mrb_load_nstring_cxt(mrb, expr, len, c); - - mrbc_context_free(mrb, c); -} - -mrb_value -mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len, mrb_bool *exc) -{ - void (*tmp)(struct mrb_state *, struct mrb_irep *, mrb_code *, mrb_value *); - mrb_value ruby_code; - mrb_value s; - mrb_value v; - mrb_value recv; - - /* disable code_fetch_hook */ - tmp = mrb->code_fetch_hook; - mrb->code_fetch_hook = NULL; - - mrdb_check_syntax(mrb, dbg, expr, len); - if (mrb->exc) { - v = mrb_obj_value(mrb->exc); - mrb->exc = 0; - } - else { - /* - * begin - * expr - * rescue => e - * e - * end - */ - ruby_code = mrb_str_new_lit(mrb, "begin\n"); - ruby_code = mrb_str_cat(mrb, ruby_code, expr, len); - ruby_code = mrb_str_cat_lit(mrb, ruby_code, "\nrescue => e\ne\nend"); - - recv = dbg->regs[0]; - - v = mrb_funcall(mrb, recv, "instance_eval", 1, ruby_code); - } - - if (exc) { - *exc = mrb_obj_is_kind_of(mrb, v, mrb->eException_class); - } - - s = mrb_funcall(mrb, v, "inspect", 0); - - /* enable code_fetch_hook */ - mrb->code_fetch_hook = tmp; - - return s; -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -/* - * apiprint.h - */ - -#ifndef APIPRINT_H_ -#define APIPRINT_H_ - -#include "mruby.h" -#include "mrdb.h" - -mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*); - -#endif /* APIPRINT_H_ */ diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,428 +0,0 @@ -/* -** cmdbreak.c -** -*/ - -#include -#include -#include "mruby.h" -#include "mruby/dump.h" -#include "mruby/debug.h" -#include "mruby/string.h" -#include "mrdb.h" -#include "mrdberror.h" -#include "apibreak.h" - -#define BREAK_SET_MSG_LINE "Breakpoint %d: file %s, line %d.\n" -#define BREAK_SET_MSG_METHOD "Breakpoint %d: method %s.\n" -#define BREAK_SET_MSG_CLASS_METHOD "Breakpoint %d: class %s, method %s.\n" -#define BREAK_INFO_MSG_HEADER "Num Type Enb What" -#define BREAK_INFO_MSG_LINEBREAK "%-8ubreakpoint %s at %s:%u\n" -#define BREAK_INFO_MSG_METHODBREAK "%-8ubreakpoint %s in %s:%s\n" -#define BREAK_INFO_MSG_METHODBREAK_NOCLASS "%-8ubreakpoint %s in %s\n" -#define BREAK_INFO_MSG_ENABLE "y" -#define BREAK_INFO_MSG_DISABLE "n" - -#define BREAK_ERR_MSG_INVALIDARG "Internal error." -#define BREAK_ERR_MSG_BLANK "Try \'help break\' for more information." -#define BREAK_ERR_MSG_RANGEOVER "The line number range is from 1 to 65535." -#define BREAK_ERR_MSG_NUMOVER "Exceeded the setable number of breakpoint." -#define BREAK_ERR_MSG_NOOVER "Breakno is over the available number.Please 'quit' and restart mrdb." -#define BREAK_ERR_MSG_INVALIDSTR "String \'%s\' is invalid.\n" -#define BREAK_ERR_MSG_INVALIDLINENO "Line %d in file \"%s\" is unavailable.\n" -#define BREAK_ERR_MSG_INVALIDCLASS "Class name \'%s\' is invalid.\n" -#define BREAK_ERR_MSG_INVALIDMETHOD "Method name \'%s\' is invalid.\n" -#define BREAK_ERR_MSG_INVALIDFILE "Source file named \"%s\" is unavailable.\n" -#define BREAK_ERR_MSG_INVALIDBPNO "warning: bad breakpoint number at or near '%s'\n" -#define BREAK_ERR_MSG_INVALIDBPNO_INFO "Args must be numbers variables." -#define BREAK_ERR_MSG_NOBPNO "No breakpoint number %d.\n" -#define BREAK_ERR_MSG_NOBPNO_INFO "No breakpoint matching '%d'\n" -#define BREAK_ERR_MSG_NOBPNO_INFOALL "No breakpoints." - -#define LINENO_MAX_DIGIT 6 -#define BPNO_LETTER_NUM 9 - -typedef int32_t (*all_command_func)(mrb_state *, mrb_debug_context *); -typedef int32_t (*select_command_func)(mrb_state *, mrb_debug_context *, uint32_t); - -static void -print_api_common_error(int32_t error) -{ - switch(error) { - case MRB_DEBUG_INVALID_ARGUMENT: - puts(BREAK_ERR_MSG_INVALIDARG); - break; - default: - break; - } -} - -#undef STRTOUL -#define STRTOUL(ul,s) { \ - int i; \ - ul = 0; \ - for(i=0; ISDIGIT(s[i]); i++) ul = 10*ul + (s[i] -'0'); \ -} - -static int32_t -parse_breakpoint_no(char* args) -{ - char* ps = args; - uint32_t l; - - if((*ps == '0')||(strlen(ps) >= BPNO_LETTER_NUM)) { - return 0; - } - - while( !(ISBLANK(*ps)||ISCNTRL(*ps)) ) { - if(!ISDIGIT(*ps)) { - return 0; - } - ps++; - } - - STRTOUL(l, args); - return l; -} - -static mrb_bool -exe_set_command_all(mrb_state *mrb, mrdb_state *mrdb, all_command_func func) -{ - int32_t ret = MRB_DEBUG_OK; - - if(mrdb->wcnt == 1) { - ret = func(mrb, mrdb->dbg); - print_api_common_error(ret); - return TRUE; - } - return FALSE; -} - -static void -exe_set_command_select(mrb_state *mrb, mrdb_state *mrdb, select_command_func func) -{ - char* ps; - int32_t ret = MRB_DEBUG_OK; - int32_t bpno = 0; - int32_t i; - - for(i=1; iwcnt; i++) { - ps = mrdb->words[i]; - bpno = parse_breakpoint_no(ps); - if(bpno == 0) { - printf(BREAK_ERR_MSG_INVALIDBPNO, ps); - break; - } - ret = func(mrb, mrdb->dbg, (uint32_t)bpno); - if(ret == MRB_DEBUG_BREAK_INVALID_NO) { - printf(BREAK_ERR_MSG_NOBPNO, bpno); - } - else if(ret != MRB_DEBUG_OK) { - print_api_common_error(ret); - } - } -} - -mrb_debug_bptype -check_bptype(char* args) -{ - char* ps = args; - - if(ISBLANK(*ps)||ISCNTRL(*ps)) { - puts(BREAK_ERR_MSG_BLANK); - return MRB_DEBUG_BPTYPE_NONE; - } - - if(!ISDIGIT(*ps)) { - return MRB_DEBUG_BPTYPE_METHOD; - } - - while( !(ISBLANK(*ps)||ISCNTRL(*ps)) ) { - if(!ISDIGIT(*ps)) { - printf(BREAK_ERR_MSG_INVALIDSTR, args); - return MRB_DEBUG_BPTYPE_NONE; - } - ps++; - } - - if((*args == '0')||(strlen(args) >= LINENO_MAX_DIGIT)) { - puts(BREAK_ERR_MSG_RANGEOVER); - return MRB_DEBUG_BPTYPE_NONE; - } - - return MRB_DEBUG_BPTYPE_LINE; -} - -static void -print_breakpoint(mrb_debug_breakpoint *bp) -{ - const char* enable_letter[] = {BREAK_INFO_MSG_DISABLE, BREAK_INFO_MSG_ENABLE}; - - if(bp->type == MRB_DEBUG_BPTYPE_LINE) { - printf(BREAK_INFO_MSG_LINEBREAK, - bp->bpno, enable_letter[bp->enable], bp->point.linepoint.file, bp->point.linepoint.lineno); - } - else { - if(bp->point.methodpoint.class_name == NULL) { - printf(BREAK_INFO_MSG_METHODBREAK_NOCLASS, - bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.method_name); - } - else { - printf(BREAK_INFO_MSG_METHODBREAK, - bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.class_name, bp->point.methodpoint.method_name); - } - } -} - -static void -info_break_all(mrb_state *mrb, mrdb_state *mrdb) -{ - int32_t bpnum = 0; - int32_t i = 0; - int32_t ret = MRB_DEBUG_OK; - mrb_debug_breakpoint *bp_list; - - bpnum = mrb_debug_get_breaknum(mrb, mrdb->dbg); - if(bpnum < 0) { - print_api_common_error(bpnum); - return; - } - else if(bpnum == 0) { - puts(BREAK_ERR_MSG_NOBPNO_INFOALL); - return; - } - bp_list = (mrb_debug_breakpoint*)mrb_malloc(mrb, bpnum * sizeof(mrb_debug_breakpoint)); - - ret = mrb_debug_get_break_all(mrb, mrdb->dbg, (uint32_t)bpnum, bp_list); - if(ret < 0) { - print_api_common_error(ret); - return; - } - puts(BREAK_INFO_MSG_HEADER); - for(i = 0 ; i < bpnum ; i++) { - print_breakpoint(&bp_list[i]); - } - - mrb_free(mrb, bp_list); -} - -static void -info_break_select(mrb_state *mrb, mrdb_state *mrdb) -{ - int32_t ret = MRB_DEBUG_OK; - int32_t bpno = 0; - char* ps = mrdb->command; - mrb_debug_breakpoint bp; - mrb_bool isFirst = TRUE; - int32_t i; - - for(i=2; iwcnt; i++) { - ps = mrdb->words[i]; - bpno = parse_breakpoint_no(ps); - if(bpno == 0) { - puts(BREAK_ERR_MSG_INVALIDBPNO_INFO); - break; - } - - ret = mrb_debug_get_break(mrb, mrdb->dbg, bpno, &bp); - if(ret == MRB_DEBUG_BREAK_INVALID_NO) { - printf(BREAK_ERR_MSG_NOBPNO_INFO, bpno); - break; - } - else if(ret != MRB_DEBUG_OK) { - print_api_common_error(ret); - break; - } - else if(isFirst == TRUE) { - isFirst = FALSE; - puts(BREAK_INFO_MSG_HEADER); - } - print_breakpoint(&bp); - } -} - -mrb_debug_bptype -parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method) -{ - mrb_debug_context *dbg = mrdb->dbg; - char *args; - char *body; - mrb_debug_bptype type; - uint32_t l; - - if(mrdb->wcnt <= 1) { - puts(BREAK_ERR_MSG_BLANK); - return MRB_DEBUG_BPTYPE_NONE; - } - - args = mrdb->words[1]; - if((body = strrchr(args, ':')) == NULL) { - body = args; - type = check_bptype(body); - } else { - if(body == args) { - printf(BREAK_ERR_MSG_INVALIDSTR, args); - return MRB_DEBUG_BPTYPE_NONE; - } - *body = '\0'; - type = check_bptype(++body); - } - - switch(type) { - case MRB_DEBUG_BPTYPE_LINE: - STRTOUL(l, body); - if( l <= 65535 ) { - *line = l; - *file = (body == args)? mrb_debug_get_filename(dbg->irep, (uint32_t)(dbg->pc - dbg->irep->iseq)): args; - } else { - puts(BREAK_ERR_MSG_RANGEOVER); - type = MRB_DEBUG_BPTYPE_NONE; - } - break; - case MRB_DEBUG_BPTYPE_METHOD: - if(body == args) { - /* method only */ - if( ISUPPER(*body)||ISLOWER(*body)||(*body == '_') ) { - *method = body; - *cname = NULL; - } else { - printf(BREAK_ERR_MSG_INVALIDMETHOD, args); - type = MRB_DEBUG_BPTYPE_NONE; - } - } else { - if( ISUPPER(*args) ) { - switch(*body) { - case '@': case '$': case '?': case '.': case ',': case ':': - case ';': case '#': case '\\': case '\'': case '\"': - printf(BREAK_ERR_MSG_INVALIDMETHOD, body); - type = MRB_DEBUG_BPTYPE_NONE; - break; - default: - *method = body; - *cname = args; - break; - } - } else { - printf(BREAK_ERR_MSG_INVALIDCLASS, args); - type = MRB_DEBUG_BPTYPE_NONE; - } - } - break; - case MRB_DEBUG_BPTYPE_NONE: - default: - break; - } - - return type; -} - -dbgcmd_state -dbgcmd_break(mrb_state *mrb, mrdb_state *mrdb) -{ - mrb_debug_bptype type; - mrb_debug_context *dbg = mrdb->dbg; - const char *file = NULL; - uint32_t line = 0; - char *cname = NULL; - char *method = NULL; - int32_t ret; - - type = parse_breakcommand(mrdb, &file, &line, &cname, &method); - switch (type) { - case MRB_DEBUG_BPTYPE_LINE: - ret = mrb_debug_set_break_line(mrb, dbg, file, line); - break; - case MRB_DEBUG_BPTYPE_METHOD: - ret = mrb_debug_set_break_method(mrb, dbg, cname, method); - break; - case MRB_DEBUG_BPTYPE_NONE: - default: - return DBGST_PROMPT; - } - - if (ret >= 0) { - if (type == MRB_DEBUG_BPTYPE_LINE) { - printf(BREAK_SET_MSG_LINE, ret, file, line); - } else if ((type == MRB_DEBUG_BPTYPE_METHOD)&&(cname == NULL)) { - printf(BREAK_SET_MSG_METHOD, ret, method); - } else { - printf(BREAK_SET_MSG_CLASS_METHOD, ret, cname, method); - } - } else { - switch (ret) { - case MRB_DEBUG_BREAK_INVALID_LINENO: - printf(BREAK_ERR_MSG_INVALIDLINENO, line, file); - break; - case MRB_DEBUG_BREAK_INVALID_FILE: - printf(BREAK_ERR_MSG_INVALIDFILE, file); - break; - case MRB_DEBUG_BREAK_NUM_OVER: - puts(BREAK_ERR_MSG_NUMOVER); - break; - case MRB_DEBUG_BREAK_NO_OVER: - puts(BREAK_ERR_MSG_NOOVER); - break; - case MRB_DEBUG_INVALID_ARGUMENT: - puts(BREAK_ERR_MSG_INVALIDARG); - break; - case MRB_DEBUG_NOBUF: - puts("T.B.D."); - break; - default: - break; - } - } - - return DBGST_PROMPT; -} - -dbgcmd_state -dbgcmd_info_break(mrb_state *mrb, mrdb_state *mrdb) -{ - if(mrdb->wcnt == 2) { - info_break_all(mrb, mrdb); - } - else { - info_break_select(mrb, mrdb); - } - - return DBGST_PROMPT; -} - -dbgcmd_state -dbgcmd_delete(mrb_state *mrb, mrdb_state *mrdb) -{ - mrb_bool ret = FALSE; - - ret = exe_set_command_all(mrb, mrdb, mrb_debug_delete_break_all); - if(ret != TRUE) { - exe_set_command_select(mrb, mrdb, mrb_debug_delete_break); - } - - return DBGST_PROMPT; -} - -dbgcmd_state -dbgcmd_enable(mrb_state *mrb, mrdb_state *mrdb) -{ - mrb_bool ret = FALSE; - - ret = exe_set_command_all(mrb, mrdb, mrb_debug_enable_break_all); - if(ret != TRUE) { - exe_set_command_select(mrb, mrdb, mrb_debug_enable_break); - } - - return DBGST_PROMPT; -} - -dbgcmd_state -dbgcmd_disable(mrb_state *mrb, mrdb_state *mrdb) -{ - mrb_bool ret = FALSE; - - ret = exe_set_command_all(mrb, mrdb, mrb_debug_disable_break_all); - if(ret != TRUE) { - exe_set_command_select(mrb, mrdb, mrb_debug_disable_break); - } - return DBGST_PROMPT; -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,501 +0,0 @@ -/* -** cmdmisc.c - mruby debugger miscellaneous command functions -** -*/ - -#include -#include -#include - -#include "apilist.h" -#include "mruby/compile.h" - -typedef struct help_msg { - const char *cmd1; - const char *cmd2; - const char *short_msg; - const char *long_msg; -} help_msg; - -static help_msg help_msg_list[] = { - { - "b[reak]", NULL, "Set breakpoint", - "Usage: break [file:]line\n" - " break [class:]method\n" - "\n" - "Set breakpoint at specified line or method.\n" - "If \'[file:]line\' is specified, break at start of code for that line (in a file).\n" - "If \'[class:]method\' is specified, break at start of code for that method (of the class).\n" - }, - { - "c[ontinue]", NULL, "Continue program being debugged", - "Usage: continue [N]\n" - "\n" - "Continue program stopped by a breakpoint.\n" - "If N, which is non negative value, is passed,\n" - "proceed program until the N-th breakpoint is coming.\n" - "If N is not passed, N is assumed 1.\n" - }, - { - "d[elete]", NULL, "Delete some breakpoints", - "Usage: delete [bpno1 [bpno2 [... [bpnoN]]]]\n" - "\n" - "Delete some breakpoints.\n" - "Arguments are breakpoint numbers with spaces in between.\n" - "To delete all breakpoints, give no argument.\n" - }, - { - "dis[able]", NULL, "Disable some breakpoints", - "Usage: disable [bpno1 [bpno2 [... [bpnoN]]]]\n" - "\n" - "Disable some breakpoints.\n" - "Arguments are breakpoint numbers with spaces in between.\n" - "To disable all breakpoints, give no argument.\n" - }, - { - "en[able]", NULL, "Enable some breakpoints", - "Usage: enable [bpno1 [bpno2 [... [bpnoN]]]]\n" - "\n" - "Enable some breakpoints.\n" - "Arguments are breakpoint numbers with spaces in between.\n" - "To enable all breakpoints, give no argument.\n" - }, - { - "ev[al]", NULL, "Evaluate expression", - "Usage: eval expr\n" - "\n" - "It evaluates and prints the value of the mruby expression.\n" - "This is equivalent to the \'print\' command.\n" - }, - { - "h[elp]", NULL, "Print this help", - "Usage: help [command]\n" - "\n" - "With no arguments, help displays a short list of commands.\n" - "With a command name as help argument, help displays how to use that command.\n" - }, - { - "i[nfo]", "b[reakpoints]", "Status of breakpoints", - "Usage: info breakpoints [bpno1 [bpno2 [... [bpnoN]]]]\n" - "\n" - "Status of specified breakpoints (all user-settable breakpoints if no argument).\n" - "Arguments are breakpoint numbers with spaces in between.\n" - }, - { - "l[ist]", NULL, "List specified line", - "Usage: list\n" - " list first[,last]\n" - " list filename:first[,last]\n" - "\n" - "Print lines from a source file.\n" - "\n" - "With first and last, list prints lines from first to last.\n" - "When last is empty, it stands for ten lines away from first.\n" - "With filename, list prints lines in the specified source file.\n" - }, - { - "p[rint]", NULL, "Print value of expression", - "Usage: print expr\n" - "\n" - "It evaluates and prints the value of the mruby expression.\n" - "This is equivalent to the \'eval\' command.\n" - }, - { - "q[uit]", NULL, "Exit mrdb", - "Usage: quit\n" - "\n" - "Exit mrdb.\n" - }, - { - "r[un]", NULL, "Start debugged program", - "Usage: run\n" - "\n" - "Start debugged program.\n" - }, - { - "s[tep]", NULL, "Step program until it reaches a different source line", - "Usage: step\n" - "\n" - "Step program until it reaches a different source line.\n" - }, - { NULL, NULL, NULL, NULL } -}; - -typedef struct listcmd_parser_state { - mrb_bool parse_error; - mrb_bool has_line_min; - mrb_bool has_line_max; - char *filename; - uint16_t line_min; - uint16_t line_max; -} listcmd_parser_state; - -static listcmd_parser_state* -listcmd_parser_state_new(mrb_state *mrb) -{ - listcmd_parser_state *st = mrb_malloc(mrb, sizeof(listcmd_parser_state)); - memset(st, 0, sizeof(listcmd_parser_state)); - return st; -} - -static void -listcmd_parser_state_free(mrb_state *mrb, listcmd_parser_state *st) -{ - if (st != NULL) { - if (st->filename != NULL) { - mrb_free(mrb, st->filename); - } - mrb_free(mrb, st); - } -} - -static mrb_bool -parse_uint(char **sp, uint16_t *n) -{ - char *p; - int i; - - if (*sp == NULL || **sp == '\0') { - return FALSE; - } - - for (p = *sp; *p != '\0' && ISDIGIT(*p); p++) ; - - if (p != *sp && (i = atoi(*sp)) >= 0) { - *n = (uint16_t)i; - *sp = p; - return TRUE; - } - return FALSE; -} - -static mrb_bool -skip_char(char **sp, char c) -{ - if (*sp != NULL && **sp == c) { - ++*sp; - return TRUE; - } - return FALSE; -} - -static mrb_bool -parse_lineno(mrb_state *mrb, char **sp, listcmd_parser_state *st) -{ - if (*sp == NULL || **sp == '\0') { - return FALSE; - } - - st->has_line_min = FALSE; - st->has_line_max = FALSE; - - if (parse_uint(sp, &st->line_min)) { - st->has_line_min = TRUE; - } - else { - return FALSE; - } - - if (skip_char(sp, ',')) { - if (parse_uint(sp, &st->line_max)) { - st->has_line_max = TRUE; - } - else { - st->parse_error = TRUE; - return FALSE; - } - } - return TRUE; -} - -static mrb_bool -parse_filename(mrb_state *mrb, char **sp, listcmd_parser_state *st) -{ - char *p; - int len; - - if (st->filename != NULL) { - mrb_free(mrb, st->filename); - st->filename = NULL; - } - - if ((p = strchr(*sp, ':')) != NULL) { - len = p - *sp; - } - else { - len = strlen(*sp); - } - - if (len > 0) { - st->filename = mrb_malloc(mrb, len + 1); - strncpy(st->filename, *sp, len); - st->filename[len] = '\0'; - *sp += len; - return TRUE; - } - else { - return FALSE; - } -} - -char* -replace_ext(mrb_state *mrb, const char *filename, const char *ext) -{ - size_t len; - char *p, *s; - - if (filename == NULL) { - return NULL; - } - - if ((p = strrchr(filename, '.')) != NULL && strchr(p, '/') == NULL) { - len = p - filename; - } - else { - len = strlen(filename); - } - - s = mrb_malloc(mrb, len + strlen(ext) + 1); - memset(s, '\0', len + strlen(ext) + 1); - strncpy(s, filename, len); - strcat(s, ext); - - return s; -} - -static mrb_bool -parse_listcmd_args(mrb_state *mrb, mrdb_state *mrdb, listcmd_parser_state *st) -{ - char *p; - - switch (mrdb->wcnt) { - case 2: - p = mrdb->words[1]; - - /* mrdb->words[1] ::= | ':' | */ - if (!parse_lineno(mrb, &p, st)) { - if (parse_filename(mrb, &p, st)) { - if (skip_char(&p, ':')) { - if (!parse_lineno(mrb, &p, st)) { - st->parse_error = TRUE; - } - } - } - else { - st->parse_error = TRUE; - } - } - if (*p != '\0') { - st->parse_error = TRUE; - } - break; - case 1: - case 0: - /* do nothing */ - break; - default: - st->parse_error = TRUE; - printf("too many arguments\n"); - break; - } - - if (!st->parse_error) { - if (!st->has_line_min) { - st->line_min = (!st->filename && mrdb->dbg->prvline > 0) ? mrdb->dbg->prvline : 1; - } - - if (!st->has_line_max) { - st->line_max = st->line_min + 9; - } - - if (st->filename == NULL) { - if (mrdb->dbg->prvfile && strcmp(mrdb->dbg->prvfile, "-")) { - st->filename = replace_ext(mrb, mrdb->dbg->prvfile, ".rb"); - } - } - } - - if (st->parse_error || st->filename == NULL) { - return FALSE; - } - - return TRUE; -} - -static mrb_bool -check_cmd_pattern(const char *pattern, const char *cmd) -{ - char *lbracket, *rbracket, *p, *q; - - if (pattern == NULL && cmd == NULL) { - return TRUE; - } - if (pattern == NULL || cmd == NULL) { - return FALSE; - } - if((lbracket = strchr(pattern, '[')) == NULL) { - return !strcmp(pattern, cmd); - } - if ((rbracket = strchr(pattern, ']')) == NULL) { - return FALSE; - } - if (strncmp(pattern, cmd, lbracket - pattern)) { - return FALSE; - } - - p = lbracket + 1; - q = (char *)cmd + (lbracket - pattern); - - for ( ; p < rbracket && *q != '\0'; p++, q++) { - if (*p != *q) { - break; - } - } - return *q == '\0'; -} - -static help_msg* -get_help_msg(char *cmd1, char *cmd2) -{ - help_msg *p; - - if (cmd1 == NULL) { - return NULL; - } - for (p = help_msg_list; p->cmd1 != NULL; p++) { - if (check_cmd_pattern(p->cmd1, cmd1) && check_cmd_pattern(p->cmd2, cmd2)) { - return p; - } - } - return NULL; -} - -static mrb_bool -show_short_help(void) -{ - help_msg *p; - - printf("Commands\n"); - - for (p = help_msg_list; p->cmd1 != NULL; p++) { - if (p->cmd2 == NULL) { - printf(" %s -- %s\n", p->cmd1, p->short_msg); - } - else { - printf(" %s %s -- %s\n", p->cmd1, p->cmd2, p->short_msg); - } - } - return TRUE; -} - -static mrb_bool -show_long_help(char *cmd1, char *cmd2) -{ - help_msg *help; - - if ((help = get_help_msg(cmd1, cmd2)) == NULL) { - return FALSE; - } - printf("%s", help->long_msg); - return TRUE; -} - -dbgcmd_state -dbgcmd_list(mrb_state *mrb, mrdb_state *mrdb) -{ - char *filename; - listcmd_parser_state *st = listcmd_parser_state_new(mrb); - - if (parse_listcmd_args(mrb, mrdb, st)) { - if ((filename = mrb_debug_get_source(mrb, mrdb, mrdb->srcpath, st->filename)) == NULL) { - filename = st->filename; - } - mrb_debug_list(mrb, mrdb->dbg, filename, st->line_min, st->line_max); - - if (filename != NULL && filename != st->filename) { - mrb_free(mrb, filename); - } - listcmd_parser_state_free(mrb, st); - } - - return DBGST_PROMPT; -} - -dbgcmd_state -dbgcmd_help(mrb_state *mrb, mrdb_state *mrdb) -{ - mrb_bool is_valid; - int i; - - switch (mrdb->wcnt) { - case 0: - case 1: - is_valid = show_short_help(); - break; - case 2: - is_valid = show_long_help(mrdb->words[1], NULL); - break; - case 3: - is_valid = show_long_help(mrdb->words[1], mrdb->words[2]); - break; - default: - is_valid = FALSE; - break; - } - - if (!is_valid) { - printf("Invalid command \""); - for (i = 1; i < mrdb->wcnt; i++) { - printf("%s%s", i == 1 ? "" : " ", mrdb->words[i]); - } - printf("\". Try \"help\".\n"); - } - - return DBGST_PROMPT; -} - -dbgcmd_state -dbgcmd_quit(mrb_state *mrb, mrdb_state *mrdb) -{ - switch (mrdb->dbg->xm) { - case DBG_RUN: - case DBG_STEP: - case DBG_NEXT: - while (1) { - char c; - int buf; - - printf("The program is running. Exit anyway? (y or n) "); - fflush(stdout); - - if ((buf = getchar()) == EOF) { - mrdb->dbg->xm = DBG_QUIT; - break; - } - c = buf; - while (buf != '\n' && (buf = getchar()) != EOF) ; - - if (c == 'y' || c == 'Y') { - mrdb->dbg->xm = DBG_QUIT; - break; - } - else if (c == 'n' || c == 'N') { - break; - } - else { - printf("Please answer y or n.\n"); - } - } - break; - default: - mrdb->dbg->xm = DBG_QUIT; - break; - } - - if (mrdb->dbg->xm == DBG_QUIT) { - struct RClass *exc; - exc = mrb_define_class(mrb, "DebuggerExit", mrb_class_get(mrb, "Exception")); - mrb_raise(mrb, exc, "Exit mrdb."); - } - return DBGST_PROMPT; -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -/* -** cmdprint.c - mruby debugger print command functions -** -*/ - -#include -#include "mrdb.h" -#include "mruby/value.h" -#include "mruby/class.h" -#include "mruby/compile.h" -#include "mruby/error.h" -#include "mruby/numeric.h" -#include "mruby/string.h" -#include "apiprint.h" - -dbgcmd_state -dbgcmd_print(mrb_state *mrb, mrdb_state *mrdb) -{ - mrb_value expr; - mrb_value result; - mrb_value s; - uint8_t wcnt; - int ai; - - if (mrdb->wcnt <= 1) { - puts("Parameter not specified."); - return DBGST_PROMPT; - } - - ai = mrb_gc_arena_save(mrb); - - /* eval expr */ - expr = mrb_str_new_cstr(mrb, NULL); - for (wcnt=1; wcntwcnt; wcnt++) { - expr = mrb_str_cat_lit(mrb, expr, " "); - expr = mrb_str_cat_cstr(mrb, expr, mrdb->words[wcnt]); - } - - result = mrb_debug_eval(mrb, mrdb->dbg, RSTRING_PTR(expr), RSTRING_LEN(expr), NULL); - - /* $print_no = result */ - s = mrb_str_cat_lit(mrb, result, "\0"); - printf("$%lu = %s\n", (unsigned long)mrdb->print_no++, RSTRING_PTR(s)); - - if (mrdb->print_no == 0) { - mrdb->print_no = 1; - } - - mrb_gc_arena_restore(mrb, ai); - - return DBGST_PROMPT; -} - -dbgcmd_state -dbgcmd_eval(mrb_state *mrb, mrdb_state *mrdb) -{ - return dbgcmd_print(mrb, mrdb); -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/* -** cmdrun.c - mruby debugger run command functions -** -*/ - -#include "mruby/opcode.h" -#include "mrdb.h" - -dbgcmd_state -dbgcmd_run(mrb_state *mrb, mrdb_state *mrdb) -{ - mrb_debug_context *dbg = mrdb->dbg; - - if( dbg->xm == DBG_INIT ){ - dbg->xm = DBG_RUN; - } else { - dbg->xm = DBG_QUIT; - if( dbg->xphase == DBG_PHASE_RUNNING ){ - struct RClass *exc; - puts("Start it from the beginning."); - exc = mrb_define_class(mrb, "DebuggerRestart", mrb_class_get(mrb, "Exception")); - mrb_raise(mrb, exc, "Restart mrdb."); - } - } - - return DBGST_RESTART; -} - -dbgcmd_state -dbgcmd_continue(mrb_state *mrb, mrdb_state *mrdb) -{ - mrb_debug_context *dbg = mrdb->dbg; - int ccnt = 1; - - if( mrdb->wcnt > 1 ){ - sscanf(mrdb->words[1], "%d", &ccnt); - } - dbg->ccnt = (uint16_t)(ccnt > 0 ? ccnt : 1); /* count of continue */ - - if( dbg->xphase == DBG_PHASE_AFTER_RUN ){ - puts("The program is not running."); - dbg->xm = DBG_QUIT; - } else { - dbg->xm = DBG_RUN; - } - return DBGST_CONTINUE; -} - -dbgcmd_state -dbgcmd_step(mrb_state *mrb, mrdb_state *mrdb) -{ - mrdb->dbg->xm = DBG_STEP; - return DBGST_CONTINUE; -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,746 +0,0 @@ -/* -** mrdb.c - mruby debugger -** -*/ - -#include -#include -#include -#include - -#include "mruby.h" -#include "mruby/dump.h" -#include "mruby/debug.h" -#include "mruby/class.h" -#include "mruby/opcode.h" -#include "mruby/variable.h" - -#include "mrdb.h" -#include "apibreak.h" -#include "apilist.h" - -void mrdb_state_free(mrb_state *); - -static mrb_debug_context *_debug_context = NULL; -static mrdb_state *_mrdb_state = NULL; - -struct _args { - FILE *rfp; - char* fname; - char* srcpath; - int argc; - char** argv; - mrb_bool mrbfile : 1; -}; - -typedef struct debug_command { - const char *cmd1; - const char *cmd2; - uint8_t len1; - uint8_t len2; - uint8_t div; - debug_command_id id; - debug_command_func func; -} debug_command; - -static const debug_command debug_command_list[] = { - {"break", NULL, 1, 0, 0, DBGCMD_BREAK, dbgcmd_break}, /* b[reak] */ - {"continue", NULL, 1, 0, 0, DBGCMD_CONTINUE, dbgcmd_continue}, /* c[ontinue] */ - {"delete", NULL, 1, 0, 1, DBGCMD_DELETE, dbgcmd_delete}, /* d[elete] */ - {"disable", NULL, 3, 0, 1, DBGCMD_DISABLE, dbgcmd_disable}, /* dis[able] */ - {"enable", NULL, 2, 0, 1, DBGCMD_ENABLE, dbgcmd_enable}, /* en[able] */ - {"eval", NULL, 2, 0, 0, DBGCMD_EVAL, dbgcmd_eval}, /* ev[al] */ - {"help", NULL, 1, 0, 1, DBGCMD_HELP, dbgcmd_help}, /* h[elp] */ - {"info", "breakpoints", 1, 1, 1, DBGCMD_INFO_BREAK, dbgcmd_info_break}, /* i[nfo] b[reakpoints] */ - {"list", NULL, 1, 0, 1, DBGCMD_LIST, dbgcmd_list}, /* l[ist] */ - {"print", NULL, 1, 0, 0, DBGCMD_PRINT, dbgcmd_print}, /* p[rint] */ - {"quit", NULL, 1, 0, 0, DBGCMD_QUIT, dbgcmd_quit}, /* q[uit] */ - {"run", NULL, 1, 0, 0, DBGCMD_RUN, dbgcmd_run}, /* r[un] */ - {"step", NULL, 1, 0, 1, DBGCMD_STEP, dbgcmd_step}, /* s[tep] */ - {NULL} -}; - - -static void -usage(const char *name) -{ - static const char *const usage_msg[] = { - "switches:", - "-b load and execute RiteBinary (mrb) file", - "-d specify source directory", - "--version print the version", - "--copyright print the copyright", - NULL - }; - const char *const *p = usage_msg; - - printf("Usage: %s [switches] programfile\n", name); - while (*p) { - printf(" %s\n", *p++); - } -} - -static int -parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) -{ - char **origargv = argv; - static const struct _args args_zero = { 0 }; - - *args = args_zero; - - for (argc--,argv++; argc > 0; argc--,argv++) { - char *item; - if (argv[0][0] != '-') break; - - item = argv[0] + 1; - switch (*item++) { - case 'b': - args->mrbfile = TRUE; - break; - case 'd': - if (item[0]) { - goto append_srcpath; - } - else if (argc > 1) { - argc--; argv++; - item = argv[0]; -append_srcpath: - if (!args->srcpath) { - size_t buflen; - char *buf; - - buflen = strlen(item) + 1; - buf = (char *)mrb_malloc(mrb, buflen); - memcpy(buf, item, buflen); - args->srcpath = buf; - } - else { - size_t srcpathlen; - size_t itemlen; - - srcpathlen = strlen(args->srcpath); - itemlen = strlen(item); - args->srcpath = - (char *)mrb_realloc(mrb, args->srcpath, srcpathlen + itemlen + 2); - args->srcpath[srcpathlen] = '\n'; - memcpy(args->srcpath + srcpathlen + 1, item, itemlen + 1); - } - } - else { - printf("%s: No path specified for -d\n", *origargv); - return EXIT_SUCCESS; - } - break; - case '-': - if (strcmp((*argv) + 2, "version") == 0) { - mrb_show_version(mrb); - exit(EXIT_SUCCESS); - } - else if (strcmp((*argv) + 2, "copyright") == 0) { - mrb_show_copyright(mrb); - exit(EXIT_SUCCESS); - } - default: - return EXIT_FAILURE; - } - } - - if (args->rfp == NULL) { - if (*argv == NULL) { - printf("%s: Program file not specified.\n", *origargv); - return EXIT_FAILURE; - } - else { - args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r"); - if (args->rfp == NULL) { - printf("%s: Cannot open program file. (%s)\n", *origargv, *argv); - return EXIT_FAILURE; - } - args->fname = argv[0]; - argc--; argv++; - } - } - args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1)); - memcpy(args->argv, argv, (argc+1) * sizeof(char*)); - args->argc = argc; - - return EXIT_SUCCESS; -} - -static void -cleanup(mrb_state *mrb, struct _args *args) -{ - if (args->rfp) - fclose(args->rfp); - if (args->srcpath) - mrb_free(mrb, args->srcpath); - if (args->argv) - mrb_free(mrb, args->argv); - mrdb_state_free(mrb); - mrb_close(mrb); -} - -static mrb_debug_context* -mrb_debug_context_new(mrb_state *mrb) -{ - mrb_debug_context *dbg = mrb_malloc(mrb, sizeof(mrb_debug_context)); - - memset(dbg, 0, sizeof(mrb_debug_context)); - - dbg->xm = DBG_INIT; - dbg->xphase = DBG_PHASE_BEFORE_RUN; - dbg->next_bpno = 1; - - return dbg; -} - -mrb_debug_context* -mrb_debug_context_get(mrb_state *mrb) -{ - if (!_debug_context) { - _debug_context = mrb_debug_context_new(mrb); - } - return _debug_context; -} - -void -mrb_debug_context_set(mrb_debug_context *dbg) -{ - _debug_context = dbg; -} - -void -mrb_debug_context_free(mrb_state *mrb) -{ - if (_debug_context) { - mrb_debug_delete_break_all(mrb, _debug_context); - mrb_free(mrb, _debug_context); - _debug_context = NULL; - } -} - -static mrdb_state* -mrdb_state_new(mrb_state *mrb) -{ - mrdb_state *mrdb = mrb_malloc(mrb, sizeof(mrdb_state)); - - memset(mrdb, 0, sizeof(mrdb_state)); - - mrdb->dbg = mrb_debug_context_get(mrb); - mrdb->command = mrb_malloc(mrb, MAX_COMMAND_LINE+1); - mrdb->print_no = 1; - - return mrdb; -} - -mrdb_state* -mrdb_state_get(mrb_state *mrb) -{ - if (!_mrdb_state) { - _mrdb_state = mrdb_state_new(mrb); - } - return _mrdb_state; -} - -void -mrdb_state_set(mrdb_state *mrdb) -{ - _mrdb_state = mrdb; -} - -void -mrdb_state_free(mrb_state *mrb) -{ - mrb_debug_context_free(mrb); - if (_mrdb_state) { - mrb_free(mrb, _mrdb_state->command); - mrb_free(mrb, _mrdb_state); - _mrdb_state = NULL; - } -} - -static char* -get_command(mrb_state *mrb, mrdb_state *mrdb) -{ - int i; - int c; - - for (i=0; icommand[i] = c; - } - - if (i == 0 && feof(stdin)) { - clearerr(stdin); - strcpy(mrdb->command, "quit"); - i += sizeof("quit") - 1; - } - - if (i == MAX_COMMAND_LINE) { - for ( ; (c=getchar()) != EOF && c !='\n'; i++) ; - } - - if (i > MAX_COMMAND_LINE) { - printf("command line too long.\n"); - i = 0; /* discard command data */ - } - mrdb->command[i] = '\0'; - - return mrdb->command; -} - -static char* -pick_out_word(mrb_state *mrb, char **pp) -{ - char *ps; - - for (ps=*pp; ISBLANK(*ps); ps++) ; - if (*ps == '\0') { - return NULL; - } - - if (*ps == '\"' || *ps == '\'') { - *pp = strchr(ps+1, *ps); - if (*pp) (*pp)++; - } - else { - *pp = strpbrk(ps, " \t"); - } - - if (!*pp) { - *pp = ps + strlen(ps); - } - - if (**pp != '\0') { - **pp = '\0'; - (*pp)++; - } - - return ps; -} - -static debug_command* -parse_command(mrb_state *mrb, mrdb_state *mrdb, char *buf) -{ - debug_command *cmd = NULL; - char *p = buf; - size_t wlen; - - /* get word #1 */ - mrdb->words[0] = pick_out_word(mrb, &p); - if (!mrdb->words[0]) { - return NULL; - } - mrdb->wcnt = 1; - /* set remain parameter */ - for ( ; *p && ISBLANK(*p); p++) ; - if (*p) { - mrdb->words[mrdb->wcnt++] = p; - } - - /* check word #1 */ - for (cmd=(debug_command*)debug_command_list; cmd->cmd1; cmd++) { - wlen = strlen(mrdb->words[0]); - if (wlen >= cmd->len1 && - strncmp(mrdb->words[0], cmd->cmd1, wlen) == 0) { - break; - } - } - - if (cmd->cmd2) { - if (mrdb->wcnt > 1) { - /* get word #2 */ - mrdb->words[1] = pick_out_word(mrb, &p); - if (mrdb->words[1]) { - /* update remain parameter */ - for ( ; *p && ISBLANK(*p); p++) ; - if (*p) { - mrdb->words[mrdb->wcnt++] = p; - } - } - } - - /* check word #1,#2 */ - for ( ; cmd->cmd1; cmd++) { - wlen = strlen(mrdb->words[0]); - if (wlen < cmd->len1 || - strncmp(mrdb->words[0], cmd->cmd1, wlen)) { - continue; - } - - if (!cmd->cmd2) break; /* word #1 only */ - - if (mrdb->wcnt == 1) continue; /* word #2 not specified */ - - wlen = strlen(mrdb->words[1]); - if (wlen >= cmd->len2 && - strncmp(mrdb->words[1], cmd->cmd2, wlen) == 0) { - break; /* word #1 and #2 */ - } - } - } - - /* divide remain parameters */ - if (cmd->cmd1 && cmd->div) { - p = mrdb->words[--mrdb->wcnt]; - for ( ; mrdb->wcntwcnt++) { - mrdb->words[mrdb->wcnt] = pick_out_word(mrb, &p); - if (!mrdb->words[mrdb->wcnt]) { - break; - } - } - } - - return cmd->cmd1 ? cmd : NULL; -} - -static void -print_info_stopped_break(mrb_state *mrb, mrdb_state *mrdb) -{ - mrb_debug_breakpoint bp; - int32_t ret; - uint16_t lineno; - const char *file; - const char *method_name; - const char *class_name; - - ret = mrb_debug_get_break(mrb, mrdb->dbg, mrdb->dbg->stopped_bpno, &bp); - if(ret == 0) { - switch(bp.type) { - case MRB_DEBUG_BPTYPE_LINE: - file = bp.point.linepoint.file; - lineno = bp.point.linepoint.lineno; - printf("Breakpoint %d, at %s:%d\n", bp.bpno, file, lineno); - break; - case MRB_DEBUG_BPTYPE_METHOD: - method_name = bp.point.methodpoint.method_name; - class_name = bp.point.methodpoint.class_name; - if(class_name == NULL) { - printf("Breakpoint %d, %s\n", bp.bpno, method_name); - } - else { - printf("Breakpoint %d, %s:%s\n", bp.bpno, class_name, method_name); - } - if(mrdb->dbg->isCfunc) { - printf("Stopped before calling the C function.\n"); - } - break; - default: - break; - } - } -} - -static void -print_info_stopped_step_next(mrb_state *mrb, mrdb_state *mrdb) -{ - const char* file = mrdb->dbg->prvfile; - uint16_t lineno = mrdb->dbg->prvline; - printf("%s:%d\n", file, lineno); -} - -static void -print_info_stopped_code(mrb_state *mrb, mrdb_state *mrdb) -{ - char* file = mrb_debug_get_source(mrb, mrdb, mrdb->srcpath, mrdb->dbg->prvfile); - uint16_t lineno = mrdb->dbg->prvline; - if(file != NULL) { - mrb_debug_list(mrb, mrdb->dbg, file, lineno, lineno); - mrb_free(mrb, file); - } -} - -static void -print_info_stopped(mrb_state *mrb, mrdb_state *mrdb) -{ - switch(mrdb->dbg->bm) { - case BRK_BREAK: - print_info_stopped_break(mrb, mrdb); - print_info_stopped_code(mrb, mrdb); - break; - case BRK_STEP: - case BRK_NEXT: - print_info_stopped_step_next(mrb, mrdb); - print_info_stopped_code(mrb, mrdb); - break; - default: - break; - } -} - -static debug_command* -get_and_parse_command(mrb_state *mrb, mrdb_state *mrdb) -{ - debug_command *cmd = NULL; - char *p; - int i; - - while (!cmd) { - for (p=NULL; !p || *p=='\0'; ) { - printf("(%s:%d) ", mrdb->dbg->prvfile, mrdb->dbg->prvline); - fflush(stdout); - p = get_command(mrb, mrdb); - } - - cmd = parse_command(mrb, mrdb, p); -#ifdef _DBG_MRDB_PARSER_ - for (i=0; iwcnt; i++) { - printf("%d: %s\n", i, mrdb->words[i]); - } -#endif - if (!cmd) { - printf("invalid command ("); - for (i=0; iwcnt; i++) { - if (i>0) { - printf(" "); - } - printf("%s", mrdb->words[i]); - } - puts(")"); - } - } - return cmd; -} - -static int32_t -check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs) -{ - struct RClass* c; - mrb_sym sym; - int32_t bpno; - mrb_bool isCfunc; - - mrb_debug_context *dbg = mrb_debug_context_get(mrb); - - isCfunc = FALSE; - bpno = dbg->method_bpno; - dbg->method_bpno = 0; - - switch(GET_OPCODE(*pc)) { - case OP_SEND: - case OP_SENDB: - c = mrb_class(mrb, regs[GETARG_A(*pc)]); - sym = irep->syms[GETARG_B(*pc)]; - break; - case OP_SUPER: - c = mrb->c->ci->target_class->super; - sym = mrb->c->ci->mid; - break; - default: - sym = 0; - break; - } - if(sym != 0) { - dbg->method_bpno = mrb_debug_check_breakpoint_method(mrb, dbg, c, sym, &isCfunc); - if(isCfunc) { - bpno = dbg->method_bpno; - dbg->method_bpno = 0; - } - } - dbg->isCfunc = isCfunc; - return bpno; -} - -static void -mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs) -{ - const char *file; - int32_t line; - int32_t bpno; - - mrb_debug_context *dbg = mrb_debug_context_get(mrb); - - mrb_assert(dbg); - - dbg->irep = irep; - dbg->pc = pc; - dbg->regs = regs; - - if(dbg->xphase == DBG_PHASE_RESTART) { - dbg->root_irep = irep; - dbg->prvfile = NULL; - dbg->prvline = 0; - dbg->xm = DBG_RUN; - dbg->xphase = DBG_PHASE_RUNNING; - } - - file = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq)); - line = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq)); - - switch (dbg->xm) { - case DBG_STEP: - case DBG_NEXT: // temporary - if (!file || (dbg->prvfile == file && dbg->prvline == line)) { - return; - } - dbg->method_bpno = 0; - dbg->bm = BRK_STEP; - break; - - case DBG_RUN: - bpno = check_method_breakpoint(mrb, irep, pc, regs); - if (bpno > 0) { - dbg->stopped_bpno = bpno; - dbg->bm = BRK_BREAK; - break; - } - if (dbg->prvfile != file || dbg->prvline != line) { - bpno = mrb_debug_check_breakpoint_line(mrb, dbg, file, line); - if (bpno > 0) { - dbg->stopped_bpno = bpno; - dbg->bm = BRK_BREAK; - break; - } - } - dbg->prvfile = file; - dbg->prvline = line; - return; - case DBG_INIT: - dbg->root_irep = irep; - dbg->bm = BRK_INIT; - if (!file || line < 0) { - puts("Cannot get debugging information."); - } - break; - - default: - return; - } - - dbg->prvfile = file; - dbg->prvline = line; - - if(dbg->bm == BRK_BREAK && --dbg->ccnt > 0) { - return; - } - dbg->break_hook(mrb, dbg); - - dbg->xphase = DBG_PHASE_RUNNING; -} - -static mrdb_exemode -mrb_debug_break_hook(mrb_state *mrb, mrb_debug_context *dbg) -{ - debug_command *cmd; - dbgcmd_state st = DBGST_CONTINUE; - mrdb_state *mrdb = mrdb_state_get(mrb); - - print_info_stopped(mrb, mrdb); - - while (1) { - cmd = get_and_parse_command(mrb, mrdb); - mrb_assert(cmd); - - st = cmd->func(mrb, mrdb); - - if( (st == DBGST_CONTINUE) || (st == DBGST_RESTART) ) break; - } - return dbg->xm; -} - -int -main(int argc, char **argv) -{ - mrb_state *mrb = mrb_open(); - int n = -1; - struct _args args; - mrb_value v; - mrdb_state *mrdb; - mrdb_state *mrdb_backup; - mrb_debug_context* dbg_backup; - debug_command *cmd; - - l_restart: - - if (mrb == NULL) { - fputs("Invalid mrb_state, exiting mruby\n", stderr); - return EXIT_FAILURE; - } - - /* parse command parameters */ - n = parse_args(mrb, argc, argv, &args); - if (n == EXIT_FAILURE || args.rfp == NULL) { - cleanup(mrb, &args); - usage(argv[0]); - return n; - } - - /* initialize debugger information */ - mrdb = mrdb_state_get(mrb); - mrb_assert(mrdb && mrdb->dbg); - mrdb->srcpath = args.srcpath; - - if(mrdb->dbg->xm == DBG_QUIT) { - mrdb->dbg->xphase = DBG_PHASE_RESTART; - } - else { - mrdb->dbg->xphase = DBG_PHASE_BEFORE_RUN; - } - mrdb->dbg->xm = DBG_INIT; - mrdb->dbg->ccnt = 1; - - /* setup hook functions */ - mrb->code_fetch_hook = mrb_code_fetch_hook; - mrdb->dbg->break_hook = mrb_debug_break_hook; - - if (args.mrbfile) { /* .mrb */ - v = mrb_load_irep_file(mrb, args.rfp); - } - else { /* .rb */ - mrbc_context *cc = mrbc_context_new(mrb); - mrbc_filename(mrb, cc, args.fname); - v = mrb_load_file_cxt(mrb, args.rfp, cc); - mrbc_context_free(mrb, cc); - } - if (mrdb->dbg->xm == DBG_QUIT && !mrb_undef_p(v) && mrb->exc) { - const char *classname = mrb_obj_classname(mrb, mrb_obj_value(mrb->exc)); - if (!strcmp(classname, "DebuggerExit")) { - cleanup(mrb, &args); - return 0; - } - if (!strcmp(classname, "DebuggerRestart")) { - mrdb_backup = mrdb_state_get(mrb); - dbg_backup = mrb_debug_context_get(mrb); - - mrdb_state_set(NULL); - mrb_debug_context_set(NULL); - - cleanup(mrb, &args); - mrb = mrb_open(); - - mrdb_state_set(mrdb_backup); - mrb_debug_context_set(dbg_backup); - - goto l_restart; - } - } - puts("mruby application exited."); - mrdb->dbg->xphase = DBG_PHASE_AFTER_RUN; - if (!mrb_undef_p(v)) { - if (mrb->exc) { - mrb_print_error(mrb); - } - else { - printf(" => "); - mrb_p(mrb, v); - } - } - - mrdb->dbg->prvfile = "-"; - mrdb->dbg->prvline = 0; - - while (1) { - cmd = get_and_parse_command(mrb, mrdb); - mrb_assert(cmd); - - if (cmd->id == DBGCMD_QUIT) { - break; - } - - if( cmd->func(mrb, mrdb) == DBGST_RESTART ) goto l_restart; - } - - cleanup(mrb, &args); - - return 0; -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -/* -** mrdbconf.h - mruby debugger configuration -** -*/ - -#ifndef MRDBCONF_H -#define MRDBCONF_H - -/* configuration options: */ -/* maximum size for command buffer */ -#define MAX_COMMAND_LINE 1024 - -/* maximum number of setable breakpoint */ -#define MAX_BREAKPOINT 5 - -#endif diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -/* -** mrdberror.h - mruby debugger error code -** -*/ - -#ifndef MRDBERROR_H -#define MRDBERROR_H - -#define MRB_DEBUG_OK (0) -#define MRB_DEBUG_NOBUF (-1) -#define MRB_DEBUG_INVALID_ARGUMENT (-2) - -#define MRB_DEBUG_BREAK_INVALID_LINENO (-11) -#define MRB_DEBUG_BREAK_INVALID_FILE (-12) -#define MRB_DEBUG_BREAK_INVALID_NO (-13) -#define MRB_DEBUG_BREAK_NUM_OVER (-14) -#define MRB_DEBUG_BREAK_NO_OVER (-15) - -#endif - diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,163 +0,0 @@ -/* -** mrdb.h - mruby debugger -** -*/ - -#ifndef MRDB_H -#define MRDB_H - -#include "mruby.h" - -#include "mrdbconf.h" - -#ifdef _MSC_VER -# define __func__ __FUNCTION__ -#endif - -#define MAX_COMMAND_WORD (16) - -typedef enum debug_command_id { - DBGCMD_RUN, - DBGCMD_CONTINUE, - DBGCMD_NEXT, - DBGCMD_STEP, - DBGCMD_BREAK, - DBGCMD_INFO_BREAK, - DBGCMD_WATCH, - DBGCMD_INFO_WATCH, - DBGCMD_ENABLE, - DBGCMD_DISABLE, - DBGCMD_DELETE, - DBGCMD_PRINT, - DBGCMD_DISPLAY, - DBGCMD_INFO_DISPLAY, - DBGCMD_DELETE_DISPLAY, - DBGCMD_EVAL, - DBGCMD_BACKTRACE, - DBGCMD_LIST, - DBGCMD_HELP, - DBGCMD_QUIT, - DBGCMD_UNKNOWN -} debug_command_id; - -typedef enum dbgcmd_state { - DBGST_CONTINUE, - DBGST_PROMPT, - DBGST_COMMAND_ERROR, - DBGST_MAX, - DBGST_RESTART -} dbgcmd_state; - -typedef enum mrdb_exemode { - DBG_INIT, - DBG_RUN, - DBG_STEP, - DBG_NEXT, - DBG_QUIT, -} mrdb_exemode; - -typedef enum mrdb_exephase { - DBG_PHASE_BEFORE_RUN, - DBG_PHASE_RUNNING, - DBG_PHASE_AFTER_RUN, - DBG_PHASE_RESTART, -} mrdb_exephase; - -typedef enum mrdb_brkmode { - BRK_INIT, - BRK_BREAK, - BRK_STEP, - BRK_NEXT, - BRK_QUIT, -} mrdb_brkmode; - -typedef enum { - MRB_DEBUG_BPTYPE_NONE, - MRB_DEBUG_BPTYPE_LINE, - MRB_DEBUG_BPTYPE_METHOD, -} mrb_debug_bptype; - -struct mrb_irep; -struct mrbc_context; -struct mrb_debug_context; - -typedef struct mrb_debug_linepoint { - const char *file; - uint16_t lineno; -} mrb_debug_linepoint; - -typedef struct mrb_debug_methodpoint { - const char *class_name; - const char *method_name; -} mrb_debug_methodpoint; - -typedef struct mrb_debug_breakpoint { - uint32_t bpno; - uint8_t enable; - mrb_debug_bptype type; - union point { - mrb_debug_linepoint linepoint; - mrb_debug_methodpoint methodpoint; - } point; -} mrb_debug_breakpoint; - -typedef struct mrb_debug_context { - struct mrb_irep *root_irep; - struct mrb_irep *irep; - mrb_code *pc; - mrb_value *regs; - - const char *prvfile; - int32_t prvline; - - mrdb_exemode xm; - mrdb_exephase xphase; - mrdb_brkmode bm; - int16_t bmi; - - uint16_t ccnt; - uint16_t scnt; - - mrb_debug_breakpoint bp[MAX_BREAKPOINT]; - uint32_t bpnum; - int32_t next_bpno; - int32_t method_bpno; - int32_t stopped_bpno; - mrb_bool isCfunc; - - mrdb_exemode (*break_hook)(mrb_state *mrb, struct mrb_debug_context *dbg); - -} mrb_debug_context; - -typedef struct mrdb_state { - char *command; - uint8_t wcnt; - uint8_t pi; - char *words[MAX_COMMAND_WORD]; - const char *srcpath; - uint32_t print_no; - - mrb_debug_context *dbg; -} mrdb_state; - -typedef dbgcmd_state (*debug_command_func)(mrb_state*, mrdb_state*); - -/* cmdrun.c */ -dbgcmd_state dbgcmd_run(mrb_state*, mrdb_state*); -dbgcmd_state dbgcmd_continue(mrb_state*, mrdb_state*); -dbgcmd_state dbgcmd_step(mrb_state*, mrdb_state*); -/* cmdbreak.c */ -dbgcmd_state dbgcmd_break(mrb_state*, mrdb_state*); -dbgcmd_state dbgcmd_info_break(mrb_state*, mrdb_state*); -dbgcmd_state dbgcmd_delete(mrb_state*, mrdb_state*); -dbgcmd_state dbgcmd_enable(mrb_state*, mrdb_state*); -dbgcmd_state dbgcmd_disable(mrb_state*, mrdb_state*); -/* cmdprint.c */ -dbgcmd_state dbgcmd_print(mrb_state*, mrdb_state*); -dbgcmd_state dbgcmd_eval(mrb_state*, mrdb_state*); -/* cmdmisc.c */ -dbgcmd_state dbgcmd_list(mrb_state*, mrdb_state*); -dbgcmd_state dbgcmd_help(mrb_state*, mrdb_state*); -dbgcmd_state dbgcmd_quit(mrb_state*, mrdb_state*); - -#endif diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -require 'open3' - -assert('mirb normal operations') do - o, s = Open3.capture2('bin/mirb', :stdin_data => "a=1\nb=2\na+b\n") - assert_true o.include?('=> 3') - assert_true o.include?('=> 2') -end - -assert('regression for #1563') do - o, s = Open3.capture2('bin/mirb', :stdin_data => "a=1;b=2;c=3\nb\nc") - assert_true o.include?('=> 3') -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -MRuby::Gem::Specification.new('mruby-bin-mirb') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'mirb command' - - if spec.build.cc.search_header_path 'readline/readline.h' - spec.cc.defines << "ENABLE_READLINE" - if spec.build.cc.search_header_path 'termcap.h' - if MRUBY_BUILD_HOST_IS_CYGWIN || MRUBY_BUILD_HOST_IS_OPENBSD - if spec.build.cc.search_header_path 'termcap.h' - if MRUBY_BUILD_HOST_IS_CYGWIN then - spec.linker.libraries << 'ncurses' - else - spec.linker.libraries << 'termcap' - end - end - end - end - if RUBY_PLATFORM.include?('netbsd') - spec.linker.libraries << 'edit' - else - spec.linker.libraries << 'readline' - if spec.build.cc.search_header_path 'curses.h' - spec.linker.libraries << 'ncurses' - end - end - elsif spec.build.cc.search_header_path 'linenoise.h' - spec.cc.defines << "ENABLE_LINENOISE" - end - - spec.bins = %w(mirb) - spec.add_dependency('mruby-compiler', :core => 'mruby-compiler') -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,493 +0,0 @@ -/* -** mirb - Embeddable Interactive Ruby Shell -** -** This program takes code from the user in -** an interactive way and executes it -** immediately. It's a REPL... -*/ - -#include -#include -#include -#include - -#ifdef ENABLE_READLINE -#include -#include -#define MIRB_ADD_HISTORY(line) add_history(line) -#define MIRB_READLINE(ch) readline(ch) -#define MIRB_WRITE_HISTORY(path) write_history(path) -#define MIRB_READ_HISTORY(path) read_history(path) -#define MIRB_USING_HISTORY() using_history() -#elif defined(ENABLE_LINENOISE) -#define ENABLE_READLINE -#include -#define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line) -#define MIRB_READLINE(ch) linenoise(ch) -#define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path) -#define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path) -#define MIRB_USING_HISTORY() -#endif - -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/proc.h" -#include "mruby/compile.h" -#include "mruby/string.h" - -#ifdef ENABLE_READLINE - -static const char history_file_name[] = ".mirb_history"; - -static char * -get_history_path(mrb_state *mrb) -{ - char *path = NULL; - const char *home = getenv("HOME"); - -#ifdef _WIN32 - if (home != NULL) { - home = getenv("USERPROFILE"); - } -#endif - - if (home != NULL) { - int len = snprintf(NULL, 0, "%s/%s", home, history_file_name); - if (len >= 0) { - size_t size = len + 1; - path = (char *)mrb_malloc_simple(mrb, size); - if (path != NULL) { - int n = snprintf(path, size, "%s/%s", home, history_file_name); - if (n != len) { - mrb_free(mrb, path); - path = NULL; - } - } - } - } - - return path; -} - -#endif - -static void -p(mrb_state *mrb, mrb_value obj, int prompt) -{ - mrb_value val; - - val = mrb_funcall(mrb, obj, "inspect", 0); - if (prompt) { - if (!mrb->exc) { - fputs(" => ", stdout); - } - else { - val = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0); - } - } - if (!mrb_string_p(val)) { - val = mrb_obj_as_string(mrb, obj); - } - fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout); - putc('\n', stdout); -} - -/* Guess if the user might want to enter more - * or if he wants an evaluation of his code now */ -static mrb_bool -is_code_block_open(struct mrb_parser_state *parser) -{ - mrb_bool code_block_open = FALSE; - - /* check for heredoc */ - if (parser->parsing_heredoc != NULL) return TRUE; - if (parser->heredoc_end_now) { - parser->heredoc_end_now = FALSE; - return FALSE; - } - - /* check for unterminated string */ - if (parser->lex_strterm) return TRUE; - - /* check if parser error are available */ - if (0 < parser->nerr) { - const char unexpected_end[] = "syntax error, unexpected $end"; - const char *message = parser->error_buffer[0].message; - - /* a parser error occur, we have to check if */ - /* we need to read one more line or if there is */ - /* a different issue which we have to show to */ - /* the user */ - - if (strncmp(message, unexpected_end, sizeof(unexpected_end) - 1) == 0) { - code_block_open = TRUE; - } - else if (strcmp(message, "syntax error, unexpected keyword_end") == 0) { - code_block_open = FALSE; - } - else if (strcmp(message, "syntax error, unexpected tREGEXP_BEG") == 0) { - code_block_open = FALSE; - } - return code_block_open; - } - - switch (parser->lstate) { - - /* all states which need more code */ - - case EXPR_BEG: - /* beginning of a statement, */ - /* that means previous line ended */ - code_block_open = FALSE; - break; - case EXPR_DOT: - /* a message dot was the last token, */ - /* there has to come more */ - code_block_open = TRUE; - break; - case EXPR_CLASS: - /* a class keyword is not enough! */ - /* we need also a name of the class */ - code_block_open = TRUE; - break; - case EXPR_FNAME: - /* a method name is necessary */ - code_block_open = TRUE; - break; - case EXPR_VALUE: - /* if, elsif, etc. without condition */ - code_block_open = TRUE; - break; - - /* now all the states which are closed */ - - case EXPR_ARG: - /* an argument is the last token */ - code_block_open = FALSE; - break; - - /* all states which are unsure */ - - case EXPR_CMDARG: - break; - case EXPR_END: - /* an expression was ended */ - break; - case EXPR_ENDARG: - /* closing parenthese */ - break; - case EXPR_ENDFN: - /* definition end */ - break; - case EXPR_MID: - /* jump keyword like break, return, ... */ - break; - case EXPR_MAX_STATE: - /* don't know what to do with this token */ - break; - default: - /* this state is unexpected! */ - break; - } - - return code_block_open; -} - -struct _args { - mrb_bool verbose : 1; - int argc; - char** argv; -}; - -static void -usage(const char *name) -{ - static const char *const usage_msg[] = { - "switches:", - "-v print version number, then run in verbose mode", - "--verbose run in verbose mode", - "--version print the version", - "--copyright print the copyright", - NULL - }; - const char *const *p = usage_msg; - - printf("Usage: %s [switches]\n", name); - while (*p) - printf(" %s\n", *p++); -} - -static int -parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) -{ - static const struct _args args_zero = { 0 }; - - *args = args_zero; - - for (argc--,argv++; argc > 0; argc--,argv++) { - char *item; - if (argv[0][0] != '-') break; - - item = argv[0] + 1; - switch (*item++) { - case 'v': - if (!args->verbose) mrb_show_version(mrb); - args->verbose = TRUE; - break; - case '-': - if (strcmp((*argv) + 2, "version") == 0) { - mrb_show_version(mrb); - exit(EXIT_SUCCESS); - } - else if (strcmp((*argv) + 2, "verbose") == 0) { - args->verbose = TRUE; - break; - } - else if (strcmp((*argv) + 2, "copyright") == 0) { - mrb_show_copyright(mrb); - exit(EXIT_SUCCESS); - } - default: - return EXIT_FAILURE; - } - } - return EXIT_SUCCESS; -} - -static void -cleanup(mrb_state *mrb, struct _args *args) -{ - mrb_close(mrb); -} - -/* Print a short remark for the user */ -static void -print_hint(void) -{ - printf("mirb - Embeddable Interactive Ruby Shell\n\n"); -} - -#ifndef ENABLE_READLINE -/* Print the command line prompt of the REPL */ -static void -print_cmdline(int code_block_open) -{ - if (code_block_open) { - printf("* "); - } - else { - printf("> "); - } - fflush(stdout); -} -#endif - -void mrb_codedump_all(mrb_state*, struct RProc*); - -static int -check_keyword(const char *buf, const char *word) -{ - const char *p = buf; - size_t len = strlen(word); - - /* skip preceding spaces */ - while (*p && isspace((unsigned char)*p)) { - p++; - } - /* check keyword */ - if (strncmp(p, word, len) != 0) { - return 0; - } - p += len; - /* skip trailing spaces */ - while (*p) { - if (!isspace((unsigned char)*p)) return 0; - p++; - } - return 1; -} - -int -main(int argc, char **argv) -{ - char ruby_code[1024] = { 0 }; - char last_code_line[1024] = { 0 }; -#ifndef ENABLE_READLINE - int last_char; - int char_index; -#else - char *history_path; -#endif - mrbc_context *cxt; - struct mrb_parser_state *parser; - mrb_state *mrb; - mrb_value result; - struct _args args; - int n; - mrb_bool code_block_open = FALSE; - int ai; - unsigned int stack_keep = 0; - - /* new interpreter instance */ - mrb = mrb_open(); - if (mrb == NULL) { - fputs("Invalid mrb interpreter, exiting mirb\n", stderr); - return EXIT_FAILURE; - } - mrb_define_global_const(mrb, "ARGV", mrb_ary_new_capa(mrb, 0)); - - n = parse_args(mrb, argc, argv, &args); - if (n == EXIT_FAILURE) { - cleanup(mrb, &args); - usage(argv[0]); - return n; - } - -#ifdef ENABLE_READLINE - history_path = get_history_path(mrb); - if (history_path == NULL) { - fputs("failed to get history path\n", stderr); - mrb_close(mrb); - return EXIT_FAILURE; - } - - MIRB_USING_HISTORY(); - MIRB_READ_HISTORY(history_path); -#endif - - print_hint(); - - cxt = mrbc_context_new(mrb); - cxt->capture_errors = TRUE; - cxt->lineno = 1; - mrbc_filename(mrb, cxt, "(mirb)"); - if (args.verbose) cxt->dump_result = TRUE; - - ai = mrb_gc_arena_save(mrb); - - while (TRUE) { - char *utf8; - -#ifndef ENABLE_READLINE - print_cmdline(code_block_open); - - char_index = 0; - while ((last_char = getchar()) != '\n') { - if (last_char == EOF) break; - if (char_index > sizeof(last_code_line)-2) { - fputs("input string too long\n", stderr); - continue; - } - last_code_line[char_index++] = last_char; - } - if (last_char == EOF) { - fputs("\n", stdout); - break; - } - - last_code_line[char_index++] = '\n'; - last_code_line[char_index] = '\0'; -#else - char* line = MIRB_READLINE(code_block_open ? "* " : "> "); - if (line == NULL) { - printf("\n"); - break; - } - if (strlen(line) > sizeof(last_code_line)-2) { - fputs("input string too long\n", stderr); - continue; - } - strcpy(last_code_line, line); - strcat(last_code_line, "\n"); - MIRB_ADD_HISTORY(line); - free(line); -#endif - - if (code_block_open) { - if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) { - fputs("concatenated input string too long\n", stderr); - continue; - } - strcat(ruby_code, last_code_line); - } - else { - if (check_keyword(last_code_line, "quit") || check_keyword(last_code_line, "exit")) { - break; - } - strcpy(ruby_code, last_code_line); - } - - utf8 = mrb_utf8_from_locale(ruby_code, -1); - if (!utf8) abort(); - - /* parse code */ - parser = mrb_parser_new(mrb); - if (parser == NULL) { - fputs("create parser state error\n", stderr); - break; - } - parser->s = utf8; - parser->send = utf8 + strlen(utf8); - parser->lineno = cxt->lineno; - mrb_parser_parse(parser, cxt); - code_block_open = is_code_block_open(parser); - mrb_utf8_free(utf8); - - if (code_block_open) { - /* no evaluation of code */ - } - else { - if (0 < parser->nerr) { - /* syntax error */ - printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message); - } - else { - /* generate bytecode */ - struct RProc *proc = mrb_generate_code(mrb, parser); - if (proc == NULL) { - fputs("codegen error\n", stderr); - mrb_parser_free(parser); - break; - } - - if (args.verbose) { - mrb_codedump_all(mrb, proc); - } - /* pass a proc for evaulation */ - /* evaluate the bytecode */ - result = mrb_context_run(mrb, - proc, - mrb_top_self(mrb), - stack_keep); - stack_keep = proc->body.irep->nlocals; - /* did an exception occur? */ - if (mrb->exc) { - p(mrb, mrb_obj_value(mrb->exc), 0); - mrb->exc = 0; - } - else { - /* no */ - if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){ - result = mrb_any_to_s(mrb, result); - } - p(mrb, result, 1); - } - } - ruby_code[0] = '\0'; - last_code_line[0] = '\0'; - mrb_gc_arena_restore(mrb, ai); - } - mrb_parser_free(parser); - cxt->lineno++; - } - -#ifdef ENABLE_READLINE - MIRB_WRITE_HISTORY(history_path); - mrb_free(mrb, history_path); -#endif - - mrbc_context_free(mrb, cxt); - mrb_close(mrb); - - return 0; -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -MRuby::Gem::Specification.new 'mruby-bin-mrbc' do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'mruby compiler executable' - - spec.add_dependency 'mruby-compiler', :core => 'mruby-compiler' - - exec = exefile("#{build.build_dir}/bin/mrbc") - mrbc_objs = Dir.glob("#{spec.dir}/tools/mrbc/*.c").map { |f| objfile(f.pathmap("#{spec.build_dir}/tools/mrbc/%n")) }.flatten - - file exec => mrbc_objs + [libfile("#{build.build_dir}/lib/libmruby_core")] do |t| - build.linker.run t.name, t.prerequisites - end - - build.bins << 'mrbc' unless build.bins.find { |v| v == 'mrbc' } -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,336 +0,0 @@ -#include -#include -#include -#include "mruby.h" -#include "mruby/compile.h" -#include "mruby/dump.h" -#include "mruby/proc.h" - -#define RITEBIN_EXT ".mrb" -#define C_EXT ".c" - -struct mrbc_args { - int argc; - char **argv; - int idx; - const char *prog; - const char *outfile; - const char *initname; - mrb_bool check_syntax : 1; - mrb_bool verbose : 1; - unsigned int flags : 4; -}; - -static void -usage(const char *name) -{ - static const char *const usage_msg[] = { - "switches:", - "-c check syntax only", - "-o place the output into ", - "-v print version number, then turn on verbose mode", - "-g produce debugging information", - "-B binary output in C language format", - "-e generate little endian iseq data", - "-E generate big endian iseq data", - "--verbose run at verbose mode", - "--version print the version", - "--copyright print the copyright", - NULL - }; - const char *const *p = usage_msg; - - printf("Usage: %s [switches] programfile\n", name); - while (*p) - printf(" %s\n", *p++); -} - -static char * -get_outfilename(mrb_state *mrb, char *infile, const char *ext) -{ - size_t infilelen; - size_t extlen; - char *outfile; - char *p; - - infilelen = strlen(infile); - extlen = strlen(ext); - outfile = (char*)mrb_malloc(mrb, infilelen + extlen + 1); - memcpy(outfile, infile, infilelen + 1); - if (*ext) { - if ((p = strrchr(outfile, '.')) == NULL) - p = outfile + infilelen; - memcpy(p, ext, extlen + 1); - } - - return outfile; -} - -static int -parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args) -{ - char *outfile = NULL; - static const struct mrbc_args args_zero = { 0 }; - int i; - - *args = args_zero; - args->argc = argc; - args->argv = argv; - args->prog = argv[0]; - - for (i=1; ioutfile) { - fprintf(stderr, "%s: an output file is already specified. (%s)\n", - args->prog, outfile); - return -1; - } - if (argv[i][2] == '\0' && argv[i+1]) { - i++; - args->outfile = get_outfilename(mrb, argv[i], ""); - } - else { - args->outfile = get_outfilename(mrb, argv[i] + 2, ""); - } - break; - case 'B': - if (argv[i][2] == '\0' && argv[i+1]) { - i++; - args->initname = argv[i]; - } - else { - args->initname = argv[i]+2; - } - if (*args->initname == '\0') { - fprintf(stderr, "%s: function name is not specified.\n", args->prog); - return -1; - } - break; - case 'c': - args->check_syntax = TRUE; - break; - case 'v': - if (!args->verbose) mrb_show_version(mrb); - args->verbose = TRUE; - break; - case 'g': - args->flags |= DUMP_DEBUG_INFO; - break; - case 'E': - args->flags = DUMP_ENDIAN_BIG | (args->flags & ~DUMP_ENDIAN_MASK); - break; - case 'e': - args->flags = DUMP_ENDIAN_LIL | (args->flags & ~DUMP_ENDIAN_MASK); - break; - case 'h': - return -1; - case '-': - if (argv[i][1] == '\n') { - return i; - } - if (strcmp(argv[i] + 2, "version") == 0) { - mrb_show_version(mrb); - exit(EXIT_SUCCESS); - } - else if (strcmp(argv[i] + 2, "verbose") == 0) { - args->verbose = TRUE; - break; - } - else if (strcmp(argv[i] + 2, "copyright") == 0) { - mrb_show_copyright(mrb); - exit(EXIT_SUCCESS); - } - return -1; - default: - return i; - } - } - else { - break; - } - } - if (args->verbose && args->initname && (args->flags & DUMP_ENDIAN_MASK) == 0) { - fprintf(stderr, "%s: generating %s endian C file. specify -e/-E for cross compiling.\n", - args->prog, bigendian_p() ? "big" : "little"); - } - return i; -} - -static void -cleanup(mrb_state *mrb, struct mrbc_args *args) -{ - mrb_free(mrb, (void*)args->outfile); - mrb_close(mrb); -} - -static int -partial_hook(struct mrb_parser_state *p) -{ - mrbc_context *c = p->cxt; - struct mrbc_args *args = (struct mrbc_args *)c->partial_data; - const char *fn; - - if (p->f) fclose(p->f); - if (args->idx >= args->argc) { - p->f = NULL; - return -1; - } - fn = args->argv[args->idx++]; - p->f = fopen(fn, "r"); - if (p->f == NULL) { - fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn); - return -1; - } - mrb_parser_set_filename(p, fn); - return 0; -} - -static mrb_value -load_file(mrb_state *mrb, struct mrbc_args *args) -{ - mrbc_context *c; - mrb_value result; - char *input = args->argv[args->idx]; - FILE *infile; - mrb_bool need_close = FALSE; - - c = mrbc_context_new(mrb); - if (args->verbose) - c->dump_result = TRUE; - c->no_exec = TRUE; - if (input[0] == '-' && input[1] == '\0') { - infile = stdin; - } - else { - need_close = TRUE; - if ((infile = fopen(input, "r")) == NULL) { - fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, input); - return mrb_nil_value(); - } - } - mrbc_filename(mrb, c, input); - args->idx++; - if (args->idx < args->argc) { - need_close = FALSE; - mrbc_partial_hook(mrb, c, partial_hook, (void*)args); - } - - result = mrb_load_file_cxt(mrb, infile, c); - if (need_close) fclose(infile); - mrbc_context_free(mrb, c); - if (mrb_undef_p(result)) { - return mrb_nil_value(); - } - return result; -} - -static int -dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, struct RProc *proc, struct mrbc_args *args) -{ - int n = MRB_DUMP_OK; - mrb_irep *irep = proc->body.irep; - - if (args->initname) { - n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname); - if (n == MRB_DUMP_INVALID_ARGUMENT) { - fprintf(stderr, "%s: invalid C language symbol name\n", args->initname); - } - } - else { - n = mrb_dump_irep_binary(mrb, irep, args->flags, wfp); - } - if (n != MRB_DUMP_OK) { - fprintf(stderr, "%s: error in mrb dump (%s) %d\n", args->prog, outfile, n); - } - return n; -} - -int -main(int argc, char **argv) -{ - mrb_state *mrb = mrb_open(); - int n, result; - struct mrbc_args args; - FILE *wfp; - mrb_value load; - - if (mrb == NULL) { - fputs("Invalid mrb_state, exiting mrbc\n", stderr); - return EXIT_FAILURE; - } - - n = parse_args(mrb, argc, argv, &args); - if (n < 0) { - cleanup(mrb, &args); - usage(argv[0]); - return EXIT_FAILURE; - } - if (n == argc) { - fprintf(stderr, "%s: no program file given\n", args.prog); - return EXIT_FAILURE; - } - if (args.outfile == NULL && !args.check_syntax) { - if (n + 1 == argc) { - args.outfile = get_outfilename(mrb, argv[n], args.initname ? C_EXT : RITEBIN_EXT); - } - else { - fprintf(stderr, "%s: output file should be specified to compile multiple files\n", args.prog); - return EXIT_FAILURE; - } - } - - args.idx = n; - load = load_file(mrb, &args); - if (mrb_nil_p(load)) { - cleanup(mrb, &args); - return EXIT_FAILURE; - } - if (args.check_syntax) { - printf("%s:%s:Syntax OK\n", args.prog, argv[n]); - } - - if (args.check_syntax) { - cleanup(mrb, &args); - return EXIT_SUCCESS; - } - - if (args.outfile) { - if (strcmp("-", args.outfile) == 0) { - wfp = stdout; - } - else if ((wfp = fopen(args.outfile, "wb")) == NULL) { - fprintf(stderr, "%s: cannot open output file:(%s)\n", args.prog, args.outfile); - return EXIT_FAILURE; - } - } - else { - fprintf(stderr, "Output file is required\n"); - return EXIT_FAILURE; - } - result = dump_file(mrb, wfp, args.outfile, mrb_proc_ptr(load), &args); - fclose(wfp); - cleanup(mrb, &args); - if (result != MRB_DUMP_OK) { - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - -void -mrb_init_mrblib(mrb_state *mrb) -{ -} - -#ifndef DISABLE_GEMS -void -mrb_init_mrbgems(mrb_state *mrb) -{ -} - -void -mrb_final_mrbgems(mrb_state *mrb) -{ -} -#endif diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -require 'tempfile' - -assert('regression for #1564') do - o = `#{cmd('mruby')} -e #{shellquote('<<')} 2>&1` - assert_equal o, "-e:1:2: syntax error, unexpected tLSHFT\n" - o = `#{cmd('mruby')} -e #{shellquote('<<-')} 2>&1` - assert_equal o, "-e:1:3: syntax error, unexpected tLSHFT\n" -end - -assert('regression for #1572') do - script, bin = Tempfile.new('test.rb'), Tempfile.new('test.mrb') - File.write script.path, 'p "ok"' - system "#{cmd('mrbc')} -g -o #{bin.path} #{script.path}" - o = `#{cmd('mruby')} -b #{bin.path}`.strip - assert_equal o, '"ok"' -end - -assert '$0 value' do - script, bin = Tempfile.new('test.rb'), Tempfile.new('test.mrb') - - # .rb script - script.write "p $0\n" - script.flush - assert_equal "\"#{script.path}\"", `#{cmd('mruby')} "#{script.path}"`.chomp - - # .mrb file - `#{cmd('mrbc')} -o "#{bin.path}" "#{script.path}"` - assert_equal "\"#{bin.path}\"", `#{cmd('mruby')} -b "#{bin.path}"`.chomp - - # one liner - assert_equal '"-e"', `#{cmd('mruby')} -e #{shellquote('p $0')}`.chomp -end - -assert '__END__', '8.6' do - script = Tempfile.new('test.rb') - - script.write < 'mruby-compiler') -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,248 +0,0 @@ -#include -#include -#include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/compile.h" -#include "mruby/dump.h" -#include "mruby/variable.h" - -#ifdef MRB_DISABLE_STDIO -static void -p(mrb_state *mrb, mrb_value obj) -{ - mrb_value val = mrb_inspect(mrb, obj); - - fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout); - putc('\n', stdout); -} -#else -#define p(mrb,obj) mrb_p(mrb,obj) -#endif - -struct _args { - FILE *rfp; - char* cmdline; - mrb_bool fname : 1; - mrb_bool mrbfile : 1; - mrb_bool check_syntax : 1; - mrb_bool verbose : 1; - int argc; - char** argv; -}; - -static void -usage(const char *name) -{ - static const char *const usage_msg[] = { - "switches:", - "-b load and execute RiteBinary (mrb) file", - "-c check syntax only", - "-e 'command' one line of script", - "-v print version number, then run in verbose mode", - "--verbose run in verbose mode", - "--version print the version", - "--copyright print the copyright", - NULL - }; - const char *const *p = usage_msg; - - printf("Usage: %s [switches] programfile\n", name); - while (*p) - printf(" %s\n", *p++); -} - -static int -parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) -{ - char **origargv = argv; - static const struct _args args_zero = { 0 }; - - *args = args_zero; - - for (argc--,argv++; argc > 0; argc--,argv++) { - char *item; - if (argv[0][0] != '-') break; - - if (strlen(*argv) <= 1) { - argc--; argv++; - args->rfp = stdin; - break; - } - - item = argv[0] + 1; - switch (*item++) { - case 'b': - args->mrbfile = TRUE; - break; - case 'c': - args->check_syntax = TRUE; - break; - case 'e': - if (item[0]) { - goto append_cmdline; - } - else if (argc > 1) { - argc--; argv++; - item = argv[0]; -append_cmdline: - if (!args->cmdline) { - size_t buflen; - char *buf; - - buflen = strlen(item) + 1; - buf = (char *)mrb_malloc(mrb, buflen); - memcpy(buf, item, buflen); - args->cmdline = buf; - } - else { - size_t cmdlinelen; - size_t itemlen; - - cmdlinelen = strlen(args->cmdline); - itemlen = strlen(item); - args->cmdline = - (char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2); - args->cmdline[cmdlinelen] = '\n'; - memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1); - } - } - else { - printf("%s: No code specified for -e\n", *origargv); - return EXIT_SUCCESS; - } - break; - case 'v': - if (!args->verbose) mrb_show_version(mrb); - args->verbose = TRUE; - break; - case '-': - if (strcmp((*argv) + 2, "version") == 0) { - mrb_show_version(mrb); - exit(EXIT_SUCCESS); - } - else if (strcmp((*argv) + 2, "verbose") == 0) { - args->verbose = TRUE; - break; - } - else if (strcmp((*argv) + 2, "copyright") == 0) { - mrb_show_copyright(mrb); - exit(EXIT_SUCCESS); - } - default: - return EXIT_FAILURE; - } - } - - if (args->rfp == NULL && args->cmdline == NULL) { - if (*argv == NULL) args->rfp = stdin; - else { - args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r"); - if (args->rfp == NULL) { - printf("%s: Cannot open program file. (%s)\n", *origargv, *argv); - return EXIT_FAILURE; - } - args->fname = TRUE; - args->cmdline = argv[0]; - argc--; argv++; - } - } - args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1)); - memcpy(args->argv, argv, (argc+1) * sizeof(char*)); - args->argc = argc; - - return EXIT_SUCCESS; -} - -static void -cleanup(mrb_state *mrb, struct _args *args) -{ - if (args->rfp && args->rfp != stdin) - fclose(args->rfp); - if (!args->fname) - mrb_free(mrb, args->cmdline); - mrb_free(mrb, args->argv); - mrb_close(mrb); -} - -int -main(int argc, char **argv) -{ - mrb_state *mrb = mrb_open(); - int n = -1; - int i; - struct _args args; - mrb_value ARGV; - mrbc_context *c; - mrb_value v; - mrb_sym zero_sym; - - if (mrb == NULL) { - fputs("Invalid mrb_state, exiting mruby\n", stderr); - return EXIT_FAILURE; - } - - n = parse_args(mrb, argc, argv, &args); - if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) { - cleanup(mrb, &args); - usage(argv[0]); - return n; - } - - ARGV = mrb_ary_new_capa(mrb, args.argc); - for (i = 0; i < args.argc; i++) { - char* utf8 = mrb_utf8_from_locale(args.argv[i], -1); - if (utf8) { - mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8)); - mrb_utf8_free(utf8); - } - } - mrb_define_global_const(mrb, "ARGV", ARGV); - - c = mrbc_context_new(mrb); - if (args.verbose) - c->dump_result = TRUE; - if (args.check_syntax) - c->no_exec = TRUE; - - /* Set $0 */ - zero_sym = mrb_intern_lit(mrb, "$0"); - if (args.rfp) { - const char *cmdline; - cmdline = args.cmdline ? args.cmdline : "-"; - mrbc_filename(mrb, c, cmdline); - mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline)); - } - else { - mrbc_filename(mrb, c, "-e"); - mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e")); - } - - /* Load program */ - if (args.mrbfile) { - v = mrb_load_irep_file_cxt(mrb, args.rfp, c); - } - else if (args.rfp) { - v = mrb_load_file_cxt(mrb, args.rfp, c); - } - else { - char* utf8 = mrb_utf8_from_locale(args.cmdline, -1); - if (!utf8) abort(); - v = mrb_load_string_cxt(mrb, utf8, c); - mrb_utf8_free(utf8); - } - - mrbc_context_free(mrb, c); - if (mrb->exc) { - if (!mrb_undef_p(v)) { - mrb_print_error(mrb); - } - n = -1; - } - else if (args.check_syntax) { - printf("Syntax OK\n"); - } - cleanup(mrb, &args); - - return n == 0 ? EXIT_SUCCESS : EXIT_FAILURE; -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mruby-config/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mruby-config/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mruby-config/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mruby-config/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -module MRuby - class Build - def exefile(name) - if name.is_a?(Array) - name.flatten.map { |n| exefile(n) } - elsif name !~ /\./ - "#{name}#{exts.executable}" - else - name - end - end - end -end - -MRuby.each_target do - next if kind_of? MRuby::CrossBuild - - mruby_config = 'mruby-config' + (ENV['OS'] == 'Windows_NT' ? '.bat' : '') - mruby_config_path = "#{build_dir}/bin/#{mruby_config}" - @bins << mruby_config - - file mruby_config_path => libfile("#{build_dir}/lib/libmruby") do |t| - FileUtils.copy "#{File.dirname(__FILE__)}/#{mruby_config}", t.name - config = Hash[open("#{build_dir}/lib/libmruby.flags.mak").read.split("\n").map {|x| a = x.split(/\s*=\s*/, 2); [a[0], a[1].gsub('\\"', '"') ]}] - IO.write(t.name, File.open(t.name) {|f| - f.read.gsub (/echo (MRUBY_CFLAGS|MRUBY_LIBS|MRUBY_LDFLAGS_BEFORE_LIBS|MRUBY_LDFLAGS)/) {|x| config[$1].empty? ? '' : "echo #{config[$1]}"} - }) - FileUtils.chmod(0755, t.name) - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mruby-config/mruby-config nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mruby-config/mruby-config --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mruby-config/mruby-config 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mruby-config/mruby-config 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#!/bin/sh - -while [ $# -gt 0 ]; do - case $1 in - --cflags) echo MRUBY_CFLAGS;; - --ldflags) echo MRUBY_LDFLAGS;; - --ldflags-before-libs) echo MRUBY_LDFLAGS_BEFORE_LIBS;; - --libs) echo MRUBY_LIBS;; - --help) echo "Usage: mruby-config [switches]" - echo " switches:" - echo " --cflags print flags passed to compiler" - echo " --ldflags print flags passed to linker" - echo " --ldflags-before-libs print flags passwd to linker before linked libraries" - echo " --libs print linked libraries" - exit 0;; - esac - shift -done diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mruby-config/mruby-config.bat nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mruby-config/mruby-config.bat --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-mruby-config/mruby-config.bat 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-mruby-config/mruby-config.bat 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -@echo off - -:top -shift -if "%0" equ "" goto :eof -if "%0" equ "--cflags" goto cflags -if "%0" equ "--ldflags" goto ldflags -if "%0" equ "--ldflags-before-libs" goto ldflagsbeforelibs -if "%0" equ "--libs" goto libs -if "%0" equ "--help" goto showhelp -echo Invalid Option -goto :eof - -:cflags -echo MRUBY_CFLAGS -goto top - -:libs -echo MRUBY_LIBS -goto top - -:ldflags -echo MRUBY_LDFLAGS -goto top - -:ldflagsbeforelibs -echo MRUBY_LDFLAGS_BEFORE_LIBS -goto top - -:showhelp -echo Usage: mruby-config [switches] -echo switches: -echo --cflags print flags passed to compiler -echo --ldflags print flags passed to linker -echo --ldflags-before-libs print flags passwd to linker before linked libraries -echo --libs print linked libraries diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -require 'tempfile' - -assert('no files') do - o = `#{cmd('mruby-strip')} 2>&1` - assert_equal 1, $?.exitstatus - assert_equal "no files to strip", o.split("\n")[0] -end - -assert('file not found') do - o = `#{cmd('mruby-strip')} not_found.mrb 2>&1` - assert_equal 1, $?.exitstatus - assert_equal "can't open file for reading not_found.mrb\n", o -end - -assert('not irep file') do - t = Tempfile.new('script.rb') - t.write 'p test\n' - t.flush - o = `#{cmd('mruby-strip')} #{t.path} 2>&1` - assert_equal 1, $?.exitstatus - assert_equal "can't read irep file #{t.path}\n", o -end - -assert('success') do - script_file, compiled1, compiled2 = - Tempfile.new('script.rb'), Tempfile.new('c1.mrb'), Tempfile.new('c2.mrb') - script_file.write "p 'test'\n" - script_file.flush - `#{cmd('mrbc')} -g -o #{compiled1.path} #{script_file.path}` - `#{cmd('mrbc')} -g -o #{compiled2.path} #{script_file.path}` - - o = `#{cmd('mruby-strip')} #{compiled1.path}` - assert_equal 0, $?.exitstatus - assert_equal "", o - assert_equal `#{cmd('mruby')} #{script_file.path}`, `#{cmd('mruby')} -b #{compiled1.path}` - - o = `#{cmd('mruby-strip')} #{compiled1.path} #{compiled2.path}` - assert_equal 0, $?.exitstatus - assert_equal "", o -end - -assert('check debug section') do - script_file, with_debug, without_debug = - Tempfile.new('script.rb'), Tempfile.new('c1.mrb'), Tempfile.new('c2.mrb') - script_file.write "p 'test'\n" - script_file.flush - `#{cmd('mrbc')} -o #{without_debug.path} #{script_file.path}` - `#{cmd('mrbc')} -g -o #{with_debug.path} #{script_file.path}` - - assert_true with_debug.size >= without_debug.size - - `#{cmd('mruby-strip')} #{with_debug.path}` - assert_equal without_debug.size, with_debug.size -end - -assert('check lv section') do - script_file, with_lv, without_lv = - Tempfile.new('script.rb'), Tempfile.new('c1.mrb'), Tempfile.new('c2.mrb') - script_file.write < -#include -#include -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/dump.h" - -struct strip_args { - int argc_start; - int argc; - char **argv; - mrb_bool lvar; -}; - - -static void -irep_remove_lv(mrb_state *mrb, mrb_irep *irep) -{ - size_t i; - - if (irep->lv) { - mrb_free(mrb, irep->lv); - irep->lv = NULL; - } - - for (i = 0; i < irep->rlen; ++i) { - irep_remove_lv(mrb, irep->reps[i]); - } -} - -static void -print_usage(const char *f) -{ - printf("Usage: %s [switches] irepfiles\n", f); - printf("switches:\n"); - printf(" -l, --lvar remove LVAR section too.\n"); -} - -static int -parse_args(int argc, char **argv, struct strip_args *args) -{ - int i; - - args->argc_start = 0; - args->argc = argc; - args->argv = argv; - args->lvar = FALSE; - - for (i = 1; i < argc; ++i) { - const size_t len = strlen(argv[i]); - if (len >= 2 && argv[i][0] == '-') { - switch (argv[i][1]) { - case 'l': - args->lvar = TRUE; - break; - case '-': - if (strncmp((*argv) + 2, "lvar", len) == 0) { - args->lvar = TRUE; - break; - } - default: - return -1; - } - } - else { - break; - } - } - - args->argc_start = i; - return i; -} - -static int -strip(mrb_state *mrb, struct strip_args *args) -{ - int i; - - for (i = args->argc_start; i < args->argc; ++i) { - char *filename; - FILE *rfile; - mrb_irep *irep; - FILE *wfile; - int dump_result; - - filename = args->argv[i]; - rfile = fopen(filename, "rb"); - if (rfile == NULL) { - fprintf(stderr, "can't open file for reading %s\n", filename); - return EXIT_FAILURE; - } - - irep = mrb_read_irep_file(mrb, rfile); - fclose(rfile); - if (irep == NULL) { - fprintf(stderr, "can't read irep file %s\n", filename); - return EXIT_FAILURE; - } - - /* clear lv if --lvar is enabled */ - if (args->lvar) { - irep_remove_lv(mrb, irep); - } - - wfile = fopen(filename, "wb"); - if (wfile == NULL) { - fprintf(stderr, "can't open file for writing %s\n", filename); - mrb_irep_decref(mrb, irep); - return EXIT_FAILURE; - } - - /* debug flag must always be false */ - dump_result = mrb_dump_irep_binary(mrb, irep, FALSE, wfile); - - fclose(wfile); - mrb_irep_decref(mrb, irep); - - if (dump_result != MRB_DUMP_OK) { - fprintf(stderr, "error occurred during dumping %s\n", filename); - return EXIT_FAILURE; - } - } - return EXIT_SUCCESS; -} - -int -main(int argc, char **argv) -{ - struct strip_args args; - int args_result; - mrb_state *mrb; - int ret; - - if (argc <= 1) { - printf("no files to strip\n"); - print_usage(argv[0]); - return EXIT_FAILURE; - } - - args_result = parse_args(argc, argv, &args); - if (args_result < 0) { - print_usage(argv[0]); - return EXIT_FAILURE; - } - mrb = mrb_open_core(mrb_default_allocf, NULL); - if (mrb == NULL) { - fputs("Invalid mrb_state, exiting mruby-strip\n", stderr); - return EXIT_FAILURE; - } - - ret = strip(mrb, &args); - - mrb_close(mrb); - return ret; -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/bintest/mrbc.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/bintest/mrbc.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/bintest/mrbc.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/bintest/mrbc.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -require 'tempfile' - -assert('Compiling multiple files without new line in last line. #2361') do - a, b, out = Tempfile.new('a.rb'), Tempfile.new('b.rb'), Tempfile.new('out.mrb') - a.write('module A; end') - a.flush - b.write('module B; end') - b.flush - result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} #{b.path} 2>&1` - assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp - assert_equal 0, $?.exitstatus -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/core/codegen.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/core/codegen.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/core/codegen.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/core/codegen.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,2767 +0,0 @@ -/* -** codegen.c - mruby code generator -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include -#include -#include "mruby.h" -#include "mruby/compile.h" -#include "mruby/proc.h" -#include "mruby/numeric.h" -#include "mruby/string.h" -#include "mruby/debug.h" -#include "node.h" -#include "mruby/opcode.h" -#include "mruby/re.h" -#include "mruby/throw.h" - -typedef mrb_ast_node node; -typedef struct mrb_parser_state parser_state; - -enum looptype { - LOOP_NORMAL, - LOOP_BLOCK, - LOOP_FOR, - LOOP_BEGIN, - LOOP_RESCUE, -}; - -struct loopinfo { - enum looptype type; - int pc1, pc2, pc3, acc; - int ensure_level; - struct loopinfo *prev; -}; - -typedef struct scope { - mrb_state *mrb; - mrb_pool *mpool; - struct mrb_jmpbuf jmp; - - struct scope *prev; - - node *lv; - - int sp; - int pc; - int lastlabel; - int ainfo:15; - mrb_bool mscope:1; - - struct loopinfo *loop; - int ensure_level; - char const *filename; - uint16_t lineno; - - mrb_code *iseq; - uint16_t *lines; - int icapa; - - mrb_irep *irep; - size_t pcapa; - size_t scapa; - size_t rcapa; - - uint16_t nlocals; - uint16_t nregs; - int ai; - - int debug_start_pos; - uint16_t filename_index; - parser_state* parser; -} codegen_scope; - -static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv); -static void scope_finish(codegen_scope *s); -static struct loopinfo *loop_push(codegen_scope *s, enum looptype t); -static void loop_break(codegen_scope *s, node *tree); -static void loop_pop(codegen_scope *s, int val); - -static void gen_assignment(codegen_scope *s, node *tree, int sp, int val); -static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val); - -static void codegen(codegen_scope *s, node *tree, int val); -static void raise_error(codegen_scope *s, const char *msg); - -static void -codegen_error(codegen_scope *s, const char *message) -{ - if (!s) return; - while (s->prev) { - codegen_scope *tmp = s->prev; - mrb_pool_close(s->mpool); - s = tmp; - } -#ifndef MBB_DISABLE_STDIO - if (s->filename && s->lineno) { - fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message); - } - else { - fprintf(stderr, "codegen error: %s\n", message); - } -#endif - MRB_THROW(&s->jmp); -} - -static void* -codegen_palloc(codegen_scope *s, size_t len) -{ - void *p = mrb_pool_alloc(s->mpool, len); - - if (!p) codegen_error(s, "pool memory allocation"); - return p; -} - -static void* -codegen_malloc(codegen_scope *s, size_t len) -{ - void *p = mrb_malloc_simple(s->mrb, len); - - if (!p) codegen_error(s, "mrb_malloc"); - return p; -} - -static void* -codegen_realloc(codegen_scope *s, void *p, size_t len) -{ - p = mrb_realloc_simple(s->mrb, p, len); - - if (!p && len > 0) codegen_error(s, "mrb_realloc"); - return p; -} - -static int -new_label(codegen_scope *s) -{ - s->lastlabel = s->pc; - return s->pc; -} - -static inline int -genop(codegen_scope *s, mrb_code i) -{ - if (s->pc == s->icapa) { - s->icapa *= 2; - s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); - if (s->lines) { - s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa); - s->irep->lines = s->lines; - } - } - s->iseq[s->pc] = i; - if (s->lines) { - s->lines[s->pc] = s->lineno; - } - return s->pc++; -} - -#define NOVAL 0 -#define VAL 1 - -static mrb_bool -no_optimize(codegen_scope *s) -{ - if (s && s->parser && s->parser->no_optimize) - return TRUE; - return FALSE; -} - -static int -genop_peep(codegen_scope *s, mrb_code i, int val) -{ - /* peephole optimization */ - if (!no_optimize(s) && s->lastlabel != s->pc && s->pc > 0) { - mrb_code i0 = s->iseq[s->pc-1]; - int c1 = GET_OPCODE(i); - int c0 = GET_OPCODE(i0); - - switch (c1) { - case OP_MOVE: - if (GETARG_A(i) == GETARG_B(i)) { - /* skip useless OP_MOVE */ - return 0; - } - if (val) break; - switch (c0) { - case OP_MOVE: - if (GETARG_A(i) == GETARG_A(i0)) { - /* skip overriden OP_MOVE */ - s->pc--; - s->iseq[s->pc] = i; - } - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0)) { - /* skip swapping OP_MOVE */ - return 0; - } - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->pc--; - return genop_peep(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)), val); - } - break; - case OP_LOADI: - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0)); - return 0; - } - break; - case OP_ARRAY: - case OP_HASH: - case OP_RANGE: - case OP_AREF: - case OP_GETUPVAR: - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0)); - return 0; - } - break; - case OP_LOADSYM: - case OP_GETGLOBAL: - case OP_GETIV: - case OP_GETCV: - case OP_GETCONST: - case OP_GETSPECIAL: - case OP_LOADL: - case OP_STRING: - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0)); - return 0; - } - break; - case OP_SCLASS: - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0)); - return 0; - } - break; - case OP_LOADNIL: - case OP_LOADSELF: - case OP_LOADT: - case OP_LOADF: - case OP_OCLASS: - if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i)); - return 0; - } - break; - default: - break; - } - break; - case OP_SETIV: - case OP_SETCV: - case OP_SETCONST: - case OP_SETMCNST: - case OP_SETGLOBAL: - if (val) break; - if (c0 == OP_MOVE) { - if (GETARG_A(i) == GETARG_A(i0)) { - s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i)); - return 0; - } - } - break; - case OP_SETUPVAR: - if (val) break; - if (c0 == OP_MOVE) { - if (GETARG_A(i) == GETARG_A(i0)) { - s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i)); - return 0; - } - } - break; - case OP_EPOP: - if (c0 == OP_EPOP) { - s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i)); - return 0; - } - break; - case OP_POPERR: - if (c0 == OP_POPERR) { - s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i)); - return 0; - } - break; - case OP_RETURN: - switch (c0) { - case OP_RETURN: - return 0; - case OP_MOVE: - if (GETARG_A(i0) >= s->nlocals) { - s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL); - return 0; - } - break; - case OP_SETIV: - case OP_SETCV: - case OP_SETCONST: - case OP_SETMCNST: - case OP_SETUPVAR: - case OP_SETGLOBAL: - s->pc--; - genop_peep(s, i0, NOVAL); - i0 = s->iseq[s->pc-1]; - return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL)); -#if 0 - case OP_SEND: - if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) { - s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0)); - return; - } - break; -#endif - default: - break; - } - break; - case OP_ADD: - case OP_SUB: - if (c0 == OP_LOADI) { - int c = GETARG_sBx(i0); - - if (c1 == OP_SUB) c = -c; - if (c > 127 || c < -127) break; - if (0 <= c) - s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c); - else - s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c); - return 0; - } - case OP_STRCAT: - if (c0 == OP_STRING) { - mrb_value v = s->irep->pool[GETARG_Bx(i0)]; - - if (mrb_string_p(v) && RSTRING_LEN(v) == 0) { - s->pc--; - return 0; - } - } - break; - case OP_JMPIF: - case OP_JMPNOT: - if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) { - s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i)); - return s->pc-1; - } - break; - default: - break; - } - } - return genop(s, i); -} - -static void -scope_error(codegen_scope *s) -{ - exit(EXIT_FAILURE); -} - -static inline void -dispatch(codegen_scope *s, int pc) -{ - int diff = s->pc - pc; - mrb_code i = s->iseq[pc]; - int c = GET_OPCODE(i); - - s->lastlabel = s->pc; - switch (c) { - case OP_JMP: - case OP_JMPIF: - case OP_JMPNOT: - case OP_ONERR: - break; - default: -#ifndef MRB_DISABLE_STDIO - fprintf(stderr, "bug: dispatch on non JMP op\n"); -#endif - scope_error(s); - break; - } - s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff); -} - -static void -dispatch_linked(codegen_scope *s, int pc) -{ - mrb_code i; - int pos; - - if (!pc) return; - for (;;) { - i = s->iseq[pc]; - pos = GETARG_sBx(i); - dispatch(s, pc); - if (!pos) break; - pc = pos; - } -} - -#define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0) -static void -push_(codegen_scope *s) -{ - if (s->sp > 511) { - codegen_error(s, "too complex expression"); - } - s->sp++; - nregs_update; -} - -static void -push_n_(codegen_scope *s, size_t n) -{ - if (s->sp+n > 511) { - codegen_error(s, "too complex expression"); - } - s->sp+=n; - nregs_update; -} - -#define push() push_(s) -#define push_n(n) push_n_(s,n) -#define pop_(s) ((s)->sp--) -#define pop() pop_(s) -#define pop_n(n) (s->sp-=(n)) -#define cursp() (s->sp) - -static inline int -new_lit(codegen_scope *s, mrb_value val) -{ - size_t i; - mrb_value *pv; - - switch (mrb_type(val)) { - case MRB_TT_STRING: - for (i=0; iirep->plen; i++) { - mrb_int len; - pv = &s->irep->pool[i]; - - if (mrb_type(*pv) != MRB_TT_STRING) continue; - if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue; - if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0) - return i; - } - break; - case MRB_TT_FLOAT: - for (i=0; iirep->plen; i++) { - pv = &s->irep->pool[i]; - if (mrb_type(*pv) != MRB_TT_FLOAT) continue; - if (mrb_float(*pv) == mrb_float(val)) return i; - } - break; - case MRB_TT_FIXNUM: - for (i=0; iirep->plen; i++) { - pv = &s->irep->pool[i]; - if (!mrb_fixnum_p(*pv)) continue; - if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i; - } - break; - default: - /* should not happen */ - return 0; - } - - if (s->irep->plen == s->pcapa) { - s->pcapa *= 2; - s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa); - } - - pv = &s->irep->pool[s->irep->plen]; - i = s->irep->plen++; - - switch (mrb_type(val)) { - case MRB_TT_STRING: - *pv = mrb_str_pool(s->mrb, val); - break; - - case MRB_TT_FLOAT: -#ifdef MRB_WORD_BOXING - *pv = mrb_float_pool(s->mrb, mrb_float(val)); - break; -#endif - case MRB_TT_FIXNUM: - *pv = val; - break; - - default: - /* should not happen */ - break; - } - return i; -} - -static inline int -new_msym(codegen_scope *s, mrb_sym sym) -{ - size_t i, len; - - mrb_assert(s->irep); - - len = s->irep->slen; - if (len > 256) len = 256; - for (i=0; iirep->syms[i] == sym) return i; - if (s->irep->syms[i] == 0) break; - } - if (i == 256) { - codegen_error(s, "too many symbols (max 256)"); - } - s->irep->syms[i] = sym; - if (i == s->irep->slen) s->irep->slen++; - return i; -} - -static inline int -new_sym(codegen_scope *s, mrb_sym sym) -{ - size_t i; - - for (i=0; iirep->slen; i++) { - if (s->irep->syms[i] == sym) return i; - } - if (s->irep->slen > 125 && s->irep->slen < 256) { - s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*65536); - for (i = 0; i < 256 - s->irep->slen; i++) { - static const mrb_sym mrb_sym_zero = { 0 }; - s->irep->syms[i + s->irep->slen] = mrb_sym_zero; - } - s->irep->slen = 256; - } - s->irep->syms[s->irep->slen] = sym; - return s->irep->slen++; -} - -static int -node_len(node *tree) -{ - int n = 0; - - while (tree) { - n++; - tree = tree->cdr; - } - return n; -} - -#define sym(x) ((mrb_sym)(intptr_t)(x)) -#define lv_name(lv) sym((lv)->car) -static int -lv_idx(codegen_scope *s, mrb_sym id) -{ - node *lv = s->lv; - int n = 1; - - while (lv) { - if (lv_name(lv) == id) return n; - n++; - lv = lv->cdr; - } - return 0; -} - -static void -for_body(codegen_scope *s, node *tree) -{ - codegen_scope *prev = s; - int idx; - struct loopinfo *lp; - node *n2; - mrb_code c; - - /* generate receiver */ - codegen(s, tree->cdr->car, VAL); - /* generate loop-block */ - s = scope_new(s->mrb, s, NULL); - if (s == NULL) { - raise_error(prev, "unexpected scope"); - } - - push(); /* push for a block parameter */ - - lp = loop_push(s, LOOP_FOR); - lp->pc1 = new_label(s); - - /* generate loop variable */ - n2 = tree->car; - genop(s, MKOP_Ax(OP_ENTER, 0x40000)); - if (n2->car && !n2->car->cdr && !n2->cdr) { - gen_assignment(s, n2->car->car, 1, NOVAL); - } - else { - gen_vmassignment(s, n2, 1, VAL); - } - codegen(s, tree->cdr->cdr->car, VAL); - pop(); - if (s->pc > 0) { - c = s->iseq[s->pc-1]; - if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) - genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); - } - loop_pop(s, NOVAL); - scope_finish(s); - s = prev; - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK)); - pop(); - idx = new_msym(s, mrb_intern_lit(s->mrb, "each")); - genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0)); -} - -static int -lambda_body(codegen_scope *s, node *tree, int blk) -{ - mrb_code c; - codegen_scope *parent = s; - s = scope_new(s->mrb, s, tree->car); - if (s == NULL) { - raise_error(parent, "unexpected scope"); - } - - s->mscope = !blk; - - if (blk) { - struct loopinfo *lp = loop_push(s, LOOP_BLOCK); - lp->pc1 = new_label(s); - } - tree = tree->cdr; - if (tree->car) { - mrb_aspec a; - int ma, oa, ra, pa, ka, kd, ba; - int pos, i; - node *n, *opt; - - ma = node_len(tree->car->car); - n = tree->car->car; - while (n) { - n = n->cdr; - } - oa = node_len(tree->car->cdr->car); - ra = tree->car->cdr->cdr->car ? 1 : 0; - pa = node_len(tree->car->cdr->cdr->cdr->car); - ka = kd = 0; - ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0; - - a = ((mrb_aspec)(ma & 0x1f) << 18) - | ((mrb_aspec)(oa & 0x1f) << 13) - | ((ra & 1) << 12) - | ((pa & 0x1f) << 7) - | ((ka & 0x1f) << 2) - | ((kd & 1)<< 1) - | (ba & 1); - s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */ - | ((ra & 1) << 5) - | (pa & 0x1f); - genop(s, MKOP_Ax(OP_ENTER, a)); - pos = new_label(s); - for (i=0; i 0) { - genop(s, MKOP_sBx(OP_JMP, 0)); - } - opt = tree->car->cdr->car; - i = 0; - while (opt) { - int idx; - - dispatch(s, pos+i); - codegen(s, opt->car->cdr, VAL); - idx = lv_idx(s, (mrb_sym)(intptr_t)opt->car->car); - pop(); - genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL); - i++; - opt = opt->cdr; - } - if (oa > 0) { - dispatch(s, pos+i); - } - } - codegen(s, tree->cdr->car, VAL); - pop(); - if (s->pc > 0) { - c = s->iseq[s->pc-1]; - if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) { - if (s->nregs == 0) { - genop(s, MKOP_A(OP_LOADNIL, 0)); - genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); - } - else { - genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); - } - } - } - if (blk) { - loop_pop(s, NOVAL); - } - scope_finish(s); - return parent->irep->rlen - 1; -} - -static int -scope_body(codegen_scope *s, node *tree, int val) -{ - codegen_scope *scope = scope_new(s->mrb, s, tree->car); - if (scope == NULL) { - raise_error(s, "unexpected scope"); - } - - codegen(scope, tree->cdr, VAL); - if (!s->iseq) { - genop(scope, MKOP_A(OP_STOP, 0)); - } - else if (!val) { - genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); - } - else { - if (scope->nregs == 0) { - genop(scope, MKOP_A(OP_LOADNIL, 0)); - genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); - } - else { - genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL); - } - } - scope_finish(scope); - if (!s->irep) { - /* should not happen */ - return 0; - } - return s->irep->rlen - 1; -} - -static mrb_bool -nosplat(node *t) -{ - while (t) { - if ((intptr_t)t->car->car == NODE_SPLAT) return FALSE; - t = t->cdr; - } - return TRUE; -} - -static mrb_sym -attrsym(codegen_scope *s, mrb_sym a) -{ - const char *name; - mrb_int len; - char *name2; - - name = mrb_sym2name_len(s->mrb, a, &len); - name2 = (char *)codegen_palloc(s, - (size_t)len - + 1 /* '=' */ - + 1 /* '\0' */ - ); - mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - memcpy(name2, name, (size_t)len); - name2[len] = '='; - name2[len+1] = '\0'; - - return mrb_intern(s->mrb, name2, len+1); -} - -static int -gen_values(codegen_scope *s, node *t, int val) -{ - int n = 0; - int is_splat; - - while (t) { - is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */ - if (n >= 127 || is_splat) { - if (val) { - pop_n(n); - genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n)); - push(); - codegen(s, t->car, VAL); - pop(); pop(); - if (is_splat) { - genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1)); - } - else { - genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); - } - t = t->cdr; - while (t) { - push(); - codegen(s, t->car, VAL); - pop(); pop(); - if ((intptr_t)t->car->car == NODE_SPLAT) { - genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1)); - } - else { - genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); - } - t = t->cdr; - } - } - else { - codegen(s, t->car->cdr, NOVAL); - t = t->cdr; - while (t) { - codegen(s, t->car, NOVAL); - t = t->cdr; - } - } - return -1; - } - /* normal (no splat) mode */ - codegen(s, t->car, val); - n++; - t = t->cdr; - } - return n; -} - -#define CALL_MAXARGS 127 - -static void -gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) -{ - mrb_sym sym = name ? name : sym(tree->cdr->car); - int idx; - int n = 0, noop = 0, sendv = 0, blk = 0; - - codegen(s, tree->car, VAL); /* receiver */ - idx = new_msym(s, sym); - tree = tree->cdr->cdr->car; - if (tree) { - n = gen_values(s, tree->car, VAL); - if (n < 0) { - n = noop = sendv = 1; - push(); - } - } - if (sp) { - if (sendv) { - pop(); - genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp)); - push(); - } - else { - genop(s, MKOP_AB(OP_MOVE, cursp(), sp)); - push(); - n++; - } - } - if (tree && tree->cdr) { - noop = 1; - codegen(s, tree->cdr, VAL); - pop(); - } - else { - blk = cursp(); - } - push();pop(); - pop_n(n+1); - { - mrb_int symlen; - const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen); - - if (!noop && symlen == 1 && symname[0] == '+') { - genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val); - } - else if (!noop && symlen == 1 && symname[0] == '-') { - genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val); - } - else if (!noop && symlen == 1 && symname[0] == '*') { - genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n)); - } - else if (!noop && symlen == 1 && symname[0] == '/') { - genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n)); - } - else if (!noop && symlen == 1 && symname[0] == '<') { - genop(s, MKOP_ABC(OP_LT, cursp(), idx, n)); - } - else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=') { - genop(s, MKOP_ABC(OP_LE, cursp(), idx, n)); - } - else if (!noop && symlen == 1 && symname[0] == '>') { - genop(s, MKOP_ABC(OP_GT, cursp(), idx, n)); - } - else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=') { - genop(s, MKOP_ABC(OP_GE, cursp(), idx, n)); - } - else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=') { - genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n)); - } - else { - if (sendv) n = CALL_MAXARGS; - if (blk > 0) { /* no block */ - genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n)); - } - else { - genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n)); - } - } - } - if (val) { - push(); - } -} - -static void -gen_assignment(codegen_scope *s, node *tree, int sp, int val) -{ - int idx; - int type = (intptr_t)tree->car; - - tree = tree->cdr; - switch ((intptr_t)type) { - case NODE_GVAR: - idx = new_sym(s, sym(tree)); - genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val); - break; - case NODE_LVAR: - idx = lv_idx(s, sym(tree)); - if (idx > 0) { - if (idx != sp) { - genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val); - } - break; - } - else { /* upvar */ - int lv = 0; - codegen_scope *up = s->prev; - - while (up) { - idx = lv_idx(up, sym(tree)); - if (idx > 0) { - genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val); - break; - } - lv++; - up = up->prev; - } - } - break; - case NODE_IVAR: - idx = new_sym(s, sym(tree)); - genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val); - break; - case NODE_CVAR: - idx = new_sym(s, sym(tree)); - genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val); - break; - case NODE_CONST: - idx = new_sym(s, sym(tree)); - genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val); - break; - case NODE_COLON2: - idx = new_sym(s, sym(tree->cdr)); - genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL); - push(); - codegen(s, tree->car, VAL); - pop_n(2); - genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val); - break; - - case NODE_CALL: - push(); - gen_call(s, tree, attrsym(s, sym(tree->cdr->car)), sp, NOVAL); - pop(); - if (val) { - genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val); - } - break; - - case NODE_MASGN: - gen_vmassignment(s, tree->car, sp, val); - break; - - /* splat without assignment */ - case NODE_NIL: - break; - - default: -#ifndef MRB_DISABLE_STDIO - printf("unknown lhs %d\n", type); -#endif - break; - } - if (val) push(); -} - -static void -gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) -{ - int n = 0, post = 0; - node *t, *p; - - if (tree->car) { /* pre */ - t = tree->car; - n = 0; - while (t) { - genop(s, MKOP_ABC(OP_AREF, cursp(), rhs, n)); - gen_assignment(s, t->car, cursp(), NOVAL); - n++; - t = t->cdr; - } - } - t = tree->cdr; - if (t) { - if (t->cdr) { /* post count */ - p = t->cdr->car; - while (p) { - post++; - p = p->cdr; - } - } - if (val) { - genop(s, MKOP_AB(OP_MOVE, cursp(), rhs)); - } - else { - pop(); - } - push_n(post); - pop_n(post); - genop(s, MKOP_ABC(OP_APOST, cursp(), n, post)); - n = 1; - if (t->car) { /* rest */ - gen_assignment(s, t->car, cursp(), NOVAL); - } - if (t->cdr && t->cdr->car) { - t = t->cdr->car; - while (t) { - gen_assignment(s, t->car, cursp()+n, NOVAL); - t = t->cdr; - n++; - } - } - push(); - } -} - -static void -gen_send_intern(codegen_scope *s) -{ - pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0)); - push(); -} -static void -gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val) -{ - if (val) { - int i = 0, j = 0; - - while (tree) { - switch ((intptr_t)tree->car->car) { - case NODE_STR: - if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0)) - break; - /* fall through */ - case NODE_BEGIN: - codegen(s, tree->car, VAL); - ++j; - break; - - case NODE_LITERAL_DELIM: - if (j > 0) { - j = 0; - ++i; - if (sym) - gen_send_intern(s); - } - break; - } - if (j >= 2) { - pop(); pop(); - genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); - push(); - j = 1; - } - tree = tree->cdr; - } - if (j > 0) { - ++i; - if (sym) - gen_send_intern(s); - } - pop_n(i); - genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i)); - push(); - } - else { - while (tree) { - switch ((intptr_t)tree->car->car) { - case NODE_BEGIN: case NODE_BLOCK: - codegen(s, tree->car, NOVAL); - } - tree = tree->cdr; - } - } -} - -static void -raise_error(codegen_scope *s, const char *msg) -{ - int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg)); - - genop(s, MKOP_ABx(OP_ERR, 1, idx)); -} - -static double -readint_float(codegen_scope *s, const char *p, int base) -{ - const char *e = p + strlen(p); - double f = 0; - int n; - - if (*p == '+') p++; - while (p < e) { - char c = *p; - c = tolower((unsigned char)c); - for (n=0; n= 2 && base <= 36); - if (*p == '+') p++; - while (p < e) { - char c = *p; - c = tolower((unsigned char)c); - for (n=0; n result) { - *overflow = TRUE; - return 0; - } - result *= base; - result -= n; - } - else { - if ((MRB_INT_MAX - n)/base < result) { - *overflow = TRUE; - return 0; - } - result *= base; - result += n; - } - p++; - } - *overflow = FALSE; - return result; -} - -static void -codegen(codegen_scope *s, node *tree, int val) -{ - int nt; - - if (!tree) return; - - if (s->irep && s->filename_index != tree->filename_index) { - s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); - mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc); - s->debug_start_pos = s->pc; - s->filename_index = tree->filename_index; - s->filename = mrb_parser_get_filename(s->parser, tree->filename_index); - } - - nt = (intptr_t)tree->car; - s->lineno = tree->lineno; - tree = tree->cdr; - switch (nt) { - case NODE_BEGIN: - if (val && !tree) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - push(); - } - while (tree) { - codegen(s, tree->car, tree->cdr ? NOVAL : val); - tree = tree->cdr; - } - break; - - case NODE_RESCUE: - { - int onerr, noexc, exend, pos1, pos2, tmp; - struct loopinfo *lp; - - onerr = genop(s, MKOP_Bx(OP_ONERR, 0)); - lp = loop_push(s, LOOP_BEGIN); - lp->pc1 = onerr; - if (tree->car) { - codegen(s, tree->car, val); - if (val) pop(); - } - lp->type = LOOP_RESCUE; - noexc = genop(s, MKOP_Bx(OP_JMP, 0)); - dispatch(s, onerr); - tree = tree->cdr; - exend = 0; - pos1 = 0; - if (tree->car) { - node *n2 = tree->car; - int exc = cursp(); - - genop(s, MKOP_A(OP_RESCUE, exc)); - push(); - while (n2) { - node *n3 = n2->car; - node *n4 = n3->car; - - if (pos1) dispatch(s, pos1); - pos2 = 0; - do { - if (n4) { - codegen(s, n4->car, VAL); - } - else { - genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError")))); - push(); - } - genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); - pop(); - if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) { - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1)); - } - else { - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); - } - tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); - pos2 = tmp; - if (n4) { - n4 = n4->cdr; - } - } while (n4); - pos1 = genop(s, MKOP_sBx(OP_JMP, 0)); - dispatch_linked(s, pos2); - - pop(); - if (n3->cdr->car) { - gen_assignment(s, n3->cdr->car, exc, NOVAL); - } - if (n3->cdr->cdr->car) { - codegen(s, n3->cdr->cdr->car, val); - if (val) pop(); - } - tmp = genop(s, MKOP_sBx(OP_JMP, exend)); - exend = tmp; - n2 = n2->cdr; - push(); - } - if (pos1) { - dispatch(s, pos1); - genop(s, MKOP_A(OP_RAISE, exc)); - } - } - pop(); - tree = tree->cdr; - dispatch(s, noexc); - genop(s, MKOP_A(OP_POPERR, 1)); - if (tree->car) { - codegen(s, tree->car, val); - } - else if (val) { - push(); - } - dispatch_linked(s, exend); - loop_pop(s, NOVAL); - } - break; - - case NODE_ENSURE: - { - int idx; - int epush = s->pc; - - genop(s, MKOP_Bx(OP_EPUSH, 0)); - s->ensure_level++; - codegen(s, tree->car, val); - idx = scope_body(s, tree->cdr, NOVAL); - s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx); - s->ensure_level--; - genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL); - } - break; - - case NODE_LAMBDA: - { - int idx = lambda_body(s, tree, 1); - - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA)); - push(); - } - break; - - case NODE_BLOCK: - { - int idx = lambda_body(s, tree, 1); - - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK)); - push(); - } - break; - - case NODE_IF: - { - int pos1, pos2; - node *e = tree->cdr->cdr->car; - - switch ((intptr_t)tree->car->car) { - case NODE_TRUE: - case NODE_INT: - case NODE_STR: - codegen(s, tree->cdr->car, val); - return; - case NODE_FALSE: - case NODE_NIL: - codegen(s, e, val); - return; - } - codegen(s, tree->car, VAL); - pop(); - pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL); - - codegen(s, tree->cdr->car, val); - if (val && !(tree->cdr->car)) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - push(); - } - if (e) { - if (val) pop(); - pos2 = genop(s, MKOP_sBx(OP_JMP, 0)); - dispatch(s, pos1); - codegen(s, e, val); - dispatch(s, pos2); - } - else { - if (val) { - pop(); - pos2 = genop(s, MKOP_sBx(OP_JMP, 0)); - dispatch(s, pos1); - genop(s, MKOP_A(OP_LOADNIL, cursp())); - dispatch(s, pos2); - push(); - } - else { - dispatch(s, pos1); - } - } - } - break; - - case NODE_AND: - { - int pos; - - codegen(s, tree->car, VAL); - pop(); - pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0)); - codegen(s, tree->cdr, val); - dispatch(s, pos); - } - break; - - case NODE_OR: - { - int pos; - - codegen(s, tree->car, VAL); - pop(); - pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0)); - codegen(s, tree->cdr, val); - dispatch(s, pos); - } - break; - - case NODE_WHILE: - { - struct loopinfo *lp = loop_push(s, LOOP_NORMAL); - - lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0)); - lp->pc2 = new_label(s); - codegen(s, tree->cdr, NOVAL); - dispatch(s, lp->pc1); - codegen(s, tree->car, VAL); - pop(); - genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc)); - - loop_pop(s, val); - } - break; - - case NODE_UNTIL: - { - struct loopinfo *lp = loop_push(s, LOOP_NORMAL); - - lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0)); - lp->pc2 = new_label(s); - codegen(s, tree->cdr, NOVAL); - dispatch(s, lp->pc1); - codegen(s, tree->car, VAL); - pop(); - genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc)); - - loop_pop(s, val); - } - break; - - case NODE_FOR: - for_body(s, tree); - if (val) push(); - break; - - case NODE_CASE: - { - int head = 0; - int pos1, pos2, pos3, tmp; - node *n; - - pos3 = 0; - if (tree->car) { - head = cursp(); - codegen(s, tree->car, VAL); - } - tree = tree->cdr; - while (tree) { - n = tree->car->car; - pos1 = pos2 = 0; - while (n) { - codegen(s, n->car, VAL); - if (head) { - genop(s, MKOP_AB(OP_MOVE, cursp(), head)); - pop(); - if ((intptr_t)n->car->car == NODE_SPLAT) { - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1)); - } - else { - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); - } - } - else { - pop(); - } - tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); - pos2 = tmp; - n = n->cdr; - } - if (tree->car->car) { - pos1 = genop(s, MKOP_sBx(OP_JMP, 0)); - dispatch_linked(s, pos2); - } - codegen(s, tree->car->cdr, val); - if (val) pop(); - tmp = genop(s, MKOP_sBx(OP_JMP, pos3)); - pos3 = tmp; - if (pos1) dispatch(s, pos1); - tree = tree->cdr; - } - if (val) { - int pos = cursp(); - genop(s, MKOP_A(OP_LOADNIL, cursp())); - if (pos3) dispatch_linked(s, pos3); - if (head) pop(); - genop(s, MKOP_AB(OP_MOVE, cursp(), pos)); - push(); - } - else { - if (pos3) { - dispatch_linked(s, pos3); - } - if (head) { - pop(); - } - } - } - break; - - case NODE_SCOPE: - scope_body(s, tree, NOVAL); - break; - - case NODE_FCALL: - case NODE_CALL: - gen_call(s, tree, 0, 0, val); - break; - - case NODE_DOT2: - codegen(s, tree->car, val); - codegen(s, tree->cdr, val); - if (val) { - pop(); pop(); - genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE)); - push(); - } - break; - - case NODE_DOT3: - codegen(s, tree->car, val); - codegen(s, tree->cdr, val); - if (val) { - pop(); pop(); - genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE)); - push(); - } - break; - - case NODE_COLON2: - { - int sym = new_sym(s, sym(tree->cdr)); - - codegen(s, tree->car, VAL); - pop(); - genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); - if (val) push(); - } - break; - - case NODE_COLON3: - { - int sym = new_sym(s, sym(tree)); - - genop(s, MKOP_A(OP_OCLASS, cursp())); - genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); - if (val) push(); - } - break; - - case NODE_ARRAY: - { - int n; - - n = gen_values(s, tree, val); - if (n >= 0) { - if (val) { - pop_n(n); - genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n)); - push(); - } - } - else if (val) { - push(); - } - } - break; - - case NODE_HASH: - { - int len = 0; - mrb_bool update = FALSE; - - while (tree) { - codegen(s, tree->car->car, val); - codegen(s, tree->car->cdr, val); - len++; - tree = tree->cdr; - if (val && len == 126) { - pop_n(len*2); - genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len)); - if (update) { - pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1)); - } - push(); - update = TRUE; - len = 0; - } - } - if (val) { - pop_n(len*2); - genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len)); - if (update) { - pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1)); - } - push(); - } - } - break; - - case NODE_SPLAT: - codegen(s, tree, VAL); - break; - - case NODE_ASGN: - codegen(s, tree->cdr, VAL); - pop(); - gen_assignment(s, tree->car, cursp(), val); - break; - - case NODE_MASGN: - { - int len = 0, n = 0, post = 0; - node *t = tree->cdr, *p; - int rhs = cursp(); - - if ((intptr_t)t->car == NODE_ARRAY && nosplat(t->cdr)) { - /* fixed rhs */ - t = t->cdr; - while (t) { - codegen(s, t->car, VAL); - len++; - t = t->cdr; - } - tree = tree->car; - if (tree->car) { /* pre */ - t = tree->car; - n = 0; - while (t) { - gen_assignment(s, t->car, rhs+n, NOVAL); - n++; - t = t->cdr; - } - } - t = tree->cdr; - if (t) { - if (t->cdr) { /* post count */ - p = t->cdr->car; - while (p) { - post++; - p = p->cdr; - } - } - if (t->car) { /* rest (len - pre - post) */ - int rn; - - if (len < post + n) { - rn = 0; - } - else { - rn = len - post - n; - } - genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn)); - gen_assignment(s, t->car, cursp(), NOVAL); - n += rn; - } - if (t->cdr && t->cdr->car) { - t = t->cdr->car; - while (ncar, rhs+n, NOVAL); - t = t->cdr; - n++; - } - } - } - pop_n(len); - if (val) { - genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len)); - push(); - } - } - else { - /* variable rhs */ - codegen(s, t, VAL); - gen_vmassignment(s, tree->car, rhs, val); - if (!val) { - pop(); - } - } - } - break; - - case NODE_OP_ASGN: - { - mrb_sym sym = sym(tree->cdr->car); - mrb_int len; - const char *name = mrb_sym2name_len(s->mrb, sym, &len); - int idx; - - codegen(s, tree->car, VAL); - if (len == 2 && - ((name[0] == '|' && name[1] == '|') || - (name[0] == '&' && name[1] == '&'))) { - int pos; - - pop(); - pos = genop_peep(s, MKOP_AsBx(name[0] == '|' ? OP_JMPIF : OP_JMPNOT, cursp(), 0), NOVAL); - codegen(s, tree->cdr->cdr->car, VAL); - pop(); - gen_assignment(s, tree->car, cursp(), val); - dispatch(s, pos); - break; - } - codegen(s, tree->cdr->cdr->car, VAL); - push(); pop(); - pop(); pop(); - - idx = new_msym(s, sym); - if (len == 1 && name[0] == '+') { - genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val); - } - else if (len == 1 && name[0] == '-') { - genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val); - } - else if (len == 1 && name[0] == '*') { - genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1)); - } - else if (len == 1 && name[0] == '/') { - genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1)); - } - else if (len == 1 && name[0] == '<') { - genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1)); - } - else if (len == 2 && name[0] == '<' && name[1] == '=') { - genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1)); - } - else if (len == 1 && name[0] == '>') { - genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1)); - } - else if (len == 2 && name[0] == '>' && name[1] == '=') { - genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1)); - } - else { - genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1)); - } - } - gen_assignment(s, tree->car, cursp(), val); - break; - - case NODE_SUPER: - { - int n = 0, noop = 0, sendv = 0; - - push(); /* room for receiver */ - if (tree) { - node *args = tree->car; - if (args) { - n = gen_values(s, args, VAL); - if (n < 0) { - n = noop = sendv = 1; - push(); - } - } - } - if (tree && tree->cdr) { - codegen(s, tree->cdr, VAL); - pop(); - } - else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - push(); pop(); - } - pop_n(n+1); - if (sendv) n = CALL_MAXARGS; - genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n)); - if (val) push(); - } - break; - - case NODE_ZSUPER: - { - codegen_scope *s2 = s; - int lv = 0, ainfo = 0; - - push(); /* room for receiver */ - while (!s2->mscope) { - lv++; - s2 = s2->prev; - if (!s2) break; - } - if (s2) ainfo = s2->ainfo; - genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf))); - push(); push(); pop(); /* ARGARY pushes two values */ - if (tree && tree->cdr) { - codegen(s, tree->cdr, VAL); - pop(); - } - pop(); pop(); - genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS)); - if (val) push(); - } - break; - - case NODE_RETURN: - if (tree) { - codegen(s, tree, VAL); - pop(); - } - else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - } - if (s->loop) { - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN)); - } - else { - genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); - } - if (val) push(); - break; - - case NODE_YIELD: - { - codegen_scope *s2 = s; - int lv = 0, ainfo = 0; - int n = 0, sendv = 0; - - while (!s2->mscope) { - lv++; - s2 = s2->prev; - if (!s2) break; - } - if (s2) ainfo = s2->ainfo; - genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf))); - push(); - if (tree) { - n = gen_values(s, tree, VAL); - if (n < 0) { - n = sendv = 1; - push(); - } - } - pop_n(n+1); - if (sendv) n = CALL_MAXARGS; - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n)); - if (val) push(); - } - break; - - case NODE_BREAK: - loop_break(s, tree); - if (val) push(); - break; - - case NODE_NEXT: - if (!s->loop) { - raise_error(s, "unexpected next"); - } - else if (s->loop->type == LOOP_NORMAL) { - if (s->ensure_level > s->loop->ensure_level) { - genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL); - } - codegen(s, tree, NOVAL); - genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc)); - } - else { - if (tree) { - codegen(s, tree, VAL); - pop(); - } - else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - } - genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); - } - if (val) push(); - break; - - case NODE_REDO: - if (!s->loop) { - raise_error(s, "unexpected redo"); - } - else { - if (s->ensure_level > s->loop->ensure_level) { - genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL); - } - genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc)); - } - break; - - case NODE_RETRY: - { - const char *msg = "unexpected retry"; - - if (!s->loop) { - raise_error(s, msg); - } - else { - struct loopinfo *lp = s->loop; - int n = 0; - - while (lp && lp->type != LOOP_RESCUE) { - if (lp->type == LOOP_BEGIN) { - n++; - } - lp = lp->prev; - } - if (!lp) { - raise_error(s, msg); - } - else { - if (n > 0) { - while (n--) { - genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL); - } - } - if (s->ensure_level > lp->ensure_level) { - genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL); - } - genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc)); - } - } - } - break; - - case NODE_LVAR: - if (val) { - int idx = lv_idx(s, sym(tree)); - - if (idx > 0) { - genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL); - } - else { - int lv = 0; - codegen_scope *up = s->prev; - - while (up) { - idx = lv_idx(up, sym(tree)); - if (idx > 0) { - genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv)); - break; - } - lv++; - up = up->prev; - } - } - push(); - } - break; - - case NODE_GVAR: - if (val) { - int sym = new_sym(s, sym(tree)); - - genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); - push(); - } - break; - - case NODE_IVAR: - if (val) { - int sym = new_sym(s, sym(tree)); - - genop(s, MKOP_ABx(OP_GETIV, cursp(), sym)); - push(); - } - break; - - case NODE_CVAR: - if (val) { - int sym = new_sym(s, sym(tree)); - - genop(s, MKOP_ABx(OP_GETCV, cursp(), sym)); - push(); - } - break; - - case NODE_CONST: - { - int sym = new_sym(s, sym(tree)); - - genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym)); - if (val) { - push(); - } - } - break; - - case NODE_DEFINED: - codegen(s, tree, VAL); - break; - - case NODE_BACK_REF: - if (val) { - char buf[2] = { '$' }; - mrb_value str; - int sym; - - buf[1] = (char)(intptr_t)tree; - str = mrb_str_new(s->mrb, buf, 2); - sym = new_sym(s, mrb_intern_str(s->mrb, str)); - genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); - push(); - } - break; - - case NODE_NTH_REF: - if (val) { - int sym; - mrb_state *mrb = s->mrb; - mrb_value fix = mrb_fixnum_value((intptr_t)tree); - mrb_value str = mrb_str_buf_new(mrb, 4); - - mrb_str_cat_lit(mrb, str, "$"); - mrb_str_cat_str(mrb, str, mrb_fixnum_to_str(mrb, fix, 10)); - sym = new_sym(s, mrb_intern_str(mrb, str)); - genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); - push(); - } - break; - - case NODE_ARG: - /* should not happen */ - break; - - case NODE_BLOCK_ARG: - codegen(s, tree, VAL); - break; - - case NODE_INT: - if (val) { - char *p = (char*)tree->car; - int base = (intptr_t)tree->cdr->car; - mrb_int i; - mrb_code co; - mrb_bool overflow; - - i = readint_mrb_int(s, p, base, FALSE, &overflow); - if (overflow) { - double f = readint_float(s, p, base); - int off = new_lit(s, mrb_float_value(s->mrb, f)); - - genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); - } - else { - if (i < MAXARG_sBx && i > -MAXARG_sBx) { - co = MKOP_AsBx(OP_LOADI, cursp(), i); - } - else { - int off = new_lit(s, mrb_fixnum_value(i)); - co = MKOP_ABx(OP_LOADL, cursp(), off); - } - genop(s, co); - } - push(); - } - break; - - case NODE_FLOAT: - if (val) { - char *p = (char*)tree; - mrb_float f = str_to_mrb_float(p); - int off = new_lit(s, mrb_float_value(s->mrb, f)); - - genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); - push(); - } - break; - - case NODE_NEGATE: - { - nt = (intptr_t)tree->car; - tree = tree->cdr; - switch (nt) { - case NODE_FLOAT: - { - char *p = (char*)tree; - mrb_float f = str_to_mrb_float(p); - int off = new_lit(s, mrb_float_value(s->mrb, -f)); - - genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); - push(); - } - break; - - case NODE_INT: - { - char *p = (char*)tree->car; - int base = (intptr_t)tree->cdr->car; - mrb_int i; - mrb_code co; - mrb_bool overflow; - - i = readint_mrb_int(s, p, base, TRUE, &overflow); - if (overflow) { - double f = readint_float(s, p, base); - int off = new_lit(s, mrb_float_value(s->mrb, -f)); - - genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); - } - else { - if (i < MAXARG_sBx && i > -MAXARG_sBx) { - co = MKOP_AsBx(OP_LOADI, cursp(), i); - } - else { - int off = new_lit(s, mrb_fixnum_value(i)); - co = MKOP_ABx(OP_LOADL, cursp(), off); - } - genop(s, co); - } - push(); - } - break; - - default: - { - int sym = new_msym(s, mrb_intern_lit(s->mrb, "-")); - - genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); - push(); - codegen(s, tree, VAL); - pop(); pop(); - genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2)); - } - break; - } - } - break; - - case NODE_STR: - if (val) { - char *p = (char*)tree->car; - size_t len = (intptr_t)tree->cdr; - int ai = mrb_gc_arena_save(s->mrb); - int off = new_lit(s, mrb_str_new(s->mrb, p, len)); - - mrb_gc_arena_restore(s->mrb, ai); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); - push(); - } - break; - - case NODE_HEREDOC: - tree = ((struct mrb_parser_heredoc_info *)tree)->doc; - /* fall through */ - case NODE_DSTR: - if (val) { - node *n = tree; - - if (!n) break; - codegen(s, n->car, VAL); - n = n->cdr; - while (n) { - codegen(s, n->car, VAL); - pop(); pop(); - genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); - push(); - n = n->cdr; - } - } - else { - node *n = tree; - - while (n) { - if ((intptr_t)n->car->car != NODE_STR) { - codegen(s, n->car, NOVAL); - } - n = n->cdr; - } - } - break; - - case NODE_WORDS: - gen_literal_array(s, tree, FALSE, val); - break; - - case NODE_SYMBOLS: - gen_literal_array(s, tree, TRUE, val); - break; - - case NODE_DXSTR: - { - node *n; - int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel")); - - if (val == NOVAL) { push(); } - genop(s, MKOP_A(OP_OCLASS, cursp())); - genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); - push(); - codegen(s, tree->car, VAL); - n = tree->cdr; - while (n) { - if ((intptr_t)n->car->car == NODE_XSTR) { - n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR; - mrb_assert(!n->cdr); /* must be the end */ - } - codegen(s, n->car, VAL); - pop(); pop(); - genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); - push(); - n = n->cdr; - } - pop(); - pop(); - sym = new_sym(s, mrb_intern_lit(s->mrb, "`")); - genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); - if (val == NOVAL) { pop(); } - else { push(); } - mrb_gc_arena_restore(s->mrb, ai); - } - break; - - case NODE_XSTR: - { - char *p = (char*)tree->car; - size_t len = (intptr_t)tree->cdr; - int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel")); - int off = new_lit(s, mrb_str_new(s->mrb, p, len)); - - if (val == NOVAL) { push(); } - genop(s, MKOP_A(OP_OCLASS, cursp())); - genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); - push(); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); - pop(); - sym = new_sym(s, mrb_intern_lit(s->mrb, "`")); - genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); - if (val == NOVAL) { pop(); } - else { push(); } - mrb_gc_arena_restore(s->mrb, ai); - } - break; - - case NODE_REGX: - if (val) { - char *p1 = (char*)tree->car; - char *p2 = (char*)tree->cdr->car; - char *p3 = (char*)tree->cdr->cdr; - int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); - int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1)); - int argc = 1; - - genop(s, MKOP_A(OP_OCLASS, cursp())); - genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); - push(); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); - if (p2 || p3) { - push(); - if (p2) { - off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); - } else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - } - argc++; - if (p3) { - push(); - off = new_lit(s, mrb_str_new(s->mrb, p3, 1)); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); - argc++; - pop(); - } - pop(); - } - pop(); - sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); - genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); - mrb_gc_arena_restore(s->mrb, ai); - push(); - } - break; - - case NODE_DREGX: - if (val) { - node *n = tree->car; - int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); - int argc = 1; - int off; - char *p; - - genop(s, MKOP_A(OP_OCLASS, cursp())); - genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); - push(); - codegen(s, n->car, VAL); - n = n->cdr; - while (n) { - codegen(s, n->car, VAL); - pop(); pop(); - genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); - push(); - n = n->cdr; - } - n = tree->cdr->cdr; - if (n->car) { - p = (char*)n->car; - off = new_lit(s, mrb_str_new_cstr(s->mrb, p)); - codegen(s, tree->car, VAL); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); - pop(); - genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); - } - if (n->cdr) { - char *p2 = (char*)n->cdr; - - push(); - off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); - argc++; - pop(); - } - pop(); - sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); - genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); - mrb_gc_arena_restore(s->mrb, ai); - push(); - } - else { - node *n = tree->car; - - while (n) { - if ((intptr_t)n->car->car != NODE_STR) { - codegen(s, n->car, NOVAL); - } - n = n->cdr; - } - } - break; - - case NODE_SYM: - if (val) { - int sym = new_sym(s, sym(tree)); - - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); - push(); - } - break; - - case NODE_DSYM: - codegen(s, tree, val); - if (val) { - gen_send_intern(s); - } - break; - - case NODE_SELF: - if (val) { - genop(s, MKOP_A(OP_LOADSELF, cursp())); - push(); - } - break; - - case NODE_NIL: - if (val) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - push(); - } - break; - - case NODE_TRUE: - if (val) { - genop(s, MKOP_A(OP_LOADT, cursp())); - push(); - } - break; - - case NODE_FALSE: - if (val) { - genop(s, MKOP_A(OP_LOADF, cursp())); - push(); - } - break; - - case NODE_ALIAS: - { - int a = new_msym(s, sym(tree->car)); - int b = new_msym(s, sym(tree->cdr)); - int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method")); - - genop(s, MKOP_A(OP_TCLASS, cursp())); - push(); - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a)); - push(); - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b)); - push(); - genop(s, MKOP_A(OP_LOADNIL, cursp())); - pop_n(3); - genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2)); - if (val) { - push(); - } - } - break; - - case NODE_UNDEF: - { - int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method")); - int num = 0; - node *t = tree; - - genop(s, MKOP_A(OP_TCLASS, cursp())); - push(); - while (t) { - int symbol = new_msym(s, sym(t->car)); - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol)); - push(); - t = t->cdr; - num++; - } - pop_n(num + 1); - genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num)); - if (val) { - push(); - } - } - break; - - case NODE_CLASS: - { - int idx; - - if (tree->car->car == (node*)0) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - push(); - } - else if (tree->car->car == (node*)1) { - genop(s, MKOP_A(OP_OCLASS, cursp())); - push(); - } - else { - codegen(s, tree->car->car, VAL); - } - if (tree->cdr->car) { - codegen(s, tree->cdr->car, VAL); - } - else { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - push(); - } - pop(); pop(); - idx = new_msym(s, sym(tree->car->cdr)); - genop(s, MKOP_AB(OP_CLASS, cursp(), idx)); - idx = scope_body(s, tree->cdr->cdr->car, val); - genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); - if (val) { - push(); - } - } - break; - - case NODE_MODULE: - { - int idx; - - if (tree->car->car == (node*)0) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - push(); - } - else if (tree->car->car == (node*)1) { - genop(s, MKOP_A(OP_OCLASS, cursp())); - push(); - } - else { - codegen(s, tree->car->car, VAL); - } - pop(); - idx = new_msym(s, sym(tree->car->cdr)); - genop(s, MKOP_AB(OP_MODULE, cursp(), idx)); - idx = scope_body(s, tree->cdr->car, val); - genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); - if (val) { - push(); - } - } - break; - - case NODE_SCLASS: - { - int idx; - - codegen(s, tree->car, VAL); - pop(); - genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp())); - idx = scope_body(s, tree->cdr->car, val); - genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); - if (val) { - push(); - } - } - break; - - case NODE_DEF: - { - int sym = new_msym(s, sym(tree->car)); - int idx = lambda_body(s, tree->cdr, 0); - - genop(s, MKOP_A(OP_TCLASS, cursp())); - push(); - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD)); - push(); pop(); - pop(); - genop(s, MKOP_AB(OP_METHOD, cursp(), sym)); - if (val) { - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); - push(); - } - } - break; - - case NODE_SDEF: - { - node *recv = tree->car; - int sym = new_msym(s, sym(tree->cdr->car)); - int idx = lambda_body(s, tree->cdr->cdr, 0); - - codegen(s, recv, VAL); - pop(); - genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp())); - push(); - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD)); - pop(); - genop(s, MKOP_AB(OP_METHOD, cursp(), sym)); - if (val) { - genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); - push(); - } - } - break; - - case NODE_POSTEXE: - codegen(s, tree, NOVAL); - break; - - default: - break; - } -} - -static void -scope_add_irep(codegen_scope *s, mrb_irep *irep) -{ - if (s->irep == NULL) { - s->irep = irep; - return; - } - if (s->irep->rlen == s->rcapa) { - s->rcapa *= 2; - s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa); - } - s->irep->reps[s->irep->rlen] = irep; - s->irep->rlen++; -} - -static codegen_scope* -scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) -{ - static const codegen_scope codegen_scope_zero = { 0 }; - mrb_pool *pool = mrb_pool_open(mrb); - codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope)); - - if (!p) return NULL; - *p = codegen_scope_zero; - p->mrb = mrb; - p->mpool = pool; - if (!prev) return p; - p->prev = prev; - p->ainfo = -1; - p->mscope = 0; - - p->irep = mrb_add_irep(mrb); - scope_add_irep(prev, p->irep); - - p->rcapa = 8; - p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa); - - p->icapa = 1024; - p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); - p->irep->iseq = p->iseq; - - p->pcapa = 32; - p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); - p->irep->plen = 0; - - p->scapa = 256; - p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa); - p->irep->slen = 0; - - p->lv = lv; - p->sp += node_len(lv)+1; /* add self */ - p->nlocals = p->sp; - if (lv) { - node *n = lv; - size_t i = 0; - - p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1)); - for (i=0, n=lv; n; i++,n=n->cdr) { - p->irep->lv[i].name = lv_name(n); - if (lv_name(n)) { - p->irep->lv[i].r = lv_idx(p, lv_name(n)); - } - else { - p->irep->lv[i].r = 0; - } - } - mrb_assert(i + 1 == p->nlocals); - } - p->ai = mrb_gc_arena_save(mrb); - - p->filename = prev->filename; - if (p->filename) { - p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa); - } - p->lineno = prev->lineno; - - /* debug setting */ - p->debug_start_pos = 0; - if (p->filename) { - mrb_debug_info_alloc(mrb, p->irep); - p->irep->filename = p->filename; - p->irep->lines = p->lines; - } - else { - p->irep->debug_info = NULL; - } - p->parser = prev->parser; - p->filename_index = prev->filename_index; - - return p; -} - -static void -scope_finish(codegen_scope *s) -{ - mrb_state *mrb = s->mrb; - mrb_irep *irep = s->irep; - size_t fname_len; - char *fname; - - irep->flags = 0; - if (s->iseq) { - irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc); - irep->ilen = s->pc; - if (s->lines) { - irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc); - } - else { - irep->lines = 0; - } - } - irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen); - irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen); - irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen); - if (s->filename) { - s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); - mrb_debug_info_append_file(mrb, s->irep, s->debug_start_pos, s->pc); - - fname_len = strlen(s->filename); - fname = (char*)codegen_malloc(s, fname_len + 1); - memcpy(fname, s->filename, fname_len); - fname[fname_len] = '\0'; - irep->filename = fname; - } - - irep->nlocals = s->nlocals; - irep->nregs = s->nregs; - - mrb_gc_arena_restore(mrb, s->ai); - mrb_pool_close(s->mpool); -} - -static struct loopinfo* -loop_push(codegen_scope *s, enum looptype t) -{ - struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo)); - - p->type = t; - p->pc1 = p->pc2 = p->pc3 = 0; - p->prev = s->loop; - p->ensure_level = s->ensure_level; - p->acc = cursp(); - s->loop = p; - - return p; -} - -static void -loop_break(codegen_scope *s, node *tree) -{ - if (!s->loop) { - codegen(s, tree, NOVAL); - raise_error(s, "unexpected break"); - } - else { - struct loopinfo *loop; - - if (tree) { - codegen(s, tree, VAL); - pop(); - } - - loop = s->loop; - while (loop && loop->type == LOOP_BEGIN) { - genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL); - loop = loop->prev; - } - while (loop && loop->type == LOOP_RESCUE) { - loop = loop->prev; - } - if (!loop) { - codegen_error(s, "unexpected break"); - } - - if (loop->type == LOOP_NORMAL) { - int tmp; - - if (s->ensure_level > s->loop->ensure_level) { - genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL); - } - if (tree) { - genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL); - } - tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3)); - loop->pc3 = tmp; - } - else { - genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK)); - } - } -} - -static void -loop_pop(codegen_scope *s, int val) -{ - if (val) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - } - dispatch_linked(s, s->loop->pc3); - s->loop = s->loop->prev; - if (val) push(); -} - -MRB_API struct RProc* -mrb_generate_code(mrb_state *mrb, parser_state *p) -{ - codegen_scope *scope = scope_new(mrb, 0, 0); - struct RProc *proc; - - if (!scope) { - return NULL; - } - scope->mrb = mrb; - scope->parser = p; - scope->filename = p->filename; - scope->filename_index = p->current_filename_index; - - MRB_TRY(&scope->jmp) { - /* prepare irep */ - codegen(scope, p->tree, NOVAL); - proc = mrb_proc_new(mrb, scope->irep); - mrb_irep_decref(mrb, scope->irep); - mrb_pool_close(scope->mpool); - return proc; - } - MRB_CATCH(&scope->jmp) { - if (scope->filename == scope->irep->filename) { - scope->irep->filename = NULL; - } - mrb_irep_decref(mrb, scope->irep); - mrb_pool_close(scope->mpool); - return NULL; - } - MRB_END_EXC(&scope->jmp); -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/core/keywords nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/core/keywords --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/core/keywords 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/core/keywords 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -%{ -struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;}; -const struct kwtable *mrb_reserved_word(const char *, unsigned int); -static const struct kwtable *reserved_word(const char *, unsigned int); -#define mrb_reserved_word(str, len) reserved_word(str, len) -%} - -struct kwtable; -%% -__ENCODING__, {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END -__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END -__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END -BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END -END, {keyword_END, keyword_END}, EXPR_END -alias, {keyword_alias, keyword_alias}, EXPR_FNAME -and, {keyword_and, keyword_and}, EXPR_VALUE -begin, {keyword_begin, keyword_begin}, EXPR_BEG -break, {keyword_break, keyword_break}, EXPR_MID -case, {keyword_case, keyword_case}, EXPR_VALUE -class, {keyword_class, keyword_class}, EXPR_CLASS -def, {keyword_def, keyword_def}, EXPR_FNAME -do, {keyword_do, keyword_do}, EXPR_BEG -else, {keyword_else, keyword_else}, EXPR_BEG -elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE -end, {keyword_end, keyword_end}, EXPR_END -ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG -false, {keyword_false, keyword_false}, EXPR_END -for, {keyword_for, keyword_for}, EXPR_VALUE -if, {keyword_if, modifier_if}, EXPR_VALUE -in, {keyword_in, keyword_in}, EXPR_VALUE -module, {keyword_module, keyword_module}, EXPR_VALUE -next, {keyword_next, keyword_next}, EXPR_MID -nil, {keyword_nil, keyword_nil}, EXPR_END -not, {keyword_not, keyword_not}, EXPR_ARG -or, {keyword_or, keyword_or}, EXPR_VALUE -redo, {keyword_redo, keyword_redo}, EXPR_END -rescue, {keyword_rescue, modifier_rescue}, EXPR_MID -retry, {keyword_retry, keyword_retry}, EXPR_END -return, {keyword_return, keyword_return}, EXPR_MID -self, {keyword_self, keyword_self}, EXPR_END -super, {keyword_super, keyword_super}, EXPR_ARG -then, {keyword_then, keyword_then}, EXPR_BEG -true, {keyword_true, keyword_true}, EXPR_END -undef, {keyword_undef, keyword_undef}, EXPR_FNAME -unless, {keyword_unless, modifier_unless}, EXPR_VALUE -until, {keyword_until, modifier_until}, EXPR_VALUE -when, {keyword_when, keyword_when}, EXPR_VALUE -while, {keyword_while, modifier_while}, EXPR_VALUE -yield, {keyword_yield, keyword_yield}, EXPR_ARG -%% diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/core/lex.def nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/core/lex.def --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/core/lex.def 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/core/lex.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,212 +0,0 @@ -/* ANSI-C code produced by gperf version 3.0.4 */ -/* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' /home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords */ - -#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ - && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ - && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ - && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ - && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ - && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ - && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ - && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ - && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ - && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ - && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ - && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ - && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ - && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ - && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ - && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ - && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ - && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ - && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ - && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ - && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ - && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ - && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) -/* The character set is not based on ISO-646. */ -#error "gperf generated tables don't work with this execution character set. Please report a bug to ." -#endif - -#line 1 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - -struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;}; -const struct kwtable *mrb_reserved_word(const char *, unsigned int); -static const struct kwtable *reserved_word(const char *, unsigned int); -#define mrb_reserved_word(str, len) reserved_word(str, len) -#line 8 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" -struct kwtable; - -#define TOTAL_KEYWORDS 40 -#define MIN_WORD_LENGTH 2 -#define MAX_WORD_LENGTH 12 -#define MIN_HASH_VALUE 8 -#define MAX_HASH_VALUE 50 -/* maximum key range = 43, duplicates = 0 */ - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static unsigned int -hash (register const char *str, register unsigned int len) -{ - static const unsigned char asso_values[] = - { - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 14, 51, 16, 8, - 11, 13, 51, 51, 51, 51, 10, 51, 13, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 11, 51, 13, 1, 26, - 4, 1, 8, 28, 51, 23, 51, 1, 1, 27, - 5, 19, 21, 51, 8, 3, 3, 11, 51, 21, - 24, 16, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, - 51, 51, 51, 51, 51, 51 - }; - register int hval = len; - - switch (hval) - { - default: - hval += asso_values[(unsigned char)str[2]]; - /*FALLTHROUGH*/ - case 2: - case 1: - hval += asso_values[(unsigned char)str[0]]; - break; - } - return hval + asso_values[(unsigned char)str[len - 1]]; -} - -#ifdef __GNUC__ -__inline -#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ -__attribute__ ((__gnu_inline__)) -#endif -#endif -const struct kwtable * -mrb_reserved_word (register const char *str, register unsigned int len) -{ - static const struct kwtable wordlist[] = - { - {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, -#line 18 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"break", {keyword_break, keyword_break}, EXPR_MID}, -#line 23 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"else", {keyword_else, keyword_else}, EXPR_BEG}, -#line 33 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"nil", {keyword_nil, keyword_nil}, EXPR_END}, -#line 26 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG}, -#line 25 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"end", {keyword_end, keyword_end}, EXPR_END}, -#line 42 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"then", {keyword_then, keyword_then}, EXPR_BEG}, -#line 34 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"not", {keyword_not, keyword_not}, EXPR_ARG}, -#line 27 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"false", {keyword_false, keyword_false}, EXPR_END}, -#line 40 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"self", {keyword_self, keyword_self}, EXPR_END}, -#line 24 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE}, -#line 37 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID}, -#line 43 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"true", {keyword_true, keyword_true}, EXPR_END}, -#line 46 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"until", {keyword_until, modifier_until}, EXPR_VALUE}, -#line 45 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE}, -#line 39 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"return", {keyword_return, keyword_return}, EXPR_MID}, -#line 21 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"def", {keyword_def, keyword_def}, EXPR_FNAME}, -#line 16 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"and", {keyword_and, keyword_and}, EXPR_VALUE}, -#line 22 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"do", {keyword_do, keyword_do}, EXPR_BEG}, -#line 49 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"yield", {keyword_yield, keyword_yield}, EXPR_ARG}, -#line 28 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"for", {keyword_for, keyword_for}, EXPR_VALUE}, -#line 44 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME}, -#line 35 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"or", {keyword_or, keyword_or}, EXPR_VALUE}, -#line 30 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"in", {keyword_in, keyword_in}, EXPR_VALUE}, -#line 47 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"when", {keyword_when, keyword_when}, EXPR_VALUE}, -#line 38 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"retry", {keyword_retry, keyword_retry}, EXPR_END}, -#line 29 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"if", {keyword_if, modifier_if}, EXPR_VALUE}, -#line 19 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"case", {keyword_case, keyword_case}, EXPR_VALUE}, -#line 36 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"redo", {keyword_redo, keyword_redo}, EXPR_END}, -#line 32 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"next", {keyword_next, keyword_next}, EXPR_MID}, -#line 41 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"super", {keyword_super, keyword_super}, EXPR_ARG}, -#line 31 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"module", {keyword_module, keyword_module}, EXPR_VALUE}, -#line 17 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"begin", {keyword_begin, keyword_begin}, EXPR_BEG}, -#line 12 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END}, -#line 11 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END}, -#line 10 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END}, -#line 14 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"END", {keyword_END, keyword_END}, EXPR_END}, -#line 15 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME}, -#line 13 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END}, - {""}, -#line 20 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"class", {keyword_class, keyword_class}, EXPR_CLASS}, - {""}, {""}, -#line 48 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - {"while", {keyword_while, modifier_while}, EXPR_VALUE} - }; - - if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) - { - register int key = hash (str, len); - - if (key <= MAX_HASH_VALUE && key >= 0) - { - register const char *s = wordlist[key].name; - - if (*str == *s && !strcmp (str + 1, s + 1)) - return &wordlist[key]; - } - } - return 0; -} -#line 50 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords" - diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/core/node.h nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/core/node.h --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/core/node.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/core/node.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -/* -** node.h - nodes of abstract syntax tree -** -** See Copyright Notice in mruby.h -*/ - -#ifndef NODE_H -#define NODE_H - -enum node_type { - NODE_METHOD, - NODE_FBODY, - NODE_CFUNC, - NODE_SCOPE, - NODE_BLOCK, - NODE_IF, - NODE_CASE, - NODE_WHEN, - NODE_OPT_N, - NODE_WHILE, - NODE_UNTIL, - NODE_ITER, - NODE_FOR, - NODE_BREAK, - NODE_NEXT, - NODE_REDO, - NODE_RETRY, - NODE_BEGIN, - NODE_RESCUE, - NODE_ENSURE, - NODE_AND, - NODE_OR, - NODE_NOT, - NODE_MASGN, - NODE_ASGN, - NODE_CDECL, - NODE_CVASGN, - NODE_CVDECL, - NODE_OP_ASGN, - NODE_CALL, - NODE_FCALL, - NODE_VCALL, - NODE_SUPER, - NODE_ZSUPER, - NODE_ARRAY, - NODE_ZARRAY, - NODE_HASH, - NODE_RETURN, - NODE_YIELD, - NODE_LVAR, - NODE_DVAR, - NODE_GVAR, - NODE_IVAR, - NODE_CONST, - NODE_CVAR, - NODE_NTH_REF, - NODE_BACK_REF, - NODE_MATCH, - NODE_MATCH2, - NODE_MATCH3, - NODE_INT, - NODE_FLOAT, - NODE_NEGATE, - NODE_LAMBDA, - NODE_SYM, - NODE_STR, - NODE_DSTR, - NODE_XSTR, - NODE_DXSTR, - NODE_REGX, - NODE_DREGX, - NODE_DREGX_ONCE, - NODE_LIST, - NODE_ARG, - NODE_ARGSCAT, - NODE_ARGSPUSH, - NODE_SPLAT, - NODE_TO_ARY, - NODE_SVALUE, - NODE_BLOCK_ARG, - NODE_DEF, - NODE_SDEF, - NODE_ALIAS, - NODE_UNDEF, - NODE_CLASS, - NODE_MODULE, - NODE_SCLASS, - NODE_COLON2, - NODE_COLON3, - NODE_CREF, - NODE_DOT2, - NODE_DOT3, - NODE_FLIP2, - NODE_FLIP3, - NODE_ATTRSET, - NODE_SELF, - NODE_NIL, - NODE_TRUE, - NODE_FALSE, - NODE_DEFINED, - NODE_NEWLINE, - NODE_POSTEXE, - NODE_ALLOCA, - NODE_DMETHOD, - NODE_BMETHOD, - NODE_MEMO, - NODE_IFUNC, - NODE_DSYM, - NODE_ATTRASGN, - NODE_HEREDOC, - NODE_LITERAL_DELIM, - NODE_WORDS, - NODE_SYMBOLS, - NODE_LAST -}; - -#endif /* NODE_H */ diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/core/parse.y nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/core/parse.y --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/core/parse.y 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/core/parse.y 1970-01-01 00:00:00.000000000 +0000 @@ -1,6436 +0,0 @@ -/* -** parse.y - mruby parser -** -** See Copyright Notice in mruby.h -*/ - -%{ -#undef PARSER_DEBUG -#ifdef PARSER_DEBUG -# define YYDEBUG 1 -#endif -#define YYERROR_VERBOSE 1 -/* - * Force yacc to use our memory management. This is a little evil because - * the macros assume that "parser_state *p" is in scope - */ -#define YYMALLOC(n) mrb_malloc(p->mrb, (n)) -#define YYFREE(o) mrb_free(p->mrb, (o)) -#define YYSTACK_USE_ALLOCA 0 - -#include -#include -#include -#include -#include "mruby.h" -#include "mruby/compile.h" -#include "mruby/proc.h" -#include "mruby/error.h" -#include "node.h" -#include "mruby/throw.h" - -#define YYLEX_PARAM p - -typedef mrb_ast_node node; -typedef struct mrb_parser_state parser_state; -typedef struct mrb_parser_heredoc_info parser_heredoc_info; - -static int yyparse(parser_state *p); -static int yylex(void *lval, parser_state *p); -static void yyerror(parser_state *p, const char *s); -static void yywarn(parser_state *p, const char *s); -static void yywarning(parser_state *p, const char *s); -static void backref_error(parser_state *p, node *n); -static void tokadd(parser_state *p, int32_t c); - -#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) - -typedef unsigned int stack_type; - -#define BITSTACK_PUSH(stack, n) ((stack) = ((stack)<<1)|((n)&1)) -#define BITSTACK_POP(stack) ((stack) = (stack) >> 1) -#define BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1)) -#define BITSTACK_SET_P(stack) ((stack)&1) - -#define COND_PUSH(n) BITSTACK_PUSH(p->cond_stack, (n)) -#define COND_POP() BITSTACK_POP(p->cond_stack) -#define COND_LEXPOP() BITSTACK_LEXPOP(p->cond_stack) -#define COND_P() BITSTACK_SET_P(p->cond_stack) - -#define CMDARG_PUSH(n) BITSTACK_PUSH(p->cmdarg_stack, (n)) -#define CMDARG_POP() BITSTACK_POP(p->cmdarg_stack) -#define CMDARG_LEXPOP() BITSTACK_LEXPOP(p->cmdarg_stack) -#define CMDARG_P() BITSTACK_SET_P(p->cmdarg_stack) - -#define SET_LINENO(c,n) ((c)->lineno = (n)) -#define NODE_LINENO(c,n) do {\ - if (n) {\ - (c)->filename_index = (n)->filename_index;\ - (c)->lineno = (n)->lineno;\ - }\ -} while (0) - -#define sym(x) ((mrb_sym)(intptr_t)(x)) -#define nsym(x) ((node*)(intptr_t)(x)) - -static inline mrb_sym -intern_cstr_gen(parser_state *p, const char *s) -{ - return mrb_intern_cstr(p->mrb, s); -} -#define intern_cstr(s) intern_cstr_gen(p,(s)) - -static inline mrb_sym -intern_gen(parser_state *p, const char *s, size_t len) -{ - return mrb_intern(p->mrb, s, len); -} -#define intern(s,len) intern_gen(p,(s),(len)) - -static inline mrb_sym -intern_gen_c(parser_state *p, const char c) -{ - return mrb_intern(p->mrb, &c, 1); -} -#define intern_c(c) intern_gen_c(p,(c)) - -static void -cons_free_gen(parser_state *p, node *cons) -{ - cons->cdr = p->cells; - p->cells = cons; -} -#define cons_free(c) cons_free_gen(p, (c)) - -static void* -parser_palloc(parser_state *p, size_t size) -{ - void *m = mrb_pool_alloc(p->pool, size); - - if (!m) { - MRB_THROW(p->jmp); - } - return m; -} - -static node* -cons_gen(parser_state *p, node *car, node *cdr) -{ - node *c; - - if (p->cells) { - c = p->cells; - p->cells = p->cells->cdr; - } - else { - c = (node *)parser_palloc(p, sizeof(mrb_ast_node)); - } - - c->car = car; - c->cdr = cdr; - c->lineno = p->lineno; - c->filename_index = p->current_filename_index; - return c; -} -#define cons(a,b) cons_gen(p,(a),(b)) - -static node* -list1_gen(parser_state *p, node *a) -{ - return cons(a, 0); -} -#define list1(a) list1_gen(p, (a)) - -static node* -list2_gen(parser_state *p, node *a, node *b) -{ - return cons(a, cons(b,0)); -} -#define list2(a,b) list2_gen(p, (a),(b)) - -static node* -list3_gen(parser_state *p, node *a, node *b, node *c) -{ - return cons(a, cons(b, cons(c,0))); -} -#define list3(a,b,c) list3_gen(p, (a),(b),(c)) - -static node* -list4_gen(parser_state *p, node *a, node *b, node *c, node *d) -{ - return cons(a, cons(b, cons(c, cons(d, 0)))); -} -#define list4(a,b,c,d) list4_gen(p, (a),(b),(c),(d)) - -static node* -list5_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e) -{ - return cons(a, cons(b, cons(c, cons(d, cons(e, 0))))); -} -#define list5(a,b,c,d,e) list5_gen(p, (a),(b),(c),(d),(e)) - -static node* -list6_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e, node *f) -{ - return cons(a, cons(b, cons(c, cons(d, cons(e, cons(f, 0)))))); -} -#define list6(a,b,c,d,e,f) list6_gen(p, (a),(b),(c),(d),(e),(f)) - -static node* -append_gen(parser_state *p, node *a, node *b) -{ - node *c = a; - - if (!a) return b; - while (c->cdr) { - c = c->cdr; - } - if (b) { - c->cdr = b; - } - return a; -} -#define append(a,b) append_gen(p,(a),(b)) -#define push(a,b) append_gen(p,(a),list1(b)) - -static char* -parser_strndup(parser_state *p, const char *s, size_t len) -{ - char *b = (char *)parser_palloc(p, len+1); - - memcpy(b, s, len); - b[len] = '\0'; - return b; -} -#undef strndup -#define strndup(s,len) parser_strndup(p, s, len) - -static char* -parser_strdup(parser_state *p, const char *s) -{ - return parser_strndup(p, s, strlen(s)); -} -#undef strdup -#define strdup(s) parser_strdup(p, s) - -/* xxx ----------------------------- */ - -static node* -local_switch(parser_state *p) -{ - node *prev = p->locals; - - p->locals = cons(0, 0); - return prev; -} - -static void -local_resume(parser_state *p, node *prev) -{ - p->locals = prev; -} - -static void -local_nest(parser_state *p) -{ - p->locals = cons(0, p->locals); -} - -static void -local_unnest(parser_state *p) -{ - if (p->locals) { - p->locals = p->locals->cdr; - } -} - -static mrb_bool -local_var_p(parser_state *p, mrb_sym sym) -{ - node *l = p->locals; - - while (l) { - node *n = l->car; - while (n) { - if (sym(n->car) == sym) return TRUE; - n = n->cdr; - } - l = l->cdr; - } - return FALSE; -} - -static void -local_add_f(parser_state *p, mrb_sym sym) -{ - if (p->locals) { - p->locals->car = push(p->locals->car, nsym(sym)); - } -} - -static void -local_add(parser_state *p, mrb_sym sym) -{ - if (!local_var_p(p, sym)) { - local_add_f(p, sym); - } -} - -static node* -locals_node(parser_state *p) -{ - return p->locals ? p->locals->car : NULL; -} - -/* (:scope (vars..) (prog...)) */ -static node* -new_scope(parser_state *p, node *body) -{ - return cons((node*)NODE_SCOPE, cons(locals_node(p), body)); -} - -/* (:begin prog...) */ -static node* -new_begin(parser_state *p, node *body) -{ - if (body) { - return list2((node*)NODE_BEGIN, body); - } - return cons((node*)NODE_BEGIN, 0); -} - -#define newline_node(n) (n) - -/* (:rescue body rescue else) */ -static node* -new_rescue(parser_state *p, node *body, node *resq, node *els) -{ - return list4((node*)NODE_RESCUE, body, resq, els); -} - -/* (:ensure body ensure) */ -static node* -new_ensure(parser_state *p, node *a, node *b) -{ - return cons((node*)NODE_ENSURE, cons(a, cons(0, b))); -} - -/* (:nil) */ -static node* -new_nil(parser_state *p) -{ - return list1((node*)NODE_NIL); -} - -/* (:true) */ -static node* -new_true(parser_state *p) -{ - return list1((node*)NODE_TRUE); -} - -/* (:false) */ -static node* -new_false(parser_state *p) -{ - return list1((node*)NODE_FALSE); -} - -/* (:alias new old) */ -static node* -new_alias(parser_state *p, mrb_sym a, mrb_sym b) -{ - return cons((node*)NODE_ALIAS, cons(nsym(a), nsym(b))); -} - -/* (:if cond then else) */ -static node* -new_if(parser_state *p, node *a, node *b, node *c) -{ - return list4((node*)NODE_IF, a, b, c); -} - -/* (:unless cond then else) */ -static node* -new_unless(parser_state *p, node *a, node *b, node *c) -{ - return list4((node*)NODE_IF, a, c, b); -} - -/* (:while cond body) */ -static node* -new_while(parser_state *p, node *a, node *b) -{ - return cons((node*)NODE_WHILE, cons(a, b)); -} - -/* (:until cond body) */ -static node* -new_until(parser_state *p, node *a, node *b) -{ - return cons((node*)NODE_UNTIL, cons(a, b)); -} - -/* (:for var obj body) */ -static node* -new_for(parser_state *p, node *v, node *o, node *b) -{ - return list4((node*)NODE_FOR, v, o, b); -} - -/* (:case a ((when ...) body) ((when...) body)) */ -static node* -new_case(parser_state *p, node *a, node *b) -{ - node *n = list2((node*)NODE_CASE, a); - node *n2 = n; - - while (n2->cdr) { - n2 = n2->cdr; - } - n2->cdr = b; - return n; -} - -/* (:postexe a) */ -static node* -new_postexe(parser_state *p, node *a) -{ - return cons((node*)NODE_POSTEXE, a); -} - -/* (:self) */ -static node* -new_self(parser_state *p) -{ - return list1((node*)NODE_SELF); -} - -/* (:call a b c) */ -static node* -new_call(parser_state *p, node *a, mrb_sym b, node *c) -{ - node *n = list4((node*)NODE_CALL, a, nsym(b), c); - NODE_LINENO(n, a); - return n; -} - -/* (:fcall self mid args) */ -static node* -new_fcall(parser_state *p, mrb_sym b, node *c) -{ - node *n = new_self(p); - NODE_LINENO(n, c); - n = list4((node*)NODE_FCALL, n, nsym(b), c); - NODE_LINENO(n, c); - return n; -} - -/* (:super . c) */ -static node* -new_super(parser_state *p, node *c) -{ - return cons((node*)NODE_SUPER, c); -} - -/* (:zsuper) */ -static node* -new_zsuper(parser_state *p) -{ - return list1((node*)NODE_ZSUPER); -} - -/* (:yield . c) */ -static node* -new_yield(parser_state *p, node *c) -{ - if (c) { - if (c->cdr) { - yyerror(p, "both block arg and actual block given"); - } - return cons((node*)NODE_YIELD, c->car); - } - return cons((node*)NODE_YIELD, 0); -} - -/* (:return . c) */ -static node* -new_return(parser_state *p, node *c) -{ - return cons((node*)NODE_RETURN, c); -} - -/* (:break . c) */ -static node* -new_break(parser_state *p, node *c) -{ - return cons((node*)NODE_BREAK, c); -} - -/* (:next . c) */ -static node* -new_next(parser_state *p, node *c) -{ - return cons((node*)NODE_NEXT, c); -} - -/* (:redo) */ -static node* -new_redo(parser_state *p) -{ - return list1((node*)NODE_REDO); -} - -/* (:retry) */ -static node* -new_retry(parser_state *p) -{ - return list1((node*)NODE_RETRY); -} - -/* (:dot2 a b) */ -static node* -new_dot2(parser_state *p, node *a, node *b) -{ - return cons((node*)NODE_DOT2, cons(a, b)); -} - -/* (:dot3 a b) */ -static node* -new_dot3(parser_state *p, node *a, node *b) -{ - return cons((node*)NODE_DOT3, cons(a, b)); -} - -/* (:colon2 b c) */ -static node* -new_colon2(parser_state *p, node *b, mrb_sym c) -{ - return cons((node*)NODE_COLON2, cons(b, nsym(c))); -} - -/* (:colon3 . c) */ -static node* -new_colon3(parser_state *p, mrb_sym c) -{ - return cons((node*)NODE_COLON3, nsym(c)); -} - -/* (:and a b) */ -static node* -new_and(parser_state *p, node *a, node *b) -{ - return cons((node*)NODE_AND, cons(a, b)); -} - -/* (:or a b) */ -static node* -new_or(parser_state *p, node *a, node *b) -{ - return cons((node*)NODE_OR, cons(a, b)); -} - -/* (:array a...) */ -static node* -new_array(parser_state *p, node *a) -{ - return cons((node*)NODE_ARRAY, a); -} - -/* (:splat . a) */ -static node* -new_splat(parser_state *p, node *a) -{ - return cons((node*)NODE_SPLAT, a); -} - -/* (:hash (k . v) (k . v)...) */ -static node* -new_hash(parser_state *p, node *a) -{ - return cons((node*)NODE_HASH, a); -} - -/* (:sym . a) */ -static node* -new_sym(parser_state *p, mrb_sym sym) -{ - return cons((node*)NODE_SYM, nsym(sym)); -} - -static mrb_sym -new_strsym(parser_state *p, node* str) -{ - const char *s = (const char*)str->cdr->car; - size_t len = (size_t)str->cdr->cdr; - - return mrb_intern(p->mrb, s, len); -} - -/* (:lvar . a) */ -static node* -new_lvar(parser_state *p, mrb_sym sym) -{ - return cons((node*)NODE_LVAR, nsym(sym)); -} - -/* (:gvar . a) */ -static node* -new_gvar(parser_state *p, mrb_sym sym) -{ - return cons((node*)NODE_GVAR, nsym(sym)); -} - -/* (:ivar . a) */ -static node* -new_ivar(parser_state *p, mrb_sym sym) -{ - return cons((node*)NODE_IVAR, nsym(sym)); -} - -/* (:cvar . a) */ -static node* -new_cvar(parser_state *p, mrb_sym sym) -{ - return cons((node*)NODE_CVAR, nsym(sym)); -} - -/* (:const . a) */ -static node* -new_const(parser_state *p, mrb_sym sym) -{ - return cons((node*)NODE_CONST, nsym(sym)); -} - -/* (:undef a...) */ -static node* -new_undef(parser_state *p, mrb_sym sym) -{ - return list2((node*)NODE_UNDEF, nsym(sym)); -} - -/* (:class class super body) */ -static node* -new_class(parser_state *p, node *c, node *s, node *b) -{ - return list4((node*)NODE_CLASS, c, s, cons(locals_node(p), b)); -} - -/* (:sclass obj body) */ -static node* -new_sclass(parser_state *p, node *o, node *b) -{ - return list3((node*)NODE_SCLASS, o, cons(locals_node(p), b)); -} - -/* (:module module body) */ -static node* -new_module(parser_state *p, node *m, node *b) -{ - return list3((node*)NODE_MODULE, m, cons(locals_node(p), b)); -} - -/* (:def m lv (arg . body)) */ -static node* -new_def(parser_state *p, mrb_sym m, node *a, node *b) -{ - return list5((node*)NODE_DEF, nsym(m), locals_node(p), a, b); -} - -/* (:sdef obj m lv (arg . body)) */ -static node* -new_sdef(parser_state *p, node *o, mrb_sym m, node *a, node *b) -{ - return list6((node*)NODE_SDEF, o, nsym(m), locals_node(p), a, b); -} - -/* (:arg . sym) */ -static node* -new_arg(parser_state *p, mrb_sym sym) -{ - return cons((node*)NODE_ARG, nsym(sym)); -} - -/* (m o r m2 b) */ -/* m: (a b c) */ -/* o: ((a . e1) (b . e2)) */ -/* r: a */ -/* m2: (a b c) */ -/* b: a */ -static node* -new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, mrb_sym blk) -{ - node *n; - - n = cons(m2, nsym(blk)); - n = cons(nsym(rest), n); - n = cons(opt, n); - return cons(m, n); -} - -/* (:block_arg . a) */ -static node* -new_block_arg(parser_state *p, node *a) -{ - return cons((node*)NODE_BLOCK_ARG, a); -} - -/* (:block arg body) */ -static node* -new_block(parser_state *p, node *a, node *b) -{ - return list4((node*)NODE_BLOCK, locals_node(p), a, b); -} - -/* (:lambda arg body) */ -static node* -new_lambda(parser_state *p, node *a, node *b) -{ - return list4((node*)NODE_LAMBDA, locals_node(p), a, b); -} - -/* (:asgn lhs rhs) */ -static node* -new_asgn(parser_state *p, node *a, node *b) -{ - return cons((node*)NODE_ASGN, cons(a, b)); -} - -/* (:masgn mlhs=(pre rest post) mrhs) */ -static node* -new_masgn(parser_state *p, node *a, node *b) -{ - return cons((node*)NODE_MASGN, cons(a, b)); -} - -/* (:asgn lhs rhs) */ -static node* -new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b) -{ - return list4((node*)NODE_OP_ASGN, a, nsym(op), b); -} - -/* (:int . i) */ -static node* -new_int(parser_state *p, const char *s, int base) -{ - return list3((node*)NODE_INT, (node*)strdup(s), (node*)(intptr_t)base); -} - -/* (:float . i) */ -static node* -new_float(parser_state *p, const char *s) -{ - return cons((node*)NODE_FLOAT, (node*)strdup(s)); -} - -/* (:str . (s . len)) */ -static node* -new_str(parser_state *p, const char *s, int len) -{ - return cons((node*)NODE_STR, cons((node*)strndup(s, len), (node*)(intptr_t)len)); -} - -/* (:dstr . a) */ -static node* -new_dstr(parser_state *p, node *a) -{ - return cons((node*)NODE_DSTR, a); -} - -/* (:str . (s . len)) */ -static node* -new_xstr(parser_state *p, const char *s, int len) -{ - return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), (node*)(intptr_t)len)); -} - -/* (:xstr . a) */ -static node* -new_dxstr(parser_state *p, node *a) -{ - return cons((node*)NODE_DXSTR, a); -} - -/* (:dsym . a) */ -static node* -new_dsym(parser_state *p, node *a) -{ - return cons((node*)NODE_DSYM, new_dstr(p, a)); -} - -/* (:str . (a . a)) */ -static node* -new_regx(parser_state *p, const char *p1, const char* p2, const char* p3) -{ - return cons((node*)NODE_REGX, cons((node*)p1, cons((node*)p2, (node*)p3))); -} - -/* (:dregx . a) */ -static node* -new_dregx(parser_state *p, node *a, node *b) -{ - return cons((node*)NODE_DREGX, cons(a, b)); -} - -/* (:backref . n) */ -static node* -new_back_ref(parser_state *p, int n) -{ - return cons((node*)NODE_BACK_REF, (node*)(intptr_t)n); -} - -/* (:nthref . n) */ -static node* -new_nth_ref(parser_state *p, int n) -{ - return cons((node*)NODE_NTH_REF, (node*)(intptr_t)n); -} - -/* (:heredoc . a) */ -static node* -new_heredoc(parser_state *p) -{ - parser_heredoc_info *inf = (parser_heredoc_info *)parser_palloc(p, sizeof(parser_heredoc_info)); - return cons((node*)NODE_HEREDOC, (node*)inf); -} - -static void -new_bv(parser_state *p, mrb_sym id) -{ -} - -static node* -new_literal_delim(parser_state *p) -{ - return cons((node*)NODE_LITERAL_DELIM, 0); -} - -/* (:words . a) */ -static node* -new_words(parser_state *p, node *a) -{ - return cons((node*)NODE_WORDS, a); -} - -/* (:symbols . a) */ -static node* -new_symbols(parser_state *p, node *a) -{ - return cons((node*)NODE_SYMBOLS, a); -} - -/* xxx ----------------------------- */ - -/* (:call a op) */ -static node* -call_uni_op(parser_state *p, node *recv, const char *m) -{ - return new_call(p, recv, intern_cstr(m), 0); -} - -/* (:call a op b) */ -static node* -call_bin_op(parser_state *p, node *recv, const char *m, node *arg1) -{ - return new_call(p, recv, intern_cstr(m), list1(list1(arg1))); -} - -static void -args_with_block(parser_state *p, node *a, node *b) -{ - if (b) { - if (a->cdr) { - yyerror(p, "both block arg and actual block given"); - } - a->cdr = b; - } -} - -static void -call_with_block(parser_state *p, node *a, node *b) -{ - node *n; - - if (a->car == (node*)NODE_SUPER || - a->car == (node*)NODE_ZSUPER) { - if (!a->cdr) a->cdr = cons(0, b); - else { - args_with_block(p, a->cdr, b); - } - } - else { - n = a->cdr->cdr->cdr; - if (!n->car) n->car = cons(0, b); - else { - args_with_block(p, n->car, b); - } - } -} - -static node* -negate_lit(parser_state *p, node *n) -{ - return cons((node*)NODE_NEGATE, n); -} - -static node* -cond(node *n) -{ - return n; -} - -static node* -ret_args(parser_state *p, node *n) -{ - if (n->cdr) { - yyerror(p, "block argument should not be given"); - return NULL; - } - if (!n->car->cdr) return n->car->car; - return new_array(p, n->car); -} - -static void -assignable(parser_state *p, node *lhs) -{ - if ((int)(intptr_t)lhs->car == NODE_LVAR) { - local_add(p, sym(lhs->cdr)); - } -} - -static node* -var_reference(parser_state *p, node *lhs) -{ - node *n; - - if ((int)(intptr_t)lhs->car == NODE_LVAR) { - if (!local_var_p(p, sym(lhs->cdr))) { - n = new_fcall(p, sym(lhs->cdr), 0); - cons_free(lhs); - return n; - } - } - - return lhs; -} - -typedef enum mrb_string_type string_type; - -static node* -new_strterm(parser_state *p, string_type type, int term, int paren) -{ - return cons((node*)(intptr_t)type, cons((node*)0, cons((node*)(intptr_t)paren, (node*)(intptr_t)term))); -} - -static void -end_strterm(parser_state *p) -{ - cons_free(p->lex_strterm->cdr->cdr); - cons_free(p->lex_strterm->cdr); - cons_free(p->lex_strterm); - p->lex_strterm = NULL; -} - -static parser_heredoc_info * -parsing_heredoc_inf(parser_state *p) -{ - node *nd = p->parsing_heredoc; - if (nd == NULL) - return NULL; - /* mrb_assert(nd->car->car == NODE_HEREDOC); */ - return (parser_heredoc_info*)nd->car->cdr; -} - -static void -heredoc_treat_nextline(parser_state *p) -{ - if (p->heredocs_from_nextline == NULL) - return; - if (p->parsing_heredoc == NULL) { - node *n; - p->parsing_heredoc = p->heredocs_from_nextline; - p->lex_strterm_before_heredoc = p->lex_strterm; - p->lex_strterm = new_strterm(p, parsing_heredoc_inf(p)->type, 0, 0); - n = p->all_heredocs; - if (n) { - while (n->cdr) - n = n->cdr; - n->cdr = p->parsing_heredoc; - } - else { - p->all_heredocs = p->parsing_heredoc; - } - } - else { - node *n, *m; - m = p->heredocs_from_nextline; - while (m->cdr) - m = m->cdr; - n = p->all_heredocs; - mrb_assert(n != NULL); - if (n == p->parsing_heredoc) { - m->cdr = n; - p->all_heredocs = p->heredocs_from_nextline; - p->parsing_heredoc = p->heredocs_from_nextline; - } - else { - while (n->cdr != p->parsing_heredoc) { - n = n->cdr; - mrb_assert(n != NULL); - } - m->cdr = n->cdr; - n->cdr = p->heredocs_from_nextline; - p->parsing_heredoc = p->heredocs_from_nextline; - } - } - p->heredocs_from_nextline = NULL; -} - -static void -heredoc_end(parser_state *p) -{ - p->parsing_heredoc = p->parsing_heredoc->cdr; - if (p->parsing_heredoc == NULL) { - p->lstate = EXPR_BEG; - p->cmd_start = TRUE; - end_strterm(p); - p->lex_strterm = p->lex_strterm_before_heredoc; - p->lex_strterm_before_heredoc = NULL; - p->heredoc_end_now = TRUE; - } - else { - /* next heredoc */ - p->lex_strterm->car = (node*)(intptr_t)parsing_heredoc_inf(p)->type; - } -} -#define is_strterm_type(p,str_func) ((int)(intptr_t)((p)->lex_strterm->car) & (str_func)) - -/* xxx ----------------------------- */ - -%} - -%pure-parser -%parse-param {parser_state *p} -%lex-param {parser_state *p} - -%union { - node *nd; - mrb_sym id; - int num; - stack_type stack; - const struct vtable *vars; -} - -%token - keyword_class - keyword_module - keyword_def - keyword_begin - keyword_if - keyword_unless - keyword_while - keyword_until - keyword_for - -%token - keyword_undef - keyword_rescue - keyword_ensure - keyword_end - keyword_then - keyword_elsif - keyword_else - keyword_case - keyword_when - keyword_break - keyword_next - keyword_redo - keyword_retry - keyword_in - keyword_do - keyword_do_cond - keyword_do_block - keyword_do_LAMBDA - keyword_return - keyword_yield - keyword_super - keyword_self - keyword_nil - keyword_true - keyword_false - keyword_and - keyword_or - keyword_not - modifier_if - modifier_unless - modifier_while - modifier_until - modifier_rescue - keyword_alias - keyword_BEGIN - keyword_END - keyword__LINE__ - keyword__FILE__ - keyword__ENCODING__ - -%token tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL -%token tINTEGER tFLOAT tCHAR tXSTRING tREGEXP -%token tSTRING tSTRING_PART tSTRING_MID -%token tNTH_REF tBACK_REF -%token tREGEXP_END - -%type singleton string string_rep string_interp xstring regexp -%type literal numeric cpath symbol -%type top_compstmt top_stmts top_stmt -%type bodystmt compstmt stmts stmt expr arg primary command command_call method_call -%type expr_value arg_value primary_value -%type if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure -%type args call_args opt_call_args -%type paren_args opt_paren_args variable -%type command_args aref_args opt_block_arg block_arg var_ref var_lhs -%type command_asgn mrhs superclass block_call block_command -%type f_block_optarg f_block_opt -%type f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs -%type assoc_list assocs assoc undef_list backref for_var -%type block_param opt_block_param block_param_def f_opt -%type bv_decls opt_bv_decl bvar f_larglist lambda_body -%type brace_block cmd_brace_block do_block lhs none f_bad_arg -%type mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner -%type fsym sym basic_symbol operation operation2 operation3 -%type cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_opt_asgn -%type heredoc words symbols - -%token tUPLUS /* unary+ */ -%token tUMINUS /* unary- */ -%token tPOW /* ** */ -%token tCMP /* <=> */ -%token tEQ /* == */ -%token tEQQ /* === */ -%token tNEQ /* != */ -%token tGEQ /* >= */ -%token tLEQ /* <= */ -%token tANDOP tOROP /* && and || */ -%token tMATCH tNMATCH /* =~ and !~ */ -%token tDOT2 tDOT3 /* .. and ... */ -%token tAREF tASET /* [] and []= */ -%token tLSHFT tRSHFT /* << and >> */ -%token tCOLON2 /* :: */ -%token tCOLON3 /* :: at EXPR_BEG */ -%token tOP_ASGN /* +=, -= etc. */ -%token tASSOC /* => */ -%token tLPAREN /* ( */ -%token tLPAREN_ARG /* ( */ -%token tRPAREN /* ) */ -%token tLBRACK /* [ */ -%token tLBRACE /* { */ -%token tLBRACE_ARG /* { */ -%token tSTAR /* * */ -%token tAMPER /* & */ -%token tLAMBDA /* -> */ -%token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG -%token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG -%token tHEREDOC_BEG /* <<, <<- */ -%token tHEREDOC_END tLITERAL_DELIM tHD_LITERAL_DELIM -%token tHD_STRING_PART tHD_STRING_MID - -/* - * precedence table - */ - -%nonassoc tLOWEST -%nonassoc tLBRACE_ARG - -%nonassoc modifier_if modifier_unless modifier_while modifier_until -%left keyword_or keyword_and -%right keyword_not -%right '=' tOP_ASGN -%left modifier_rescue -%right '?' ':' -%nonassoc tDOT2 tDOT3 -%left tOROP -%left tANDOP -%nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH -%left '>' tGEQ '<' tLEQ -%left '|' '^' -%left '&' -%left tLSHFT tRSHFT -%left '+' '-' -%left '*' '/' '%' -%right tUMINUS_NUM tUMINUS -%right tPOW -%right '!' '~' tUPLUS - -%token tLAST_TOKEN - -%% -program : { - p->lstate = EXPR_BEG; - if (!p->locals) p->locals = cons(0,0); - } - top_compstmt - { - p->tree = new_scope(p, $2); - NODE_LINENO(p->tree, $2); - } - ; - -top_compstmt : top_stmts opt_terms - { - $$ = $1; - } - ; - -top_stmts : none - { - $$ = new_begin(p, 0); - } - | top_stmt - { - $$ = new_begin(p, $1); - NODE_LINENO($$, $1); - } - | top_stmts terms top_stmt - { - $$ = push($1, newline_node($3)); - } - | error top_stmt - { - $$ = new_begin(p, 0); - } - ; - -top_stmt : stmt - | keyword_BEGIN - { - $$ = local_switch(p); - } - '{' top_compstmt '}' - { - yyerror(p, "BEGIN not supported"); - local_resume(p, $2); - $$ = 0; - } - ; - -bodystmt : compstmt - opt_rescue - opt_else - opt_ensure - { - if ($2) { - $$ = new_rescue(p, $1, $2, $3); - NODE_LINENO($$, $1); - } - else if ($3) { - yywarn(p, "else without rescue is useless"); - $$ = push($1, $3); - } - else { - $$ = $1; - } - if ($4) { - if ($$) { - $$ = new_ensure(p, $$, $4); - } - else { - $$ = push($4, new_nil(p)); - } - } - } - ; - -compstmt : stmts opt_terms - { - $$ = $1; - } - ; - -stmts : none - { - $$ = new_begin(p, 0); - } - | stmt - { - $$ = new_begin(p, $1); - NODE_LINENO($$, $1); - } - | stmts terms stmt - { - $$ = push($1, newline_node($3)); - } - | error stmt - { - $$ = new_begin(p, $2); - } - ; - -stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym - { - $$ = new_alias(p, $2, $4); - } - | keyword_undef undef_list - { - $$ = $2; - } - | stmt modifier_if expr_value - { - $$ = new_if(p, cond($3), $1, 0); - } - | stmt modifier_unless expr_value - { - $$ = new_unless(p, cond($3), $1, 0); - } - | stmt modifier_while expr_value - { - $$ = new_while(p, cond($3), $1); - } - | stmt modifier_until expr_value - { - $$ = new_until(p, cond($3), $1); - } - | stmt modifier_rescue stmt - { - $$ = new_rescue(p, $1, list1(list3(0, 0, $3)), 0); - } - | keyword_END '{' compstmt '}' - { - yyerror(p, "END not suported"); - $$ = new_postexe(p, $3); - } - | command_asgn - | mlhs '=' command_call - { - $$ = new_masgn(p, $1, $3); - } - | var_lhs tOP_ASGN command_call - { - $$ = new_op_asgn(p, $1, $2, $3); - } - | primary_value '[' opt_call_args rbracket tOP_ASGN command_call - { - $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3), $5, $6); - } - | primary_value '.' tIDENTIFIER tOP_ASGN command_call - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | primary_value '.' tCONSTANT tOP_ASGN command_call - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call - { - yyerror(p, "constant re-assignment"); - $$ = 0; - } - | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | backref tOP_ASGN command_call - { - backref_error(p, $1); - $$ = new_begin(p, 0); - } - | lhs '=' mrhs - { - $$ = new_asgn(p, $1, new_array(p, $3)); - } - | mlhs '=' arg_value - { - $$ = new_masgn(p, $1, $3); - } - | mlhs '=' mrhs - { - $$ = new_masgn(p, $1, new_array(p, $3)); - } - | expr - ; - -command_asgn : lhs '=' command_call - { - $$ = new_asgn(p, $1, $3); - } - | lhs '=' command_asgn - { - $$ = new_asgn(p, $1, $3); - } - ; - - -expr : command_call - | expr keyword_and expr - { - $$ = new_and(p, $1, $3); - } - | expr keyword_or expr - { - $$ = new_or(p, $1, $3); - } - | keyword_not opt_nl expr - { - $$ = call_uni_op(p, cond($3), "!"); - } - | '!' command_call - { - $$ = call_uni_op(p, cond($2), "!"); - } - | arg - ; - -expr_value : expr - { - if (!$1) $$ = new_nil(p); - else $$ = $1; - } - ; - -command_call : command - | block_command - ; - -block_command : block_call - | block_call dot_or_colon operation2 command_args - ; - -cmd_brace_block : tLBRACE_ARG - { - local_nest(p); - } - opt_block_param - compstmt - '}' - { - $$ = new_block(p, $3, $4); - local_unnest(p); - } - ; - -command : operation command_args %prec tLOWEST - { - $$ = new_fcall(p, $1, $2); - } - | operation command_args cmd_brace_block - { - args_with_block(p, $2, $3); - $$ = new_fcall(p, $1, $2); - } - | primary_value '.' operation2 command_args %prec tLOWEST - { - $$ = new_call(p, $1, $3, $4); - } - | primary_value '.' operation2 command_args cmd_brace_block - { - args_with_block(p, $4, $5); - $$ = new_call(p, $1, $3, $4); - } - | primary_value tCOLON2 operation2 command_args %prec tLOWEST - { - $$ = new_call(p, $1, $3, $4); - } - | primary_value tCOLON2 operation2 command_args cmd_brace_block - { - args_with_block(p, $4, $5); - $$ = new_call(p, $1, $3, $4); - } - | keyword_super command_args - { - $$ = new_super(p, $2); - } - | keyword_yield command_args - { - $$ = new_yield(p, $2); - } - | keyword_return call_args - { - $$ = new_return(p, ret_args(p, $2)); - } - | keyword_break call_args - { - $$ = new_break(p, ret_args(p, $2)); - } - | keyword_next call_args - { - $$ = new_next(p, ret_args(p, $2)); - } - ; - -mlhs : mlhs_basic - { - $$ = $1; - } - | tLPAREN mlhs_inner rparen - { - $$ = $2; - } - ; - -mlhs_inner : mlhs_basic - | tLPAREN mlhs_inner rparen - { - $$ = $2; - } - ; - -mlhs_basic : mlhs_list - { - $$ = list1($1); - } - | mlhs_list mlhs_item - { - $$ = list1(push($1,$2)); - } - | mlhs_list tSTAR mlhs_node - { - $$ = list2($1, $3); - } - | mlhs_list tSTAR mlhs_node ',' mlhs_post - { - $$ = list3($1, $3, $5); - } - | mlhs_list tSTAR - { - $$ = list2($1, new_nil(p)); - } - | mlhs_list tSTAR ',' mlhs_post - { - $$ = list3($1, new_nil(p), $4); - } - | tSTAR mlhs_node - { - $$ = list2(0, $2); - } - | tSTAR mlhs_node ',' mlhs_post - { - $$ = list3(0, $2, $4); - } - | tSTAR - { - $$ = list2(0, new_nil(p)); - } - | tSTAR ',' mlhs_post - { - $$ = list3(0, new_nil(p), $3); - } - ; - -mlhs_item : mlhs_node - | tLPAREN mlhs_inner rparen - { - $$ = new_masgn(p, $2, NULL); - } - ; - -mlhs_list : mlhs_item ',' - { - $$ = list1($1); - } - | mlhs_list mlhs_item ',' - { - $$ = push($1, $2); - } - ; - -mlhs_post : mlhs_item - { - $$ = list1($1); - } - | mlhs_list mlhs_item - { - $$ = push($1, $2); - } - ; - -mlhs_node : variable - { - assignable(p, $1); - } - | primary_value '[' opt_call_args rbracket - { - $$ = new_call(p, $1, intern("[]",2), $3); - } - | primary_value '.' tIDENTIFIER - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value tCOLON2 tIDENTIFIER - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value '.' tCONSTANT - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value tCOLON2 tCONSTANT - { - if (p->in_def || p->in_single) - yyerror(p, "dynamic constant assignment"); - $$ = new_colon2(p, $1, $3); - } - | tCOLON3 tCONSTANT - { - if (p->in_def || p->in_single) - yyerror(p, "dynamic constant assignment"); - $$ = new_colon3(p, $2); - } - | backref - { - backref_error(p, $1); - $$ = 0; - } - ; - -lhs : variable - { - assignable(p, $1); - } - | primary_value '[' opt_call_args rbracket - { - $$ = new_call(p, $1, intern("[]",2), $3); - } - | primary_value '.' tIDENTIFIER - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value tCOLON2 tIDENTIFIER - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value '.' tCONSTANT - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value tCOLON2 tCONSTANT - { - if (p->in_def || p->in_single) - yyerror(p, "dynamic constant assignment"); - $$ = new_colon2(p, $1, $3); - } - | tCOLON3 tCONSTANT - { - if (p->in_def || p->in_single) - yyerror(p, "dynamic constant assignment"); - $$ = new_colon3(p, $2); - } - | backref - { - backref_error(p, $1); - $$ = 0; - } - ; - -cname : tIDENTIFIER - { - yyerror(p, "class/module name must be CONSTANT"); - } - | tCONSTANT - ; - -cpath : tCOLON3 cname - { - $$ = cons((node*)1, nsym($2)); - } - | cname - { - $$ = cons((node*)0, nsym($1)); - } - | primary_value tCOLON2 cname - { - $$ = cons($1, nsym($3)); - } - ; - -fname : tIDENTIFIER - | tCONSTANT - | tFID - | op - { - p->lstate = EXPR_ENDFN; - $$ = $1; - } - | reswords - { - p->lstate = EXPR_ENDFN; - $$ = $1; - } - ; - -fsym : fname - | basic_symbol - ; - -undef_list : fsym - { - $$ = new_undef(p, $1); - } - | undef_list ',' {p->lstate = EXPR_FNAME;} fsym - { - $$ = push($1, nsym($4)); - } - ; - -op : '|' { $$ = intern_c('|'); } - | '^' { $$ = intern_c('^'); } - | '&' { $$ = intern_c('&'); } - | tCMP { $$ = intern("<=>",3); } - | tEQ { $$ = intern("==",2); } - | tEQQ { $$ = intern("===",3); } - | tMATCH { $$ = intern("=~",2); } - | tNMATCH { $$ = intern("!~",2); } - | '>' { $$ = intern_c('>'); } - | tGEQ { $$ = intern(">=",2); } - | '<' { $$ = intern_c('<'); } - | tLEQ { $$ = intern("<=",2); } - | tNEQ { $$ = intern("!=",2); } - | tLSHFT { $$ = intern("<<",2); } - | tRSHFT { $$ = intern(">>",2); } - | '+' { $$ = intern_c('+'); } - | '-' { $$ = intern_c('-'); } - | '*' { $$ = intern_c('*'); } - | tSTAR { $$ = intern_c('*'); } - | '/' { $$ = intern_c('/'); } - | '%' { $$ = intern_c('%'); } - | tPOW { $$ = intern("**",2); } - | '!' { $$ = intern_c('!'); } - | '~' { $$ = intern_c('~'); } - | tUPLUS { $$ = intern("+@",2); } - | tUMINUS { $$ = intern("-@",2); } - | tAREF { $$ = intern("[]",2); } - | tASET { $$ = intern("[]=",3); } - | '`' { $$ = intern_c('`'); } - ; - -reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ - | keyword_BEGIN | keyword_END - | keyword_alias | keyword_and | keyword_begin - | keyword_break | keyword_case | keyword_class | keyword_def - | keyword_do | keyword_else | keyword_elsif - | keyword_end | keyword_ensure | keyword_false - | keyword_for | keyword_in | keyword_module | keyword_next - | keyword_nil | keyword_not | keyword_or | keyword_redo - | keyword_rescue | keyword_retry | keyword_return | keyword_self - | keyword_super | keyword_then | keyword_true | keyword_undef - | keyword_when | keyword_yield | keyword_if | keyword_unless - | keyword_while | keyword_until - ; - -arg : lhs '=' arg - { - $$ = new_asgn(p, $1, $3); - } - | lhs '=' arg modifier_rescue arg - { - $$ = new_asgn(p, $1, new_rescue(p, $3, list1(list3(0, 0, $5)), 0)); - } - | var_lhs tOP_ASGN arg - { - $$ = new_op_asgn(p, $1, $2, $3); - } - | var_lhs tOP_ASGN arg modifier_rescue arg - { - $$ = new_op_asgn(p, $1, $2, new_rescue(p, $3, list1(list3(0, 0, $5)), 0)); - } - | primary_value '[' opt_call_args rbracket tOP_ASGN arg - { - $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3), $5, $6); - } - | primary_value '.' tIDENTIFIER tOP_ASGN arg - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | primary_value '.' tCONSTANT tOP_ASGN arg - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | primary_value tCOLON2 tCONSTANT tOP_ASGN arg - { - yyerror(p, "constant re-assignment"); - $$ = new_begin(p, 0); - } - | tCOLON3 tCONSTANT tOP_ASGN arg - { - yyerror(p, "constant re-assignment"); - $$ = new_begin(p, 0); - } - | backref tOP_ASGN arg - { - backref_error(p, $1); - $$ = new_begin(p, 0); - } - | arg tDOT2 arg - { - $$ = new_dot2(p, $1, $3); - } - | arg tDOT3 arg - { - $$ = new_dot3(p, $1, $3); - } - | arg '+' arg - { - $$ = call_bin_op(p, $1, "+", $3); - } - | arg '-' arg - { - $$ = call_bin_op(p, $1, "-", $3); - } - | arg '*' arg - { - $$ = call_bin_op(p, $1, "*", $3); - } - | arg '/' arg - { - $$ = call_bin_op(p, $1, "/", $3); - } - | arg '%' arg - { - $$ = call_bin_op(p, $1, "%", $3); - } - | arg tPOW arg - { - $$ = call_bin_op(p, $1, "**", $3); - } - | tUMINUS_NUM tINTEGER tPOW arg - { - $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@"); - } - | tUMINUS_NUM tFLOAT tPOW arg - { - $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@"); - } - | tUPLUS arg - { - $$ = call_uni_op(p, $2, "+@"); - } - | tUMINUS arg - { - $$ = call_uni_op(p, $2, "-@"); - } - | arg '|' arg - { - $$ = call_bin_op(p, $1, "|", $3); - } - | arg '^' arg - { - $$ = call_bin_op(p, $1, "^", $3); - } - | arg '&' arg - { - $$ = call_bin_op(p, $1, "&", $3); - } - | arg tCMP arg - { - $$ = call_bin_op(p, $1, "<=>", $3); - } - | arg '>' arg - { - $$ = call_bin_op(p, $1, ">", $3); - } - | arg tGEQ arg - { - $$ = call_bin_op(p, $1, ">=", $3); - } - | arg '<' arg - { - $$ = call_bin_op(p, $1, "<", $3); - } - | arg tLEQ arg - { - $$ = call_bin_op(p, $1, "<=", $3); - } - | arg tEQ arg - { - $$ = call_bin_op(p, $1, "==", $3); - } - | arg tEQQ arg - { - $$ = call_bin_op(p, $1, "===", $3); - } - | arg tNEQ arg - { - $$ = call_bin_op(p, $1, "!=", $3); - } - | arg tMATCH arg - { - $$ = call_bin_op(p, $1, "=~", $3); - } - | arg tNMATCH arg - { - $$ = call_bin_op(p, $1, "!~", $3); - } - | '!' arg - { - $$ = call_uni_op(p, cond($2), "!"); - } - | '~' arg - { - $$ = call_uni_op(p, cond($2), "~"); - } - | arg tLSHFT arg - { - $$ = call_bin_op(p, $1, "<<", $3); - } - | arg tRSHFT arg - { - $$ = call_bin_op(p, $1, ">>", $3); - } - | arg tANDOP arg - { - $$ = new_and(p, $1, $3); - } - | arg tOROP arg - { - $$ = new_or(p, $1, $3); - } - | arg '?' arg opt_nl ':' arg - { - $$ = new_if(p, cond($1), $3, $6); - } - | primary - { - $$ = $1; - } - ; - -arg_value : arg - { - $$ = $1; - if (!$$) $$ = new_nil(p); - } - ; - -aref_args : none - | args trailer - { - $$ = $1; - NODE_LINENO($$, $1); - } - | args ',' assocs trailer - { - $$ = push($1, new_hash(p, $3)); - } - | assocs trailer - { - $$ = cons(new_hash(p, $1), 0); - NODE_LINENO($$, $1); - } - ; - -paren_args : '(' opt_call_args rparen - { - $$ = $2; - } - ; - -opt_paren_args : none - | paren_args - ; - -opt_call_args : none - | call_args - | args ',' - { - $$ = cons($1,0); - NODE_LINENO($$, $1); - } - | args ',' assocs ',' - { - $$ = cons(push($1, new_hash(p, $3)), 0); - NODE_LINENO($$, $1); - } - | assocs ',' - { - $$ = cons(list1(new_hash(p, $1)), 0); - NODE_LINENO($$, $1); - } - ; - -call_args : command - { - $$ = cons(list1($1), 0); - NODE_LINENO($$, $1); - } - | args opt_block_arg - { - $$ = cons($1, $2); - NODE_LINENO($$, $1); - } - | assocs opt_block_arg - { - $$ = cons(list1(new_hash(p, $1)), $2); - NODE_LINENO($$, $1); - } - | args ',' assocs opt_block_arg - { - $$ = cons(push($1, new_hash(p, $3)), $4); - NODE_LINENO($$, $1); - } - | block_arg - { - $$ = cons(0, $1); - NODE_LINENO($$, $1); - } - ; - -command_args : { - $$ = p->cmdarg_stack; - CMDARG_PUSH(1); - } - call_args - { - p->cmdarg_stack = $1; - $$ = $2; - } - ; - -block_arg : tAMPER arg_value - { - $$ = new_block_arg(p, $2); - } - ; - -opt_block_arg : ',' block_arg - { - $$ = $2; - } - | none - { - $$ = 0; - } - ; - -args : arg_value - { - $$ = cons($1, 0); - NODE_LINENO($$, $1); - } - | tSTAR arg_value - { - $$ = cons(new_splat(p, $2), 0); - NODE_LINENO($$, $2); - } - | args ',' arg_value - { - $$ = push($1, $3); - } - | args ',' tSTAR arg_value - { - $$ = push($1, new_splat(p, $4)); - } - | args ',' heredoc_bodies arg_value - { - $$ = push($1, $4); - } - | args ',' heredoc_bodies tSTAR arg_value - { - $$ = push($1, new_splat(p, $5)); - } - ; - -mrhs : args ',' arg_value - { - $$ = push($1, $3); - } - | args ',' tSTAR arg_value - { - $$ = push($1, new_splat(p, $4)); - } - | tSTAR arg_value - { - $$ = list1(new_splat(p, $2)); - } - ; - -primary : literal - | string - | xstring - | regexp - | heredoc - | var_ref - | backref - | tFID - { - $$ = new_fcall(p, $1, 0); - } - | keyword_begin - { - $$ = p->cmdarg_stack; - p->cmdarg_stack = 0; - } - bodystmt - keyword_end - { - p->cmdarg_stack = $2; - $$ = $3; - } - | tLPAREN_ARG - { - $$ = p->cmdarg_stack; - p->cmdarg_stack = 0; - } - expr {p->lstate = EXPR_ENDARG;} rparen - { - p->cmdarg_stack = $2; - $$ = $3; - } - | tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen - { - $$ = 0; - } - | tLPAREN compstmt ')' - { - $$ = $2; - } - | primary_value tCOLON2 tCONSTANT - { - $$ = new_colon2(p, $1, $3); - } - | tCOLON3 tCONSTANT - { - $$ = new_colon3(p, $2); - } - | tLBRACK aref_args ']' - { - $$ = new_array(p, $2); - NODE_LINENO($$, $2); - } - | tLBRACE assoc_list '}' - { - $$ = new_hash(p, $2); - NODE_LINENO($$, $2); - } - | keyword_return - { - $$ = new_return(p, 0); - } - | keyword_yield '(' call_args rparen - { - $$ = new_yield(p, $3); - } - | keyword_yield '(' rparen - { - $$ = new_yield(p, 0); - } - | keyword_yield - { - $$ = new_yield(p, 0); - } - | keyword_not '(' expr rparen - { - $$ = call_uni_op(p, cond($3), "!"); - } - | keyword_not '(' rparen - { - $$ = call_uni_op(p, new_nil(p), "!"); - } - | operation brace_block - { - $$ = new_fcall(p, $1, cons(0, $2)); - } - | method_call - | method_call brace_block - { - call_with_block(p, $1, $2); - $$ = $1; - } - | tLAMBDA - { - local_nest(p); - $$ = p->lpar_beg; - p->lpar_beg = ++p->paren_nest; - } - f_larglist - { - $$ = p->cmdarg_stack; - p->cmdarg_stack = 0; - } - lambda_body - { - p->lpar_beg = $2; - $$ = new_lambda(p, $3, $5); - local_unnest(p); - p->cmdarg_stack = $4; - CMDARG_LEXPOP(); - } - | keyword_if expr_value then - compstmt - if_tail - keyword_end - { - $$ = new_if(p, cond($2), $4, $5); - SET_LINENO($$, $1); - } - | keyword_unless expr_value then - compstmt - opt_else - keyword_end - { - $$ = new_unless(p, cond($2), $4, $5); - SET_LINENO($$, $1); - } - | keyword_while {COND_PUSH(1);} expr_value do {COND_POP();} - compstmt - keyword_end - { - $$ = new_while(p, cond($3), $6); - SET_LINENO($$, $1); - } - | keyword_until {COND_PUSH(1);} expr_value do {COND_POP();} - compstmt - keyword_end - { - $$ = new_until(p, cond($3), $6); - SET_LINENO($$, $1); - } - | keyword_case expr_value opt_terms - case_body - keyword_end - { - $$ = new_case(p, $2, $4); - } - | keyword_case opt_terms case_body keyword_end - { - $$ = new_case(p, 0, $3); - } - | keyword_for for_var keyword_in - {COND_PUSH(1);} - expr_value do - {COND_POP();} - compstmt - keyword_end - { - $$ = new_for(p, $2, $5, $8); - SET_LINENO($$, $1); - } - | keyword_class - cpath superclass - { - if (p->in_def || p->in_single) - yyerror(p, "class definition in method body"); - $$ = local_switch(p); - } - bodystmt - keyword_end - { - $$ = new_class(p, $2, $3, $5); - SET_LINENO($$, $1); - local_resume(p, $4); - } - | keyword_class - tLSHFT expr - { - $$ = p->in_def; - p->in_def = 0; - } - term - { - $$ = cons(local_switch(p), (node*)(intptr_t)p->in_single); - p->in_single = 0; - } - bodystmt - keyword_end - { - $$ = new_sclass(p, $3, $7); - SET_LINENO($$, $1); - local_resume(p, $6->car); - p->in_def = $4; - p->in_single = (int)(intptr_t)$6->cdr; - } - | keyword_module - cpath - { - if (p->in_def || p->in_single) - yyerror(p, "module definition in method body"); - $$ = local_switch(p); - } - bodystmt - keyword_end - { - $$ = new_module(p, $2, $4); - SET_LINENO($$, $1); - local_resume(p, $3); - } - | keyword_def fname - { - $$ = p->cmdarg_stack; - p->cmdarg_stack = 0; - } - { - p->in_def++; - $$ = local_switch(p); - } - f_arglist - bodystmt - keyword_end - { - $$ = new_def(p, $2, $5, $6); - SET_LINENO($$, $1); - local_resume(p, $4); - p->in_def--; - p->cmdarg_stack = $3; - } - | keyword_def singleton dot_or_colon - { - p->lstate = EXPR_FNAME; - $$ = p->cmdarg_stack; - p->cmdarg_stack = 0; - } - fname - { - p->in_single++; - p->lstate = EXPR_ENDFN; /* force for args */ - $$ = local_switch(p); - } - f_arglist - bodystmt - keyword_end - { - $$ = new_sdef(p, $2, $5, $7, $8); - SET_LINENO($$, $1); - local_resume(p, $6); - p->in_single--; - p->cmdarg_stack = $4; - } - | keyword_break - { - $$ = new_break(p, 0); - } - | keyword_next - { - $$ = new_next(p, 0); - } - | keyword_redo - { - $$ = new_redo(p); - } - | keyword_retry - { - $$ = new_retry(p); - } - ; - -primary_value : primary - { - $$ = $1; - if (!$$) $$ = new_nil(p); - } - ; - -then : term - | keyword_then - | term keyword_then - ; - -do : term - | keyword_do_cond - ; - -if_tail : opt_else - | keyword_elsif expr_value then - compstmt - if_tail - { - $$ = new_if(p, cond($2), $4, $5); - } - ; - -opt_else : none - | keyword_else compstmt - { - $$ = $2; - } - ; - -for_var : lhs - { - $$ = list1(list1($1)); - } - | mlhs - ; - -f_marg : f_norm_arg - { - $$ = new_arg(p, $1); - } - | tLPAREN f_margs rparen - { - $$ = new_masgn(p, $2, 0); - } - ; - -f_marg_list : f_marg - { - $$ = list1($1); - } - | f_marg_list ',' f_marg - { - $$ = push($1, $3); - } - ; - -f_margs : f_marg_list - { - $$ = list3($1,0,0); - } - | f_marg_list ',' tSTAR f_norm_arg - { - $$ = list3($1, new_arg(p, $4), 0); - } - | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list - { - $$ = list3($1, new_arg(p, $4), $6); - } - | f_marg_list ',' tSTAR - { - $$ = list3($1, (node*)-1, 0); - } - | f_marg_list ',' tSTAR ',' f_marg_list - { - $$ = list3($1, (node*)-1, $5); - } - | tSTAR f_norm_arg - { - $$ = list3(0, new_arg(p, $2), 0); - } - | tSTAR f_norm_arg ',' f_marg_list - { - $$ = list3(0, new_arg(p, $2), $4); - } - | tSTAR - { - $$ = list3(0, (node*)-1, 0); - } - | tSTAR ',' f_marg_list - { - $$ = list3(0, (node*)-1, $3); - } - ; - -block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, $5, 0, $6); - } - | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, $5, $7, $8); - } - | f_arg ',' f_block_optarg opt_f_block_arg - { - $$ = new_args(p, $1, $3, 0, 0, $4); - } - | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, 0, $5, $6); - } - | f_arg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, $3, 0, $4); - } - | f_arg ',' - { - $$ = new_args(p, $1, 0, 1, 0, 0); - } - | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, $3, $5, $6); - } - | f_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, 0, 0, $2); - } - | f_block_optarg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, $3, 0, $4); - } - | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, $3, $5, $6); - } - | f_block_optarg opt_f_block_arg - { - $$ = new_args(p, 0, $1, 0, 0, $2); - } - | f_block_optarg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, 0, $3, $4); - } - | f_rest_arg opt_f_block_arg - { - $$ = new_args(p, 0, 0, $1, 0, $2); - } - | f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, 0, $1, $3, $4); - } - | f_block_arg - { - $$ = new_args(p, 0, 0, 0, 0, $1); - } - ; - -opt_block_param : none - | block_param_def - { - p->cmd_start = TRUE; - $$ = $1; - } - ; - -block_param_def : '|' opt_bv_decl '|' - { - $$ = 0; - } - | tOROP - { - $$ = 0; - } - | '|' block_param opt_bv_decl '|' - { - $$ = $2; - } - ; - - -opt_bv_decl : opt_nl - { - $$ = 0; - } - | opt_nl ';' bv_decls opt_nl - { - $$ = 0; - } - ; - -bv_decls : bvar - | bv_decls ',' bvar - ; - -bvar : tIDENTIFIER - { - local_add_f(p, $1); - new_bv(p, $1); - } - | f_bad_arg - ; - -f_larglist : '(' f_args opt_bv_decl ')' - { - $$ = $2; - } - | f_args - { - $$ = $1; - } - ; - -lambda_body : tLAMBEG compstmt '}' - { - $$ = $2; - } - | keyword_do_LAMBDA compstmt keyword_end - { - $$ = $2; - } - ; - -do_block : keyword_do_block - { - local_nest(p); - } - opt_block_param - compstmt - keyword_end - { - $$ = new_block(p,$3,$4); - local_unnest(p); - } - ; - -block_call : command do_block - { - if ($1->car == (node*)NODE_YIELD) { - yyerror(p, "block given to yield"); - } - else { - call_with_block(p, $1, $2); - } - $$ = $1; - } - | block_call dot_or_colon operation2 opt_paren_args - { - $$ = new_call(p, $1, $3, $4); - } - | block_call dot_or_colon operation2 opt_paren_args brace_block - { - $$ = new_call(p, $1, $3, $4); - call_with_block(p, $$, $5); - } - | block_call dot_or_colon operation2 command_args do_block - { - $$ = new_call(p, $1, $3, $4); - call_with_block(p, $$, $5); - } - ; - -method_call : operation paren_args - { - $$ = new_fcall(p, $1, $2); - } - | primary_value '.' operation2 opt_paren_args - { - $$ = new_call(p, $1, $3, $4); - } - | primary_value tCOLON2 operation2 paren_args - { - $$ = new_call(p, $1, $3, $4); - } - | primary_value tCOLON2 operation3 - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value '.' paren_args - { - $$ = new_call(p, $1, intern("call",4), $3); - } - | primary_value tCOLON2 paren_args - { - $$ = new_call(p, $1, intern("call",4), $3); - } - | keyword_super paren_args - { - $$ = new_super(p, $2); - } - | keyword_super - { - $$ = new_zsuper(p); - } - | primary_value '[' opt_call_args rbracket - { - $$ = new_call(p, $1, intern("[]",2), $3); - } - ; - -brace_block : '{' - { - local_nest(p); - $$ = p->lineno; - } - opt_block_param - compstmt '}' - { - $$ = new_block(p,$3,$4); - SET_LINENO($$, $2); - local_unnest(p); - } - | keyword_do - { - local_nest(p); - $$ = p->lineno; - } - opt_block_param - compstmt keyword_end - { - $$ = new_block(p,$3,$4); - SET_LINENO($$, $2); - local_unnest(p); - } - ; - -case_body : keyword_when args then - compstmt - cases - { - $$ = cons(cons($2, $4), $5); - } - ; - -cases : opt_else - { - if ($1) { - $$ = cons(cons(0, $1), 0); - } - else { - $$ = 0; - } - } - | case_body - ; - -opt_rescue : keyword_rescue exc_list exc_var then - compstmt - opt_rescue - { - $$ = list1(list3($2, $3, $5)); - if ($6) $$ = append($$, $6); - } - | none - ; - -exc_list : arg_value - { - $$ = list1($1); - } - | mrhs - | none - ; - -exc_var : tASSOC lhs - { - $$ = $2; - } - | none - ; - -opt_ensure : keyword_ensure compstmt - { - $$ = $2; - } - | none - ; - -literal : numeric - | symbol - | words - | symbols - ; - -string : tCHAR - | tSTRING - | tSTRING_BEG tSTRING - { - $$ = $2; - } - | tSTRING_BEG string_rep tSTRING - { - $$ = new_dstr(p, push($2, $3)); - } - ; - -string_rep : string_interp - | string_rep string_interp - { - $$ = append($1, $2); - } - ; - -string_interp : tSTRING_MID - { - $$ = list1($1); - } - | tSTRING_PART - { - $$ = p->lex_strterm; - p->lex_strterm = NULL; - } - compstmt - '}' - { - p->lex_strterm = $2; - $$ = list2($1, $3); - } - | tLITERAL_DELIM - { - $$ = list1(new_literal_delim(p)); - } - | tHD_LITERAL_DELIM heredoc_bodies - { - $$ = list1(new_literal_delim(p)); - } - ; - -xstring : tXSTRING_BEG tXSTRING - { - $$ = $2; - } - | tXSTRING_BEG string_rep tXSTRING - { - $$ = new_dxstr(p, push($2, $3)); - } - ; - -regexp : tREGEXP_BEG tREGEXP - { - $$ = $2; - } - | tREGEXP_BEG string_rep tREGEXP - { - $$ = new_dregx(p, $2, $3); - } - ; - -heredoc : tHEREDOC_BEG - ; - -opt_heredoc_bodies : /* none */ - | heredoc_bodies - ; - -heredoc_bodies : heredoc_body - | heredoc_bodies heredoc_body - ; - -heredoc_body : tHEREDOC_END - { - parser_heredoc_info * inf = parsing_heredoc_inf(p); - inf->doc = push(inf->doc, new_str(p, "", 0)); - heredoc_end(p); - } - | heredoc_string_rep tHEREDOC_END - { - heredoc_end(p); - } - ; - -heredoc_string_rep : heredoc_string_interp - | heredoc_string_rep heredoc_string_interp - ; - -heredoc_string_interp : tHD_STRING_MID - { - parser_heredoc_info * inf = parsing_heredoc_inf(p); - inf->doc = push(inf->doc, $1); - heredoc_treat_nextline(p); - } - | tHD_STRING_PART - { - $$ = p->lex_strterm; - p->lex_strterm = NULL; - } - compstmt - '}' - { - parser_heredoc_info * inf = parsing_heredoc_inf(p); - p->lex_strterm = $2; - inf->doc = push(push(inf->doc, $1), $3); - } - ; - -words : tWORDS_BEG tSTRING - { - $$ = new_words(p, list1($2)); - } - | tWORDS_BEG string_rep tSTRING - { - $$ = new_words(p, push($2, $3)); - } - ; - - -symbol : basic_symbol - { - $$ = new_sym(p, $1); - } - | tSYMBEG tSTRING_BEG string_interp tSTRING - { - p->lstate = EXPR_END; - $$ = new_dsym(p, push($3, $4)); - } - ; - -basic_symbol : tSYMBEG sym - { - p->lstate = EXPR_END; - $$ = $2; - } - ; - -sym : fname - | tIVAR - | tGVAR - | tCVAR - | tSTRING - { - $$ = new_strsym(p, $1); - } - | tSTRING_BEG tSTRING - { - $$ = new_strsym(p, $2); - } - ; - -symbols : tSYMBOLS_BEG tSTRING - { - $$ = new_symbols(p, list1($2)); - } - | tSYMBOLS_BEG string_rep tSTRING - { - $$ = new_symbols(p, push($2, $3)); - } - ; - -numeric : tINTEGER - | tFLOAT - | tUMINUS_NUM tINTEGER %prec tLOWEST - { - $$ = negate_lit(p, $2); - } - | tUMINUS_NUM tFLOAT %prec tLOWEST - { - $$ = negate_lit(p, $2); - } - ; - -variable : tIDENTIFIER - { - $$ = new_lvar(p, $1); - } - | tIVAR - { - $$ = new_ivar(p, $1); - } - | tGVAR - { - $$ = new_gvar(p, $1); - } - | tCVAR - { - $$ = new_cvar(p, $1); - } - | tCONSTANT - { - $$ = new_const(p, $1); - } - ; - -var_lhs : variable - { - assignable(p, $1); - } - ; - -var_ref : variable - { - $$ = var_reference(p, $1); - } - | keyword_nil - { - $$ = new_nil(p); - } - | keyword_self - { - $$ = new_self(p); - } - | keyword_true - { - $$ = new_true(p); - } - | keyword_false - { - $$ = new_false(p); - } - | keyword__FILE__ - { - if (!p->filename) { - p->filename = "(null)"; - } - $$ = new_str(p, p->filename, strlen(p->filename)); - } - | keyword__LINE__ - { - char buf[16]; - - snprintf(buf, sizeof(buf), "%d", p->lineno); - $$ = new_int(p, buf, 10); - } - ; - -backref : tNTH_REF - | tBACK_REF - ; - -superclass : /* term */ - { - $$ = 0; - } - | '<' - { - p->lstate = EXPR_BEG; - p->cmd_start = TRUE; - } - expr_value term - { - $$ = $3; - } /* - | error term - { - yyerrok; - $$ = 0; - } */ - ; - -f_arglist : '(' f_args rparen - { - $$ = $2; - p->lstate = EXPR_BEG; - p->cmd_start = TRUE; - } - | f_args term - { - $$ = $1; - } - ; - -f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, $5, 0, $6); - } - | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, $5, $7, $8); - } - | f_arg ',' f_optarg opt_f_block_arg - { - $$ = new_args(p, $1, $3, 0, 0, $4); - } - | f_arg ',' f_optarg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, 0, $5, $6); - } - | f_arg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, $3, 0, $4); - } - | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, $3, $5, $6); - } - | f_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, 0, 0, $2); - } - | f_optarg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, $3, 0, $4); - } - | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, $3, $5, $6); - } - | f_optarg opt_f_block_arg - { - $$ = new_args(p, 0, $1, 0, 0, $2); - } - | f_optarg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, 0, $3, $4); - } - | f_rest_arg opt_f_block_arg - { - $$ = new_args(p, 0, 0, $1, 0, $2); - } - | f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, 0, $1, $3, $4); - } - | f_block_arg - { - $$ = new_args(p, 0, 0, 0, 0, $1); - } - | /* none */ - { - local_add_f(p, 0); - $$ = new_args(p, 0, 0, 0, 0, 0); - } - ; - -f_bad_arg : tCONSTANT - { - yyerror(p, "formal argument cannot be a constant"); - $$ = 0; - } - | tIVAR - { - yyerror(p, "formal argument cannot be an instance variable"); - $$ = 0; - } - | tGVAR - { - yyerror(p, "formal argument cannot be a global variable"); - $$ = 0; - } - | tCVAR - { - yyerror(p, "formal argument cannot be a class variable"); - $$ = 0; - } - ; - -f_norm_arg : f_bad_arg - { - $$ = 0; - } - | tIDENTIFIER - { - local_add_f(p, $1); - $$ = $1; - } - ; - -f_arg_item : f_norm_arg - { - $$ = new_arg(p, $1); - } - | tLPAREN f_margs rparen - { - $$ = new_masgn(p, $2, 0); - } - ; - -f_arg : f_arg_item - { - $$ = list1($1); - } - | f_arg ',' f_arg_item - { - $$ = push($1, $3); - } - ; - -f_opt_asgn : tIDENTIFIER '=' - { - local_add_f(p, $1); - $$ = $1; - } - ; - -f_opt : f_opt_asgn arg_value - { - $$ = cons(nsym($1), $2); - } - ; - -f_block_opt : f_opt_asgn primary_value - { - $$ = cons(nsym($1), $2); - } - ; - -f_block_optarg : f_block_opt - { - $$ = list1($1); - } - | f_block_optarg ',' f_block_opt - { - $$ = push($1, $3); - } - ; - -f_optarg : f_opt - { - $$ = list1($1); - } - | f_optarg ',' f_opt - { - $$ = push($1, $3); - } - ; - -restarg_mark : '*' - | tSTAR - ; - -f_rest_arg : restarg_mark tIDENTIFIER - { - local_add_f(p, $2); - $$ = $2; - } - | restarg_mark - { - local_add_f(p, 0); - $$ = -1; - } - ; - -blkarg_mark : '&' - | tAMPER - ; - -f_block_arg : blkarg_mark tIDENTIFIER - { - local_add_f(p, $2); - $$ = $2; - } - ; - -opt_f_block_arg : ',' f_block_arg - { - $$ = $2; - } - | none - { - local_add_f(p, 0); - $$ = 0; - } - ; - -singleton : var_ref - { - $$ = $1; - if (!$$) $$ = new_nil(p); - } - | '(' {p->lstate = EXPR_BEG;} expr rparen - { - if ($3 == 0) { - yyerror(p, "can't define singleton method for ()."); - } - else { - switch ((enum node_type)(int)(intptr_t)$3->car) { - case NODE_STR: - case NODE_DSTR: - case NODE_XSTR: - case NODE_DXSTR: - case NODE_DREGX: - case NODE_MATCH: - case NODE_FLOAT: - case NODE_ARRAY: - case NODE_HEREDOC: - yyerror(p, "can't define singleton method for literals"); - default: - break; - } - } - $$ = $3; - } - ; - -assoc_list : none - | assocs trailer - { - $$ = $1; - } - ; - -assocs : assoc - { - $$ = list1($1); - NODE_LINENO($$, $1); - } - | assocs ',' assoc - { - $$ = push($1, $3); - } - ; - -assoc : arg_value tASSOC arg_value - { - $$ = cons($1, $3); - } - | tLABEL arg_value - { - $$ = cons(new_sym(p, $1), $2); - } - ; - -operation : tIDENTIFIER - | tCONSTANT - | tFID - ; - -operation2 : tIDENTIFIER - | tCONSTANT - | tFID - | op - ; - -operation3 : tIDENTIFIER - | tFID - | op - ; - -dot_or_colon : '.' - | tCOLON2 - ; - -opt_terms : /* none */ - | terms - ; - -opt_nl : /* none */ - | nl - ; - -rparen : opt_nl ')' - ; - -rbracket : opt_nl ']' - ; - -trailer : /* none */ - | nl - | ',' - ; - -term : ';' {yyerrok;} - | nl - ; - -nl : '\n' - { - p->lineno++; - p->column = 0; - } - opt_heredoc_bodies - -terms : term - | terms ';' {yyerrok;} - ; - -none : /* none */ - { - $$ = 0; - } - ; -%% -#define yylval (*((YYSTYPE*)(p->ylval))) - -static void -yyerror(parser_state *p, const char *s) -{ - char* c; - int n; - - if (! p->capture_errors) { -#ifndef MRB_DISABLE_STDIO - if (p->filename) { - fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s); - } - else { - fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s); - } -#endif - } - else if (p->nerr < sizeof(p->error_buffer) / sizeof(p->error_buffer[0])) { - n = strlen(s); - c = (char *)parser_palloc(p, n + 1); - memcpy(c, s, n + 1); - p->error_buffer[p->nerr].message = c; - p->error_buffer[p->nerr].lineno = p->lineno; - p->error_buffer[p->nerr].column = p->column; - } - p->nerr++; -} - -static void -yyerror_i(parser_state *p, const char *fmt, int i) -{ - char buf[256]; - - snprintf(buf, sizeof(buf), fmt, i); - yyerror(p, buf); -} - -static void -yywarn(parser_state *p, const char *s) -{ - char* c; - int n; - - if (! p->capture_errors) { -#ifndef MRB_DISABLE_STDIO - if (p->filename) { - fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s); - } - else { - fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s); - } -#endif - } - else if (p->nwarn < sizeof(p->warn_buffer) / sizeof(p->warn_buffer[0])) { - n = strlen(s); - c = (char *)parser_palloc(p, n + 1); - memcpy(c, s, n + 1); - p->warn_buffer[p->nwarn].message = c; - p->warn_buffer[p->nwarn].lineno = p->lineno; - p->warn_buffer[p->nwarn].column = p->column; - } - p->nwarn++; -} - -static void -yywarning(parser_state *p, const char *s) -{ - yywarn(p, s); -} - -static void -yywarning_s(parser_state *p, const char *fmt, const char *s) -{ - char buf[256]; - - snprintf(buf, sizeof(buf), fmt, s); - yywarning(p, buf); -} - -static void -backref_error(parser_state *p, node *n) -{ - int c; - - c = (int)(intptr_t)n->car; - - if (c == NODE_NTH_REF) { - yyerror_i(p, "can't set variable $%d", (int)(intptr_t)n->cdr); - } - else if (c == NODE_BACK_REF) { - yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr); - } - else { - mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c)); - } -} - -static void pushback(parser_state *p, int c); -static mrb_bool peeks(parser_state *p, const char *s); -static mrb_bool skips(parser_state *p, const char *s); - -static inline int -nextc(parser_state *p) -{ - int c; - - if (p->pb) { - node *tmp; - - c = (int)(intptr_t)p->pb->car; - tmp = p->pb; - p->pb = p->pb->cdr; - cons_free(tmp); - } - else { -#ifndef MRB_DISABLE_STDIO - if (p->f) { - if (feof(p->f)) goto eof; - c = fgetc(p->f); - if (c == EOF) goto eof; - } - else -#endif - if (!p->s || p->s >= p->send) { - goto eof; - } - else { - c = (unsigned char)*p->s++; - } - } - if (c >= 0) { - p->column++; - } - if (c == '\r') { - c = nextc(p); - if (c != '\n') { - pushback(p, c); - return '\r'; - } - return c; - } - return c; - - eof: - if (!p->cxt) return -1; - else { - if (p->cxt->partial_hook(p) < 0) - return -1; /* end of program(s) */ - return -2; /* end of a file in the program files */ - } -} - -static void -pushback(parser_state *p, int c) -{ - if (c >= 0) { - p->column--; - } - p->pb = cons((node*)(intptr_t)c, p->pb); -} - -static void -skip(parser_state *p, char term) -{ - int c; - - for (;;) { - c = nextc(p); - if (c < 0) break; - if (c == term) break; - } -} - -static int -peekc_n(parser_state *p, int n) -{ - node *list = 0; - int c0; - - do { - c0 = nextc(p); - if (c0 == -1) return c0; /* do not skip partial EOF */ - list = push(list, (node*)(intptr_t)c0); - } while(n--); - if (p->pb) { - p->pb = append((node*)list, p->pb); - } - else { - p->pb = list; - } - return c0; -} - -static mrb_bool -peek_n(parser_state *p, int c, int n) -{ - return peekc_n(p, n) == c && c >= 0; -} -#define peek(p,c) peek_n((p), (c), 0) - -static mrb_bool -peeks(parser_state *p, const char *s) -{ - int len = strlen(s); - -#ifndef MRB_DISABLE_STDIO - if (p->f) { - int n = 0; - while (*s) { - if (!peek_n(p, *s++, n++)) return FALSE; - } - return TRUE; - } - else -#endif - if (p->s && p->s + len <= p->send) { - if (memcmp(p->s, s, len) == 0) return TRUE; - } - return FALSE; -} - -static mrb_bool -skips(parser_state *p, const char *s) -{ - int c; - - for (;;) { - /* skip until first char */ - for (;;) { - c = nextc(p); - if (c < 0) return c; - if (c == '\n') { - p->lineno++; - p->column = 0; - } - if (c == *s) break; - } - s++; - if (peeks(p, s)) { - int len = strlen(s); - - while (len--) { - if (nextc(p) == '\n') { - p->lineno++; - p->column = 0; - } - } - return TRUE; - } - else{ - s--; - } - } - return FALSE; -} - - -static int -newtok(parser_state *p) -{ - p->bidx = 0; - return p->column - 1; -} - -static void -tokadd(parser_state *p, int32_t c) -{ - char utf8[4]; - unsigned len; - - /* mrb_assert(-0x10FFFF <= c && c <= 0xFF); */ - if (c >= 0) { - /* Single byte from source or non-Unicode escape */ - utf8[0] = (char)c; - len = 1; - } - else { - /* Unicode character */ - c = -c; - if (c < 0x80) { - utf8[0] = (char)c; - len = 1; - } - else if (c < 0x800) { - utf8[0] = (char)(0xC0 | (c >> 6)); - utf8[1] = (char)(0x80 | (c & 0x3F)); - len = 2; - } - else if (c < 0x10000) { - utf8[0] = (char)(0xE0 | (c >> 12) ); - utf8[1] = (char)(0x80 | ((c >> 6) & 0x3F)); - utf8[2] = (char)(0x80 | ( c & 0x3F)); - len = 3; - } - else { - utf8[0] = (char)(0xF0 | (c >> 18) ); - utf8[1] = (char)(0x80 | ((c >> 12) & 0x3F)); - utf8[2] = (char)(0x80 | ((c >> 6) & 0x3F)); - utf8[3] = (char)(0x80 | ( c & 0x3F)); - len = 4; - } - } - if (p->bidx+len <= MRB_PARSER_BUF_SIZE) { - unsigned i; - for (i = 0; i < len; i++) { - p->buf[p->bidx++] = utf8[i]; - } - } -} - -static int -toklast(parser_state *p) -{ - return p->buf[p->bidx-1]; -} - -static void -tokfix(parser_state *p) -{ - int i = p->bidx, imax = MRB_PARSER_BUF_SIZE - 1; - - if (i > imax) { - i = imax; - yyerror(p, "string too long (truncated)"); - } - p->buf[i] = '\0'; -} - -static const char* -tok(parser_state *p) -{ - return p->buf; -} - -static int -toklen(parser_state *p) -{ - return p->bidx; -} - -#define IS_ARG() (p->lstate == EXPR_ARG || p->lstate == EXPR_CMDARG) -#define IS_END() (p->lstate == EXPR_END || p->lstate == EXPR_ENDARG || p->lstate == EXPR_ENDFN) -#define IS_BEG() (p->lstate == EXPR_BEG || p->lstate == EXPR_MID || p->lstate == EXPR_VALUE || p->lstate == EXPR_CLASS) -#define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c)) -#define IS_LABEL_POSSIBLE() ((p->lstate == EXPR_BEG && !cmd_state) || IS_ARG()) -#define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1)) - -static int -scan_oct(const int *start, int len, int *retlen) -{ - const int *s = start; - int retval = 0; - - /* mrb_assert(len <= 3) */ - while (len-- && *s >= '0' && *s <= '7') { - retval <<= 3; - retval |= *s++ - '0'; - } - *retlen = s - start; - - return retval; -} - -static int32_t -scan_hex(const int *start, int len, int *retlen) -{ - static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF"; - const int *s = start; - int32_t retval = 0; - char *tmp; - - /* mrb_assert(len <= 8) */ - while (len-- && *s && (tmp = (char*)strchr(hexdigit, *s))) { - retval <<= 4; - retval |= (tmp - hexdigit) & 15; - s++; - } - *retlen = s - start; - - return retval; -} - -/* Return negative to indicate Unicode code point */ -static int32_t -read_escape(parser_state *p) -{ - int32_t c; - - switch (c = nextc(p)) { - case '\\':/* Backslash */ - return c; - - case 'n':/* newline */ - return '\n'; - - case 't':/* horizontal tab */ - return '\t'; - - case 'r':/* carriage-return */ - return '\r'; - - case 'f':/* form-feed */ - return '\f'; - - case 'v':/* vertical tab */ - return '\13'; - - case 'a':/* alarm(bell) */ - return '\007'; - - case 'e':/* escape */ - return 033; - - case '0': case '1': case '2': case '3': /* octal constant */ - case '4': case '5': case '6': case '7': - { - int buf[3]; - int i; - - buf[0] = c; - for (i=1; i<3; i++) { - buf[i] = nextc(p); - if (buf[i] < 0) goto eof; - if (buf[i] < '0' || '7' < buf[i]) { - pushback(p, buf[i]); - break; - } - } - c = scan_oct(buf, i, &i); - } - return c; - - case 'x': /* hex constant */ - { - int buf[2]; - int i; - - for (i=0; i<2; i++) { - buf[i] = nextc(p); - if (buf[i] < 0) goto eof; - if (!ISXDIGIT(buf[i])) { - pushback(p, buf[i]); - break; - } - } - c = scan_hex(buf, i, &i); - if (i == 0) { - yyerror(p, "Invalid escape character syntax"); - return 0; - } - } - return c; - - case 'u': /* Unicode */ - { - int buf[9]; - int i; - - /* Look for opening brace */ - i = 0; - buf[0] = nextc(p); - if (buf[0] < 0) goto eof; - if (buf[0] == '{') { - /* \u{xxxxxxxx} form */ - for (i=0; i<9; i++) { - buf[i] = nextc(p); - if (buf[i] < 0) goto eof; - if (buf[i] == '}') { - break; - } - else if (!ISXDIGIT(buf[i])) { - yyerror(p, "Invalid escape character syntax"); - pushback(p, buf[i]); - return 0; - } - } - } - else if (ISXDIGIT(buf[0])) { - /* \uxxxx form */ - for (i=1; i<4; i++) { - buf[i] = nextc(p); - if (buf[i] < 0) goto eof; - if (!ISXDIGIT(buf[i])) { - pushback(p, buf[i]); - break; - } - } - } - else { - pushback(p, buf[0]); - } - c = scan_hex(buf, i, &i); - if (i == 0) { - yyerror(p, "Invalid escape character syntax"); - return 0; - } - if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) { - yyerror(p, "Invalid Unicode code point"); - return 0; - } - } - return -c; - - case 'b':/* backspace */ - return '\010'; - - case 's':/* space */ - return ' '; - - case 'M': - if ((c = nextc(p)) != '-') { - yyerror(p, "Invalid escape character syntax"); - pushback(p, c); - return '\0'; - } - if ((c = nextc(p)) == '\\') { - return read_escape(p) | 0x80; - } - else if (c < 0) goto eof; - else { - return ((c & 0xff) | 0x80); - } - - case 'C': - if ((c = nextc(p)) != '-') { - yyerror(p, "Invalid escape character syntax"); - pushback(p, c); - return '\0'; - } - case 'c': - if ((c = nextc(p))== '\\') { - c = read_escape(p); - } - else if (c == '?') - return 0177; - else if (c < 0) goto eof; - return c & 0x9f; - - eof: - case -1: - case -2: /* end of a file */ - yyerror(p, "Invalid escape character syntax"); - return '\0'; - - default: - return c; - } -} - -static int -parse_string(parser_state *p) -{ - int c; - string_type type = (string_type)(intptr_t)p->lex_strterm->car; - int nest_level = (intptr_t)p->lex_strterm->cdr->car; - int beg = (intptr_t)p->lex_strterm->cdr->cdr->car; - int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr; - parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL; - - newtok(p); - while ((c = nextc(p)) != end || nest_level != 0) { - if (hinf && (c == '\n' || c < 0)) { - mrb_bool line_head; - tokadd(p, '\n'); - tokfix(p); - p->lineno++; - p->column = 0; - line_head = hinf->line_head; - hinf->line_head = TRUE; - if (line_head) { - /* check whether end of heredoc */ - const char *s = tok(p); - int len = toklen(p); - if (hinf->allow_indent) { - while (ISSPACE(*s) && len > 0) { - ++s; - --len; - } - } - if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) { - return tHEREDOC_END; - } - } - if (c < 0) { - char buf[256]; - snprintf(buf, sizeof(buf), "can't find heredoc delimiter \"%s\" anywhere before EOF", hinf->term); - yyerror(p, buf); - return 0; - } - yylval.nd = new_str(p, tok(p), toklen(p)); - return tHD_STRING_MID; - } - if (c < 0) { - yyerror(p, "unterminated string meets end of file"); - return 0; - } - else if (c == beg) { - nest_level++; - p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level; - } - else if (c == end) { - nest_level--; - p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level; - } - else if (c == '\\') { - c = nextc(p); - if (type & STR_FUNC_EXPAND) { - if (c == end || c == beg) { - tokadd(p, c); - } - else if (c == '\n') { - p->lineno++; - p->column = 0; - if (type & STR_FUNC_ARRAY) { - tokadd(p, '\n'); - } - } - else if (type & STR_FUNC_REGEXP) { - tokadd(p, '\\'); - tokadd(p, c); - } - else { - pushback(p, c); - tokadd(p, read_escape(p)); - if (hinf) - hinf->line_head = FALSE; - } - } - else { - if (c != beg && c != end) { - if (c == '\n') { - p->lineno++; - p->column = 0; - } - if (!(c == '\\' || ((type & STR_FUNC_ARRAY) && ISSPACE(c)))) { - tokadd(p, '\\'); - } - } - tokadd(p, c); - } - continue; - } - else if ((c == '#') && (type & STR_FUNC_EXPAND)) { - c = nextc(p); - if (c == '{') { - tokfix(p); - p->lstate = EXPR_BEG; - p->cmd_start = TRUE; - yylval.nd = new_str(p, tok(p), toklen(p)); - if (hinf) { - hinf->line_head = FALSE; - return tHD_STRING_PART; - } - return tSTRING_PART; - } - tokadd(p, '#'); - pushback(p, c); - continue; - } - if ((type & STR_FUNC_ARRAY) && ISSPACE(c)) { - if (toklen(p) == 0) { - do { - if (c == '\n') { - p->lineno++; - p->column = 0; - heredoc_treat_nextline(p); - if (p->parsing_heredoc != NULL) { - return tHD_LITERAL_DELIM; - } - } - c = nextc(p); - } while (ISSPACE(c)); - pushback(p, c); - return tLITERAL_DELIM; - } - else { - pushback(p, c); - tokfix(p); - yylval.nd = new_str(p, tok(p), toklen(p)); - return tSTRING_MID; - } - } - tokadd(p, c); - } - - tokfix(p); - p->lstate = EXPR_END; - end_strterm(p); - - if (type & STR_FUNC_XQUOTE) { - yylval.nd = new_xstr(p, tok(p), toklen(p)); - return tXSTRING; - } - - if (type & STR_FUNC_REGEXP) { - int f = 0; - int re_opt; - char *s = strndup(tok(p), toklen(p)); - char flags[3]; - char *flag = flags; - char enc = '\0'; - char *encp; - char *dup; - - newtok(p); - while (re_opt = nextc(p), re_opt >= 0 && ISALPHA(re_opt)) { - switch (re_opt) { - case 'i': f |= 1; break; - case 'x': f |= 2; break; - case 'm': f |= 4; break; - case 'u': f |= 16; break; - case 'n': f |= 32; break; - default: tokadd(p, re_opt); break; - } - } - pushback(p, re_opt); - if (toklen(p)) { - char msg[128]; - tokfix(p); - snprintf(msg, sizeof(msg), "unknown regexp option%s - %s", - toklen(p) > 1 ? "s" : "", tok(p)); - yyerror(p, msg); - } - if (f != 0) { - if (f & 1) *flag++ = 'i'; - if (f & 2) *flag++ = 'x'; - if (f & 4) *flag++ = 'm'; - if (f & 16) enc = 'u'; - if (f & 32) enc = 'n'; - } - if (flag > flags) { - dup = strndup(flags, (size_t)(flag - flags)); - } else { - dup = NULL; - } - if (enc) { - encp = strndup(&enc, 1); - } else { - encp = NULL; - } - yylval.nd = new_regx(p, s, dup, encp); - - return tREGEXP; - } - - yylval.nd = new_str(p, tok(p), toklen(p)); - return tSTRING; -} - - -static int -heredoc_identifier(parser_state *p) -{ - int c; - int type = str_heredoc; - mrb_bool indent = FALSE; - mrb_bool quote = FALSE; - node *newnode; - parser_heredoc_info *info; - - c = nextc(p); - if (ISSPACE(c) || c == '=') { - pushback(p, c); - return 0; - } - if (c == '-') { - indent = TRUE; - c = nextc(p); - } - if (c == '\'' || c == '"') { - int term = c; - if (c == '\'') - quote = TRUE; - newtok(p); - while ((c = nextc(p)) >= 0 && c != term) { - if (c == '\n') { - c = -1; - break; - } - tokadd(p, c); - } - if (c < 0) { - yyerror(p, "unterminated here document identifier"); - return 0; - } - } - else { - if (c < 0) { - return 0; /* missing here document identifier */ - } - if (! identchar(c)) { - pushback(p, c); - if (indent) pushback(p, '-'); - return 0; - } - newtok(p); - do { - tokadd(p, c); - } while ((c = nextc(p)) >= 0 && identchar(c)); - pushback(p, c); - } - tokfix(p); - newnode = new_heredoc(p); - info = (parser_heredoc_info*)newnode->cdr; - info->term = strndup(tok(p), toklen(p)); - info->term_len = toklen(p); - if (! quote) - type |= STR_FUNC_EXPAND; - info->type = (string_type)type; - info->allow_indent = indent; - info->line_head = TRUE; - info->doc = NULL; - p->heredocs_from_nextline = push(p->heredocs_from_nextline, newnode); - p->lstate = EXPR_END; - - yylval.nd = newnode; - return tHEREDOC_BEG; -} - -static int -arg_ambiguous(parser_state *p) -{ - yywarning(p, "ambiguous first argument; put parentheses or even spaces"); - return 1; -} - -#include "lex.def" - -static int -parser_yylex(parser_state *p) -{ - int32_t c; - int space_seen = 0; - int cmd_state; - enum mrb_lex_state_enum last_state; - int token_column; - - if (p->lex_strterm) { - if (is_strterm_type(p, STR_FUNC_HEREDOC)) { - if (p->parsing_heredoc != NULL) - return parse_string(p); - } - else - return parse_string(p); - } - cmd_state = p->cmd_start; - p->cmd_start = FALSE; - retry: - last_state = p->lstate; - switch (c = nextc(p)) { - case '\004': /* ^D */ - case '\032': /* ^Z */ - case '\0': /* NUL */ - case -1: /* end of script. */ - if (p->heredocs_from_nextline) - goto maybe_heredoc; - return 0; - - /* white spaces */ - case ' ': case '\t': case '\f': case '\r': - case '\13': /* '\v' */ - space_seen = 1; - goto retry; - - case '#': /* it's a comment */ - skip(p, '\n'); - /* fall through */ - case -2: /* end of a file */ - case '\n': - maybe_heredoc: - heredoc_treat_nextline(p); - switch (p->lstate) { - case EXPR_BEG: - case EXPR_FNAME: - case EXPR_DOT: - case EXPR_CLASS: - case EXPR_VALUE: - p->lineno++; - p->column = 0; - if (p->parsing_heredoc != NULL) { - if (p->lex_strterm) { - return parse_string(p); - } - } - goto retry; - default: - break; - } - if (p->parsing_heredoc != NULL) { - return '\n'; - } - while ((c = nextc(p))) { - switch (c) { - case ' ': case '\t': case '\f': case '\r': - case '\13': /* '\v' */ - space_seen = 1; - break; - case '.': - if ((c = nextc(p)) != '.') { - pushback(p, c); - pushback(p, '.'); - goto retry; - } - case -1: /* EOF */ - case -2: /* end of a file */ - goto normal_newline; - default: - pushback(p, c); - goto normal_newline; - } - } - normal_newline: - p->cmd_start = TRUE; - p->lstate = EXPR_BEG; - return '\n'; - - case '*': - if ((c = nextc(p)) == '*') { - if ((c = nextc(p)) == '=') { - yylval.id = intern("**",2); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - pushback(p, c); - c = tPOW; - } - else { - if (c == '=') { - yylval.id = intern_c('*'); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - pushback(p, c); - if (IS_SPCARG(c)) { - yywarning(p, "'*' interpreted as argument prefix"); - c = tSTAR; - } - else if (IS_BEG()) { - c = tSTAR; - } - else { - c = '*'; - } - } - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - } - else { - p->lstate = EXPR_BEG; - } - return c; - - case '!': - c = nextc(p); - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - if (c == '@') { - return '!'; - } - } - else { - p->lstate = EXPR_BEG; - } - if (c == '=') { - return tNEQ; - } - if (c == '~') { - return tNMATCH; - } - pushback(p, c); - return '!'; - - case '=': - if (p->column == 1) { - static const char begin[] = "begin"; - static const char end[] = "\n=end"; - if (peeks(p, begin)) { - c = peekc_n(p, sizeof(begin)-1); - if (c < 0 || ISSPACE(c)) { - do { - if (!skips(p, end)) { - yyerror(p, "embedded document meets end of file"); - return 0; - } - c = nextc(p); - } while (!(c < 0 || ISSPACE(c))); - if (c != '\n') skip(p, '\n'); - p->lineno++; - p->column = 0; - goto retry; - } - } - } - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - } - else { - p->lstate = EXPR_BEG; - } - if ((c = nextc(p)) == '=') { - if ((c = nextc(p)) == '=') { - return tEQQ; - } - pushback(p, c); - return tEQ; - } - if (c == '~') { - return tMATCH; - } - else if (c == '>') { - return tASSOC; - } - pushback(p, c); - return '='; - - case '<': - c = nextc(p); - if (c == '<' && - p->lstate != EXPR_DOT && - p->lstate != EXPR_CLASS && - !IS_END() && - (!IS_ARG() || space_seen)) { - int token = heredoc_identifier(p); - if (token) - return token; - } - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - } - else { - p->lstate = EXPR_BEG; - if (p->lstate == EXPR_CLASS) { - p->cmd_start = TRUE; - } - } - if (c == '=') { - if ((c = nextc(p)) == '>') { - return tCMP; - } - pushback(p, c); - return tLEQ; - } - if (c == '<') { - if ((c = nextc(p)) == '=') { - yylval.id = intern("<<",2); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - pushback(p, c); - return tLSHFT; - } - pushback(p, c); - return '<'; - - case '>': - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - } - else { - p->lstate = EXPR_BEG; - } - if ((c = nextc(p)) == '=') { - return tGEQ; - } - if (c == '>') { - if ((c = nextc(p)) == '=') { - yylval.id = intern(">>",2); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - pushback(p, c); - return tRSHFT; - } - pushback(p, c); - return '>'; - - case '"': - p->lex_strterm = new_strterm(p, str_dquote, '"', 0); - return tSTRING_BEG; - - case '\'': - p->lex_strterm = new_strterm(p, str_squote, '\'', 0); - return parse_string(p); - - case '`': - if (p->lstate == EXPR_FNAME) { - p->lstate = EXPR_ENDFN; - return '`'; - } - if (p->lstate == EXPR_DOT) { - if (cmd_state) - p->lstate = EXPR_CMDARG; - else - p->lstate = EXPR_ARG; - return '`'; - } - p->lex_strterm = new_strterm(p, str_xquote, '`', 0); - return tXSTRING_BEG; - - case '?': - if (IS_END()) { - p->lstate = EXPR_VALUE; - return '?'; - } - c = nextc(p); - if (c < 0) { - yyerror(p, "incomplete character syntax"); - return 0; - } - if (ISSPACE(c)) { - if (!IS_ARG()) { - int c2; - switch (c) { - case ' ': - c2 = 's'; - break; - case '\n': - c2 = 'n'; - break; - case '\t': - c2 = 't'; - break; - case '\v': - c2 = 'v'; - break; - case '\r': - c2 = 'r'; - break; - case '\f': - c2 = 'f'; - break; - default: - c2 = 0; - break; - } - if (c2) { - char buf[256]; - snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2); - yyerror(p, buf); - } - } - ternary: - pushback(p, c); - p->lstate = EXPR_VALUE; - return '?'; - } - newtok(p); - /* need support UTF-8 if configured */ - if ((isalnum(c) || c == '_')) { - int c2 = nextc(p); - pushback(p, c2); - if ((isalnum(c2) || c2 == '_')) { - goto ternary; - } - } - if (c == '\\') { - c = read_escape(p); - tokadd(p, c); - } - else { - tokadd(p, c); - } - tokfix(p); - yylval.nd = new_str(p, tok(p), toklen(p)); - p->lstate = EXPR_END; - return tCHAR; - - case '&': - if ((c = nextc(p)) == '&') { - p->lstate = EXPR_BEG; - if ((c = nextc(p)) == '=') { - yylval.id = intern("&&",2); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - pushback(p, c); - return tANDOP; - } - else if (c == '=') { - yylval.id = intern_c('&'); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - pushback(p, c); - if (IS_SPCARG(c)) { - yywarning(p, "'&' interpreted as argument prefix"); - c = tAMPER; - } - else if (IS_BEG()) { - c = tAMPER; - } - else { - c = '&'; - } - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - } - else { - p->lstate = EXPR_BEG; - } - return c; - - case '|': - if ((c = nextc(p)) == '|') { - p->lstate = EXPR_BEG; - if ((c = nextc(p)) == '=') { - yylval.id = intern("||",2); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - pushback(p, c); - return tOROP; - } - if (c == '=') { - yylval.id = intern_c('|'); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - } - else { - p->lstate = EXPR_BEG; - } - pushback(p, c); - return '|'; - - case '+': - c = nextc(p); - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - if (c == '@') { - return tUPLUS; - } - pushback(p, c); - return '+'; - } - if (c == '=') { - yylval.id = intern_c('+'); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) { - p->lstate = EXPR_BEG; - pushback(p, c); - if (c >= 0 && ISDIGIT(c)) { - c = '+'; - goto start_num; - } - return tUPLUS; - } - p->lstate = EXPR_BEG; - pushback(p, c); - return '+'; - - case '-': - c = nextc(p); - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - if (c == '@') { - return tUMINUS; - } - pushback(p, c); - return '-'; - } - if (c == '=') { - yylval.id = intern_c('-'); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - if (c == '>') { - p->lstate = EXPR_ENDFN; - return tLAMBDA; - } - if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) { - p->lstate = EXPR_BEG; - pushback(p, c); - if (c >= 0 && ISDIGIT(c)) { - return tUMINUS_NUM; - } - return tUMINUS; - } - p->lstate = EXPR_BEG; - pushback(p, c); - return '-'; - - case '.': - p->lstate = EXPR_BEG; - if ((c = nextc(p)) == '.') { - if ((c = nextc(p)) == '.') { - return tDOT3; - } - pushback(p, c); - return tDOT2; - } - pushback(p, c); - if (c >= 0 && ISDIGIT(c)) { - yyerror(p, "no . floating literal anymore; put 0 before dot"); - } - p->lstate = EXPR_DOT; - return '.'; - - start_num: - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - int is_float, seen_point, seen_e, nondigit; - - is_float = seen_point = seen_e = nondigit = 0; - p->lstate = EXPR_END; - newtok(p); - if (c == '-' || c == '+') { - tokadd(p, c); - c = nextc(p); - } - if (c == '0') { -#define no_digits() do {yyerror(p,"numeric literal without digits"); return 0;} while (0) - int start = toklen(p); - c = nextc(p); - if (c == 'x' || c == 'X') { - /* hexadecimal */ - c = nextc(p); - if (c >= 0 && ISXDIGIT(c)) { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (!ISXDIGIT(c)) break; - nondigit = 0; - tokadd(p, tolower(c)); - } while ((c = nextc(p)) >= 0); - } - pushback(p, c); - tokfix(p); - if (toklen(p) == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 16); - return tINTEGER; - } - if (c == 'b' || c == 'B') { - /* binary */ - c = nextc(p); - if (c == '0' || c == '1') { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (c != '0' && c != '1') break; - nondigit = 0; - tokadd(p, c); - } while ((c = nextc(p)) >= 0); - } - pushback(p, c); - tokfix(p); - if (toklen(p) == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 2); - return tINTEGER; - } - if (c == 'd' || c == 'D') { - /* decimal */ - c = nextc(p); - if (c >= 0 && ISDIGIT(c)) { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (!ISDIGIT(c)) break; - nondigit = 0; - tokadd(p, c); - } while ((c = nextc(p)) >= 0); - } - pushback(p, c); - tokfix(p); - if (toklen(p) == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 10); - return tINTEGER; - } - if (c == '_') { - /* 0_0 */ - goto octal_number; - } - if (c == 'o' || c == 'O') { - /* prefixed octal */ - c = nextc(p); - if (c < 0 || c == '_' || !ISDIGIT(c)) { - no_digits(); - } - } - if (c >= '0' && c <= '7') { - /* octal */ - octal_number: - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (c < '0' || c > '9') break; - if (c > '7') goto invalid_octal; - nondigit = 0; - tokadd(p, c); - } while ((c = nextc(p)) >= 0); - - if (toklen(p) > start) { - pushback(p, c); - tokfix(p); - if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 8); - return tINTEGER; - } - if (nondigit) { - pushback(p, c); - goto trailing_uc; - } - } - if (c > '7' && c <= '9') { - invalid_octal: - yyerror(p, "Invalid octal digit"); - } - else if (c == '.' || c == 'e' || c == 'E') { - tokadd(p, '0'); - } - else { - pushback(p, c); - yylval.nd = new_int(p, "0", 10); - return tINTEGER; - } - } - - for (;;) { - switch (c) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - nondigit = 0; - tokadd(p, c); - break; - - case '.': - if (nondigit) goto trailing_uc; - if (seen_point || seen_e) { - goto decode_num; - } - else { - int c0 = nextc(p); - if (c0 < 0 || !ISDIGIT(c0)) { - pushback(p, c0); - goto decode_num; - } - c = c0; - } - tokadd(p, '.'); - tokadd(p, c); - is_float++; - seen_point++; - nondigit = 0; - break; - - case 'e': - case 'E': - if (nondigit) { - pushback(p, c); - c = nondigit; - goto decode_num; - } - if (seen_e) { - goto decode_num; - } - tokadd(p, c); - seen_e++; - is_float++; - nondigit = c; - c = nextc(p); - if (c != '-' && c != '+') continue; - tokadd(p, c); - nondigit = c; - break; - - case '_': /* '_' in number just ignored */ - if (nondigit) goto decode_num; - nondigit = c; - break; - - default: - goto decode_num; - } - c = nextc(p); - } - - decode_num: - pushback(p, c); - if (nondigit) { - trailing_uc: - yyerror_i(p, "trailing '%c' in number", nondigit); - } - tokfix(p); - if (is_float) { - double d; - char *endp; - - errno = 0; - d = strtod(tok(p), &endp); - if (d == 0 && endp == tok(p)) { - yywarning_s(p, "corrupted float value %s", tok(p)); - } - else if (errno == ERANGE) { - yywarning_s(p, "float %s out of range", tok(p)); - errno = 0; - } - yylval.nd = new_float(p, tok(p)); - return tFLOAT; - } - yylval.nd = new_int(p, tok(p), 10); - return tINTEGER; - } - - case ')': - case ']': - p->paren_nest--; - /* fall through */ - case '}': - COND_LEXPOP(); - CMDARG_LEXPOP(); - if (c == ')') - p->lstate = EXPR_ENDFN; - else - p->lstate = EXPR_ENDARG; - return c; - - case ':': - c = nextc(p); - if (c == ':') { - if (IS_BEG() || p->lstate == EXPR_CLASS || IS_SPCARG(-1)) { - p->lstate = EXPR_BEG; - return tCOLON3; - } - p->lstate = EXPR_DOT; - return tCOLON2; - } - if (IS_END() || ISSPACE(c)) { - pushback(p, c); - p->lstate = EXPR_BEG; - return ':'; - } - pushback(p, c); - p->lstate = EXPR_FNAME; - return tSYMBEG; - - case '/': - if (IS_BEG()) { - p->lex_strterm = new_strterm(p, str_regexp, '/', 0); - return tREGEXP_BEG; - } - if ((c = nextc(p)) == '=') { - yylval.id = intern_c('/'); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - pushback(p, c); - if (IS_SPCARG(c)) { - p->lex_strterm = new_strterm(p, str_regexp, '/', 0); - return tREGEXP_BEG; - } - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - } - else { - p->lstate = EXPR_BEG; - } - return '/'; - - case '^': - if ((c = nextc(p)) == '=') { - yylval.id = intern_c('^'); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - } - else { - p->lstate = EXPR_BEG; - } - pushback(p, c); - return '^'; - - case ';': - p->lstate = EXPR_BEG; - return ';'; - - case ',': - p->lstate = EXPR_BEG; - return ','; - - case '~': - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - if ((c = nextc(p)) != '@') { - pushback(p, c); - } - p->lstate = EXPR_ARG; - } - else { - p->lstate = EXPR_BEG; - } - return '~'; - - case '(': - if (IS_BEG()) { - c = tLPAREN; - } - else if (IS_SPCARG(-1)) { - c = tLPAREN_ARG; - } - p->paren_nest++; - COND_PUSH(0); - CMDARG_PUSH(0); - p->lstate = EXPR_BEG; - return c; - - case '[': - p->paren_nest++; - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - if ((c = nextc(p)) == ']') { - if ((c = nextc(p)) == '=') { - return tASET; - } - pushback(p, c); - return tAREF; - } - pushback(p, c); - return '['; - } - else if (IS_BEG()) { - c = tLBRACK; - } - else if (IS_ARG() && space_seen) { - c = tLBRACK; - } - p->lstate = EXPR_BEG; - COND_PUSH(0); - CMDARG_PUSH(0); - return c; - - case '{': - if (p->lpar_beg && p->lpar_beg == p->paren_nest) { - p->lstate = EXPR_BEG; - p->lpar_beg = 0; - p->paren_nest--; - COND_PUSH(0); - CMDARG_PUSH(0); - return tLAMBEG; - } - if (IS_ARG() || p->lstate == EXPR_END || p->lstate == EXPR_ENDFN) - c = '{'; /* block (primary) */ - else if (p->lstate == EXPR_ENDARG) - c = tLBRACE_ARG; /* block (expr) */ - else - c = tLBRACE; /* hash */ - COND_PUSH(0); - CMDARG_PUSH(0); - p->lstate = EXPR_BEG; - return c; - - case '\\': - c = nextc(p); - if (c == '\n') { - p->lineno++; - p->column = 0; - space_seen = 1; - goto retry; /* skip \\n */ - } - pushback(p, c); - return '\\'; - - case '%': - if (IS_BEG()) { - int term; - int paren; - - c = nextc(p); - quotation: - if (c < 0 || !ISALNUM(c)) { - term = c; - c = 'Q'; - } - else { - term = nextc(p); - if (isalnum(term)) { - yyerror(p, "unknown type of %string"); - return 0; - } - } - if (c < 0 || term < 0) { - yyerror(p, "unterminated quoted string meets end of file"); - return 0; - } - paren = term; - if (term == '(') term = ')'; - else if (term == '[') term = ']'; - else if (term == '{') term = '}'; - else if (term == '<') term = '>'; - else paren = 0; - - switch (c) { - case 'Q': - p->lex_strterm = new_strterm(p, str_dquote, term, paren); - return tSTRING_BEG; - - case 'q': - p->lex_strterm = new_strterm(p, str_squote, term, paren); - return parse_string(p); - - case 'W': - p->lex_strterm = new_strterm(p, str_dword, term, paren); - return tWORDS_BEG; - - case 'w': - p->lex_strterm = new_strterm(p, str_sword, term, paren); - return tWORDS_BEG; - - case 'x': - p->lex_strterm = new_strterm(p, str_xquote, term, paren); - return tXSTRING_BEG; - - case 'r': - p->lex_strterm = new_strterm(p, str_regexp, term, paren); - return tREGEXP_BEG; - - case 's': - p->lex_strterm = new_strterm(p, str_ssym, term, paren); - return tSYMBEG; - - case 'I': - p->lex_strterm = new_strterm(p, str_dsymbols, term, paren); - return tSYMBOLS_BEG; - - case 'i': - p->lex_strterm = new_strterm(p, str_ssymbols, term, paren); - return tSYMBOLS_BEG; - - default: - yyerror(p, "unknown type of %string"); - return 0; - } - } - if ((c = nextc(p)) == '=') { - yylval.id = intern_c('%'); - p->lstate = EXPR_BEG; - return tOP_ASGN; - } - if (IS_SPCARG(c)) { - goto quotation; - } - if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { - p->lstate = EXPR_ARG; - } - else { - p->lstate = EXPR_BEG; - } - pushback(p, c); - return '%'; - - case '$': - p->lstate = EXPR_END; - token_column = newtok(p); - c = nextc(p); - if (c < 0) { - yyerror(p, "incomplete global variable syntax"); - return 0; - } - switch (c) { - case '_': /* $_: last read line string */ - c = nextc(p); - if (c >= 0 && identchar(c)) { /* if there is more after _ it is a variable */ - tokadd(p, '$'); - tokadd(p, c); - break; - } - pushback(p, c); - c = '_'; - /* fall through */ - case '~': /* $~: match-data */ - case '*': /* $*: argv */ - case '$': /* $$: pid */ - case '?': /* $?: last status */ - case '!': /* $!: error string */ - case '@': /* $@: error position */ - case '/': /* $/: input record separator */ - case '\\': /* $\: output record separator */ - case ';': /* $;: field separator */ - case ',': /* $,: output field separator */ - case '.': /* $.: last read line number */ - case '=': /* $=: ignorecase */ - case ':': /* $:: load path */ - case '<': /* $<: reading filename */ - case '>': /* $>: default output handle */ - case '\"': /* $": already loaded files */ - tokadd(p, '$'); - tokadd(p, c); - tokfix(p); - yylval.id = intern_cstr(tok(p)); - return tGVAR; - - case '-': - tokadd(p, '$'); - tokadd(p, c); - c = nextc(p); - pushback(p, c); - gvar: - tokfix(p); - yylval.id = intern_cstr(tok(p)); - return tGVAR; - - case '&': /* $&: last match */ - case '`': /* $`: string before last match */ - case '\'': /* $': string after last match */ - case '+': /* $+: string matches last pattern */ - if (last_state == EXPR_FNAME) { - tokadd(p, '$'); - tokadd(p, c); - goto gvar; - } - yylval.nd = new_back_ref(p, c); - return tBACK_REF; - - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': - do { - tokadd(p, c); - c = nextc(p); - } while (c >= 0 && isdigit(c)); - pushback(p, c); - if (last_state == EXPR_FNAME) goto gvar; - tokfix(p); - { - unsigned long n = strtoul(tok(p), NULL, 10); - if (n > INT_MAX) { - yyerror_i(p, "capture group index must be <= %d", INT_MAX); - return 0; - } - yylval.nd = new_nth_ref(p, (int)n); - } - return tNTH_REF; - - default: - if (!identchar(c)) { - pushback(p, c); - return '$'; - } - /* fall through */ - case '0': - tokadd(p, '$'); - } - break; - - case '@': - c = nextc(p); - token_column = newtok(p); - tokadd(p, '@'); - if (c == '@') { - tokadd(p, '@'); - c = nextc(p); - } - if (c < 0) { - if (p->bidx == 1) { - yyerror(p, "incomplete instance variable syntax"); - } - else { - yyerror(p, "incomplete class variable syntax"); - } - return 0; - } - else if (isdigit(c)) { - if (p->bidx == 1) { - yyerror_i(p, "'@%c' is not allowed as an instance variable name", c); - } - else { - yyerror_i(p, "'@@%c' is not allowed as a class variable name", c); - } - return 0; - } - if (!identchar(c)) { - pushback(p, c); - return '@'; - } - break; - - case '_': - token_column = newtok(p); - break; - - default: - if (!identchar(c)) { - yyerror_i(p, "Invalid char '\\x%02X' in expression", c); - goto retry; - } - - token_column = newtok(p); - break; - } - - do { - tokadd(p, c); - c = nextc(p); - if (c < 0) break; - } while (identchar(c)); - if (token_column == 0 && toklen(p) == 7 && (c < 0 || c == '\n') && - strncmp(tok(p), "__END__", toklen(p)) == 0) - return -1; - - switch (tok(p)[0]) { - case '@': case '$': - pushback(p, c); - break; - default: - if ((c == '!' || c == '?') && !peek(p, '=')) { - tokadd(p, c); - } - else { - pushback(p, c); - } - } - tokfix(p); - { - int result = 0; - - switch (tok(p)[0]) { - case '$': - p->lstate = EXPR_END; - result = tGVAR; - break; - case '@': - p->lstate = EXPR_END; - if (tok(p)[1] == '@') - result = tCVAR; - else - result = tIVAR; - break; - - default: - if (toklast(p) == '!' || toklast(p) == '?') { - result = tFID; - } - else { - if (p->lstate == EXPR_FNAME) { - if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') && - (!peek(p, '=') || (peek_n(p, '>', 1)))) { - result = tIDENTIFIER; - tokadd(p, c); - tokfix(p); - } - else { - pushback(p, c); - } - } - if (result == 0 && ISUPPER(tok(p)[0])) { - result = tCONSTANT; - } - else { - result = tIDENTIFIER; - } - } - - if (IS_LABEL_POSSIBLE()) { - if (IS_LABEL_SUFFIX(0)) { - p->lstate = EXPR_BEG; - nextc(p); - tokfix(p); - yylval.id = intern_cstr(tok(p)); - return tLABEL; - } - } - if (p->lstate != EXPR_DOT) { - const struct kwtable *kw; - - /* See if it is a reserved word. */ - kw = mrb_reserved_word(tok(p), toklen(p)); - if (kw) { - enum mrb_lex_state_enum state = p->lstate; - yylval.num = p->lineno; - p->lstate = kw->state; - if (state == EXPR_FNAME) { - yylval.id = intern_cstr(kw->name); - return kw->id[0]; - } - if (p->lstate == EXPR_BEG) { - p->cmd_start = TRUE; - } - if (kw->id[0] == keyword_do) { - if (p->lpar_beg && p->lpar_beg == p->paren_nest) { - p->lpar_beg = 0; - p->paren_nest--; - return keyword_do_LAMBDA; - } - if (COND_P()) return keyword_do_cond; - if (CMDARG_P() && state != EXPR_CMDARG) - return keyword_do_block; - if (state == EXPR_ENDARG || state == EXPR_BEG) - return keyword_do_block; - return keyword_do; - } - if (state == EXPR_BEG || state == EXPR_VALUE) - return kw->id[0]; - else { - if (kw->id[0] != kw->id[1]) - p->lstate = EXPR_BEG; - return kw->id[1]; - } - } - } - - if (IS_BEG() || p->lstate == EXPR_DOT || IS_ARG()) { - if (cmd_state) { - p->lstate = EXPR_CMDARG; - } - else { - p->lstate = EXPR_ARG; - } - } - else if (p->lstate == EXPR_FNAME) { - p->lstate = EXPR_ENDFN; - } - else { - p->lstate = EXPR_END; - } - } - { - mrb_sym ident = intern_cstr(tok(p)); - - yylval.id = ident; -#if 0 - if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) { - p->lstate = EXPR_END; - } -#endif - } - return result; - } -} - -static int -yylex(void *lval, parser_state *p) -{ - p->ylval = lval; - return parser_yylex(p); -} - -static void -parser_init_cxt(parser_state *p, mrbc_context *cxt) -{ - if (!cxt) return; - if (cxt->filename) mrb_parser_set_filename(p, cxt->filename); - if (cxt->lineno) p->lineno = cxt->lineno; - if (cxt->syms) { - int i; - - p->locals = cons(0,0); - for (i=0; islen; i++) { - local_add_f(p, cxt->syms[i]); - } - } - p->capture_errors = cxt->capture_errors; - p->no_optimize = cxt->no_optimize; - if (cxt->partial_hook) { - p->cxt = cxt; - } -} - -static void -parser_update_cxt(parser_state *p, mrbc_context *cxt) -{ - node *n, *n0; - int i = 0; - - if (!cxt) return; - if ((int)(intptr_t)p->tree->car != NODE_SCOPE) return; - n0 = n = p->tree->cdr->car; - while (n) { - i++; - n = n->cdr; - } - cxt->syms = (mrb_sym *)mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym)); - cxt->slen = i; - for (i=0, n=n0; n; i++,n=n->cdr) { - cxt->syms[i] = sym(n->car); - } -} - -void mrb_codedump_all(mrb_state*, struct RProc*); -void mrb_parser_dump(mrb_state *mrb, node *tree, int offset); - -MRB_API void -mrb_parser_parse(parser_state *p, mrbc_context *c) -{ - struct mrb_jmpbuf buf; - p->jmp = &buf; - - MRB_TRY(p->jmp) { - - p->cmd_start = TRUE; - p->in_def = p->in_single = 0; - p->nerr = p->nwarn = 0; - p->lex_strterm = NULL; - - parser_init_cxt(p, c); - yyparse(p); - if (!p->tree) { - p->tree = new_nil(p); - } - parser_update_cxt(p, c); - if (c && c->dump_result) { - mrb_parser_dump(p->mrb, p->tree, 0); - } - - } - MRB_CATCH(p->jmp) { - yyerror(p, "memory allocation error"); - p->nerr++; - p->tree = 0; - return; - } - MRB_END_EXC(p->jmp); -} - -MRB_API parser_state* -mrb_parser_new(mrb_state *mrb) -{ - mrb_pool *pool; - parser_state *p; - static const parser_state parser_state_zero = { 0 }; - - pool = mrb_pool_open(mrb); - if (!pool) return NULL; - p = (parser_state *)mrb_pool_alloc(pool, sizeof(parser_state)); - if (!p) return NULL; - - *p = parser_state_zero; - p->mrb = mrb; - p->pool = pool; - - p->s = p->send = NULL; -#ifndef MRB_DISBLE_STDIO - p->f = NULL; -#endif - - p->cmd_start = TRUE; - p->in_def = p->in_single = 0; - - p->capture_errors = FALSE; - p->lineno = 1; - p->column = 0; -#if defined(PARSER_TEST) || defined(PARSER_DEBUG) - yydebug = 1; -#endif - - p->lex_strterm = NULL; - p->all_heredocs = p->parsing_heredoc = NULL; - p->lex_strterm_before_heredoc = NULL; - - p->current_filename_index = -1; - p->filename_table = NULL; - p->filename_table_length = 0; - - return p; -} - -MRB_API void -mrb_parser_free(parser_state *p) { - mrb_pool_close(p->pool); -} - -MRB_API mrbc_context* -mrbc_context_new(mrb_state *mrb) -{ - return (mrbc_context *)mrb_calloc(mrb, 1, sizeof(mrbc_context)); -} - -MRB_API void -mrbc_context_free(mrb_state *mrb, mrbc_context *cxt) -{ - mrb_free(mrb, cxt->syms); - mrb_free(mrb, cxt); -} - -MRB_API const char* -mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s) -{ - if (s) { - int len = strlen(s); - char *p = (char *)mrb_alloca(mrb, len + 1); - - memcpy(p, s, len + 1); - c->filename = p; - } - return c->filename; -} - -MRB_API void -mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*func)(struct mrb_parser_state*), void *data) -{ - c->partial_hook = func; - c->partial_data = data; -} - -MRB_API void -mrb_parser_set_filename(struct mrb_parser_state *p, const char *f) -{ - mrb_sym sym; - size_t i; - mrb_sym* new_table; - - sym = mrb_intern_cstr(p->mrb, f); - p->filename = mrb_sym2name_len(p->mrb, sym, NULL); - p->lineno = (p->filename_table_length > 0)? 0 : 1; - - for (i = 0; i < p->filename_table_length; ++i) { - if (p->filename_table[i] == sym) { - p->current_filename_index = i; - return; - } - } - - p->current_filename_index = p->filename_table_length++; - - new_table = (mrb_sym*)parser_palloc(p, sizeof(mrb_sym) * p->filename_table_length); - if (p->filename_table) { - memmove(new_table, p->filename_table, sizeof(mrb_sym) * p->filename_table_length); - } - p->filename_table = new_table; - p->filename_table[p->filename_table_length - 1] = sym; -} - -MRB_API char const* -mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) { - if (idx >= p->filename_table_length) { return NULL; } - else { - return mrb_sym2name_len(p->mrb, p->filename_table[idx], NULL); - } -} - -#ifndef MRB_DISABLE_STDIO -MRB_API parser_state* -mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c) -{ - parser_state *p; - - p = mrb_parser_new(mrb); - if (!p) return NULL; - p->s = p->send = NULL; - p->f = f; - - mrb_parser_parse(p, c); - return p; -} -#endif - -MRB_API parser_state* -mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c) -{ - parser_state *p; - - p = mrb_parser_new(mrb); - if (!p) return NULL; - p->s = s; - p->send = s + len; - - mrb_parser_parse(p, c); - return p; -} - -MRB_API parser_state* -mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c) -{ - return mrb_parse_nstring(mrb, s, strlen(s), c); -} - -static mrb_value -load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) -{ - struct RClass *target = mrb->object_class; - struct RProc *proc; - mrb_value v; - unsigned int keep = 0; - - if (!p) { - return mrb_undef_value(); - } - if (!p->tree || p->nerr) { - if (p->capture_errors) { - char buf[256]; - int n; - - n = snprintf(buf, sizeof(buf), "line %d: %s\n", - p->error_buffer[0].lineno, p->error_buffer[0].message); - mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); - mrb_parser_free(p); - return mrb_undef_value(); - } - else { - mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SYNTAX_ERROR, "syntax error")); - mrb_parser_free(p); - return mrb_undef_value(); - } - } - proc = mrb_generate_code(mrb, p); - mrb_parser_free(p); - if (proc == NULL) { - mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "codegen error")); - return mrb_undef_value(); - } - if (c) { - if (c->dump_result) mrb_codedump_all(mrb, proc); - if (c->no_exec) return mrb_obj_value(proc); - if (c->target_class) { - target = c->target_class; - } - if (c->keep_lv) { - keep = c->slen + 1; - } - else { - c->keep_lv = TRUE; - } - } - proc->target_class = target; - if (mrb->c->ci) { - mrb->c->ci->target_class = target; - } - v = mrb_toplevel_run_keep(mrb, proc, keep); - if (mrb->exc) return mrb_nil_value(); - return v; -} - -#ifndef MRB_DISABLE_STDIO -MRB_API mrb_value -mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c) -{ - return load_exec(mrb, mrb_parse_file(mrb, f, c), c); -} - -MRB_API mrb_value -mrb_load_file(mrb_state *mrb, FILE *f) -{ - return mrb_load_file_cxt(mrb, f, NULL); -} -#endif - -MRB_API mrb_value -mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c) -{ - return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c); -} - -MRB_API mrb_value -mrb_load_nstring(mrb_state *mrb, const char *s, int len) -{ - return mrb_load_nstring_cxt(mrb, s, len, NULL); -} - -MRB_API mrb_value -mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c) -{ - return mrb_load_nstring_cxt(mrb, s, strlen(s), c); -} - -MRB_API mrb_value -mrb_load_string(mrb_state *mrb, const char *s) -{ - return mrb_load_string_cxt(mrb, s, NULL); -} - -#ifndef MRB_DISABLE_STDIO - -static void -dump_prefix(node *tree, int offset) -{ - printf("%05d ", tree->lineno); - while (offset--) { - putc(' ', stdout); - putc(' ', stdout); - } -} - -static void -dump_recur(mrb_state *mrb, node *tree, int offset) -{ - while (tree) { - mrb_parser_dump(mrb, tree->car, offset); - tree = tree->cdr; - } -} - -#endif - -void -mrb_parser_dump(mrb_state *mrb, node *tree, int offset) -{ -#ifndef MRB_DISABLE_STDIO - int nodetype; - - if (!tree) return; - again: - dump_prefix(tree, offset); - nodetype = (int)(intptr_t)tree->car; - tree = tree->cdr; - switch (nodetype) { - case NODE_BEGIN: - printf("NODE_BEGIN:\n"); - dump_recur(mrb, tree, offset+1); - break; - - case NODE_RESCUE: - printf("NODE_RESCUE:\n"); - if (tree->car) { - dump_prefix(tree, offset+1); - printf("body:\n"); - mrb_parser_dump(mrb, tree->car, offset+2); - } - tree = tree->cdr; - if (tree->car) { - node *n2 = tree->car; - - dump_prefix(n2, offset+1); - printf("rescue:\n"); - while (n2) { - node *n3 = n2->car; - if (n3->car) { - dump_prefix(n2, offset+2); - printf("handle classes:\n"); - dump_recur(mrb, n3->car, offset+3); - } - if (n3->cdr->car) { - dump_prefix(n3, offset+2); - printf("exc_var:\n"); - mrb_parser_dump(mrb, n3->cdr->car, offset+3); - } - if (n3->cdr->cdr->car) { - dump_prefix(n3, offset+2); - printf("rescue body:\n"); - mrb_parser_dump(mrb, n3->cdr->cdr->car, offset+3); - } - n2 = n2->cdr; - } - } - tree = tree->cdr; - if (tree->car) { - dump_prefix(tree, offset+1); - printf("else:\n"); - mrb_parser_dump(mrb, tree->car, offset+2); - } - break; - - case NODE_ENSURE: - printf("NODE_ENSURE:\n"); - dump_prefix(tree, offset+1); - printf("body:\n"); - mrb_parser_dump(mrb, tree->car, offset+2); - dump_prefix(tree, offset+1); - printf("ensure:\n"); - mrb_parser_dump(mrb, tree->cdr->cdr, offset+2); - break; - - case NODE_LAMBDA: - printf("NODE_BLOCK:\n"); - goto block; - - case NODE_BLOCK: - block: - printf("NODE_BLOCK:\n"); - tree = tree->cdr; - if (tree->car) { - node *n = tree->car; - - if (n->car) { - dump_prefix(n, offset+1); - printf("mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); - } - n = n->cdr; - if (n->car) { - dump_prefix(n, offset+1); - printf("optional args:\n"); - { - node *n2 = n->car; - - while (n2) { - dump_prefix(n2, offset+2); - printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); - mrb_parser_dump(mrb, n2->car->cdr, 0); - n2 = n2->cdr; - } - } - } - n = n->cdr; - if (n->car) { - dump_prefix(n, offset+1); - printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); - } - n = n->cdr; - if (n->car) { - dump_prefix(n, offset+1); - printf("post mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); - } - n = n->cdr; - if (n) { - dump_prefix(n, offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); - } - } - dump_prefix(tree, offset+1); - printf("body:\n"); - mrb_parser_dump(mrb, tree->cdr->car, offset+2); - break; - - case NODE_IF: - printf("NODE_IF:\n"); - dump_prefix(tree, offset+1); - printf("cond:\n"); - mrb_parser_dump(mrb, tree->car, offset+2); - dump_prefix(tree, offset+1); - printf("then:\n"); - mrb_parser_dump(mrb, tree->cdr->car, offset+2); - if (tree->cdr->cdr->car) { - dump_prefix(tree, offset+1); - printf("else:\n"); - mrb_parser_dump(mrb, tree->cdr->cdr->car, offset+2); - } - break; - - case NODE_AND: - printf("NODE_AND:\n"); - mrb_parser_dump(mrb, tree->car, offset+1); - mrb_parser_dump(mrb, tree->cdr, offset+1); - break; - - case NODE_OR: - printf("NODE_OR:\n"); - mrb_parser_dump(mrb, tree->car, offset+1); - mrb_parser_dump(mrb, tree->cdr, offset+1); - break; - - case NODE_CASE: - printf("NODE_CASE:\n"); - if (tree->car) { - mrb_parser_dump(mrb, tree->car, offset+1); - } - tree = tree->cdr; - while (tree) { - dump_prefix(tree, offset+1); - printf("case:\n"); - dump_recur(mrb, tree->car->car, offset+2); - dump_prefix(tree, offset+1); - printf("body:\n"); - mrb_parser_dump(mrb, tree->car->cdr, offset+2); - tree = tree->cdr; - } - break; - - case NODE_WHILE: - printf("NODE_WHILE:\n"); - dump_prefix(tree, offset+1); - printf("cond:\n"); - mrb_parser_dump(mrb, tree->car, offset+2); - dump_prefix(tree, offset+1); - printf("body:\n"); - mrb_parser_dump(mrb, tree->cdr, offset+2); - break; - - case NODE_UNTIL: - printf("NODE_UNTIL:\n"); - dump_prefix(tree, offset+1); - printf("cond:\n"); - mrb_parser_dump(mrb, tree->car, offset+2); - dump_prefix(tree, offset+1); - printf("body:\n"); - mrb_parser_dump(mrb, tree->cdr, offset+2); - break; - - case NODE_FOR: - printf("NODE_FOR:\n"); - dump_prefix(tree, offset+1); - printf("var:\n"); - { - node *n2 = tree->car; - - if (n2->car) { - dump_prefix(n2, offset+2); - printf("pre:\n"); - dump_recur(mrb, n2->car, offset+3); - } - n2 = n2->cdr; - if (n2) { - if (n2->car) { - dump_prefix(n2, offset+2); - printf("rest:\n"); - mrb_parser_dump(mrb, n2->car, offset+3); - } - n2 = n2->cdr; - if (n2) { - if (n2->car) { - dump_prefix(n2, offset+2); - printf("post:\n"); - dump_recur(mrb, n2->car, offset+3); - } - } - } - } - tree = tree->cdr; - dump_prefix(tree, offset+1); - printf("in:\n"); - mrb_parser_dump(mrb, tree->car, offset+2); - tree = tree->cdr; - dump_prefix(tree, offset+1); - printf("do:\n"); - mrb_parser_dump(mrb, tree->car, offset+2); - break; - - case NODE_SCOPE: - printf("NODE_SCOPE:\n"); - { - node *n2 = tree->car; - mrb_bool first_lval = TRUE; - - if (n2 && (n2->car || n2->cdr)) { - dump_prefix(n2, offset+1); - printf("local variables:\n"); - dump_prefix(n2, offset+2); - while (n2) { - if (n2->car) { - if (!first_lval) printf(", "); - printf("%s", mrb_sym2name(mrb, sym(n2->car))); - first_lval = FALSE; - } - n2 = n2->cdr; - } - printf("\n"); - } - } - tree = tree->cdr; - offset++; - goto again; - - case NODE_FCALL: - case NODE_CALL: - printf("NODE_CALL:\n"); - mrb_parser_dump(mrb, tree->car, offset+1); - dump_prefix(tree, offset+1); - printf("method='%s' (%d)\n", - mrb_sym2name(mrb, sym(tree->cdr->car)), - (int)(intptr_t)tree->cdr->car); - tree = tree->cdr->cdr->car; - if (tree) { - dump_prefix(tree, offset+1); - printf("args:\n"); - dump_recur(mrb, tree->car, offset+2); - if (tree->cdr) { - dump_prefix(tree, offset+1); - printf("block:\n"); - mrb_parser_dump(mrb, tree->cdr, offset+2); - } - } - break; - - case NODE_DOT2: - printf("NODE_DOT2:\n"); - mrb_parser_dump(mrb, tree->car, offset+1); - mrb_parser_dump(mrb, tree->cdr, offset+1); - break; - - case NODE_DOT3: - printf("NODE_DOT3:\n"); - mrb_parser_dump(mrb, tree->car, offset+1); - mrb_parser_dump(mrb, tree->cdr, offset+1); - break; - - case NODE_COLON2: - printf("NODE_COLON2:\n"); - mrb_parser_dump(mrb, tree->car, offset+1); - dump_prefix(tree, offset+1); - printf("::%s\n", mrb_sym2name(mrb, sym(tree->cdr))); - break; - - case NODE_COLON3: - printf("NODE_COLON3: ::%s\n", mrb_sym2name(mrb, sym(tree))); - break; - - case NODE_ARRAY: - printf("NODE_ARRAY:\n"); - dump_recur(mrb, tree, offset+1); - break; - - case NODE_HASH: - printf("NODE_HASH:\n"); - while (tree) { - dump_prefix(tree, offset+1); - printf("key:\n"); - mrb_parser_dump(mrb, tree->car->car, offset+2); - dump_prefix(tree, offset+1); - printf("value:\n"); - mrb_parser_dump(mrb, tree->car->cdr, offset+2); - tree = tree->cdr; - } - break; - - case NODE_SPLAT: - printf("NODE_SPLAT:\n"); - mrb_parser_dump(mrb, tree, offset+1); - break; - - case NODE_ASGN: - printf("NODE_ASGN:\n"); - dump_prefix(tree, offset+1); - printf("lhs:\n"); - mrb_parser_dump(mrb, tree->car, offset+2); - dump_prefix(tree, offset+1); - printf("rhs:\n"); - mrb_parser_dump(mrb, tree->cdr, offset+2); - break; - - case NODE_MASGN: - printf("NODE_MASGN:\n"); - dump_prefix(tree, offset+1); - printf("mlhs:\n"); - { - node *n2 = tree->car; - - if (n2->car) { - dump_prefix(tree, offset+2); - printf("pre:\n"); - dump_recur(mrb, n2->car, offset+3); - } - n2 = n2->cdr; - if (n2) { - if (n2->car) { - dump_prefix(n2, offset+2); - printf("rest:\n"); - if (n2->car == (node*)-1) { - dump_prefix(n2, offset+2); - printf("(empty)\n"); - } - else { - mrb_parser_dump(mrb, n2->car, offset+3); - } - } - n2 = n2->cdr; - if (n2) { - if (n2->car) { - dump_prefix(n2, offset+2); - printf("post:\n"); - dump_recur(mrb, n2->car, offset+3); - } - } - } - } - dump_prefix(tree, offset+1); - printf("rhs:\n"); - mrb_parser_dump(mrb, tree->cdr, offset+2); - break; - - case NODE_OP_ASGN: - printf("NODE_OP_ASGN:\n"); - dump_prefix(tree, offset+1); - printf("lhs:\n"); - mrb_parser_dump(mrb, tree->car, offset+2); - tree = tree->cdr; - dump_prefix(tree, offset+1); - printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)), (int)(intptr_t)tree->car); - tree = tree->cdr; - mrb_parser_dump(mrb, tree->car, offset+1); - break; - - case NODE_SUPER: - printf("NODE_SUPER:\n"); - if (tree) { - dump_prefix(tree, offset+1); - printf("args:\n"); - dump_recur(mrb, tree->car, offset+2); - if (tree->cdr) { - dump_prefix(tree, offset+1); - printf("block:\n"); - mrb_parser_dump(mrb, tree->cdr, offset+2); - } - } - break; - - case NODE_ZSUPER: - printf("NODE_ZSUPER\n"); - break; - - case NODE_RETURN: - printf("NODE_RETURN:\n"); - mrb_parser_dump(mrb, tree, offset+1); - break; - - case NODE_YIELD: - printf("NODE_YIELD:\n"); - dump_recur(mrb, tree, offset+1); - break; - - case NODE_BREAK: - printf("NODE_BREAK:\n"); - mrb_parser_dump(mrb, tree, offset+1); - break; - - case NODE_NEXT: - printf("NODE_NEXT:\n"); - mrb_parser_dump(mrb, tree, offset+1); - break; - - case NODE_REDO: - printf("NODE_REDO\n"); - break; - - case NODE_RETRY: - printf("NODE_RETRY\n"); - break; - - case NODE_LVAR: - printf("NODE_LVAR %s\n", mrb_sym2name(mrb, sym(tree))); - break; - - case NODE_GVAR: - printf("NODE_GVAR %s\n", mrb_sym2name(mrb, sym(tree))); - break; - - case NODE_IVAR: - printf("NODE_IVAR %s\n", mrb_sym2name(mrb, sym(tree))); - break; - - case NODE_CVAR: - printf("NODE_CVAR %s\n", mrb_sym2name(mrb, sym(tree))); - break; - - case NODE_CONST: - printf("NODE_CONST %s\n", mrb_sym2name(mrb, sym(tree))); - break; - - case NODE_MATCH: - printf("NODE_MATCH:\n"); - dump_prefix(tree, offset + 1); - printf("lhs:\n"); - mrb_parser_dump(mrb, tree->car, offset + 2); - dump_prefix(tree, offset + 1); - printf("rhs:\n"); - mrb_parser_dump(mrb, tree->cdr, offset + 2); - break; - - case NODE_BACK_REF: - printf("NODE_BACK_REF: $%c\n", (int)(intptr_t)tree); - break; - - case NODE_NTH_REF: - printf("NODE_NTH_REF: $%d\n", (int)(intptr_t)tree); - break; - - case NODE_ARG: - printf("NODE_ARG %s\n", mrb_sym2name(mrb, sym(tree))); - break; - - case NODE_BLOCK_ARG: - printf("NODE_BLOCK_ARG:\n"); - mrb_parser_dump(mrb, tree, offset+1); - break; - - case NODE_INT: - printf("NODE_INT %s base %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr->car); - break; - - case NODE_FLOAT: - printf("NODE_FLOAT %s\n", (char*)tree); - break; - - case NODE_NEGATE: - printf("NODE_NEGATE\n"); - mrb_parser_dump(mrb, tree, offset+1); - break; - - case NODE_STR: - printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr); - break; - - case NODE_DSTR: - printf("NODE_DSTR\n"); - dump_recur(mrb, tree, offset+1); - break; - - case NODE_XSTR: - printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr); - break; - - case NODE_DXSTR: - printf("NODE_DXSTR\n"); - dump_recur(mrb, tree, offset+1); - break; - - case NODE_REGX: - printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr); - break; - - case NODE_DREGX: - printf("NODE_DREGX\n"); - dump_recur(mrb, tree->car, offset+1); - dump_prefix(tree, offset); - printf("tail: %s\n", (char*)tree->cdr->cdr->car); - dump_prefix(tree, offset); - printf("opt: %s\n", (char*)tree->cdr->cdr->cdr); - break; - - case NODE_SYM: - printf("NODE_SYM :%s\n", mrb_sym2name(mrb, sym(tree))); - break; - - case NODE_SELF: - printf("NODE_SELF\n"); - break; - - case NODE_NIL: - printf("NODE_NIL\n"); - break; - - case NODE_TRUE: - printf("NODE_TRUE\n"); - break; - - case NODE_FALSE: - printf("NODE_FALSE\n"); - break; - - case NODE_ALIAS: - printf("NODE_ALIAS %s %s:\n", - mrb_sym2name(mrb, sym(tree->car)), - mrb_sym2name(mrb, sym(tree->cdr))); - break; - - case NODE_UNDEF: - printf("NODE_UNDEF"); - { - node *t = tree; - while (t) { - printf(" %s", mrb_sym2name(mrb, sym(t->car))); - t = t->cdr; - } - } - printf(":\n"); - break; - - case NODE_CLASS: - printf("NODE_CLASS:\n"); - if (tree->car->car == (node*)0) { - dump_prefix(tree, offset+1); - printf(":%s\n", mrb_sym2name(mrb, sym(tree->car->cdr))); - } - else if (tree->car->car == (node*)1) { - dump_prefix(tree, offset+1); - printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr))); - } - else { - mrb_parser_dump(mrb, tree->car->car, offset+1); - dump_prefix(tree, offset+1); - printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr))); - } - if (tree->cdr->car) { - dump_prefix(tree, offset+1); - printf("super:\n"); - mrb_parser_dump(mrb, tree->cdr->car, offset+2); - } - dump_prefix(tree, offset+1); - printf("body:\n"); - mrb_parser_dump(mrb, tree->cdr->cdr->car->cdr, offset+2); - break; - - case NODE_MODULE: - printf("NODE_MODULE:\n"); - if (tree->car->car == (node*)0) { - dump_prefix(tree, offset+1); - printf(":%s\n", mrb_sym2name(mrb, sym(tree->car->cdr))); - } - else if (tree->car->car == (node*)1) { - dump_prefix(tree, offset+1); - printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr))); - } - else { - mrb_parser_dump(mrb, tree->car->car, offset+1); - dump_prefix(tree, offset+1); - printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr))); - } - dump_prefix(tree, offset+1); - printf("body:\n"); - mrb_parser_dump(mrb, tree->cdr->car->cdr, offset+2); - break; - - case NODE_SCLASS: - printf("NODE_SCLASS:\n"); - mrb_parser_dump(mrb, tree->car, offset+1); - dump_prefix(tree, offset+1); - printf("body:\n"); - mrb_parser_dump(mrb, tree->cdr->car->cdr, offset+2); - break; - - case NODE_DEF: - printf("NODE_DEF:\n"); - dump_prefix(tree, offset+1); - printf("%s\n", mrb_sym2name(mrb, sym(tree->car))); - tree = tree->cdr; - { - node *n2 = tree->car; - mrb_bool first_lval = TRUE; - - if (n2 && (n2->car || n2->cdr)) { - dump_prefix(n2, offset+1); - printf("local variables:\n"); - dump_prefix(n2, offset+2); - while (n2) { - if (n2->car) { - if (!first_lval) printf(", "); - printf("%s", mrb_sym2name(mrb, sym(n2->car))); - first_lval = FALSE; - } - n2 = n2->cdr; - } - printf("\n"); - } - } - tree = tree->cdr; - if (tree->car) { - node *n = tree->car; - - if (n->car) { - dump_prefix(n, offset+1); - printf("mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); - } - n = n->cdr; - if (n->car) { - dump_prefix(n, offset+1); - printf("optional args:\n"); - { - node *n2 = n->car; - - while (n2) { - dump_prefix(n2, offset+2); - printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); - mrb_parser_dump(mrb, n2->car->cdr, 0); - n2 = n2->cdr; - } - } - } - n = n->cdr; - if (n->car) { - dump_prefix(n, offset+1); - printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); - } - n = n->cdr; - if (n->car) { - dump_prefix(n, offset+1); - printf("post mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); - } - if (n->cdr) { - dump_prefix(n, offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr))); - } - } - mrb_parser_dump(mrb, tree->cdr->car, offset+1); - break; - - case NODE_SDEF: - printf("NODE_SDEF:\n"); - mrb_parser_dump(mrb, tree->car, offset+1); - tree = tree->cdr; - dump_prefix(tree, offset+1); - printf(":%s\n", mrb_sym2name(mrb, sym(tree->car))); - tree = tree->cdr->cdr; - if (tree->car) { - node *n = tree->car; - - if (n->car) { - dump_prefix(n, offset+1); - printf("mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); - } - n = n->cdr; - if (n->car) { - dump_prefix(n, offset+1); - printf("optional args:\n"); - { - node *n2 = n->car; - - while (n2) { - dump_prefix(n2, offset+2); - printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); - mrb_parser_dump(mrb, n2->car->cdr, 0); - n2 = n2->cdr; - } - } - } - n = n->cdr; - if (n->car) { - dump_prefix(n, offset+1); - printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); - } - n = n->cdr; - if (n->car) { - dump_prefix(n, offset+1); - printf("post mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); - } - n = n->cdr; - if (n) { - dump_prefix(n, offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); - } - } - tree = tree->cdr; - mrb_parser_dump(mrb, tree->car, offset+1); - break; - - case NODE_POSTEXE: - printf("NODE_POSTEXE:\n"); - mrb_parser_dump(mrb, tree, offset+1); - break; - - case NODE_HEREDOC: - printf("NODE_HEREDOC:\n"); - mrb_parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); - break; - - default: - printf("node type: %d (0x%x)\n", nodetype, (unsigned)nodetype); - break; - } -#endif -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-compiler/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-compiler/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -MRuby::Gem::Specification.new 'mruby-compiler' do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'mruby compiler library' - - current_dir = spec.dir - current_build_dir = spec.build_dir - - lex_def = "#{current_dir}/core/lex.def" - core_objs = Dir.glob("#{current_dir}/core/*.c").map { |f| - next nil if build.cxx_abi_enabled? and f =~ /(codegen).c$/ - objfile(f.pathmap("#{current_build_dir}/core/%n")) - }.compact - - if build.cxx_abi_enabled? - core_objs << - build.compile_as_cxx("#{current_build_dir}/core/y.tab.c", "#{current_build_dir}/core/y.tab.cxx", - objfile("#{current_build_dir}/y.tab"), ["#{current_dir}/core"]) << - build.compile_as_cxx("#{current_dir}/core/codegen.c", "#{current_build_dir}/core/codegen.cxx") - else - core_objs << objfile("#{current_build_dir}/core/y.tab") - file objfile("#{current_build_dir}/core/y.tab") => "#{current_build_dir}/core/y.tab.c" do |t| - cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"] - end - end - file objfile("#{current_build_dir}/core/y.tab") => lex_def - - # Parser - file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y"] do |t| - yacc.run t.name, t.prerequisites.first - end - - # Lexical analyzer - file lex_def => "#{current_dir}/core/keywords" do |t| - gperf.run t.name, t.prerequisites.first - end - - file libfile("#{build.build_dir}/lib/libmruby_core") => core_objs - build.libmruby << core_objs -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enumerator/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enumerator/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enumerator/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enumerator/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -MRuby::Gem::Specification.new('mruby-enumerator') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.add_dependency('mruby-fiber', :core => 'mruby-fiber') - spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext' - spec.summary = 'Enumerator class' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,634 +0,0 @@ -## -# enumerator.rb Enumerator class -# See Copyright Notice in mruby.h - -## -# A class which allows both internal and external iteration. -# -# An Enumerator can be created by the following methods. -# - {Kernel#to_enum} -# - {Kernel#enum_for} -# - {Enumerator#initialize Enumerator.new} -# -# Most methods have two forms: a block form where the contents -# are evaluated for each item in the enumeration, and a non-block form -# which returns a new Enumerator wrapping the iteration. -# -# enumerator = %w(one two three).each -# puts enumerator.class # => Enumerator -# -# enumerator.each_with_object("foo") do |item, obj| -# puts "#{obj}: #{item}" -# end -# -# # foo: one -# # foo: two -# # foo: three -# -# enum_with_obj = enumerator.each_with_object("foo") -# puts enum_with_obj.class # => Enumerator -# -# enum_with_obj.each do |item, obj| -# puts "#{obj}: #{item}" -# end -# -# # foo: one -# # foo: two -# # foo: three -# -# This allows you to chain Enumerators together. For example, you -# can map a list's elements to strings containing the index -# and the element as a string via: -# -# puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" } -# # => ["0:foo", "1:bar", "2:baz"] -# -# An Enumerator can also be used as an external iterator. -# For example, Enumerator#next returns the next value of the iterator -# or raises StopIteration if the Enumerator is at the end. -# -# e = [1,2,3].each # returns an enumerator object. -# puts e.next # => 1 -# puts e.next # => 2 -# puts e.next # => 3 -# puts e.next # raises StopIteration -# -# You can use this to implement an internal iterator as follows: -# -# def ext_each(e) -# while true -# begin -# vs = e.next_values -# rescue StopIteration -# return $!.result -# end -# y = yield(*vs) -# e.feed y -# end -# end -# -# o = Object.new -# -# def o.each -# puts yield -# puts yield(1) -# puts yield(1, 2) -# 3 -# end -# -# # use o.each as an internal iterator directly. -# puts o.each {|*x| puts x; [:b, *x] } -# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3 -# -# # convert o.each to an external iterator for -# # implementing an internal iterator. -# puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] } -# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3 -# -class Enumerator - include Enumerable - - ## - # @overload initialize(size = nil, &block) - # @overload initialize(obj, method = :each, *args) - # - # Creates a new Enumerator object, which can be used as an - # Enumerable. - # - # In the first form, iteration is defined by the given block, in - # which a "yielder" object, given as block parameter, can be used to - # yield a value by calling the +yield+ method (aliased as +<<+): - # - # fib = Enumerator.new do |y| - # a = b = 1 - # loop do - # y << a - # a, b = b, a + b - # end - # end - # - # p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] - # - def initialize(obj=nil, meth=:each, *args, &block) - if block_given? - obj = Generator.new(&block) - else - raise ArgumentError unless obj - end - - @obj = obj - @meth = meth - @args = args.dup - @fib = nil - @dst = nil - @lookahead = nil - @feedvalue = nil - @stop_exc = false - end - attr_accessor :obj, :meth, :args, :fib - private :obj, :meth, :args, :fib - - def initialize_copy(obj) - raise TypeError, "can't copy type #{obj.class}" unless obj.kind_of? Enumerator - raise TypeError, "can't copy execution context" if obj.fib - @obj = obj.obj - @meth = obj.meth - @args = obj.args - @fib = nil - @lookahead = nil - @feedvalue = nil - self - end - - ## - # call-seq: - # e.with_index(offset = 0) {|(*args), idx| ... } - # e.with_index(offset = 0) - # - # Iterates the given block for each element with an index, which - # starts from +offset+. If no block is given, returns a new Enumerator - # that includes the index, starting from +offset+ - # - # +offset+:: the starting index to use - # - def with_index(offset=0) - return to_enum :with_index, offset unless block_given? - raise TypeError, "no implicit conversion of #{offset.class} into Integer" unless offset.respond_to?(:to_int) - - n = offset.to_int - 1 - enumerator_block_call do |i| - n += 1 - yield [i,n] - end - end - - ## - # call-seq: - # e.each_with_index {|(*args), idx| ... } - # e.each_with_index - # - # Same as Enumerator#with_index(0), i.e. there is no starting offset. - # - # If no block is given, a new Enumerator is returned that includes the index. - # - def each_with_index - with_index - end - - ## - # call-seq: - # e.each_with_object(obj) {|(*args), obj| ... } - # e.each_with_object(obj) - # e.with_object(obj) {|(*args), obj| ... } - # e.with_object(obj) - # - # Iterates the given block for each element with an arbitrary object, +obj+, - # and returns +obj+ - # - # If no block is given, returns a new Enumerator. - # - # @example - # to_three = Enumerator.new do |y| - # 3.times do |x| - # y << x - # end - # end - # - # to_three_with_string = to_three.with_object("foo") - # to_three_with_string.each do |x,string| - # puts "#{string}: #{x}" - # end - # - # # => foo:0 - # # => foo:1 - # # => foo:2 - # - def with_object(object) - return to_enum(:with_object, object) unless block_given? - - enumerator_block_call do |i| - yield [i,object] - end - object - end - - def inspect - return "#<#{self.class}: uninitialized>" unless @obj - - if @args && @args.size > 0 - args = @args.join(", ") - "#<#{self.class}: #{@obj}:#{@meth}(#{args})>" - else - "#<#{self.class}: #{@obj}:#{@meth}>" - end - end - - ## - # call-seq: - # enum.each { |elm| block } -> obj - # enum.each -> enum - # enum.each(*appending_args) { |elm| block } -> obj - # enum.each(*appending_args) -> an_enumerator - # - # Iterates over the block according to how this Enumerator was constructed. - # If no block and no arguments are given, returns self. - # - # === Examples - # - # "Hello, world!".scan(/\w+/) #=> ["Hello", "world"] - # "Hello, world!".to_enum(:scan, /\w+/).to_a #=> ["Hello", "world"] - # "Hello, world!".to_enum(:scan).each(/\w+/).to_a #=> ["Hello", "world"] - # - # obj = Object.new - # - # def obj.each_arg(a, b=:b, *rest) - # yield a - # yield b - # yield rest - # :method_returned - # end - # - # enum = obj.to_enum :each_arg, :a, :x - # - # enum.each.to_a #=> [:a, :x, []] - # enum.each.equal?(enum) #=> true - # enum.each { |elm| elm } #=> :method_returned - # - # enum.each(:y, :z).to_a #=> [:a, :x, [:y, :z]] - # enum.each(:y, :z).equal?(enum) #=> false - # enum.each(:y, :z) { |elm| elm } #=> :method_returned - # - def each(*argv, &block) - obj = self - if 0 < argv.length - obj = self.dup - args = obj.args - if !args.empty? - args = args.dup - args.concat argv - else - args = argv.dup - end - obj.args = args - end - return obj unless block_given? - enumerator_block_call(&block) - end - - def enumerator_block_call(&block) - @obj.__send__ @meth, *@args, &block - end - private :enumerator_block_call - - ## - # call-seq: - # e.next -> object - # - # Returns the next object in the enumerator, and move the internal position - # forward. When the position reached at the end, StopIteration is raised. - # - # === Example - # - # a = [1,2,3] - # e = a.to_enum - # p e.next #=> 1 - # p e.next #=> 2 - # p e.next #=> 3 - # p e.next #raises StopIteration - # - # Note that enumeration sequence by +next+ does not affect other non-external - # enumeration methods, unless the underlying iteration methods itself has - # side-effect - # - def next - next_values.__svalue - end - - ## - # call-seq: - # e.next_values -> array - # - # Returns the next object as an array in the enumerator, and move the - # internal position forward. When the position reached at the end, - # StopIteration is raised. - # - # This method can be used to distinguish yield and yield - # nil. - # - # === Example - # - # o = Object.new - # def o.each - # yield - # yield 1 - # yield 1, 2 - # yield nil - # yield [1, 2] - # end - # e = o.to_enum - # p e.next_values - # p e.next_values - # p e.next_values - # p e.next_values - # p e.next_values - # e = o.to_enum - # p e.next - # p e.next - # p e.next - # p e.next - # p e.next - # - # ## yield args next_values next - # # yield [] nil - # # yield 1 [1] 1 - # # yield 1, 2 [1, 2] [1, 2] - # # yield nil [nil] nil - # # yield [1, 2] [[1, 2]] [1, 2] - # - # Note that +next_values+ does not affect other non-external enumeration - # methods unless underlying iteration method itself has side-effect - # - def next_values - if @lookahead - vs = @lookahead - @lookahead = nil - return vs - end - raise @stop_exc if @stop_exc - - curr = Fiber.current - - if !@fib || !@fib.alive? - @dst = curr - @fib = Fiber.new do - result = each do |*args| - feedvalue = nil - Fiber.yield args - if @feedvalue - feedvalue = @feedvalue - @feedvalue = nil - end - feedvalue - end - @stop_exc = StopIteration.new "iteration reached an end" - @stop_exc.result = result - Fiber.yield nil - end - @lookahead = nil - end - - vs = @fib.resume curr - if @stop_exc - @fib = nil - @dst = nil - @lookahead = nil - @feedvalue = nil - raise @stop_exc - end - vs - end - - ## - # call-seq: - # e.peek -> object - # - # Returns the next object in the enumerator, but doesn't move the internal - # position forward. If the position is already at the end, StopIteration - # is raised. - # - # === Example - # - # a = [1,2,3] - # e = a.to_enum - # p e.next #=> 1 - # p e.peek #=> 2 - # p e.peek #=> 2 - # p e.peek #=> 2 - # p e.next #=> 2 - # p e.next #=> 3 - # p e.next #raises StopIteration - # - def peek - peek_values.__svalue - end - - ## - # call-seq: - # e.peek_values -> array - # - # Returns the next object as an array, similar to Enumerator#next_values, but - # doesn't move the internal position forward. If the position is already at - # the end, StopIteration is raised. - # - # === Example - # - # o = Object.new - # def o.each - # yield - # yield 1 - # yield 1, 2 - # end - # e = o.to_enum - # p e.peek_values #=> [] - # e.next - # p e.peek_values #=> [1] - # p e.peek_values #=> [1] - # e.next - # p e.peek_values #=> [1, 2] - # e.next - # p e.peek_values # raises StopIteration - # - def peek_values - if @lookahead.nil? - @lookahead = next_values - end - @lookahead.dup - end - - ## - # call-seq: - # e.rewind -> e - # - # Rewinds the enumeration sequence to the beginning. - # - # If the enclosed object responds to a "rewind" method, it is called. - # - def rewind - @obj.rewind if @obj.respond_to? :rewind - @fib = nil - @dst = nil - @lookahead = nil - @feedvalue = nil - @stop_exc = false - self - end - - ## - # call-seq: - # e.feed obj -> nil - # - # Sets the value to be returned by the next yield inside +e+. - # - # If the value is not set, the yield returns nil. - # - # This value is cleared after being yielded. - # - # # Array#map passes the array's elements to "yield" and collects the - # # results of "yield" as an array. - # # Following example shows that "next" returns the passed elements and - # # values passed to "feed" are collected as an array which can be - # # obtained by StopIteration#result. - # e = [1,2,3].map - # p e.next #=> 1 - # e.feed "a" - # p e.next #=> 2 - # e.feed "b" - # p e.next #=> 3 - # e.feed "c" - # begin - # e.next - # rescue StopIteration - # p $!.result #=> ["a", "b", "c"] - # end - # - # o = Object.new - # def o.each - # x = yield # (2) blocks - # p x # (5) => "foo" - # x = yield # (6) blocks - # p x # (8) => nil - # x = yield # (9) blocks - # p x # not reached w/o another e.next - # end - # - # e = o.to_enum - # e.next # (1) - # e.feed "foo" # (3) - # e.next # (4) - # e.next # (7) - # # (10) - # - def feed(value) - raise TypeError, "feed value already set" if @feedvalue - @feedvalue = value - nil - end - - # just for internal - class Generator - def initialize(&block) - raise TypeError, "wrong argument type #{self.class} (expected Proc)" unless block.kind_of? Proc - - @proc = block - end - - def each(*args, &block) - args.unshift Yielder.new(&block) - @proc.call(*args) - end - end - - # just for internal - class Yielder - def initialize(&block) - raise LocalJumpError, "no block given" unless block_given? - - @proc = block - end - - def yield(*args) - @proc.call(*args) - end - - def << *args - self.yield(*args) - self - end - end -end - -module Kernel - ## - # call-seq: - # obj.to_enum(method = :each, *args) -> enum - # obj.enum_for(method = :each, *args) -> enum - # obj.to_enum(method = :each, *args) {|*args| block} -> enum - # obj.enum_for(method = :each, *args){|*args| block} -> enum - # - # Creates a new Enumerator which will enumerate by calling +method+ on - # +obj+, passing +args+ if any. - # - # If a block is given, it will be used to calculate the size of - # the enumerator without the need to iterate it (see Enumerator#size). - # - # === Examples - # - # str = "xyz" - # - # enum = str.enum_for(:each_byte) - # enum.each { |b| puts b } - # # => 120 - # # => 121 - # # => 122 - # - # # protect an array from being modified by some_method - # a = [1, 2, 3] - # some_method(a.to_enum) - # - # It is typical to call to_enum when defining methods for - # a generic Enumerable, in case no block is passed. - # - # Here is such an example, with parameter passing and a sizing block: - # - # module Enumerable - # # a generic method to repeat the values of any enumerable - # def repeat(n) - # raise ArgumentError, "#{n} is negative!" if n < 0 - # unless block_given? - # return to_enum(__method__, n) do # __method__ is :repeat here - # sz = size # Call size and multiply by n... - # sz * n if sz # but return nil if size itself is nil - # end - # end - # each do |*val| - # n.times { yield *val } - # end - # end - # end - # - # %i[hello world].repeat(2) { |w| puts w } - # # => Prints 'hello', 'hello', 'world', 'world' - # enum = (1..14).repeat(3) - # # => returns an Enumerator when called without a block - # enum.first(4) # => [1, 1, 1, 2] - # - def to_enum(meth=:each, *args) - Enumerator.new self, meth, *args - end - alias :enum_for :to_enum -end - -module Enumerable - # use Enumerator to use infinite sequence - def zip(*arg) - ary = [] - arg = arg.map{|a|a.each} - i = 0 - self.each do |*val| - a = [] - a.push(val.__svalue) - idx = 0 - while idx < arg.size - begin - a.push(arg[idx].next) - rescue StopIteration - a.push(nil) - end - idx += 1 - end - ary.push(a) - i += 1 - end - ary - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enumerator/test/enumerator.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enumerator/test/enumerator.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enumerator/test/enumerator.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enumerator/test/enumerator.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,536 +0,0 @@ -@obj = Object.new -class << @obj - include Enumerable - def foo *a - a.each { |x| yield x } - end -end - -assert 'Enumerator' do - assert_equal Class, Enumerator.class -end - -assert 'Enumerator' do - assert_equal Object, Enumerator.superclass -end - -assert 'Enumerator.new' do - assert_equal [0,1,2], 3.times.map{|i| i}.sort - assert_equal [:x,:y,:z], [:x,:y,:z].each.map{|i| i}.sort - assert_equal [[:x,1],[:y,2]], {x:1, y:2}.each.map{|i| i}.sort - assert_equal [1,2,3], @obj.to_enum(:foo, 1,2,3).to_a - assert_equal [1,2,3], Enumerator.new(@obj, :foo, 1,2,3).to_a - assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3) - assert_raise(ArgumentError) { Enumerator.new } - enum = @obj.to_enum - assert_raise(NoMethodError) { enum.each {} } - - # examples - fib = Enumerator.new do |y| - a = b = 1 - loop do - y << a - a, b = b, a + b - end - end - assert_equal fib.take(10), [1,1,2,3,5,8,13,21,34,55] -end - -assert 'Enumerator#initialize_copy' do - assert_equal [1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).dup.to_a - e = @obj.to_enum :foo, 1, 2, 3 - assert_nothing_raised { assert_equal(1, e.next) } - assert_raise(TypeError) { e.dup } - - e = Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.dup - assert_nothing_raised { assert_equal(1, e.next) } - assert_raise(TypeError) { e.dup } -end - -assert 'Enumerator#with_index' do - assert_equal([[1,0],[2,1],[3,2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a) - assert_equal([[1,5],[2,6],[3,7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a) -end - -assert 'Enumerator#with_index nonnum offset' do - s = Object.new - def s.to_int; 1 end - assert_equal([[1,1],[2,2],[3,3]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a) -end - -assert 'Enumerator#with_index string offset' do - assert_raise(TypeError){ @obj.to_enum(:foo, 1, 2, 3).with_index('1').to_a } -end - -assert 'Enumerator#with_object' do - obj = [0, 1] - ret = (1..10).each.with_object(obj) {|i, memo| - memo[0] += i - memo[1] *= i - } - assert_true(obj.equal?(ret)) - assert_equal([55, 3628800], ret) -end - -assert 'Enumerator#with_object arguments' do - to_three = Enumerator.new do |y| - 3.times do |x| - y << x - end - end - - a = [] - to_three_with_string = to_three.with_object("foo") - to_three_with_string.each do |x,string| - a << "#{string}:#{x}" - end - assert_equal ["foo:0","foo:1","foo:2"], a -end - -assert 'Enumerator#inspect' do - e = (0..10).each - assert_equal("#", e.inspect) - e = Enumerator.new("FooObject", :foo, 1) - assert_equal("#", e.inspect) - e = Enumerator.new("FooObject", :foo, 1, 2, 3) - assert_equal("#", e.inspect) -end - -assert 'Enumerator#each' do - o = Object.new - def o.each(ary) - ary << 1 - yield - end - ary = [] - e = o.to_enum.each(ary) - e.next - assert_equal([1], ary) -end - -assert 'Enumerator#each arguments' do - obj = Object.new - - def obj.each_arg(a, b=:b, *rest) - yield a - yield b - yield rest - :method_returned - end - - enum = obj.to_enum :each_arg, :a, :x - - assert_equal [:a, :x, []], enum.each.to_a - assert_true enum.each.equal?(enum) - assert_equal :method_returned, enum.each { |elm| elm } - - assert_equal [:a, :x, [:y, :z]], enum.each(:y, :z).to_a - assert_false enum.each(:y, :z).equal?(enum) - assert_equal :method_returned, enum.each(:y, :z) { |elm| elm } -end - -assert 'Enumerator#next' do - e = 3.times - 3.times { |i| - assert_equal i, e.next - } - assert_raise(StopIteration) { e.next } -end - -assert 'Enumerator#next_values' do - o = Object.new - def o.each - yield - yield 1 - yield 1, 2 - end - e = o.to_enum - assert_equal nil, e.next - assert_equal 1, e.next - assert_equal [1,2], e.next - e = o.to_enum - assert_equal [], e.next_values - assert_equal [1], e.next_values - assert_equal [1,2], e.next_values -end - -assert 'Enumerator#peek' do - a = [1] - e = a.each - assert_equal 1, e.peek - assert_equal 1, e.peek - assert_equal 1, e.next - assert_raise(StopIteration) { e.peek } - assert_raise(StopIteration) { e.peek } -end - -assert 'Enumerator#peek modify' do - o = Object.new - def o.each - yield 1,2 - end - e = o.to_enum - a = e.peek - a << 3 - assert_equal([1,2], e.peek) -end - -assert 'Enumerator#peek_values' do - o = Object.new - def o.each - yield - yield 1 - yield 1, 2 - end - e = o.to_enum - assert_equal nil, e.peek - assert_equal nil, e.next - assert_equal 1, e.peek - assert_equal 1, e.next - assert_equal [1,2], e.peek - assert_equal [1,2], e.next - e = o.to_enum - assert_equal [], e.peek_values - assert_equal [], e.next_values - assert_equal [1], e.peek_values - assert_equal [1], e.next_values - assert_equal [1,2], e.peek_values - assert_equal [1,2], e.next_values - e = o.to_enum - assert_equal [], e.peek_values - assert_equal nil, e.next - assert_equal [1], e.peek_values - assert_equal 1, e.next - assert_equal [1,2], e.peek_values - assert_equal [1,2], e.next - e = o.to_enum - assert_equal nil, e.peek - assert_equal [], e.next_values - assert_equal 1, e.peek - assert_equal [1], e.next_values - assert_equal [1,2], e.peek - assert_equal [1,2], e.next_values -end - -assert 'Enumerator#peek_values modify' do - o = Object.new - def o.each - yield 1,2 - end - e = o.to_enum - a = e.peek_values - a << 3 - assert_equal [1,2], e.peek -end - -assert 'Enumerator#feed' do - o = Object.new - def o.each(ary) - ary << yield - ary << yield - ary << yield - end - ary = [] - e = o.to_enum :each, ary - e.next - e.feed 1 - e.next - e.feed 2 - e.next - e.feed 3 - assert_raise(StopIteration) { e.next } - assert_equal [1,2,3], ary -end - -assert 'Enumerator#feed mixed' do - o = Object.new - def o.each(ary) - ary << yield - ary << yield - ary << yield - end - ary = [] - e = o.to_enum :each, ary - e.next - e.feed 1 - e.next - e.next - e.feed 3 - assert_raise(StopIteration) { e.next } - assert_equal [1,nil,3], ary -end - -assert 'Enumerator#feed twice' do - o = Object.new - def o.each(ary) - ary << yield - ary << yield - ary << yield - end - ary = [] - e = o.to_enum :each, ary - e.feed 1 - assert_raise(TypeError) { e.feed 2 } -end - -assert 'Enumerator#feed before first next' do - o = Object.new - def o.each(ary) - ary << yield - ary << yield - ary << yield - end - ary = [] - e = o.to_enum :each, ary - e.feed 1 - e.next - e.next - assert_equal [1], ary -end - -assert 'Enumerator#feed yielder' do - x = nil - e = Enumerator.new {|y| x = y.yield; 10 } - e.next - e.feed 100 - assert_raise(StopIteration) { e.next } - assert_equal 100, x -end - -assert 'Enumerator#rewind' do - e = @obj.to_enum(:foo, 1, 2, 3) - assert_equal 1, e.next - assert_equal 2, e.next - e.rewind - assert_equal 1, e.next - assert_equal 2, e.next - assert_equal 3, e.next - assert_raise(StopIteration) { e.next } -end - -assert 'Enumerator#rewind clear feed' do - o = Object.new - def o.each(ary) - ary << yield - ary << yield - ary << yield - end - ary = [] - e = o.to_enum(:each, ary) - e.next - e.feed 1 - e.next - e.feed 2 - e.rewind - e.next - e.next - assert_equal([1,nil], ary) -end - -assert 'Enumerator#rewind clear' do - o = Object.new - def o.each(ary) - ary << yield - ary << yield - ary << yield - end - ary = [] - e = o.to_enum :each, ary - e.next - e.feed 1 - e.next - e.feed 2 - e.rewind - e.next - e.next - assert_equal [1,nil], ary -end - -assert 'Enumerator::Generator' do - # note: Enumerator::Generator is a class just for internal - g = Enumerator::Generator.new {|y| y << 1 << 2 << 3; :foo } - g2 = g.dup - a = [] - assert_equal(:foo, g.each {|x| a << x }) - assert_equal([1, 2, 3], a) - a = [] - assert_equal(:foo, g2.each {|x| a << x }) - assert_equal([1, 2, 3], a) -end - -assert 'Enumerator::Generator args' do - g = Enumerator::Generator.new {|y, x| y << 1 << 2 << 3; x } - a = [] - assert_equal(:bar, g.each(:bar) {|x| a << x }) - assert_equal([1, 2, 3], a) -end - -assert 'Enumerator::Yielder' do - # note: Enumerator::Yielder is a class just for internal - a = [] - y = Enumerator::Yielder.new {|x| a << x } - assert_equal(y, y << 1 << 2 << 3) - assert_equal([1, 2, 3], a) - - a = [] - y = Enumerator::Yielder.new {|x| a << x } - assert_equal([1], y.yield(1)) - assert_equal([1, 2], y.yield(2)) - assert_equal([1, 2, 3], y.yield(3)) - - assert_raise(LocalJumpError) { Enumerator::Yielder.new } -end - -assert 'next after StopIteration' do - a = [1] - e = a.each - assert_equal(1, e.next) - assert_raise(StopIteration) { e.next } - assert_raise(StopIteration) { e.next } - e.rewind - assert_equal(1, e.next) - assert_raise(StopIteration) { e.next } - assert_raise(StopIteration) { e.next } -end - -assert 'gc' do - assert_nothing_raised do - 1.times do - foo = [1,2,3].to_enum - GC.start - end - GC.start - end -end - -assert 'nested iteration' do - def (o = Object.new).each - yield :ok1 - yield [:ok2, :x].each.next - end - e = o.to_enum - assert_equal :ok1, e.next - assert_equal :ok2, e.next - assert_raise(StopIteration) { e.next } -end - -assert 'Kernel#to_enum' do - assert_equal Enumerator, [].to_enum.class - assert_raise(ArgumentError){ nil.to_enum } -end - -assert 'modifying existing methods' do - assert_equal Enumerator, loop.class - e = 3.times - i = 0 - loop_ret = loop { - assert_equal i, e.next - i += 1 - } -end - -assert 'Integral#times' do - a = 3 - b = a.times - c = [] - b.with_object(c) do |i, obj| - obj << i - end - assert_equal 3, a - assert_equal Enumerator, b.class - assert_equal [0,1,2], c -end - -assert 'Enumerable#each_with_index' do - assert_equal [['a',0],['b',1],['c',2]], ['a','b','c'].each_with_index.to_a -end - -assert 'Enumerable#map' do - a = [1,2,3] - b = a.map - c = b.with_index do |i, index| - [i*i, index*index] - end - assert_equal [1,2,3], a - assert_equal [[1,0],[4,1],[9,4]], c -end - -assert 'Enumerable#find_all' do - assert_equal [[3,4]], [[1,2],[3,4],[5,6]].find_all.each{ |i| i[1] == 4 } -end - -assert 'Array#each_index' do - a = [1,2,3] - b = a.each_index - c = [] - b.with_index do |index1,index2| - c << [index1+2,index2+5] - end - assert_equal [1,2,3], a - assert_equal [[2,5],[3,6],[4,7]], c -end - -assert 'Array#map!' do - a = [1,2,3] - b = a.map! - b.with_index do |i, index| - [i*i, index*index] - end - assert_equal [[1,0],[4,1],[9,4]], a -end - -assert 'Hash#each' do - a = {a:1,b:2} - b = a.each - c = [] - b.each do |k,v| - c << [k,v] - end - assert_equal [[:a,1], [:b,2]], c.sort -end - -assert 'Hash#each_key' do - assert_equal [:a,:b], {a:1,b:2}.each_key.to_a.sort -end - -assert 'Hash#each_value' do - assert_equal [1,2], {a:1,b:2}.each_value.to_a.sort -end - -assert 'Hash#select' do - h = {1=>2,3=>4,5=>6} - hret = h.select.with_index {|a,b| a[1] == 4} - assert_equal({3=>4}, hret) - assert_equal({1=>2,3=>4,5=>6}, h) -end - -assert 'Hash#select!' do - h = {1=>2,3=>4,5=>6} - hret = h.select!.with_index {|a,b| a[1] == 4} - assert_equal h, hret - assert_equal({3=>4}, h) -end - -assert 'Hash#reject' do - h = {1=>2,3=>4,5=>6} - hret = h.reject.with_index {|a,b| a[1] == 4} - assert_equal({1=>2,5=>6}, hret) - assert_equal({1=>2,3=>4,5=>6}, h) -end - -assert 'Hash#reject!' do - h = {1=>2,3=>4,5=>6} - hret = h.reject!.with_index {|a,b| a[1] == 4} - assert_equal h, hret - assert_equal({1=>2,5=>6}, h) -end - -assert 'Range#each' do - a = (1..5) - b = a.each - c = [] - b.each do |i| - c << i - end - assert_equal [1,2,3,4,5], c -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-enum-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Enumerable module extension' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,698 +0,0 @@ -## -# Enumerable -# -module Enumerable - ## - # call-seq: - # enum.drop(n) -> array - # - # Drops first n elements from enum, and returns rest elements - # in an array. - # - # a = [1, 2, 3, 4, 5, 0] - # a.drop(3) #=> [4, 5, 0] - - def drop(n) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) - raise ArgumentError, "attempt to drop negative size" if n < 0 - - n = n.to_int - ary = [] - self.each {|*val| n == 0 ? ary << val.__svalue : n -= 1 } - ary - end - - ## - # call-seq: - # enum.drop_while {|arr| block } -> array - # enum.drop_while -> an_enumerator - # - # Drops elements up to, but not including, the first element for - # which the block returns +nil+ or +false+ and returns an array - # containing the remaining elements. - # - # If no block is given, an enumerator is returned instead. - # - # a = [1, 2, 3, 4, 5, 0] - # a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0] - - def drop_while(&block) - return to_enum :drop_while unless block - - ary, state = [], false - self.each do |*val| - state = true if !state and !block.call(*val) - ary << val.__svalue if state - end - ary - end - - ## - # call-seq: - # enum.take(n) -> array - # - # Returns first n elements from enum. - # - # a = [1, 2, 3, 4, 5, 0] - # a.take(3) #=> [1, 2, 3] - - def take(n) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) - raise ArgumentError, "attempt to take negative size" if n < 0 - - n = n.to_int - ary = [] - self.each do |*val| - break if ary.size >= n - ary << val.__svalue - end - ary - end - - ## - # call-seq: - # enum.take_while {|arr| block } -> array - # enum.take_while -> an_enumerator - # - # Passes elements to the block until the block returns +nil+ or +false+, - # then stops iterating and returns an array of all prior elements. - # - # If no block is given, an enumerator is returned instead. - # - # a = [1, 2, 3, 4, 5, 0] - # a.take_while {|i| i < 3 } #=> [1, 2] - # - def take_while(&block) - return to_enum :take_while unless block - - ary = [] - self.each do |*val| - return ary unless block.call(*val) - ary << val.__svalue - end - ary - end - - ## - # Iterates the given block for each array of consecutive - # elements. - # - # @return [nil] - # - # @example - # (1..10).each_cons(3) {|a| p a} - # # outputs below - # [1, 2, 3] - # [2, 3, 4] - # [3, 4, 5] - # [4, 5, 6] - # [5, 6, 7] - # [6, 7, 8] - # [7, 8, 9] - # [8, 9, 10] - - def each_cons(n, &block) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) - raise ArgumentError, "invalid size" if n <= 0 - - return to_enum(:each_cons,n) unless block - ary = [] - n = n.to_int - self.each do |*val| - ary.shift if ary.size == n - ary << val.__svalue - block.call(ary.dup) if ary.size == n - end - end - - ## - # Iterates the given block for each slice of elements. - # - # @return [nil] - # - # @example - # (1..10).each_slice(3) {|a| p a} - # # outputs below - # [1, 2, 3] - # [4, 5, 6] - # [7, 8, 9] - # [10] - - def each_slice(n, &block) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) - raise ArgumentError, "invalid slice size" if n <= 0 - - return to_enum(:each_slice,n) unless block - ary = [] - n = n.to_int - self.each do |*val| - ary << val.__svalue - if ary.size == n - block.call(ary) - ary = [] - end - end - block.call(ary) unless ary.empty? - end - - ## - # call-seq: - # enum.group_by {| obj | block } -> a_hash - # enum.group_by -> an_enumerator - # - # Returns a hash, which keys are evaluated result from the - # block, and values are arrays of elements in enum - # corresponding to the key. - # - # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]} - # - def group_by(&block) - return to_enum :group_by unless block - - h = {} - self.each do |*val| - key = block.call(*val) - sv = val.__svalue - h.key?(key) ? (h[key] << sv) : (h[key] = [sv]) - end - h - end - - ## - # call-seq: - # enum.sort_by { |obj| block } -> array - # enum.sort_by -> an_enumerator - # - # Sorts enum using a set of keys generated by mapping the - # values in enum through the given block. - # - # If no block is given, an enumerator is returned instead. - - def sort_by(&block) - return to_enum :sort_by unless block - - ary = [] - orig = [] - self.each_with_index{|e, i| - orig.push(e) - ary.push([block.call(e), i]) - } - if ary.size > 1 - __sort_sub__(ary, ::Array.new(ary.size), 0, 0, ary.size - 1) do |a,b| - a <=> b - end - end - ary.collect{|e,i| orig[i]} - end - - NONE = Object.new - ## - # call-seq: - # enum.first -> obj or nil - # enum.first(n) -> an_array - # - # Returns the first element, or the first +n+ elements, of the enumerable. - # If the enumerable is empty, the first form returns nil, and the - # second form returns an empty array. - def first(n=NONE) - if n == NONE - self.each do |*val| - return val.__svalue - end - return nil - else - a = [] - i = 0 - self.each do |*val| - break if n<=i - a.push val.__svalue - i += 1 - end - a - end - end - - ## - # call-seq: - # enum.count -> int - # enum.count(item) -> int - # enum.count { |obj| block } -> int - # - # Returns the number of items in +enum+ through enumeration. - # If an argument is given, the number of items in +enum+ that - # are equal to +item+ are counted. If a block is given, it - # counts the number of elements yielding a true value. - def count(v=NONE, &block) - count = 0 - if block - self.each do |*val| - count += 1 if block.call(*val) - end - else - if v == NONE - self.each { count += 1 } - else - self.each do |*val| - count += 1 if val.__svalue == v - end - end - end - count - end - - ## - # call-seq: - # enum.flat_map { |obj| block } -> array - # enum.collect_concat { |obj| block } -> array - # enum.flat_map -> an_enumerator - # enum.collect_concat -> an_enumerator - # - # Returns a new array with the concatenated results of running - # block once for every element in enum. - # - # If no block is given, an enumerator is returned instead. - # - # [1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4] - # [[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100] - def flat_map(&block) - return to_enum :flat_map unless block - - ary = [] - self.each do |*e| - e2 = block.call(*e) - if e2.respond_to? :each - e2.each {|e3| ary.push(e3) } - else - ary.push(e2) - end - end - ary - end - alias collect_concat flat_map - - ## - # call-seq: - # enum.max_by {|obj| block } -> obj - # enum.max_by -> an_enumerator - # - # Returns the object in enum that gives the maximum - # value from the given block. - # - # If no block is given, an enumerator is returned instead. - # - # %w[albatross dog horse].max_by {|x| x.length } #=> "albatross" - - def max_by(&block) - return to_enum :max_by unless block - - first = true - max = nil - max_cmp = nil - - self.each do |*val| - if first - max = val.__svalue - max_cmp = block.call(*val) - first = false - else - if (cmp = block.call(*val)) > max_cmp - max = val.__svalue - max_cmp = cmp - end - end - end - max - end - - ## - # call-seq: - # enum.min_by {|obj| block } -> obj - # enum.min_by -> an_enumerator - # - # Returns the object in enum that gives the minimum - # value from the given block. - # - # If no block is given, an enumerator is returned instead. - # - # %w[albatross dog horse].min_by {|x| x.length } #=> "dog" - - def min_by(&block) - return to_enum :min_by unless block - - first = true - min = nil - min_cmp = nil - - self.each do |*val| - if first - min = val.__svalue - min_cmp = block.call(*val) - first = false - else - if (cmp = block.call(*val)) < min_cmp - min = val.__svalue - min_cmp = cmp - end - end - end - min - end - - ## - # call-seq: - # enum.minmax -> [min, max] - # enum.minmax { |a, b| block } -> [min, max] - # - # Returns two elements array which contains the minimum and the - # maximum value in the enumerable. The first form assumes all - # objects implement Comparable; the second uses the - # block to return a <=> b. - # - # a = %w(albatross dog horse) - # a.minmax #=> ["albatross", "horse"] - # a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"] - - def minmax(&block) - max = nil - min = nil - first = true - - self.each do |*val| - if first - val = val.__svalue - max = val - min = val - first = false - else - if block - max = val.__svalue if block.call(*val, max) > 0 - min = val.__svalue if block.call(*val, min) < 0 - else - val = val.__svalue - max = val if (val <=> max) > 0 - min = val if (val <=> min) < 0 - end - end - end - [min, max] - end - - ## - # call-seq: - # enum.minmax_by { |obj| block } -> [min, max] - # enum.minmax_by -> an_enumerator - # - # Returns a two element array containing the objects in - # enum that correspond to the minimum and maximum values respectively - # from the given block. - # - # If no block is given, an enumerator is returned instead. - # - # %w(albatross dog horse).minmax_by { |x| x.length } #=> ["dog", "albatross"] - - def minmax_by(&block) - return to_enum :minmax_by unless block - - max = nil - max_cmp = nil - min = nil - min_cmp = nil - first = true - - self.each do |*val| - if first - max = min = val.__svalue - max_cmp = min_cmp = block.call(*val) - first = false - else - if (cmp = block.call(*val)) > max_cmp - max = val.__svalue - max_cmp = cmp - end - if (cmp = block.call(*val)) < min_cmp - min = val.__svalue - min_cmp = cmp - end - end - end - [min, max] - end - - ## - # call-seq: - # enum.none? [{ |obj| block }] -> true or false - # - # Passes each element of the collection to the given block. The method - # returns true if the block never returns true - # for all elements. If the block is not given, none? will return - # true only if none of the collection members is true. - # - # %w(ant bear cat).none? { |word| word.length == 5 } #=> true - # %w(ant bear cat).none? { |word| word.length >= 4 } #=> false - # [].none? #=> true - # [nil, false].none? #=> true - # [nil, true].none? #=> false - - def none?(&block) - if block - self.each do |*val| - return false if block.call(*val) - end - else - self.each do |*val| - return false if val.__svalue - end - end - true - end - - ## - # call-seq: - # enum.one? [{ |obj| block }] -> true or false - # - # Passes each element of the collection to the given block. The method - # returns true if the block returns true - # exactly once. If the block is not given, one? will return - # true only if exactly one of the collection members is - # true. - # - # %w(ant bear cat).one? { |word| word.length == 4 } #=> true - # %w(ant bear cat).one? { |word| word.length > 4 } #=> false - # %w(ant bear cat).one? { |word| word.length < 4 } #=> false - # [nil, true, 99].one? #=> false - # [nil, true, false].one? #=> true - # - - def one?(&block) - count = 0 - if block - self.each do |*val| - count += 1 if block.call(*val) - return false if count > 1 - end - else - self.each do |*val| - count += 1 if val.__svalue - return false if count > 1 - end - end - - count == 1 ? true : false - end - - ## - # call-seq: - # enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj - # enum.each_with_object(obj) -> an_enumerator - # - # Iterates the given block for each element with an arbitrary - # object given, and returns the initially given object. - # - # If no block is given, returns an enumerator. - # - # (1..10).each_with_object([]) { |i, a| a << i*2 } - # #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] - # - - def each_with_object(obj=nil, &block) - raise ArgumentError, "wrong number of arguments (0 for 1)" if obj.nil? - - return to_enum(:each_with_object, obj) unless block - - self.each {|*val| block.call(val.__svalue, obj) } - obj - end - - ## - # call-seq: - # enum.reverse_each { |item| block } -> enum - # enum.reverse_each -> an_enumerator - # - # Builds a temporary array and traverses that array in reverse order. - # - # If no block is given, an enumerator is returned instead. - # - # (1..3).reverse_each { |v| p v } - # - # produces: - # - # 3 - # 2 - # 1 - # - - def reverse_each(&block) - return to_enum :reverse_each unless block - - ary = self.to_a - i = ary.size - 1 - while i>=0 - block.call(ary[i]) - i -= 1 - end - self - end - - ## - # call-seq: - # enum.cycle(n=nil) { |obj| block } -> nil - # enum.cycle(n=nil) -> an_enumerator - # - # Calls block for each element of enum repeatedly _n_ - # times or forever if none or +nil+ is given. If a non-positive - # number is given or the collection is empty, does nothing. Returns - # +nil+ if the loop has finished without getting interrupted. - # - # Enumerable#cycle saves elements in an internal array so changes - # to enum after the first pass have no effect. - # - # If no block is given, an enumerator is returned instead. - # - # a = ["a", "b", "c"] - # a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever. - # a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c. - # - - def cycle(n=nil, &block) - return to_enum(:cycle, n) if !block && n.nil? - - ary = [] - if n.nil? - self.each do|*val| - ary.push val - block.call(*val) - end - loop do - ary.each do|e| - block.call(*e) - end - end - else - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) - - n = n.to_int - self.each do|*val| - ary.push val - end - count = 0 - while count < n - ary.each do|e| - block.call(*e) - end - count += 1 - end - end - end - - ## - # call-seq: - # enum.find_index(value) -> int or nil - # enum.find_index { |obj| block } -> int or nil - # enum.find_index -> an_enumerator - # - # Compares each entry in enum with value or passes - # to block. Returns the index for the first for which the - # evaluated value is non-false. If no object matches, returns - # nil - # - # If neither block nor argument is given, an enumerator is returned instead. - # - # (1..10).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> nil - # (1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> 34 - # (1..100).find_index(50) #=> 49 - # - - def find_index(val=NONE, &block) - return to_enum(:find_index, val) if !block && val == NONE - - idx = 0 - if block - self.each do |*e| - return idx if block.call(*e) - idx += 1 - end - else - self.each do |*e| - return idx if e.__svalue == val - idx += 1 - end - end - nil - end - - ## - # call-seq: - # enum.zip(arg, ...) -> an_array_of_array - # - # Takes one element from enum and merges corresponding - # elements from each args. This generates a sequence of - # n-element arrays, where n is one more than the - # count of arguments. The length of the resulting sequence will be - # enum#size. If the size of any argument is less than - # enum#size, nil values are supplied. - # - - def zip(*arg) - ary = [] - arg = arg.map{|a|a.to_a} - i = 0 - self.each do |*val| - a = [] - a.push(val.__svalue) - idx = 0 - while idx < arg.size - a.push(arg[idx][i]) - idx += 1 - end - ary.push(a) - i += 1 - end - ary - end - - ## - # call-seq: - # enum.to_h -> hash - # - # Returns the result of interpreting enum as a list of - # [key, value] pairs. - # - # %i[hello world].each_with_index.to_h - # # => {:hello => 0, :world => 1} - # - - def to_h - h = {} - self.each do |*v| - v = v.__svalue - raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array - raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2 - h[v[0]] = v[1] - end - h - end - - def nil.to_h - {} - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-ext/test/enum.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-ext/test/enum.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-ext/test/enum.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-ext/test/enum.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,162 +0,0 @@ -## -# Enumerable(Ext) Test - -assert("Enumerable#drop") do - a = [1, 2, 3, 4, 5, 0] - - assert_equal [4, 5, 0], a.drop(3) - assert_equal [], a.drop(6) -end - -assert("Enumerable#drop_while") do - a = [1, 2, 3, 4, 5, 0] - assert_equal [3, 4, 5, 0], a.drop_while {|i| i < 3 } -end - -assert("Enumerable#take") do - a = [1, 2, 3, 4, 5, 0] - assert_equal [1, 2, 3], a.take(3) -end - -assert("Enumerable#take_while") do - a = [1, 2, 3, 4, 5, 0] - assert_equal [1, 2], a.take_while {|i| i < 3} -end - -assert("Enumerable#each_cons") do - a = [] - (1..5).each_cons(3){|e| a << e} - assert_equal [[1, 2, 3], [2, 3, 4], [3, 4, 5]], a -end - -assert("Enumerable#each_slice") do - a = [] - (1..10).each_slice(3){|e| a << e} - assert_equal [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]], a -end - -assert("Enumerable#group_by") do - r = (1..6).group_by {|i| i % 3 } - assert_equal [3, 6], r[0] - assert_equal [1, 4], r[1] - assert_equal [2, 5], r[2] -end - -assert("Enumerable#sort_by") do - assert_equal ["car", "train", "bicycle"], %w{car bicycle train}.sort_by {|e| e.length} -end - -assert("Enumerable#first") do - a = Object.new - a.extend Enumerable - def a.each - yield 1 - yield 2 - yield 3 - end - assert_equal 1, a.first - assert_equal [1, 2], a.first(2) - assert_equal [1, 2, 3], a.first(10) - a = Object.new - a.extend Enumerable - def a.each - end - assert_nil a.first -end - -assert("Enumerable#count") do - a = [1, 2, 4, 2] - assert_equal 4, a.count - assert_equal 2, a.count(2) - assert_equal 3, a.count{|x| x % 2 == 0} -end - -assert("Enumerable#flat_map") do - assert_equal [1, 2, 3, 4], [1, 2, 3, 4].flat_map { |e| e } - assert_equal [1, -1, 2, -2, 3, -3, 4, -4], [1, 2, 3, 4].flat_map { |e| [e, -e] } - assert_equal [1, 2, 100, 3, 4, 100], [[1, 2], [3, 4]].flat_map { |e| e + [100] } -end - -assert("Enumerable#max_by") do - assert_equal "albatross", %w[albatross dog horse].max_by { |x| x.length } -end - -assert("Enumerable#min_by") do - assert_equal "dog", %w[albatross dog horse].min_by { |x| x.length } -end - -assert("Enumerable#minmax") do - a = %w(albatross dog horse) - assert_equal ["albatross", "horse"], a.minmax - assert_equal ["dog", "albatross"], a.minmax { |a, b| a.length <=> b.length } -end - -assert("Enumerable#minmax_by") do - assert_equal ["dog", "albatross"], %w(albatross dog horse).minmax_by { |x| x.length } -end - -assert("Enumerable#none?") do - assert_true %w(ant bear cat).none? { |word| word.length == 5 } - assert_false %w(ant bear cat).none? { |word| word.length >= 4 } - assert_true [].none? - assert_true [nil, false].none? - assert_false [nil, true].none? -end - -assert("Enumerable#one?") do - assert_true %w(ant bear cat).one? { |word| word.length == 4 } - assert_false %w(ant bear cat).one? { |word| word.length > 4 } - assert_false %w(ant bear cat).one? { |word| word.length < 4 } - assert_false [nil, true, 99].one? - assert_true [nil, true, false].one? -end - -assert("Enumerable#each_with_object") do - assert_true [2, 4, 6, 8, 10, 12, 14, 16, 18, 20], (1..10).each_with_object([]) { |i, a| a << i*2 } - assert_raise(ArgumentError) { (1..10).each_with_object() { |i, a| a << i*2 } } -end - -assert("Enumerable#reverse_each") do - r = (1..3) - a = [] - assert_equal (1..3), r.reverse_each { |v| a << v } - assert_equal [3, 2, 1], a -end - -assert("Enumerable#cycle") do - a = [] - ["a", "b", "c"].cycle(2) { |v| a << v } - assert_equal ["a", "b", "c", "a", "b", "c"], a - assert_raise(TypeError) { ["a", "b", "c"].cycle("a") { |v| a << v } } -end - -assert("Enumerable#find_index") do - assert_nil (1..10).find_index { |i| i % 5 == 0 and i % 7 == 0 } - assert_equal 34, (1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } - assert_equal 49 ,(1..100).find_index(50) -end - -assert("Enumerable#zip") do - a = [ 4, 5, 6 ] - b = [ 7, 8, 9 ] - assert_equal [[4, 7], [5, 8], [6, 9]], a.zip(b) - assert_equal [[1, 4, 7], [2, 5, 8], [3, 6, 9]], [1, 2, 3].zip(a, b) - assert_equal [[1, 4, 7], [2, 5, 8]], [1, 2].zip(a, b) - assert_equal [[4, 1, 8], [5, 2, nil], [6, nil, nil]], a.zip([1, 2], [8]) -end - -assert("Enumerable#to_h") do - c = Class.new { - include Enumerable - def each - yield [1,2] - yield [3,4] - end - } - h0 = {1=>2, 3=>4} - h = c.new.to_h - assert_equal Hash, h.class - assert_equal h0, h - # mruby-enum-ext also provides nil.to_h - assert_equal Hash.new, nil.to_h -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -MRuby::Gem::Specification.new('mruby-enum-lazy') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Enumerable::Lazy class' - spec.add_dependency('mruby-enumerator', :core => 'mruby-enumerator') - spec.add_dependency('mruby-enum-ext', :core => 'mruby-enum-ext') -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,149 +0,0 @@ -module Enumerable - - # = Enumerable#lazy implementation - # - # Enumerable#lazy returns an instance of Enumerable::Lazy. - # You can use it just like as normal Enumerable object, - # except these methods act as 'lazy': - # - # - map collect - # - select find_all - # - reject - # - grep - # - drop - # - drop_while - # - take_while - # - flat_map collect_concat - # - zip - def lazy - Lazy.new(self) - end - - # == Acknowledgements - # - # Based on https://github.com/yhara/enumerable-lazy - # Inspired by https://github.com/antimon2/enumerable_lz - # http://jp.rubyist.net/magazine/?0034-Enumerable_lz (ja) - class Lazy < Enumerator - def initialize(obj, &block) - super(){|yielder| - begin - obj.each{|x| - if block - block.call(yielder, x) - else - yielder << x - end - } - rescue StopIteration - end - } - end - - def map(&block) - Lazy.new(self){|yielder, val| - yielder << block.call(val) - } - end - alias collect map - - def select(&block) - Lazy.new(self){|yielder, val| - if block.call(val) - yielder << val - end - } - end - alias find_all select - - def reject(&block) - Lazy.new(self){|yielder, val| - if not block.call(val) - yielder << val - end - } - end - - def grep(pattern) - Lazy.new(self){|yielder, val| - if pattern === val - yielder << val - end - } - end - - def drop(n) - dropped = 0 - Lazy.new(self){|yielder, val| - if dropped < n - dropped += 1 - else - yielder << val - end - } - end - - def drop_while(&block) - dropping = true - Lazy.new(self){|yielder, val| - if dropping - if not block.call(val) - yielder << val - dropping = false - end - else - yielder << val - end - } - end - - def take(n) - if n == 0 - return Lazy.new(self){raise StopIteration} - end - taken = 0 - Lazy.new(self){|yielder, val| - yielder << val - taken += 1 - if taken >= n - raise StopIteration - end - } - end - - def take_while(&block) - Lazy.new(self){|yielder, val| - if block.call(val) - yielder << val - else - raise StopIteration - end - } - end - - def flat_map(&block) - Lazy.new(self){|yielder, val| - ary = block.call(val) - # TODO: check ary is an Array - ary.each{|x| - yielder << x - } - } - end - alias collect_concat flat_map - - def zip(*args, &block) - enums = [self] + args - Lazy.new(self){|yielder, val| - ary = enums.map{|e| e.next} - if block - yielder << block.call(ary) - else - yielder << ary - end - } - end - - alias force to_a - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -assert("Enumerable::Lazy") do - a = [1, 2] - assert_equal Enumerable::Lazy, a.lazy.class -end - -assert("Enumerable::Lazy laziness") do - a = Object.new - def a.each - return to_enum :each unless block_given? - self.b << 10 - yield 1 - self.b << 20 - yield 2 - self.b << 30 - yield 3 - self.b << 40 - yield 4 - self.b << 50 - yield 5 - end - def a.b(b=nil) - @b = b if b - @b - end - - a.b([]) - assert_equal [1,2], a.each.lazy.take(2).force - assert_equal [10,20], a.b - - a.b([]) - assert_equal [2,4], a.each.lazy.select{|x|x%2==0}.take(2).force - assert_equal [10,20,30,40], a.b - - a.b([]) - assert_equal [1], a.each.lazy.take_while{|x|x<2}.take(1).force - assert_equal [10], a.b - - a.b([]) - assert_equal [1], a.each.lazy.take_while{|x|x<2}.take(4).force - assert_equal [10,20], a.b -end - -assert("Enumerable::Lazy#zip with cycle") do - e1 = [1, 2, 3].cycle - e2 = [:a, :b].cycle - assert_equal [[1,:a],[2,:b],[3,:a]], e1.lazy.zip(e2).first(3) -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-error/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-error/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-error/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-error/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -MRuby::Gem::Specification.new('mruby-error') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'extensional error handling' - - if build.cxx_abi_enabled? - @objs << build.compile_as_cxx("#{spec.dir}/src/exception.c", "#{spec.build_dir}/src/exception.cxx") - @objs.delete_if { |v| v == objfile("#{spec.build_dir}/src/exception") } - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-error/src/exception.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-error/src/exception.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-error/src/exception.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-error/src/exception.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -#include "mruby.h" -#include "mruby/throw.h" -#include "mruby/error.h" - -MRB_API mrb_value -mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state) -{ - struct mrb_jmpbuf *prev_jmp = mrb->jmp; - struct mrb_jmpbuf c_jmp; - mrb_value result = mrb_nil_value(); - - if (state) { *state = FALSE; } - - MRB_TRY(&c_jmp) { - mrb->jmp = &c_jmp; - result = body(mrb, data); - mrb->jmp = prev_jmp; - } MRB_CATCH(&c_jmp) { - mrb->jmp = prev_jmp; - result = mrb_obj_value(mrb->exc); - mrb->exc = NULL; - if (state) { *state = TRUE; } - } MRB_END_EXC(&c_jmp); - - mrb_gc_protect(mrb, result); - return result; -} - -MRB_API mrb_value -mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure, mrb_value e_data) -{ - struct mrb_jmpbuf *prev_jmp = mrb->jmp; - struct mrb_jmpbuf c_jmp; - mrb_value result; - - MRB_TRY(&c_jmp) { - mrb->jmp = &c_jmp; - result = body(mrb, b_data); - mrb->jmp = prev_jmp; - } MRB_CATCH(&c_jmp) { - mrb->jmp = prev_jmp; - ensure(mrb, e_data); - MRB_THROW(mrb->jmp); /* rethrow catched exceptions */ - } MRB_END_EXC(&c_jmp); - - ensure(mrb, e_data); - mrb_gc_protect(mrb, result); - return result; -} - -MRB_API mrb_value -mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data, - mrb_func_t rescue, mrb_value r_data) -{ - return mrb_rescue_exceptions(mrb, body, b_data, rescue, r_data, 1, &mrb->eStandardError_class); -} - -MRB_API mrb_value -mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data, - mrb_int len, struct RClass **classes) -{ - struct mrb_jmpbuf *prev_jmp = mrb->jmp; - struct mrb_jmpbuf c_jmp; - mrb_value result; - mrb_bool error_matched = FALSE; - mrb_int i; - - MRB_TRY(&c_jmp) { - mrb->jmp = &c_jmp; - result = body(mrb, b_data); - mrb->jmp = prev_jmp; - } MRB_CATCH(&c_jmp) { - mrb->jmp = prev_jmp; - - for (i = 0; i < len; ++i) { - if (mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), classes[i])) { - error_matched = TRUE; - break; - } - } - - if (!error_matched) { MRB_THROW(mrb->jmp); } - - mrb->exc = NULL; - result = rescue(mrb, r_data); - } MRB_END_EXC(&c_jmp); - - mrb_gc_protect(mrb, result); - return result; -} - -void -mrb_mruby_error_gem_init(mrb_state *mrb) -{ -} - -void -mrb_mruby_error_gem_final(mrb_state *mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-error/test/exception.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-error/test/exception.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-error/test/exception.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-error/test/exception.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -#include "mruby.h" -#include "mruby/error.h" -#include "mruby/array.h" - -static mrb_value -protect_cb(mrb_state *mrb, mrb_value b) -{ - return mrb_yield_argv(mrb, b, 0, NULL); -} - -static mrb_value -run_protect(mrb_state *mrb, mrb_value self) -{ - mrb_value b; - mrb_value ret[2]; - mrb_bool state; - mrb_get_args(mrb, "&", &b); - ret[0] = mrb_protect(mrb, protect_cb, b, &state); - ret[1] = mrb_bool_value(state); - return mrb_ary_new_from_values(mrb, 2, ret); -} - -static mrb_value -run_ensure(mrb_state *mrb, mrb_value self) -{ - mrb_value b, e; - mrb_get_args(mrb, "oo", &b, &e); - return mrb_ensure(mrb, protect_cb, b, protect_cb, e); -} - -static mrb_value -run_rescue(mrb_state *mrb, mrb_value self) -{ - mrb_value b, r; - mrb_get_args(mrb, "oo", &b, &r); - return mrb_rescue(mrb, protect_cb, b, protect_cb, r); -} - -static mrb_value -run_rescue_exceptions(mrb_state *mrb, mrb_value self) -{ - mrb_value b, r; - struct RClass *cls[1]; - mrb_get_args(mrb, "oo", &b, &r); - cls[0] = E_TYPE_ERROR; - return mrb_rescue_exceptions(mrb, protect_cb, b, protect_cb, r, 1, cls); -} - -void -mrb_mruby_error_gem_test(mrb_state *mrb) -{ - struct RClass *cls; - - cls = mrb_define_class(mrb, "ExceptionTest", mrb->object_class); - mrb_define_module_function(mrb, cls, "mrb_protect", run_protect, MRB_ARGS_NONE() | MRB_ARGS_BLOCK()); - mrb_define_module_function(mrb, cls, "mrb_ensure", run_ensure, MRB_ARGS_REQ(2)); - mrb_define_module_function(mrb, cls, "mrb_rescue", run_rescue, MRB_ARGS_REQ(2)); - mrb_define_module_function(mrb, cls, "mrb_rescue_exceptions", run_rescue_exceptions, MRB_ARGS_REQ(2)); -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-error/test/exception.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-error/test/exception.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-error/test/exception.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-error/test/exception.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -assert 'mrb_protect' do - # no failure in protect returns [result, false] - assert_equal ['test', false] do - ExceptionTest.mrb_protect { 'test' } - end - # failure in protect returns [exception, true] - result = ExceptionTest.mrb_protect { raise 'test' } - assert_kind_of RuntimeError, result[0] - assert_true result[1] -end - -assert 'mrb_ensure' do - a = false - assert_equal 'test' do - ExceptionTest.mrb_ensure Proc.new { 'test' }, Proc.new { a = true } - end - assert_true a - - a = false - assert_raise RuntimeError do - ExceptionTest.mrb_ensure Proc.new { raise 'test' }, Proc.new { a = true } - end - assert_true a -end - -assert 'mrb_rescue' do - assert_equal 'test' do - ExceptionTest.mrb_rescue Proc.new { 'test' }, Proc.new {} - end - - class CustomExp < Exception - end - - assert_raise CustomExp do - ExceptionTest.mrb_rescue Proc.new { raise CustomExp.new 'test' }, Proc.new { 'rescue' } - end - - assert_equal 'rescue' do - ExceptionTest.mrb_rescue Proc.new { raise 'test' }, Proc.new { 'rescue' } - end -end - -assert 'mrb_rescue_exceptions' do - assert_equal 'test' do - ExceptionTest.mrb_rescue_exceptions Proc.new { 'test' }, Proc.new {} - end - - assert_raise RangeError do - ExceptionTest.mrb_rescue_exceptions Proc.new { raise RangeError.new 'test' }, Proc.new { 'rescue' } - end - - assert_equal 'rescue' do - ExceptionTest.mrb_rescue_exceptions Proc.new { raise TypeError.new 'test' }, Proc.new { 'rescue' } - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-eval/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-eval/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-eval/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-eval/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -MRuby::Gem::Specification.new('mruby-eval') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'standard Kernel#eval method' - - add_dependency 'mruby-compiler', :core => 'mruby-compiler' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-eval/src/eval.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-eval/src/eval.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-eval/src/eval.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-eval/src/eval.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,262 +0,0 @@ -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/compile.h" -#include "mruby/irep.h" -#include "mruby/proc.h" -#include "mruby/opcode.h" - -static struct mrb_irep * -get_closure_irep(mrb_state *mrb, int level) -{ - struct mrb_context *c = mrb->c; - struct REnv *e = c->ci[-1].proc->env; - struct RProc *proc; - - if (level == 0) { - proc = c->ci[-1].proc; - if (MRB_PROC_CFUNC_P(proc)) { - return NULL; - } - return proc->body.irep; - } - - while (--level) { - e = (struct REnv*)e->c; - if (!e) return NULL; - } - - if (!e) return NULL; - proc = c->cibase[e->cioff].proc; - - if (!proc || MRB_PROC_CFUNC_P(proc)) { - return NULL; - } - return proc->body.irep; -} - -static inline mrb_code -search_variable(mrb_state *mrb, mrb_sym vsym, int bnest) -{ - mrb_irep *virep; - int level; - int pos; - - for (level = 0; (virep = get_closure_irep(mrb, level)); level++) { - if (!virep || virep->lv == NULL) { - continue; - } - for (pos = 0; pos < virep->nlocals - 1; pos++) { - if (vsym == virep->lv[pos].name) { - return (MKARG_B(pos + 1) | MKARG_C(level + bnest)); - } - } - } - - return 0; -} - -static mrb_bool -potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals) -{ - if (v >= nlocals) return FALSE; - /* skip arguments */ - if (v < argc+1) return FALSE; - return TRUE; -} - -static void -patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest) -{ - size_t i; - mrb_code c; - int argc = 0; - - for (i = 0; i < irep->ilen; i++) { - c = irep->iseq[i]; - switch(GET_OPCODE(c)){ - case OP_ENTER: - { - mrb_aspec ax = GETARG_Ax(c); - /* extra 1 means a slot for block */ - argc = MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1; - } - break; - - case OP_EPUSH: - patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1); - break; - - case OP_LAMBDA: - { - int arg_c = GETARG_c(c); - if (arg_c & OP_L_CAPTURE) { - patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1); - } - } - break; - - case OP_SEND: - if (GETARG_C(c) != 0) { - break; - } - { - mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)], bnest); - if (arg != 0) { - /* must replace */ - irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg; - } - } - break; - - case OP_MOVE: - /* src part */ - if (potential_upvar_p(irep->lv, GETARG_B(c), argc, irep->nlocals)) { - mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest); - if (arg != 0) { - /* must replace */ - irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg; - } - } - /* dst part */ - if (potential_upvar_p(irep->lv, GETARG_A(c), argc, irep->nlocals)) { - mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest); - if (arg != 0) { - /* must replace */ - irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_B(c)) | arg; - } - } - break; - } - } -} - -static struct RProc* -create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, char *file, mrb_int line) -{ - mrbc_context *cxt; - struct mrb_parser_state *p; - struct RProc *proc; - struct REnv *e; - struct mrb_context *c = mrb->c; - - if (!mrb_nil_p(binding)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "Binding of eval must be nil."); - } - - cxt = mrbc_context_new(mrb); - cxt->lineno = line; - if (file) { - mrbc_filename(mrb, cxt, file); - } - cxt->capture_errors = TRUE; - cxt->no_optimize = TRUE; - - p = mrb_parse_nstring(mrb, s, len, cxt); - - /* only occur when memory ran out */ - if (!p) { - mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to create parser state."); - } - - if (0 < p->nerr) { - /* parse error */ - char buf[256]; - int n; - n = snprintf(buf, sizeof(buf), "line %d: %s\n", p->error_buffer[0].lineno, p->error_buffer[0].message); - mrb_parser_free(p); - mrbc_context_free(mrb, cxt); - mrb_exc_raise(mrb, mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); - } - - proc = mrb_generate_code(mrb, p); - if (proc == NULL) { - /* codegen error */ - mrb_parser_free(p); - mrbc_context_free(mrb, cxt); - mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error"); - } - if (c->ci[-1].proc->target_class) { - proc->target_class = c->ci[-1].proc->target_class; - } - e = c->ci[-1].proc->env; - if (!e) e = c->ci[-1].env; - e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)e); - e->mid = c->ci[-1].mid; - e->cioff = c->ci - c->cibase - 1; - e->stack = c->ci->stackent; - MRB_SET_ENV_STACK_LEN(e, c->ci[-1].proc->body.irep->nlocals); - c->ci->env = e; - proc->env = e; - patch_irep(mrb, proc->body.irep, 0); - - mrb_parser_free(p); - mrbc_context_free(mrb, cxt); - - return proc; -} - -static mrb_value -f_eval(mrb_state *mrb, mrb_value self) -{ - char *s; - mrb_int len; - mrb_value binding = mrb_nil_value(); - char *file = NULL; - mrb_int line = 1; - mrb_value ret; - struct RProc *proc; - - mrb_get_args(mrb, "s|ozi", &s, &len, &binding, &file, &line); - - proc = create_proc_from_string(mrb, s, len, binding, file, line); - ret = mrb_toplevel_run(mrb, proc); - if (mrb->exc) { - mrb_exc_raise(mrb, mrb_obj_value(mrb->exc)); - } - - return ret; -} - -mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self); - -#define CI_ACC_SKIP -1 - -static mrb_value -f_instance_eval(mrb_state *mrb, mrb_value self) -{ - struct mrb_context *c = mrb->c; - mrb_value b; - mrb_int argc; mrb_value *argv; - - mrb_get_args(mrb, "*&", &argv, &argc, &b); - - if (mrb_nil_p(b)) { - char *s; - mrb_int len; - char *file = NULL; - mrb_int line = 1; - mrb_value cv; - - mrb_get_args(mrb, "s|zi", &s, &len, &file, &line); - c->ci->acc = CI_ACC_SKIP; - cv = mrb_singleton_class(mrb, self); - c->ci->target_class = mrb_class_ptr(cv); - return mrb_run(mrb, create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line), self); - } - else { - mrb_get_args(mrb, "&", &b); - return mrb_obj_instance_eval(mrb, self); - } -} - -void -mrb_mruby_eval_gem_init(mrb_state* mrb) -{ - mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3)); - mrb_define_method(mrb, mrb->kernel_module, "instance_eval", f_instance_eval, MRB_ARGS_ARG(1, 2)); -} - -void -mrb_mruby_eval_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-eval/test/eval.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-eval/test/eval.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-eval/test/eval.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-eval/test/eval.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -assert('Kernel.eval', '15.3.1.2.3') do - assert_equal(10) { Kernel.eval '1 * 10' } - assert_equal('aaa') { Kernel.eval "'a' * 3" } - assert_equal(10) { - a = 10 - Kernel.eval "a" - } - assert_equal(20) { - a = 10 - Kernel.eval "a = 20" - a - } - assert_equal(15) { - c = 5 - lambda { - a = 10 - Kernel.eval "c = a + c" - }.call - c - } - assert_equal(5) { - c = 5 - lambda { - Kernel.eval 'lambda { c }.call' - }.call - } - assert_equal(15) { - c = 5 - lambda { - a = 10 - Kernel.eval 'lambda { c = a + c }.call' - }.call - c - } - assert_equal(2) { - a = 10 - Kernel.eval 'def f(a); b=a.send(:+, 1); end' - f(1) - } -end - -assert('Kernel#eval', '15.3.1.3.12') do - assert_equal(10) { eval '1 * 10' } -end - -assert('rest arguments of eval') do - assert_raise(ArgumentError) { Kernel.eval('0', 0, 'test', 0) } - assert_equal ['test', 'test.rb', 10] do - Kernel.eval('[\'test\', __FILE__, __LINE__]', nil, 'test.rb', 10) - end -end - -assert 'eval syntax error' do - assert_raise(SyntaxError) do - eval 'p "test' - end -end - -assert('String instance_eval') do - obj = Object.new - obj.instance_variable_set :@test, 'test' - assert_raise(ArgumentError) { obj.instance_eval(0) { } } - assert_raise(ArgumentError) { obj.instance_eval('0', 'test', 0, 'test') } - assert_equal(['test.rb', 10]) { obj.instance_eval('[__FILE__, __LINE__]', 'test.rb', 10)} - assert_equal('test') { obj.instance_eval('@test') } - assert_equal('test') { obj.instance_eval { @test } } -end - -assert('Kernel.#eval(string) context') do - class TestEvalConstScope - EVAL_CONST_CLASS = 'class' - def const_string - eval 'EVAL_CONST_CLASS' - end - end - obj = TestEvalConstScope.new - assert_raise(NameError) { eval 'EVAL_CONST_CLASS' } - assert_equal('class') { obj.const_string } -end - -assert('Object#instance_eval with begin-rescue-ensure execution order') do - class HellRaiser - def raise_hell - order = [:enter_raise_hell] - begin - order.push :begin - self.instance_eval("raise 'error'") - rescue - order.push :rescue - ensure - order.push :ensure - end - order - end - end - - hell_raiser = HellRaiser.new - assert_equal([:enter_raise_hell, :begin, :rescue, :ensure], hell_raiser.raise_hell) -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-exit/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-exit/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-exit/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-exit/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-exit') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Kernel#exit method' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-exit/src/mruby-exit.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-exit/src/mruby-exit.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-exit/src/mruby-exit.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-exit/src/mruby-exit.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#include -#include "mruby.h" - -static mrb_value -f_exit(mrb_state *mrb, mrb_value self) -{ - mrb_int i = EXIT_SUCCESS; - - mrb_get_args(mrb, "|i", &i); - exit(i); - /* not reached */ - return mrb_nil_value(); -} - -void -mrb_mruby_exit_gem_init(mrb_state* mrb) -{ - mrb_define_method(mrb, mrb->kernel_module, "exit", f_exit, MRB_ARGS_OPT(1)); -} - -void -mrb_mruby_exit_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-fiber/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-fiber/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-fiber/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-fiber/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-fiber') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Fiber class' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-fiber/src/fiber.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-fiber/src/fiber.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-fiber/src/fiber.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-fiber/src/fiber.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,389 +0,0 @@ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/proc.h" - -#define fiber_ptr(o) ((struct RFiber*)mrb_ptr(o)) - -#define FIBER_STACK_INIT_SIZE 64 -#define FIBER_CI_INIT_SIZE 8 - -/* - * call-seq: - * Fiber.new{...} -> obj - * - * Creates a fiber, whose execution is suspend until it is explicitly - * resumed using Fiber#resume method. - * The code running inside the fiber can give up control by calling - * Fiber.yield in which case it yields control back to caller - * (the caller of the Fiber#resume). - * - * Upon yielding or termination the Fiber returns the value of the last - * executed expression - * - * For instance: - * - * fiber = Fiber.new do - * Fiber.yield 1 - * 2 - * end - * - * puts fiber.resume - * puts fiber.resume - * puts fiber.resume - * - * produces - * - * 1 - * 2 - * resuming dead fiber (FiberError) - * - * The Fiber#resume method accepts an arbitrary number of - * parameters, if it is the first call to resume then they - * will be passed as block arguments. Otherwise they will be the return - * value of the call to Fiber.yield - * - * Example: - * - * fiber = Fiber.new do |first| - * second = Fiber.yield first + 2 - * end - * - * puts fiber.resume 10 - * puts fiber.resume 14 - * puts fiber.resume 18 - * - * produces - * - * 12 - * 14 - * resuming dead fiber (FiberError) - * - */ -static mrb_value -fiber_init(mrb_state *mrb, mrb_value self) -{ - static const struct mrb_context mrb_context_zero = { 0 }; - struct RFiber *f = fiber_ptr(self); - struct mrb_context *c; - struct RProc *p; - mrb_callinfo *ci; - mrb_value blk; - size_t slen; - - mrb_get_args(mrb, "&", &blk); - - if (mrb_nil_p(blk)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Fiber object without a block"); - } - p = mrb_proc_ptr(blk); - if (MRB_PROC_CFUNC_P(p)) { - mrb_raise(mrb, E_FIBER_ERROR, "tried to create Fiber from C defined method"); - } - - f->cxt = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); - *f->cxt = mrb_context_zero; - c = f->cxt; - - /* initialize VM stack */ - slen = FIBER_STACK_INIT_SIZE; - if (p->body.irep->nregs > slen) { - slen += p->body.irep->nregs; - } - c->stbase = (mrb_value *)mrb_malloc(mrb, slen*sizeof(mrb_value)); - c->stend = c->stbase + slen; - c->stack = c->stbase; - -#ifdef MRB_NAN_BOXING - { - mrb_value *p = c->stbase; - mrb_value *pend = c->stend; - - while (p < pend) { - SET_NIL_VALUE(*p); - p++; - } - } -#else - memset(c->stbase, 0, slen * sizeof(mrb_value)); -#endif - - /* copy receiver from a block */ - c->stack[0] = mrb->c->stack[0]; - - /* initialize callinfo stack */ - c->cibase = (mrb_callinfo *)mrb_calloc(mrb, FIBER_CI_INIT_SIZE, sizeof(mrb_callinfo)); - c->ciend = c->cibase + FIBER_CI_INIT_SIZE; - c->ci = c->cibase; - c->ci->stackent = c->stack; - - /* adjust return callinfo */ - ci = c->ci; - ci->target_class = p->target_class; - ci->proc = p; - ci->pc = p->body.irep->iseq; - ci->nregs = p->body.irep->nregs; - ci[1] = ci[0]; - c->ci++; /* push dummy callinfo */ - - c->fib = f; - c->status = MRB_FIBER_CREATED; - - return self; -} - -static struct mrb_context* -fiber_check(mrb_state *mrb, mrb_value fib) -{ - struct RFiber *f = fiber_ptr(fib); - - mrb_assert(f->tt == MRB_TT_FIBER); - if (!f->cxt) { - mrb_raise(mrb, E_FIBER_ERROR, "uninitialized Fiber"); - } - return f->cxt; -} - -static mrb_value -fiber_result(mrb_state *mrb, const mrb_value *a, mrb_int len) -{ - if (len == 0) return mrb_nil_value(); - if (len == 1) return a[0]; - return mrb_ary_new_from_values(mrb, len, a); -} - -/* mark return from context modifying method */ -#define MARK_CONTEXT_MODIFY(c) (c)->ci->target_class = NULL - -static mrb_value -fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mrb_bool resume) -{ - struct mrb_context *c = fiber_check(mrb, self); - mrb_callinfo *ci; - - for (ci = c->ci; ci >= c->cibase; ci--) { - if (ci->acc < 0) { - mrb_raise(mrb, E_FIBER_ERROR, "can't cross C function boundary"); - } - } - if (resume && c->status == MRB_FIBER_TRANSFERRED) { - mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber"); - } - if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMING) { - mrb_raise(mrb, E_FIBER_ERROR, "double resume"); - } - if (c->status == MRB_FIBER_TERMINATED) { - mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber"); - } - mrb->c->status = resume ? MRB_FIBER_RESUMING : MRB_FIBER_TRANSFERRED; - c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c); - if (c->status == MRB_FIBER_CREATED) { - mrb_value *b = c->stack+1; - mrb_value *e = b + len; - - while (bcibase->argc = len; - if (c->prev->fib) - mrb_field_write_barrier(mrb, (struct RBasic*)c->fib, (struct RBasic*)c->prev->fib); - mrb_write_barrier(mrb, (struct RBasic*)c->fib); - c->status = MRB_FIBER_RUNNING; - mrb->c = c; - - MARK_CONTEXT_MODIFY(c); - return c->ci->proc->env->stack[0]; - } - MARK_CONTEXT_MODIFY(c); - if (c->prev->fib) - mrb_field_write_barrier(mrb, (struct RBasic*)c->fib, (struct RBasic*)c->prev->fib); - mrb_write_barrier(mrb, (struct RBasic*)c->fib); - c->status = MRB_FIBER_RUNNING; - mrb->c = c; - return fiber_result(mrb, a, len); -} - -/* - * call-seq: - * fiber.resume(args, ...) -> obj - * - * Resumes the fiber from the point at which the last Fiber.yield - * was called, or starts running it if it is the first call to - * resume. Arguments passed to resume will be the value of - * the Fiber.yield expression or will be passed as block - * parameters to the fiber's block if this is the first resume. - * - * Alternatively, when resume is called it evaluates to the arguments passed - * to the next Fiber.yield statement inside the fiber's block - * or to the block value if it runs to completion without any - * Fiber.yield - */ -static mrb_value -fiber_resume(mrb_state *mrb, mrb_value self) -{ - mrb_value *a; - mrb_int len; - - mrb_get_args(mrb, "*", &a, &len); - return fiber_switch(mrb, self, len, a, TRUE); -} - -/* resume thread with given arguments */ -MRB_API mrb_value -mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int len, const mrb_value *a) -{ - return fiber_switch(mrb, fib, len, a, TRUE); -} - -/* - * call-seq: - * fiber.alive? -> true or false - * - * Returns true if the fiber can still be resumed. After finishing - * execution of the fiber block this method will always return false. - */ -static mrb_value -fiber_alive_p(mrb_state *mrb, mrb_value self) -{ - struct mrb_context *c = fiber_check(mrb, self); - return mrb_bool_value(c->status != MRB_FIBER_TERMINATED); -} - -static mrb_value -fiber_eq(mrb_state *mrb, mrb_value self) -{ - mrb_value other; - mrb_get_args(mrb, "o", &other); - - if (mrb_type(other) != MRB_TT_FIBER) { - return mrb_false_value(); - } - return mrb_bool_value(fiber_ptr(self) == fiber_ptr(other)); -} - -/* - * call-seq: - * fiber.transfer(args, ...) -> obj - * - * Transfers control to receiver fiber of the method call. - * Unlike resume the receiver wouldn't be pushed to call - * stack of fibers. Instead it will switch to the call stack of - * transferring fiber. - * When resuming a fiber that was transferred to another fiber it would - * cause double resume error. Though when the fiber is re-transferred - * and Fiber.yield is called, the fiber would be resumable. - */ -static mrb_value -fiber_transfer(mrb_state *mrb, mrb_value self) -{ - struct mrb_context *c = fiber_check(mrb, self); - mrb_value* a; - mrb_int len; - - mrb_get_args(mrb, "*", &a, &len); - - if (c == mrb->root_c) { - mrb->c->status = MRB_FIBER_TRANSFERRED; - mrb->c = c; - c->status = MRB_FIBER_RUNNING; - MARK_CONTEXT_MODIFY(c); - mrb_write_barrier(mrb, (struct RBasic*)c->fib); - return fiber_result(mrb, a, len); - } - - if (c == mrb->c) { - return fiber_result(mrb, a, len); - } - - return fiber_switch(mrb, self, len, a, FALSE); -} - -/* yield values to the caller fiber */ -/* mrb_fiber_yield() must be called as `return mrb_fiber_yield(...)` */ -MRB_API mrb_value -mrb_fiber_yield(mrb_state *mrb, mrb_int len, const mrb_value *a) -{ - struct mrb_context *c = mrb->c; - mrb_callinfo *ci; - - for (ci = c->ci; ci >= c->cibase; ci--) { - if (ci->acc < 0) { - mrb_raise(mrb, E_FIBER_ERROR, "can't cross C function boundary"); - } - } - if (!c->prev) { - mrb_raise(mrb, E_FIBER_ERROR, "can't yield from root fiber"); - } - - c->prev->status = MRB_FIBER_RUNNING; - c->status = MRB_FIBER_SUSPENDED; - mrb->c = c->prev; - c->prev = NULL; - MARK_CONTEXT_MODIFY(mrb->c); - mrb_write_barrier(mrb, (struct RBasic*)c->fib); - return fiber_result(mrb, a, len); -} - -/* - * call-seq: - * Fiber.yield(args, ...) -> obj - * - * Yields control back to the context that resumed the fiber, passing - * along any arguments that were passed to it. The fiber will resume - * processing at this point when resume is called next. - * Any arguments passed to the next resume will be the - * value that this Fiber.yield expression evaluates to. - */ -static mrb_value -fiber_yield(mrb_state *mrb, mrb_value self) -{ - mrb_value *a; - mrb_int len; - - mrb_get_args(mrb, "*", &a, &len); - return mrb_fiber_yield(mrb, len, a); -} - -/* - * call-seq: - * Fiber.current() -> fiber - * - * Returns the current fiber. If you are not running in the context of - * a fiber this method will return the root fiber. - */ -static mrb_value -fiber_current(mrb_state *mrb, mrb_value self) -{ - if (!mrb->c->fib) { - struct RFiber *f = (struct RFiber*)mrb_obj_alloc(mrb, MRB_TT_FIBER, mrb_class_ptr(self)); - - f->cxt = mrb->c; - mrb->c->fib = f; - } - return mrb_obj_value(mrb->c->fib); -} - -void -mrb_mruby_fiber_gem_init(mrb_state* mrb) -{ - struct RClass *c; - - c = mrb_define_class(mrb, "Fiber", mrb->object_class); - MRB_SET_INSTANCE_TT(c, MRB_TT_FIBER); - - mrb_define_method(mrb, c, "initialize", fiber_init, MRB_ARGS_NONE()); - mrb_define_method(mrb, c, "resume", fiber_resume, MRB_ARGS_ANY()); - mrb_define_method(mrb, c, "transfer", fiber_transfer, MRB_ARGS_ANY()); - mrb_define_method(mrb, c, "alive?", fiber_alive_p, MRB_ARGS_NONE()); - mrb_define_method(mrb, c, "==", fiber_eq, MRB_ARGS_REQ(1)); - - mrb_define_class_method(mrb, c, "yield", fiber_yield, MRB_ARGS_ANY()); - mrb_define_class_method(mrb, c, "current", fiber_current, MRB_ARGS_NONE()); - - mrb_define_class(mrb, "FiberError", mrb->eStandardError_class); -} - -void -mrb_mruby_fiber_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-fiber/test/fiber.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-fiber/test/fiber.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-fiber/test/fiber.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-fiber/test/fiber.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,208 +0,0 @@ -assert('Fiber.new') do - f = Fiber.new{} - assert_kind_of Fiber, f -end - -assert('Fiber#resume') do - f = Fiber.new{|x| x } - assert_equal 2, f.resume(2) -end - -assert('Fiber#transfer') do - f2 = nil - f1 = Fiber.new do |v| - Fiber.yield v - f2.transfer - end - f2 = Fiber.new do - f1.transfer(1) - f1.transfer(1) - Fiber.yield 2 - end - assert_equal 1, f2.resume - assert_raise(FiberError) { f2.resume } - assert_equal 2, f2.transfer - assert_raise(FiberError) { f1.resume } - f1.transfer - f2.resume - assert_false f1.alive? - assert_false f2.alive? -end - -assert('Fiber#alive?') do - f = Fiber.new{ Fiber.yield } - f.resume - assert_true f.alive? - f.resume - assert_false f.alive? -end - -assert('Fiber#==') do - root = Fiber.current - assert_equal root, root - assert_equal root, Fiber.current - assert_false root != Fiber.current - f = Fiber.new { - assert_false root == Fiber.current - } - f.resume - assert_false f == root - assert_true f != root -end - -assert('Fiber.yield') do - f = Fiber.new{|x| Fiber.yield x } - assert_equal 3, f.resume(3) - assert_true f.alive? -end - -assert('FiberError') do - assert_equal StandardError, FiberError.superclass -end - -assert('Fiber iteration') do - f1 = Fiber.new{ - [1,2,3].each{|x| Fiber.yield(x)} - } - f2 = Fiber.new{ - [9,8,7].each{|x| Fiber.yield(x)} - } - a = [] - 3.times { - a << f1.resume - a << f2.resume - } - assert_equal [1,9,2,8,3,7], a -end - -assert('Fiber with splat in the block argument list') { - Fiber.new{|*x|x}.resume(1) == [1] -} - -assert('Fiber raises on resume when dead') do - assert_raise(FiberError) do - f = Fiber.new{} - f.resume - assert_false f.alive? - f.resume - end -end - -assert('Yield raises when called on root fiber') do - assert_raise(FiberError) { Fiber.yield } -end - -assert('Double resume of Fiber') do - f1 = Fiber.new {} - f2 = Fiber.new { - f1.resume - assert_raise(FiberError) { f2.resume } - Fiber.yield 0 - } - assert_equal 0, f2.resume - f2.resume - assert_false f1.alive? - assert_false f2.alive? -end - -assert('Recursive resume of Fiber') do - f1, f2 = nil, nil - f1 = Fiber.new { assert_raise(FiberError) { f2.resume } } - f2 = Fiber.new { - f1.resume - Fiber.yield 0 - } - f3 = Fiber.new { - f2.resume - } - assert_equal 0, f3.resume - f2.resume - assert_false f1.alive? - assert_false f2.alive? - assert_false f3.alive? -end - -assert('Root fiber resume') do - root = Fiber.current - assert_raise(FiberError) { root.resume } - f = Fiber.new { - assert_raise(FiberError) { root.resume } - } - f.resume - assert_false f.alive? -end - -assert('Fiber without block') do - assert_raise(ArgumentError) { Fiber.new } -end - - -assert('Transfer to self.') do - result = [] - f = Fiber.new { result << :start; f.transfer; result << :end } - f.transfer - assert_equal [:start, :end], result - - result = [] - f = Fiber.new { result << :start; f.transfer; result << :end } - f.resume - assert_equal [:start, :end], result -end - -assert('Resume transferred fiber') do - f = Fiber.new { - assert_raise(FiberError) { f.resume } - } - f.transfer -end - -assert('Root fiber transfer.') do - result = nil - root = Fiber.current - f = Fiber.new { - result = :ok - root.transfer - } - f.resume - assert_true f.alive? - assert_equal :ok, result -end - -assert('Break nested fiber with root fiber transfer') do - root = Fiber.current - - result = nil - f2 = nil - f1 = Fiber.new { - Fiber.yield f2.resume - result = :f1 - } - f2 = Fiber.new { - result = :to_root - root.transfer :from_f2 - result = :f2 - } - assert_equal :from_f2, f1.resume - assert_equal :to_root, result - assert_equal :f2, f2.transfer - assert_equal :f2, result - assert_false f2.alive? - assert_equal :f1, f1.resume - assert_equal :f1, result - assert_false f1.alive? -end - -assert('CRuby Fiber#transfer test.') do - ary = [] - f2 = nil - f1 = Fiber.new{ - ary << f2.transfer(:foo) - :ok - } - f2 = Fiber.new{ - ary << f1.transfer(:baz) - :ng - } - assert_equal :ok, f1.transfer - assert_equal [:baz], ary -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-hash-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-hash-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-hash-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-hash-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -MRuby::Gem::Specification.new('mruby-hash-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Hash class extension' - spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext' - spec.add_dependency 'mruby-array-ext', :core => 'mruby-array-ext' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,349 +0,0 @@ -class Hash - - # ISO does not define Hash#each_pair, so each_pair is defined in gem. - alias each_pair each - - ## - # call-seq: - # Hash[ key, value, ... ] -> new_hash - # Hash[ [ [key, value], ... ] ] -> new_hash - # Hash[ object ] -> new_hash - # - # Creates a new hash populated with the given objects. - # - # Similar to the literal `{ _key_ => _value_, ... }`. In the first - # form, keys and values occur in pairs, so there must be an even number of - # arguments. - # - # The second and third form take a single argument which is either an array - # of key-value pairs or an object convertible to a hash. - # - # Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200} - # Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200} - # Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200} - # - - def self.[](*object) - length = object.length - if length == 1 - o = object[0] - if o.respond_to?(:to_hash) - h = Hash.new - object[0].to_hash.each { |k, v| h[k] = v } - return h - elsif o.respond_to?(:to_a) - h = Hash.new - o.to_a.each do |i| - raise ArgumentError, "wrong element type #{i.class} (expected array)" unless i.respond_to?(:to_a) - k, v = nil - case i.size - when 2 - k = i[0] - v = i[1] - when 1 - k = i[0] - else - raise ArgumentError, "invalid number of elements (#{i.size} for 1..2)" - end - h[k] = v - end - return h - end - end - unless length % 2 == 0 - raise ArgumentError, 'odd number of arguments for Hash' - end - h = Hash.new - 0.step(length - 2, 2) do |i| - h[object[i]] = object[i + 1] - end - h - end - - ## - # call-seq: - # hsh.merge!(other_hash) -> hsh - # hsh.merge!(other_hash){|key, oldval, newval| block} -> hsh - # - # Adds the contents of _other_hash_ to _hsh_. If no block is specified, - # entries with duplicate keys are overwritten with the values from - # _other_hash_, otherwise the value of each duplicate key is determined by - # calling the block with the key, its value in _hsh_ and its value in - # _other_hash_. - # - # h1 = { "a" => 100, "b" => 200 } - # h2 = { "b" => 254, "c" => 300 } - # h1.merge!(h2) #=> {"a"=>100, "b"=>254, "c"=>300} - # - # h1 = { "a" => 100, "b" => 200 } - # h2 = { "b" => 254, "c" => 300 } - # h1.merge!(h2) { |key, v1, v2| v1 } - # #=> {"a"=>100, "b"=>200, "c"=>300} - # - - def merge!(other, &block) - raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash) - if block - other.each_key{|k| - self[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k] - } - else - other.each_key{|k| self[k] = other[k]} - end - self - end - - alias update merge! - - ## - # call-seq: - # hsh.fetch(key [, default] ) -> obj - # hsh.fetch(key) {| key | block } -> obj - # - # Returns a value from the hash for the given key. If the key can't be - # found, there are several options: With no other arguments, it will - # raise an KeyError exception; if default is - # given, then that will be returned; if the optional code block is - # specified, then that will be run and its result returned. - # - # h = { "a" => 100, "b" => 200 } - # h.fetch("a") #=> 100 - # h.fetch("z", "go fish") #=> "go fish" - # h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z" - # - # The following example shows that an exception is raised if the key - # is not found and a default value is not supplied. - # - # h = { "a" => 100, "b" => 200 } - # h.fetch("z") - # - # produces: - # - # prog.rb:2:in 'fetch': key not found (KeyError) - # from prog.rb:2 - # - - def fetch(key, none=NONE, &block) - unless self.key?(key) - if block - block.call(key) - elsif none != NONE - none - else - raise KeyError, "Key not found: #{key}" - end - else - self[key] - end - end - - ## - # call-seq: - # hsh.delete_if {| key, value | block } -> hsh - # hsh.delete_if -> an_enumerator - # - # Deletes every key-value pair from hsh for which block - # evaluates to true. - # - # If no block is given, an enumerator is returned instead. - # - # h = { "a" => 100, "b" => 200, "c" => 300 } - # h.delete_if {|key, value| key >= "b" } #=> {"a"=>100} - # - - def delete_if(&block) - return to_enum :delete_if unless block_given? - - self.each do |k, v| - self.delete(k) if block.call(k, v) - end - self - end - - ## - # call-seq: - # hash.flatten -> an_array - # hash.flatten(level) -> an_array - # - # Returns a new array that is a one-dimensional flattening of this - # hash. That is, for every key or value that is an array, extract - # its elements into the new array. Unlike Array#flatten, this - # method does not flatten recursively by default. The optional - # level argument determines the level of recursion to flatten. - # - # a = {1=> "one", 2 => [2,"two"], 3 => "three"} - # a.flatten # => [1, "one", 2, [2, "two"], 3, "three"] - # a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"] - # - - def flatten(level=1) - self.to_a.flatten(level) - end - - ## - # call-seq: - # hsh.invert -> new_hash - # - # Returns a new hash created by using hsh's values as keys, and - # the keys as values. - # - # h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 } - # h.invert #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"} - # - - def invert - h = Hash.new - self.each {|k, v| h[v] = k } - h - end - - ## - # call-seq: - # hsh.keep_if {| key, value | block } -> hsh - # hsh.keep_if -> an_enumerator - # - # Deletes every key-value pair from hsh for which block - # evaluates to false. - # - # If no block is given, an enumerator is returned instead. - # - - def keep_if(&block) - return to_enum :keep_if unless block_given? - - keys = [] - self.each do |k, v| - unless block.call([k, v]) - self.delete(k) - end - end - self - end - - ## - # call-seq: - # hsh.key(value) -> key - # - # Returns the key of an occurrence of a given value. If the value is - # not found, returns nil. - # - # h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 } - # h.key(200) #=> "b" - # h.key(300) #=> "c" - # h.key(999) #=> nil - # - - def key(val) - self.each do |k, v| - return k if v == val - end - nil - end - - ## - # call-seq: - # hsh.to_h -> hsh or new_hash - # - # Returns +self+. If called on a subclass of Hash, converts - # the receiver to a Hash object. - # - def to_h - self - end - - ## - # call-seq: - # hash < other -> true or false - # - # Returns true if hash is subset of - # other. - # - # h1 = {a:1, b:2} - # h2 = {a:1, b:2, c:3} - # h1 < h2 #=> true - # h2 < h1 #=> false - # h1 < h1 #=> false - # - def <(hash) - begin - hash = hash.to_hash - rescue NoMethodError - raise TypeError, "can't convert #{hash.class} to Hash" - end - size < hash.size and all? {|key, val| - hash.key?(key) and hash[key] == val - } - end - - ## - # call-seq: - # hash <= other -> true or false - # - # Returns true if hash is subset of - # other or equals to other. - # - # h1 = {a:1, b:2} - # h2 = {a:1, b:2, c:3} - # h1 <= h2 #=> true - # h2 <= h1 #=> false - # h1 <= h1 #=> true - # - def <=(hash) - begin - hash = hash.to_hash - rescue NoMethodError - raise TypeError, "can't convert #{hash.class} to Hash" - end - size <= hash.size and all? {|key, val| - hash.key?(key) and hash[key] == val - } - end - - ## - # call-seq: - # hash > other -> true or false - # - # Returns true if other is subset of - # hash. - # - # h1 = {a:1, b:2} - # h2 = {a:1, b:2, c:3} - # h1 > h2 #=> false - # h2 > h1 #=> true - # h1 > h1 #=> false - # - def >(hash) - begin - hash = hash.to_hash - rescue NoMethodError - raise TypeError, "can't convert #{hash.class} to Hash" - end - size > hash.size and hash.all? {|key, val| - key?(key) and self[key] == val - } - end - - ## - # call-seq: - # hash >= other -> true or false - # - # Returns true if other is subset of - # hash or equals to hash. - # - # h1 = {a:1, b:2} - # h2 = {a:1, b:2, c:3} - # h1 >= h2 #=> false - # h2 >= h1 #=> true - # h1 >= h1 #=> true - # - def >=(hash) - begin - hash = hash.to_hash - rescue NoMethodError - raise TypeError, "can't convert #{hash.class} to Hash" - end - size >= hash.size and hash.all? {|key, val| - key?(key) and self[key] == val - } - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-hash-ext/src/hash-ext.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-hash-ext/src/hash-ext.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-hash-ext/src/hash-ext.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-hash-ext/src/hash-ext.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* -** hash.c - Hash class -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/hash.h" - -/* - * call-seq: - * hsh.values_at(key, ...) -> array - * - * Return an array containing the values associated with the given keys. - * Also see Hash.select. - * - * h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" } - * h.values_at("cow", "cat") #=> ["bovine", "feline"] - */ - -static mrb_value -hash_values_at(mrb_state *mrb, mrb_value hash) -{ - mrb_value *argv, result; - mrb_int argc, i; - int ai; - - mrb_get_args(mrb, "*", &argv, &argc); - result = mrb_ary_new_capa(mrb, argc); - ai = mrb_gc_arena_save(mrb); - for (i = 0; i < argc; i++) { - mrb_ary_push(mrb, result, mrb_hash_get(mrb, hash, argv[i])); - mrb_gc_arena_restore(mrb, ai); - } - return result; -} - -void -mrb_mruby_hash_ext_gem_init(mrb_state *mrb) -{ - struct RClass *h; - - h = mrb->hash_class; - mrb_define_method(mrb, h, "values_at", hash_values_at, MRB_ARGS_ANY()); -} - -void -mrb_mruby_hash_ext_gem_final(mrb_state *mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-hash-ext/test/hash.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-hash-ext/test/hash.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-hash-ext/test/hash.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-hash-ext/test/hash.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,232 +0,0 @@ -## -# Hash(Ext) Test - -assert('Hash.[] Hash') do - a = Hash['a_key' => 'a_value'] - - assert_equal({'a_key' => 'a_value'}, a) -end - -assert('Hash.[] [ [ ["b_key", "b_value" ] ] ]') do - a = Hash[ [ ['b_key', 'b_value'] ] ] - - assert_equal({'b_key' => 'b_value'}, a) - - a = Hash[ [ ] ] - - assert_equal({}, a) - - assert_raise(ArgumentError) do - Hash[ [ ['b_key', 'b_value', 'b_over'] ] ] - end - - assert_raise(ArgumentError) do - Hash[ [ [] ] ] - end -end - -assert('Hash.[] "c_key", "c_value"') do - a = Hash['c_key', 'c_value', 'd_key', 1] - - assert_equal({'c_key' => 'c_value', 'd_key' => 1}, a) - - a = Hash[] - - assert_equal({}, a) - - assert_raise(ArgumentError) do - Hash['d_key'] - end -end - -assert('Hash#merge!') do - a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' } - b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' } - - result_1 = a.merge! b - - a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' } - result_2 = a.merge!(b) do |key, original, new| - original - end - - assert_equal({'abc_key' => 'abc_value', 'cba_key' => 'XXX', - 'xyz_key' => 'xyz_value' }, result_1) - assert_equal({'abc_key' => 'abc_value', 'cba_key' => 'cba_value', - 'xyz_key' => 'xyz_value' }, result_2) - - assert_raise(TypeError) do - { 'abc_key' => 'abc_value' }.merge! "a" - end -end - -assert('Hash#values_at') do - h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" } - assert_equal ["bovine", "feline"], h.values_at("cow", "cat") - - keys = [] - (0...1000).each { |v| keys.push "#{v}" } - h = Hash.new { |hash,k| hash[k] = k } - assert_equal keys, h.values_at(*keys) -end - -assert('Hash#fetch') do - h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" } - assert_equal "feline", h.fetch("cat") - assert_equal "mickey", h.fetch("mouse", "mickey") - assert_equal "minny", h.fetch("mouse"){"minny"} - assert_equal "mouse", h.fetch("mouse"){|k| k} - assert_raise(KeyError) do - h.fetch("gnu") - end -end - -assert("Hash#delete_if") do - base = { 1 => 'one', 2 => false, true => 'true', 'cat' => 99 } - h1 = { 1 => 'one', 2 => false, true => 'true' } - h2 = { 2 => false, 'cat' => 99 } - h3 = { 2 => false } - - h = base.dup - assert_equal(h, h.delete_if { false }) - assert_equal({}, h.delete_if { true }) - - h = base.dup - assert_equal(h1, h.delete_if {|k,v| k.instance_of?(String) }) - assert_equal(h1, h) - - h = base.dup - assert_equal(h2, h.delete_if {|k,v| v.instance_of?(String) }) - assert_equal(h2, h) - - h = base.dup - assert_equal(h3, h.delete_if {|k,v| v }) - assert_equal(h3, h) - - h = base.dup - n = 0 - h.delete_if {|*a| - n += 1 - assert_equal(2, a.size) - assert_equal(base[a[0]], a[1]) - h.shift - true - } - assert_equal(base.size, n) -end - -assert("Hash#flatten") do - a = {1=> "one", 2 => [2,"two"], 3 => [3, ["three"]]} - assert_equal [1, "one", 2, [2, "two"], 3, [3, ["three"]]], a.flatten - assert_equal [[1, "one"], [2, [2, "two"]], [3, [3, ["three"]]]], a.flatten(0) - assert_equal [1, "one", 2, [2, "two"], 3, [3, ["three"]]], a.flatten(1) - assert_equal [1, "one", 2, 2, "two", 3, 3, ["three"]], a.flatten(2) - assert_equal [1, "one", 2, 2, "two", 3, 3, "three"], a.flatten(3) -end - -assert("Hash#invert") do - h = { 1 => 'one', 2 => 'two', 3 => 'three', - true => 'true', nil => 'nil' }.invert - assert_equal 1, h['one'] - assert_equal true, h['true'] - assert_equal nil, h['nil'] - - h = { 'a' => 1, 'b' => 2, 'c' => 1 }.invert - assert_equal(2, h.length) - assert_include(%w[a c], h[1]) - assert_equal('b', h[2]) -end - -assert("Hash#keep_if") do - h = { 1 => 2, 3 => 4, 5 => 6 } - assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 }) - h = { 1 => 2, 3 => 4, 5 => 6 } - assert_equal({ 1 => 2, 3=> 4, 5 =>6} , h.keep_if { true }) -end - -assert("Hash#key") do - h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300, nil => 'nil', 'nil' => nil } - assert_equal "b", h.key(200) - assert_equal "c", h.key(300) - assert_nil h.key(999) - assert_nil h.key('nil') - assert_equal 'nil', h.key(nil) -end - -assert("Hash#to_h") do - h = { "a" => 100, "b" => 200 } - assert_equal Hash, h.to_h.class - assert_equal h, h.to_h -end - -assert('Hash#<') do - h1 = {a:1, b:2} - h2 = {a:1, b:2, c:3} - - assert_false(h1 < h1) - assert_true(h1 < h2) - assert_false(h2 < h1) - assert_false(h2 < h2) - - h1 = {a:1} - h2 = {a:2} - - assert_false(h1 < h1) - assert_false(h1 < h2) - assert_false(h2 < h1) - assert_false(h2 < h2) -end - -assert('Hash#<=') do - h1 = {a:1, b:2} - h2 = {a:1, b:2, c:3} - - assert_true(h1 <= h1) - assert_true(h1 <= h2) - assert_false(h2 <= h1) - assert_true(h2 <= h2) - - h1 = {a:1} - h2 = {a:2} - - assert_true(h1 <= h1) - assert_false(h1 <= h2) - assert_false(h2 <= h1) - assert_true(h2 <= h2) -end - -assert('Hash#>=') do - h1 = {a:1, b:2} - h2 = {a:1, b:2, c:3} - - assert_true(h1 >= h1) - assert_false(h1 >= h2) - assert_true(h2 >= h1) - assert_true(h2 >= h2) - - h1 = {a:1} - h2 = {a:2} - - assert_true(h1 >= h1) - assert_false(h1 >= h2) - assert_false(h2 >= h1) - assert_true(h2 >= h2) -end - -assert('Hash#>') do - h1 = {a:1, b:2} - h2 = {a:1, b:2, c:3} - - assert_false(h1 > h1) - assert_false(h1 > h2) - assert_true(h2 > h1) - assert_false(h2 > h2) - - h1 = {a:1} - h2 = {a:2} - - assert_false(h1 > h1) - assert_false(h1 > h2) - assert_false(h2 > h1) - assert_false(h2 > h2) -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-kernel-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Kernel module extension' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-kernel-ext/src/kernel.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-kernel-ext/src/kernel.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-kernel-ext/src/kernel.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-kernel-ext/src/kernel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,184 +0,0 @@ -#include "mruby.h" -#include "mruby/error.h" -#include "mruby/array.h" -#include "mruby/hash.h" - -/* - * call-seq: - * __method__ -> symbol - * - * Returns the name at the definition of the current method as a - * Symbol. - * If called outside of a method, it returns nil. - * - */ -static mrb_value -mrb_f_method(mrb_state *mrb, mrb_value self) -{ - mrb_callinfo *ci = mrb->c->ci; - ci--; - if (ci->mid) - return mrb_symbol_value(ci->mid); - else - return mrb_nil_value(); -} - -/* - * call-seq: - * Integer(arg,base=0) -> integer - * - * Converts arg to a Fixnum. - * Numeric types are converted directly (with floating point numbers - * being truncated). base (0, or between 2 and 36) is a base for - * integer string representation. If arg is a String, - * when base is omitted or equals to zero, radix indicators - * (0, 0b, and 0x) are honored. - * In any case, strings should be strictly conformed to numeric - * representation. This behavior is different from that of - * String#to_i. Non string values will be converted using - * to_int, and to_i. Passing nil - * raises a TypeError. - * - * Integer(123.999) #=> 123 - * Integer("0x1a") #=> 26 - * Integer(Time.new) #=> 1204973019 - * Integer("0930", 10) #=> 930 - * Integer("111", 2) #=> 7 - * Integer(nil) #=> TypeError - */ -static mrb_value -mrb_f_integer(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - mrb_int base = 0; - - mrb_get_args(mrb, "o|i", &arg, &base); - return mrb_convert_to_integer(mrb, arg, base); -} - -/* - * call-seq: - * Float(arg) -> float - * - * Returns arg converted to a float. Numeric types are converted - * directly, the rest are converted using arg.to_f. - * - * Float(1) #=> 1.0 - * Float(123.456) #=> 123.456 - * Float("123.456") #=> 123.456 - * Float(nil) #=> TypeError - */ -static mrb_value -mrb_f_float(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "o", &arg); - return mrb_Float(mrb, arg); -} - -/* - * call-seq: - * String(arg) -> string - * - * Returns arg as an String. - * - * First tries to call its to_str method, then its to_s method. - * - * String(self) #=> "main" - * String(self.class) #=> "Object" - * String(123456) #=> "123456" - */ -static mrb_value -mrb_f_string(mrb_state *mrb, mrb_value self) -{ - mrb_value arg, tmp; - - mrb_get_args(mrb, "o", &arg); - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_str"); - if (mrb_nil_p(tmp)) { - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_s"); - } - return tmp; -} - -/* - * call-seq: - * Array(arg) -> array - * - * Returns +arg+ as an Array. - * - * First tries to call Array#to_ary on +arg+, then Array#to_a. - * - * Array(1..5) #=> [1, 2, 3, 4, 5] - * - */ -static mrb_value -mrb_f_array(mrb_state *mrb, mrb_value self) -{ - mrb_value arg, tmp; - - mrb_get_args(mrb, "o", &arg); - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_ary"); - if (mrb_nil_p(tmp)) { - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_a"); - } - if (mrb_nil_p(tmp)) { - return mrb_ary_new_from_values(mrb, 1, &arg); - } - - return tmp; -} - -/* - * call-seq: - * Hash(arg) -> hash - * - * Converts arg to a Hash by calling - * arg.to_hash. Returns an empty Hash when - * arg is nil or []. - * - * Hash([]) #=> {} - * Hash(nil) #=> {} - * Hash(key: :value) #=> {:key => :value} - * Hash([1, 2, 3]) #=> TypeError - * - */ -static mrb_value -mrb_f_hash(mrb_state *mrb, mrb_value self) -{ - mrb_value arg, tmp; - - mrb_get_args(mrb, "o", &arg); - if (mrb_nil_p(arg)) { - return mrb_hash_new(mrb); - } - tmp = mrb_check_convert_type(mrb, arg, MRB_TT_HASH, "Hash", "to_hash"); - if (mrb_nil_p(tmp)) { - if (mrb_array_p(arg) && RARRAY_LEN(arg) == 0) { - return mrb_hash_new(mrb); - } - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into Hash", - mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, arg))); - } - return tmp; -} - -void -mrb_mruby_kernel_ext_gem_init(mrb_state *mrb) -{ - struct RClass *krn = mrb->kernel_module; - - mrb_define_module_function(mrb, krn, "fail", mrb_f_raise, MRB_ARGS_OPT(2)); - mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE()); - mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ANY()); - mrb_define_module_function(mrb, krn, "Float", mrb_f_float, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, krn, "String", mrb_f_string, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, krn, "Array", mrb_f_array, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, krn, "Hash", mrb_f_hash, MRB_ARGS_REQ(1)); -} - -void -mrb_mruby_kernel_ext_gem_final(mrb_state *mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -assert('Kernel.fail, Kernel#fail') do - assert_raise(RuntimeError) { fail } - assert_raise(RuntimeError) { Kernel.fail } -end - -assert('Kernel#__method__') do - assert_equal(:m, Class.new {def m; __method__; end}.new.m) - assert_equal(:m, Class.new {define_method(:m) {__method__}}.new.m) - c = Class.new do - [:m1, :m2].each do |m| - define_method(m) do - __method__ - end - end - end - assert_equal(:m1, c.new.m1) - assert_equal(:m2, c.new.m2) -end - -assert('Kernel#Integer') do - assert_equal(123, Integer(123.999)) - assert_equal(26, Integer("0x1a")) - assert_equal(930, Integer("0930", 10)) - assert_equal(7, Integer("111", 2)) - assert_raise(TypeError) { Integer(nil) } -end - -assert('Kernel#Float') do - assert_equal(1.0, Float(1)) - assert_equal(123.456, Float(123.456)) - assert_equal(123.456, Float("123.456")) - assert_raise(TypeError) { Float(nil) } -end - -assert('Kernel#String') do - assert_equal("main", String(self)) - assert_equal("Object", String(self.class)) - assert_equal("123456", String(123456)) -end - -assert('Kernel#Array') do - assert_equal([1], Kernel.Array(1)) - assert_equal([1, 2, 3, 4, 5], Kernel.Array([1, 2, 3, 4, 5])) - assert_equal([1, 2, 3, 4, 5], Kernel.Array(1..5)) - assert_equal([[:a, 1], [:b, 2], [:c, 3]], Kernel.Array({a:1, b:2, c:3})) -end - -assert('Kernel#Hash') do - assert_equal({}, Hash([])) - assert_equal({}, Hash(nil)) - assert_equal({:key => :value}, Hash(key: :value)) - assert_raise(TypeError) { Hash([1, 2, 3]) } -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-math/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-math/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-math/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-math/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-math') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'standard Math module' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-math/src/math.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-math/src/math.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-math/src/math.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-math/src/math.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,783 +0,0 @@ -/* -** math.c - Math module -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/array.h" - -#include - -static void -domain_error(mrb_state *mrb, const char *func) -{ - struct RClass *math = mrb_module_get(mrb, "Math"); - struct RClass *domainerror = mrb_class_get_under(mrb, math, "DomainError"); - mrb_value str = mrb_str_new_cstr(mrb, func); - mrb_raisef(mrb, domainerror, "Numerical argument is out of domain - %S", str); -} - -/* math functions not provided by Microsoft Visual C++ 2012 or older */ -#if defined _MSC_VER && _MSC_VER < 1800 - -#include - -#define MATH_TOLERANCE 1E-12 - -double -asinh(double x) -{ - double xa, ya, y; - - /* Basic formula loses precision for x < 0, but asinh is an odd function */ - xa = fabs(x); - if (xa > 3.16227E+18) { - /* Prevent x*x from overflowing; basic formula reduces to log(2*x) */ - ya = log(xa) + 0.69314718055994530942; - } - else { - /* Basic formula for asinh */ - ya = log(xa + sqrt(xa*xa + 1.0)); - } - - y = _copysign(ya, x); - return y; -} - -double -acosh(double x) -{ - double y; - - if (x > 3.16227E+18) { - /* Prevent x*x from overflowing; basic formula reduces to log(2*x) */ - y = log(x) + 0.69314718055994530942; - } - else { - /* Basic formula for acosh */ - y = log(x + sqrt(x*x - 1.0)); - } - - return y; -} - -double -atanh(double x) -{ - double y; - - if (fabs(x) < 1E-2) { - /* The sums 1+x and 1-x lose precision for small x. Use the polynomial - instead. */ - double x2 = x * x; - y = x*(1.0 + x2*(1.0/3.0 + x2*(1.0/5.0 + x2*(1.0/7.0)))); - } - else { - /* Basic formula for atanh */ - y = 0.5 * (log(1.0+x) - log(1.0-x)); - } - - return y; -} - -double -cbrt(double x) -{ - double xa, ya, y; - - /* pow(x, y) is undefined for x < 0 and y not an integer, but cbrt is an - odd function */ - xa = fabs(x); - ya = pow(xa, 1.0/3.0); - y = _copysign(ya, x); - return y; -} - -/* Declaration of complementary Error function */ -double -erfc(double x); - -/* -** Implementations of error functions -** credits to http://www.digitalmars.com/archives/cplusplus/3634.html -*/ - -/* Implementation of Error function */ -double -erf(double x) -{ - static const double two_sqrtpi = 1.128379167095512574; - double sum = x; - double term = x; - double xsqr = x*x; - int j= 1; - if (fabs(x) > 2.2) { - return 1.0 - erfc(x); - } - do { - term *= xsqr/j; - sum -= term/(2*j+1); - ++j; - term *= xsqr/j; - sum += term/(2*j+1); - ++j; - } while (fabs(term/sum) > MATH_TOLERANCE); - return two_sqrtpi*sum; -} - -/* Implementation of complementary Error function */ -double -erfc(double x) -{ - static const double one_sqrtpi= 0.564189583547756287; - double a = 1; - double b = x; - double c = x; - double d = x*x+0.5; - double q1; - double q2 = b/d; - double n = 1.0; - double t; - if (fabs(x) < 2.2) { - return 1.0 - erf(x); - } - if (x < 0.0) { /*signbit(x)*/ - return 2.0 - erfc(-x); - } - do { - t = a*n+b*x; - a = b; - b = t; - t = c*n+d*x; - c = d; - d = t; - n += 0.5; - q1 = q2; - q2 = b/d; - } while (fabs(q1-q2)/q2 > MATH_TOLERANCE); - return one_sqrtpi*exp(-x*x)*q2; -} - -#endif - -#if (defined _MSC_VER && _MSC_VER < 1800) || defined __ANDROID__ || (defined __FreeBSD__ && __FreeBSD_version < 803000) - -double -log2(double x) -{ - return log10(x)/log10(2.0); -} - -#endif - -/* - TRIGONOMETRIC FUNCTIONS -*/ - -/* - * call-seq: - * Math.sin(x) -> float - * - * Computes the sine of x (expressed in radians). Returns - * -1..1. - */ -static mrb_value -math_sin(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = sin(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.cos(x) -> float - * - * Computes the cosine of x (expressed in radians). Returns - * -1..1. - */ -static mrb_value -math_cos(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = cos(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.tan(x) -> float - * - * Returns the tangent of x (expressed in radians). - */ -static mrb_value -math_tan(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = tan(x); - - return mrb_float_value(mrb, x); -} - -/* - INVERSE TRIGONOMETRIC FUNCTIONS -*/ - -/* - * call-seq: - * Math.asin(x) -> float - * - * Computes the arc sine of x. - * @return computed value between `-(PI/2)` and `(PI/2)`. - */ -static mrb_value -math_asin(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - if (x < -1.0 || x > 1.0) { - domain_error(mrb, "asin"); - } - x = asin(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.acos(x) -> float - * - * Computes the arc cosine of x. Returns 0..PI. - */ -static mrb_value -math_acos(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - if (x < -1.0 || x > 1.0) { - domain_error(mrb, "acos"); - } - x = acos(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.atan(x) -> float - * - * Computes the arc tangent of x. Returns `-(PI/2) .. (PI/2)`. - */ -static mrb_value -math_atan(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = atan(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.atan2(y, x) -> float - * - * Computes the arc tangent given y and x. Returns - * -PI..PI. - * - * Math.atan2(-0.0, -1.0) #=> -3.141592653589793 - * Math.atan2(-1.0, -1.0) #=> -2.356194490192345 - * Math.atan2(-1.0, 0.0) #=> -1.5707963267948966 - * Math.atan2(-1.0, 1.0) #=> -0.7853981633974483 - * Math.atan2(-0.0, 1.0) #=> -0.0 - * Math.atan2(0.0, 1.0) #=> 0.0 - * Math.atan2(1.0, 1.0) #=> 0.7853981633974483 - * Math.atan2(1.0, 0.0) #=> 1.5707963267948966 - * Math.atan2(1.0, -1.0) #=> 2.356194490192345 - * Math.atan2(0.0, -1.0) #=> 3.141592653589793 - * - */ -static mrb_value -math_atan2(mrb_state *mrb, mrb_value obj) -{ - mrb_float x, y; - - mrb_get_args(mrb, "ff", &x, &y); - x = atan2(x, y); - - return mrb_float_value(mrb, x); -} - - - -/* - HYPERBOLIC TRIG FUNCTIONS -*/ -/* - * call-seq: - * Math.sinh(x) -> float - * - * Computes the hyperbolic sine of x (expressed in - * radians). - */ -static mrb_value -math_sinh(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = sinh(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.cosh(x) -> float - * - * Computes the hyperbolic cosine of x (expressed in radians). - */ -static mrb_value -math_cosh(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = cosh(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.tanh() -> float - * - * Computes the hyperbolic tangent of x (expressed in - * radians). - */ -static mrb_value -math_tanh(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = tanh(x); - - return mrb_float_value(mrb, x); -} - - -/* - INVERSE HYPERBOLIC TRIG FUNCTIONS -*/ - -/* - * call-seq: - * Math.asinh(x) -> float - * - * Computes the inverse hyperbolic sine of x. - */ -static mrb_value -math_asinh(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - - x = asinh(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.acosh(x) -> float - * - * Computes the inverse hyperbolic cosine of x. - */ -static mrb_value -math_acosh(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - if (x < 1.0) { - domain_error(mrb, "acosh"); - } - x = acosh(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.atanh(x) -> float - * - * Computes the inverse hyperbolic tangent of x. - */ -static mrb_value -math_atanh(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - if (x < -1.0 || x > 1.0) { - domain_error(mrb, "atanh"); - } - x = atanh(x); - - return mrb_float_value(mrb, x); -} - -/* - EXPONENTIALS AND LOGARITHMS -*/ - -/* - * call-seq: - * Math.exp(x) -> float - * - * Returns e**x. - * - * Math.exp(0) #=> 1.0 - * Math.exp(1) #=> 2.718281828459045 - * Math.exp(1.5) #=> 4.4816890703380645 - * - */ -static mrb_value -math_exp(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = exp(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.log(numeric) -> float - * Math.log(num,base) -> float - * - * Returns the natural logarithm of numeric. - * If additional second argument is given, it will be the base - * of logarithm. - * - * Math.log(1) #=> 0.0 - * Math.log(Math::E) #=> 1.0 - * Math.log(Math::E**3) #=> 3.0 - * Math.log(12,3) #=> 2.2618595071429146 - * - */ -static mrb_value -math_log(mrb_state *mrb, mrb_value obj) -{ - mrb_float x, base; - int argc; - - argc = mrb_get_args(mrb, "f|f", &x, &base); - if (x < 0.0) { - domain_error(mrb, "log"); - } - x = log(x); - if (argc == 2) { - if (base < 0.0) { - domain_error(mrb, "log"); - } - x /= log(base); - } - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.log2(numeric) -> float - * - * Returns the base 2 logarithm of numeric. - * - * Math.log2(1) #=> 0.0 - * Math.log2(2) #=> 1.0 - * Math.log2(32768) #=> 15.0 - * Math.log2(65536) #=> 16.0 - * - */ -static mrb_value -math_log2(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - if (x < 0.0) { - domain_error(mrb, "log2"); - } - x = log2(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.log10(numeric) -> float - * - * Returns the base 10 logarithm of numeric. - * - * Math.log10(1) #=> 0.0 - * Math.log10(10) #=> 1.0 - * Math.log10(10**100) #=> 100.0 - * - */ -static mrb_value -math_log10(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - if (x < 0.0) { - domain_error(mrb, "log10"); - } - x = log10(x); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.sqrt(numeric) -> float - * - * Returns the square root of numeric. - * - */ -static mrb_value -math_sqrt(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - if (x < 0.0) { - domain_error(mrb, "sqrt"); - } - x = sqrt(x); - - return mrb_float_value(mrb, x); -} - - -/* - * call-seq: - * Math.cbrt(numeric) -> float - * - * Returns the cube root of numeric. - * - * -9.upto(9) {|x| - * p [x, Math.cbrt(x), Math.cbrt(x)**3] - * } - * #=> - * [-9, -2.0800838230519, -9.0] - * [-8, -2.0, -8.0] - * [-7, -1.91293118277239, -7.0] - * [-6, -1.81712059283214, -6.0] - * [-5, -1.7099759466767, -5.0] - * [-4, -1.5874010519682, -4.0] - * [-3, -1.44224957030741, -3.0] - * [-2, -1.25992104989487, -2.0] - * [-1, -1.0, -1.0] - * [0, 0.0, 0.0] - * [1, 1.0, 1.0] - * [2, 1.25992104989487, 2.0] - * [3, 1.44224957030741, 3.0] - * [4, 1.5874010519682, 4.0] - * [5, 1.7099759466767, 5.0] - * [6, 1.81712059283214, 6.0] - * [7, 1.91293118277239, 7.0] - * [8, 2.0, 8.0] - * [9, 2.0800838230519, 9.0] - * - */ -static mrb_value -math_cbrt(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = cbrt(x); - - return mrb_float_value(mrb, x); -} - - -/* - * call-seq: - * Math.frexp(numeric) -> [ fraction, exponent ] - * - * Returns a two-element array containing the normalized fraction (a - * Float) and exponent (a Fixnum) of - * numeric. - * - * fraction, exponent = Math.frexp(1234) #=> [0.6025390625, 11] - * fraction * 2**exponent #=> 1234.0 - */ -static mrb_value -math_frexp(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - int exp; - - mrb_get_args(mrb, "f", &x); - x = frexp(x, &exp); - - return mrb_assoc_new(mrb, mrb_float_value(mrb, x), mrb_fixnum_value(exp)); -} - -/* - * call-seq: - * Math.ldexp(flt, int) -> float - * - * Returns the value of flt*(2**int). - * - * fraction, exponent = Math.frexp(1234) - * Math.ldexp(fraction, exponent) #=> 1234.0 - */ -static mrb_value -math_ldexp(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - mrb_int i; - - mrb_get_args(mrb, "fi", &x, &i); - x = ldexp(x, i); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.hypot(x, y) -> float - * - * Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle - * with sides x and y. - * - * Math.hypot(3, 4) #=> 5.0 - */ -static mrb_value -math_hypot(mrb_state *mrb, mrb_value obj) -{ - mrb_float x, y; - - mrb_get_args(mrb, "ff", &x, &y); - x = hypot(x, y); - - return mrb_float_value(mrb, x); -} - -/* - * call-seq: - * Math.erf(x) -> float - * - * Calculates the error function of x. - */ -static mrb_value -math_erf(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = erf(x); - - return mrb_float_value(mrb, x); -} - - -/* - * call-seq: - * Math.erfc(x) -> float - * - * Calculates the complementary error function of x. - */ -static mrb_value -math_erfc(mrb_state *mrb, mrb_value obj) -{ - mrb_float x; - - mrb_get_args(mrb, "f", &x); - x = erfc(x); - - return mrb_float_value(mrb, x); -} - -/* ------------------------------------------------------------------------*/ -void -mrb_mruby_math_gem_init(mrb_state* mrb) -{ - struct RClass *mrb_math; - mrb_math = mrb_define_module(mrb, "Math"); - - mrb_define_class_under(mrb, mrb_math, "DomainError", mrb->eStandardError_class); - -#ifdef M_PI - mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(mrb, M_PI)); -#else - mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(mrb, atan(1.0)*4.0)); -#endif - -#ifdef M_E - mrb_define_const(mrb, mrb_math, "E", mrb_float_value(mrb, M_E)); -#else - mrb_define_const(mrb, mrb_math, "E", mrb_float_value(mrb, exp(1.0))); -#endif - -#ifdef MRB_USE_FLOAT - mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(mrb, 1e-5)); -#else - mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(mrb, 1e-12)); -#endif - - mrb_define_module_function(mrb, mrb_math, "sin", math_sin, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "cos", math_cos, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "tan", math_tan, MRB_ARGS_REQ(1)); - - mrb_define_module_function(mrb, mrb_math, "asin", math_asin, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "acos", math_acos, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "atan", math_atan, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "atan2", math_atan2, MRB_ARGS_REQ(2)); - - mrb_define_module_function(mrb, mrb_math, "sinh", math_sinh, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "cosh", math_cosh, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "tanh", math_tanh, MRB_ARGS_REQ(1)); - - mrb_define_module_function(mrb, mrb_math, "asinh", math_asinh, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "acosh", math_acosh, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "atanh", math_atanh, MRB_ARGS_REQ(1)); - - mrb_define_module_function(mrb, mrb_math, "exp", math_exp, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "log", math_log, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); - mrb_define_module_function(mrb, mrb_math, "log2", math_log2, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "log10", math_log10, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "sqrt", math_sqrt, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "cbrt", math_cbrt, MRB_ARGS_REQ(1)); - - mrb_define_module_function(mrb, mrb_math, "frexp", math_frexp, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "ldexp", math_ldexp, MRB_ARGS_REQ(2)); - - mrb_define_module_function(mrb, mrb_math, "hypot", math_hypot, MRB_ARGS_REQ(2)); - - mrb_define_module_function(mrb, mrb_math, "erf", math_erf, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, mrb_math, "erfc", math_erfc, MRB_ARGS_REQ(1)); -} - -void -mrb_mruby_math_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-math/test/math.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-math/test/math.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-math/test/math.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-math/test/math.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,152 +0,0 @@ -## -# Math Test - -## -# Performs fuzzy check for equality on methods returning floats -# on the basis of the Math::TOLERANCE constant. -def check_float(a, b) - tolerance = Math::TOLERANCE - a = a.to_f - b = b.to_f - if a.finite? and b.finite? - (a-b).abs < tolerance - else - true - end -end - -assert('Math.sin 0') do - check_float(Math.sin(0), 0) -end - -assert('Math.sin PI/2') do - check_float(Math.sin(Math::PI / 2), 1) -end - -assert('Math.cos 0') do - check_float(Math.cos(0), 1) -end - -assert('Math.cos PI/2') do - check_float(Math.cos(Math::PI / 2), 0) -end - -assert('Math.tan 0') do - check_float(Math.tan(0), 0) -end - -assert('Math.tan PI/4') do - check_float(Math.tan(Math::PI / 4), 1) -end - -assert('Fundamental trig identities') do - result = true - N = 13 - N.times do |i| - a = Math::PI / N * i - ca = Math::PI / 2 - a - s = Math.sin(a) - c = Math.cos(a) - t = Math.tan(a) - result &= check_float(s, Math.cos(ca)) - result &= check_float(t, 1 / Math.tan(ca)) - result &= check_float(s ** 2 + c ** 2, 1) - result &= check_float(t ** 2 + 1, (1/c) ** 2) - result &= check_float((1/t) ** 2 + 1, (1/s) ** 2) - end - result -end - -assert('Math.erf 0') do - check_float(Math.erf(0), 0) -end - -assert('Math.exp 0') do - check_float(Math.exp(0), 1.0) -end - -assert('Math.exp 1') do - check_float(Math.exp(1), 2.718281828459045) -end - -assert('Math.exp 1.5') do - check_float(Math.exp(1.5), 4.4816890703380645) -end - -assert('Math.log 1') do - check_float(Math.log(1), 0) -end - -assert('Math.log E') do - check_float(Math.log(Math::E), 1.0) -end - -assert('Math.log E**3') do - check_float(Math.log(Math::E**3), 3.0) -end - -assert('Math.log2 1') do - check_float(Math.log2(1), 0.0) -end - -assert('Math.log2 2') do - check_float(Math.log2(2), 1.0) -end - -assert('Math.log10 1') do - check_float(Math.log10(1), 0.0) -end - -assert('Math.log10 10') do - check_float(Math.log10(10), 1.0) -end - -assert('Math.log10 10**100') do - check_float(Math.log10(10**100), 100.0) -end - -assert('Math.sqrt') do - num = [0.0, 1.0, 2.0, 3.0, 4.0] - sqr = [0, 1, 4, 9, 16] - result = true - sqr.each_with_index do |v,i| - result &= check_float(Math.sqrt(v), num[i]) - end - result -end - -assert('Math.cbrt') do - num = [-2.0, -1.0, 0.0, 1.0, 2.0] - cub = [-8, -1, 0, 1, 8] - result = true - cub.each_with_index do |v,i| - result &= check_float(Math.cbrt(v), num[i]) - end - result -end - -assert('Math.hypot') do - check_float(Math.hypot(3, 4), 5.0) -end - -assert('Math.frexp 1234') do - n = 1234 - fraction, exponent = Math.frexp(n) - check_float(Math.ldexp(fraction, exponent), n) -end - -assert('Math.erf 1') do - check_float(Math.erf(1), 0.842700792949715) -end - -assert('Math.erfc 1') do - check_float(Math.erfc(1), 0.157299207050285) -end - -assert('Math.erf -1') do - check_float(Math.erf(-1), -0.8427007929497148) -end - -assert('Math.erfc -1') do - check_float(Math.erfc(-1), 1.8427007929497148) -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-numeric-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Numeric class extension' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -module Integral - def div(other) - self.divmod(other)[0] - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -#include -#include "mruby.h" - -static mrb_value -mrb_int_chr(mrb_state *mrb, mrb_value x) -{ - mrb_int chr; - char c; - - chr = mrb_fixnum(x); - if (chr >= (1 << CHAR_BIT)) { - mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", x); - } - c = (char)chr; - - return mrb_str_new(mrb, &c, 1); -} - -void -mrb_mruby_numeric_ext_gem_init(mrb_state* mrb) -{ - struct RClass *i = mrb_class_get(mrb, "Integer"); - - mrb_define_method(mrb, i, "chr", mrb_int_chr, MRB_ARGS_NONE()); -} - -void -mrb_mruby_numeric_ext_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -## -# Numeric(Ext) Test - -assert('Integer#chr') do - assert_equal("A", 65.chr) - assert_equal("B", 0x42.chr) - - # multibyte encoding (not support yet) - assert_raise(RangeError) { 256.chr } -end - -assert('Integer#div') do - assert_equal 52, 365.div(7) -end - -assert('Float#div') do - assert_float 52, 365.2425.div(7) -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-object-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-object-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-object-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-object-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-object-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Object class extension' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-object-ext/mrblib/object.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-object-ext/mrblib/object.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-object-ext/mrblib/object.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-object-ext/mrblib/object.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -class Object - ## - # call-seq: - # obj.tap{|x|...} -> obj - # - # Yields x to the block, and then returns x. - # The primary purpose of this method is to "tap into" a method chain, - # in order to perform operations on intermediate results within the chain. - # - # (1..10) .tap {|x| puts "original: #{x.inspect}"} - # .to_a .tap {|x| puts "array: #{x.inspect}"} - # .select {|x| x%2==0} .tap {|x| puts "evens: #{x.inspect}"} - # .map { |x| x*x } .tap {|x| puts "squares: #{x.inspect}"} - # - def tap - yield self - self - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-object-ext/src/object.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-object-ext/src/object.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-object-ext/src/object.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-object-ext/src/object.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" - -/* - * call-seq: - * nil.to_a -> [] - * - * Always returns an empty array. - */ - -static mrb_value -nil_to_a(mrb_state *mrb, mrb_value obj) -{ - return mrb_ary_new(mrb); -} - -/* - * call-seq: - * nil.to_f -> 0.0 - * - * Always returns zero. - */ - -static mrb_value -nil_to_f(mrb_state *mrb, mrb_value obj) -{ - return mrb_float_value(mrb, 0.0); -} - -/* - * call-seq: - * nil.to_i -> 0 - * - * Always returns zero. - */ - -static mrb_value -nil_to_i(mrb_state *mrb, mrb_value obj) -{ - return mrb_fixnum_value(0); -} - -/* - * call-seq: - * obj.instance_exec(arg...) {|var...| block } -> obj - * - * Executes the given block within the context of the receiver - * (_obj_). In order to set the context, the variable +self+ is set - * to _obj_ while the code is executing, giving the code access to - * _obj_'s instance variables. Arguments are passed as block parameters. - * - * class KlassWithSecret - * def initialize - * @secret = 99 - * end - * end - * k = KlassWithSecret.new - * k.instance_exec(5) {|x| @secret+x } #=> 104 - */ - -static mrb_value -mrb_obj_instance_exec(mrb_state *mrb, mrb_value self) -{ - mrb_value *argv; - mrb_int argc; - mrb_value blk; - struct RClass *c; - - mrb_get_args(mrb, "*&", &argv, &argc, &blk); - - if (mrb_nil_p(blk)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); - } - - switch (mrb_type(self)) { - case MRB_TT_SYMBOL: - case MRB_TT_FIXNUM: - case MRB_TT_FLOAT: - c = NULL; - break; - default: - c = mrb_class_ptr(mrb_singleton_class(mrb, self)); - break; - } - - return mrb_yield_with_class(mrb, blk, argc, argv, self, c); -} - -void -mrb_mruby_object_ext_gem_init(mrb_state* mrb) -{ - struct RClass * n = mrb->nil_class; - - mrb_define_method(mrb, n, "to_a", nil_to_a, MRB_ARGS_NONE()); - mrb_define_method(mrb, n, "to_f", nil_to_f, MRB_ARGS_NONE()); - mrb_define_method(mrb, n, "to_i", nil_to_i, MRB_ARGS_NONE()); - - mrb_define_method(mrb, mrb->object_class, "instance_exec", mrb_obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK()); -} - -void -mrb_mruby_object_ext_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-object-ext/test/nil.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-object-ext/test/nil.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-object-ext/test/nil.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-object-ext/test/nil.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -assert('NilClass#to_a') do - assert_equal [], nil.to_a -end - -assert('NilClass#to_f') do - assert_equal 0.0, nil.to_f -end - -assert('NilClass#to_i') do - assert_equal 0, nil.to_i -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-object-ext/test/object.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-object-ext/test/object.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-object-ext/test/object.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-object-ext/test/object.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -assert('Object#instance_exec') do - class KlassWithSecret - def initialize - @secret = 99 - end - end - k = KlassWithSecret.new - assert_equal 104, k.instance_exec(5) {|x| @secret+x } -end - -assert('Object#tap') do - ret = [] - (1..10) .tap {|x| ret << "original: #{x.inspect}"} - .to_a .tap {|x| ret << "array: #{x.inspect}"} - .select {|x| x%2==0} .tap {|x| ret << "evens: #{x.inspect}"} - .map { |x| x*x } .tap {|x| ret << "squares: #{x.inspect}"} - - assert_equal [ - "original: 1..10", - "array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", - "evens: [2, 4, 6, 8, 10]", - "squares: [4, 16, 36, 64, 100]" - ], ret - assert_equal(:tap_ok, Class.new {def m; tap{return :tap_ok}; end}.new.m) -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-objectspace/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-objectspace/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-objectspace/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-objectspace/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-objectspace') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'ObjectSpace class' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,185 +0,0 @@ -#include "mruby.h" -#include "mruby/gc.h" -#include "mruby/hash.h" -#include "mruby/class.h" - -struct os_count_struct { - mrb_int total; - mrb_int freed; - mrb_int counts[MRB_TT_MAXDEFINE+1]; -}; - -static void -os_count_object_type(mrb_state *mrb, struct RBasic *obj, void *data) -{ - struct os_count_struct *obj_count; - obj_count = (struct os_count_struct*)data; - - obj_count->total++; - - if (mrb_object_dead_p(mrb, obj)) { - obj_count->freed++; - } - else { - obj_count->counts[obj->tt]++; - } -} - -/* - * call-seq: - * ObjectSpace.count_objects([result_hash]) -> hash - * - * Counts objects for each type. - * - * It returns a hash, such as: - * { - * :TOTAL=>10000, - * :FREE=>3011, - * :T_OBJECT=>6, - * :T_CLASS=>404, - * # ... - * } - * - * If the optional argument +result_hash+ is given, - * it is overwritten and returned. This is intended to avoid probe effect. - * - */ - -static mrb_value -os_count_objects(mrb_state *mrb, mrb_value self) -{ - struct os_count_struct obj_count = { 0 }; - enum mrb_vtype i; - mrb_value hash; - - if (mrb_get_args(mrb, "|H", &hash) == 0) { - hash = mrb_hash_new(mrb); - } - - if (!mrb_test(mrb_hash_empty_p(mrb, hash))) { - mrb_hash_clear(mrb, hash); - } - - mrb_objspace_each_objects(mrb, os_count_object_type, &obj_count); - - mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_lit(mrb, "TOTAL")), mrb_fixnum_value(obj_count.total)); - mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_lit(mrb, "FREE")), mrb_fixnum_value(obj_count.freed)); - - for (i = MRB_TT_FALSE; i < MRB_TT_MAXDEFINE; i++) { - mrb_value type; - switch (i) { -#define COUNT_TYPE(t) case (MRB_T ## t): type = mrb_symbol_value(mrb_intern_lit(mrb, #t)); break; - COUNT_TYPE(T_FALSE); - COUNT_TYPE(T_FREE); - COUNT_TYPE(T_TRUE); - COUNT_TYPE(T_FIXNUM); - COUNT_TYPE(T_SYMBOL); - COUNT_TYPE(T_UNDEF); - COUNT_TYPE(T_FLOAT); - COUNT_TYPE(T_CPTR); - COUNT_TYPE(T_OBJECT); - COUNT_TYPE(T_CLASS); - COUNT_TYPE(T_MODULE); - COUNT_TYPE(T_ICLASS); - COUNT_TYPE(T_SCLASS); - COUNT_TYPE(T_PROC); - COUNT_TYPE(T_ARRAY); - COUNT_TYPE(T_HASH); - COUNT_TYPE(T_STRING); - COUNT_TYPE(T_RANGE); - COUNT_TYPE(T_EXCEPTION); - COUNT_TYPE(T_FILE); - COUNT_TYPE(T_ENV); - COUNT_TYPE(T_DATA); - COUNT_TYPE(T_FIBER); -#undef COUNT_TYPE - default: - type = mrb_fixnum_value(i); break; - } - if (obj_count.counts[i]) - mrb_hash_set(mrb, hash, type, mrb_fixnum_value(obj_count.counts[i])); - } - - return hash; -} - -struct os_each_object_data { - mrb_value block; - struct RClass *target_module; - mrb_int count; -}; - -static void -os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud) -{ - struct os_each_object_data *d = (struct os_each_object_data*)ud; - - /* filter dead objects */ - if (mrb_object_dead_p(mrb, obj)) { - return; - } - - /* filter internal objects */ - switch (obj->tt) { - case MRB_TT_ENV: - case MRB_TT_ICLASS: - return; - default: - break; - } - - /* filter half baked (or internal) objects */ - if (!obj->c) return; - - /* filter class kind if target module defined */ - if (d->target_module && !mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), d->target_module)) { - return; - } - - mrb_yield(mrb, d->block, mrb_obj_value(obj)); - ++d->count; -} - -/* - * call-seq: - * ObjectSpace.each_object([module]) {|obj| ... } -> fixnum - * - * Calls the block once for each object in this Ruby process. - * Returns the number of objects found. - * If the optional argument +module+ is given, - * calls the block for only those classes or modules - * that match (or are a subclass of) +module+. - * - * If no block is given, ArgumentError is raised. - * - */ - -static mrb_value -os_each_object(mrb_state *mrb, mrb_value self) -{ - mrb_value cls = mrb_nil_value(); - struct os_each_object_data d; - mrb_get_args(mrb, "&|C", &d.block, &cls); - - if (mrb_nil_p(d.block)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "Expected block in ObjectSpace.each_object."); - } - - d.target_module = mrb_nil_p(cls) ? NULL : mrb_class_ptr(cls); - d.count = 0; - mrb_objspace_each_objects(mrb, os_each_object_cb, &d); - return mrb_fixnum_value(d.count); -} - -void -mrb_mruby_objectspace_gem_init(mrb_state *mrb) -{ - struct RClass *os = mrb_define_module(mrb, "ObjectSpace"); - mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1)); - mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1)); -} - -void -mrb_mruby_objectspace_gem_final(mrb_state *mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-objectspace/test/objectspace.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-objectspace/test/objectspace.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-objectspace/test/objectspace.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-objectspace/test/objectspace.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -assert('ObjectSpace.count_objects') do - h = {} - f = Fiber.new {} if Object.const_defined? :Fiber - ObjectSpace.count_objects(h) - assert_kind_of(Hash, h) - assert_true(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) }) - assert_true(h.values.all? {|x| x.is_a?(Integer) }) - - assert_true(h.has_key?(:TOTAL)) - assert_true(h.has_key?(:FREE)) - assert_true(h.has_key?(:T_FIBER)) if Object.const_defined? :Fiber - - assert_equal(h[:TOTAL] * 2, h.values.reduce(:+)) - - h = ObjectSpace.count_objects - assert_kind_of(Hash, h) - assert_true(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) }) - assert_true(h.values.all? {|x| x.is_a?(Integer) }) - - assert_raise(TypeError) { ObjectSpace.count_objects(1) } - - h0 = {:T_FOO=>1000} - h = ObjectSpace.count_objects(h0) - assert_false(h0.has_key?(:T_FOO)) - - GC.start - h_after = {} - h_before = ObjectSpace.count_objects - - objs = [] - 1000.times do - objs << {} - end - objs = nil - ObjectSpace.count_objects(h) - GC.start - ObjectSpace.count_objects(h_after) - - assert_equal(h[:T_HASH], h_before[:T_HASH] + 1000) - assert_equal(h_after[:T_HASH], h_before[:T_HASH]) -end - -assert('ObjectSpace.each_object') do - objs = [] - objs_count = ObjectSpace.each_object { |obj| - objs << obj - } - assert_equal objs.length, objs_count - - arys = [] - arys_count = ObjectSpace.each_object(Array) { |obj| - arys << obj - } - assert_equal arys.length, arys_count - assert_true arys.length < objs.length -end - -assert 'Check class pointer of ObjectSpace.each_object.' do - ObjectSpace.each_object { |obj| !obj } -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-print/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-print/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-print/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-print/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-print') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'standard print/puts/p' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-print/mrblib/print.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-print/mrblib/print.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-print/mrblib/print.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-print/mrblib/print.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -## -# Kernel -# -# ISO 15.3.1 -module Kernel - ## - # Invoke method +print+ on STDOUT and passing +*args+ - # - # ISO 15.3.1.2.10 - def print(*args) - i = 0 - len = args.size - while i < len - __printstr__ args[i].to_s - i += 1 - end - end - - ## - # Invoke method +puts+ on STDOUT and passing +*args*+ - # - # ISO 15.3.1.2.11 - def puts(*args) - i = 0 - len = args.size - while i < len - s = args[i].to_s - __printstr__ s - __printstr__ "\n" if (s[-1] != "\n") - i += 1 - end - __printstr__ "\n" if len == 0 - nil - end - - ## - # Print human readable object description - # - # ISO 15.3.1.3.34 - def p(*args) - i = 0 - len = args.size - while i < len - __printstr__ args[i].inspect - __printstr__ "\n" - i += 1 - end - args[0] - end - - unless Kernel.respond_to?(:sprintf) - def printf(*args) - raise NotImplementedError.new('printf not available') - end - def sprintf(*args) - raise NotImplementedError.new('sprintf not available') - end - else - def printf(*args) - __printstr__(sprintf(*args)) - nil - end - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-print/src/print.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-print/src/print.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-print/src/print.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-print/src/print.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -#include "mruby.h" -#include "mruby/string.h" -#include -#include -#include -#if defined(__MINGW32__) || defined(__MINGW64__) -# include -# include -#endif - -static void -printstr(mrb_state *mrb, mrb_value obj) -{ - if (mrb_string_p(obj)) { -#if defined(__MINGW32__) || defined(__MINGW64__) - if (isatty(fileno(stdout))) { - DWORD written; - int mlen = RSTRING_LEN(obj); - char* utf8 = RSTRING_PTR(obj); - int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, NULL, 0); - wchar_t* utf16 = mrb_malloc(mrb, (wlen+1) * sizeof(wchar_t)); - if (utf16 == NULL) return; - if (MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, utf16, wlen) > 0) { - utf16[wlen] = 0; - WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), - utf16, wlen, &written, NULL); - } - mrb_free(mrb, utf16); - } else -#endif - fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stdout); - } -} - -/* 15.3.1.2.9 */ -/* 15.3.1.3.34 */ -mrb_value -mrb_printstr(mrb_state *mrb, mrb_value self) -{ - mrb_value argv; - - mrb_get_args(mrb, "o", &argv); - printstr(mrb, argv); - - return argv; -} - -void -mrb_mruby_print_gem_init(mrb_state* mrb) -{ - struct RClass *krn; - krn = mrb->kernel_module; - mrb_define_method(mrb, krn, "__printstr__", mrb_printstr, MRB_ARGS_REQ(1)); -} - -void -mrb_mruby_print_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-proc-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-proc-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-proc-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-proc-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-proc-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Proc class extension' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -class Proc - - def ===(*args) - call(*args) - end - - def yield(*args) - call(*args) - end - - def to_proc - self - end - - def curry(arity=self.arity) - type = :proc - abs = lambda {|a| a < 0 ? -a - 1 : a} - arity = abs[arity] - if lambda? - type = :lambda - self_arity = self.arity - if (self_arity >= 0 && arity != self_arity) || - (self_arity < 0 && abs[self_arity] > arity) - raise ArgumentError, "wrong number of arguments (#{arity} for #{abs[self_arity]})" - end - end - - pproc = self - make_curry = proc do |given_args=[]| - send(type) do |*args| - new_args = given_args + args - if new_args.size >= arity - pproc[*new_args] - else - make_curry[new_args] - end - end - end - make_curry.call - end - -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-proc-ext/src/proc.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-proc-ext/src/proc.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-proc-ext/src/proc.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-proc-ext/src/proc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,167 +0,0 @@ -#include "mruby.h" -#include "mruby/proc.h" -#include "mruby/opcode.h" -#include "mruby/array.h" -#include "mruby/string.h" -#include "mruby/debug.h" - -static mrb_value -mrb_proc_lambda(mrb_state *mrb, mrb_value self) -{ - struct RProc *p = mrb_proc_ptr(self); - return mrb_bool_value(MRB_PROC_STRICT_P(p)); -} - -static mrb_value -mrb_proc_source_location(mrb_state *mrb, mrb_value self) -{ - struct RProc *p = mrb_proc_ptr(self); - - if (MRB_PROC_CFUNC_P(p)) { - return mrb_nil_value(); - } - else { - mrb_irep *irep = p->body.irep; - int32_t line; - const char *filename; - - filename = mrb_debug_get_filename(irep, 0); - line = mrb_debug_get_line(irep, 0); - - return (!filename && line == -1)? mrb_nil_value() - : mrb_assoc_new(mrb, mrb_str_new_cstr(mrb, filename), mrb_fixnum_value(line)); - } -} - -static mrb_value -mrb_proc_inspect(mrb_state *mrb, mrb_value self) -{ - struct RProc *p = mrb_proc_ptr(self); - mrb_value str = mrb_str_new_lit(mrb, "#body.irep; - const char *filename; - int32_t line; - mrb_str_cat_lit(mrb, str, "@"); - - filename = mrb_debug_get_filename(irep, 0); - mrb_str_cat_cstr(mrb, str, filename ? filename : "-"); - mrb_str_cat_lit(mrb, str, ":"); - - line = mrb_debug_get_line(irep, 0); - if (line != -1) { - mrb_str_append(mrb, str, mrb_fixnum_value(line)); - } - else { - mrb_str_cat_lit(mrb, str, "-"); - } - } - - if (MRB_PROC_STRICT_P(p)) { - mrb_str_cat_lit(mrb, str, " (lambda)"); - } - - mrb_str_cat_lit(mrb, str, ">"); - return str; -} - -static mrb_value -mrb_kernel_proc(mrb_state *mrb, mrb_value self) -{ - mrb_value blk; - - mrb_get_args(mrb, "&", &blk); - if (mrb_nil_p(blk)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); - } - - return blk; -} - -/* - * call-seq: - * prc.parameters -> array - * - * Returns the parameter information of this proc. - * - * prc = lambda{|x, y=42, *other|} - * prc.parameters #=> [[:req, :x], [:opt, :y], [:rest, :other]] - */ - -static mrb_value -mrb_proc_parameters(mrb_state *mrb, mrb_value self) -{ - struct parameters_type { - int size; - const char *name; - } *p, parameters_list [] = { - {0, "req"}, - {0, "opt"}, - {0, "rest"}, - {0, "req"}, - {0, "block"}, - {0, NULL} - }; - const struct RProc *proc = mrb_proc_ptr(self); - const struct mrb_irep *irep = proc->body.irep; - mrb_aspec aspec; - mrb_value parameters; - int i, j; - - if (MRB_PROC_CFUNC_P(proc)) { - // TODO cfunc aspec is not implemented yet - return mrb_ary_new(mrb); - } - if (!irep->lv) { - return mrb_ary_new(mrb); - } - if (GET_OPCODE(*irep->iseq) != OP_ENTER) { - return mrb_ary_new(mrb); - } - - if (!MRB_PROC_STRICT_P(proc)) { - parameters_list[0].name = "opt"; - parameters_list[3].name = "opt"; - } - - aspec = GETARG_Ax(*irep->iseq); - parameters_list[0].size = MRB_ASPEC_REQ(aspec); - parameters_list[1].size = MRB_ASPEC_OPT(aspec); - parameters_list[2].size = MRB_ASPEC_REST(aspec); - parameters_list[3].size = MRB_ASPEC_POST(aspec); - parameters_list[4].size = MRB_ASPEC_BLOCK(aspec); - - parameters = mrb_ary_new_capa(mrb, irep->nlocals-1); - for (i = 0, p = parameters_list; p->name; p++) { - mrb_value sname = mrb_symbol_value(mrb_intern_cstr(mrb, p->name)); - for (j = 0; j < p->size; i++, j++) { - mrb_assert(i < (irep->nlocals-1)); - mrb_ary_push(mrb, parameters, mrb_assoc_new(mrb, - sname, - mrb_symbol_value(irep->lv[i].name) - )); - } - } - return parameters; -} - -void -mrb_mruby_proc_ext_gem_init(mrb_state* mrb) -{ - struct RClass *p = mrb->proc_class; - mrb_define_method(mrb, p, "lambda?", mrb_proc_lambda, MRB_ARGS_NONE()); - mrb_define_method(mrb, p, "source_location", mrb_proc_source_location, MRB_ARGS_NONE()); - mrb_define_method(mrb, p, "to_s", mrb_proc_inspect, MRB_ARGS_NONE()); - mrb_define_method(mrb, p, "inspect", mrb_proc_inspect, MRB_ARGS_NONE()); - mrb_define_method(mrb, p, "parameters", mrb_proc_parameters, MRB_ARGS_NONE()); - - mrb_define_class_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()); - mrb_define_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()); -} - -void -mrb_mruby_proc_ext_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-proc-ext/test/proc.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-proc-ext/test/proc.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-proc-ext/test/proc.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-proc-ext/test/proc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -#include "mruby.h" -#include "mruby/proc.h" -#include "mruby/class.h" - -static mrb_value -return_func_name(mrb_state *mrb, mrb_value self) -{ - return mrb_cfunc_env_get(mrb, 0); -} - -static mrb_value -proc_new_cfunc_with_env(mrb_state *mrb, mrb_value self) -{ - mrb_sym n; - mrb_value n_val; - mrb_get_args(mrb, "n", &n); - n_val = mrb_symbol_value(n); - mrb_define_method_raw(mrb, mrb_class_ptr(self), n, - mrb_proc_new_cfunc_with_env(mrb, return_func_name, 1, &n_val)); - return self; -} - -static mrb_value -return_env(mrb_state *mrb, mrb_value self) -{ - mrb_int idx; - mrb_get_args(mrb, "i", &idx); - return mrb_cfunc_env_get(mrb, idx); -} - -static mrb_value -cfunc_env_get(mrb_state *mrb, mrb_value self) -{ - mrb_sym n; - mrb_value *argv; mrb_int argc; - mrb_get_args(mrb, "na", &n, &argv, &argc); - mrb_define_method_raw(mrb, mrb_class_ptr(self), n, - mrb_proc_new_cfunc_with_env(mrb, return_env, argc, argv)); - return self; -} - -static mrb_value -cfunc_without_env(mrb_state *mrb, mrb_value self) -{ - return mrb_cfunc_env_get(mrb, 0); -} - -void mrb_mruby_proc_ext_gem_test(mrb_state *mrb) -{ - struct RClass *cls; - - cls = mrb_define_class(mrb, "ProcExtTest", mrb->object_class); - mrb_define_module_function(mrb, cls, "mrb_proc_new_cfunc_with_env", proc_new_cfunc_with_env, MRB_ARGS_REQ(1)); - mrb_define_module_function(mrb, cls, "mrb_cfunc_env_get", cfunc_env_get, MRB_ARGS_REQ(2)); - mrb_define_module_function(mrb, cls, "cfunc_without_env", cfunc_without_env, MRB_ARGS_NONE()); -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-proc-ext/test/proc.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-proc-ext/test/proc.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-proc-ext/test/proc.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-proc-ext/test/proc.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -## -# Proc(Ext) Test - -assert('Proc#source_location') do - loc = Proc.new {}.source_location - next true if loc.nil? - assert_equal loc[0][-7, 7], 'proc.rb' - assert_equal loc[1], 5 -end - -assert('Proc#inspect') do - ins = Proc.new{}.inspect - assert_kind_of String, ins -end - -assert('Proc#lambda?') do - assert_true lambda{}.lambda? - assert_true !Proc.new{}.lambda? -end - -assert('Proc#===') do - proc = Proc.new {|a| a * 2} - assert_equal 20, (proc === 10) -end - -assert('Proc#yield') do - proc = Proc.new {|a| a * 2} - assert_equal 20, proc.yield(10) -end - -assert('Proc#curry') do - b = proc {|x, y, z| (x||0) + (y||0) + (z||0) } - assert_equal 6, b.curry[1][2][3] - assert_equal 6, b.curry[1, 2][3, 4] - assert_equal 6, b.curry(5)[1][2][3][4][5] - assert_equal 6, b.curry(5)[1, 2][3, 4][5] - assert_equal 1, b.curry(1)[1] - - b = lambda {|x, y, z| (x||0) + (y||0) + (z||0) } - assert_equal 6, b.curry[1][2][3] - assert_raise(ArgumentError) { b.curry[1, 2][3, 4] } - assert_raise(ArgumentError) { b.curry(5) } - assert_raise(ArgumentError) { b.curry(1) } - - assert_false(proc{}.curry.lambda?) - assert_true(lambda{}.curry.lambda?) -end - -assert('Proc#parameters') do - assert_equal([], Proc.new {}.parameters) - assert_equal([], Proc.new {||}.parameters) - assert_equal([[:opt, :a]], Proc.new {|a|}.parameters) - assert_equal([[:req, :a]], lambda {|a|}.parameters) - assert_equal([[:opt, :a]], lambda {|a=nil|}.parameters) - assert_equal([[:req, :a]], ->(a){}.parameters) - assert_equal([[:rest, :a]], Proc.new {|*a|}.parameters) - assert_equal([[:opt, :a], [:opt, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:opt, :f], [:opt, :g], [:block, :h]], Proc.new {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters) - assert_equal([[:req, :a], [:req, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:req, :f], [:req, :g], [:block, :h]], lambda {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters) -end - -assert('Proc#to_proc') do - proc = Proc.new {} - assert_equal proc, proc.to_proc -end - -assert('Kernel#proc') do - assert_true !proc{|a|}.lambda? -end - -assert('mrb_proc_new_cfunc_with_env') do - ProcExtTest.mrb_proc_new_cfunc_with_env(:test) - ProcExtTest.mrb_proc_new_cfunc_with_env(:mruby) - - t = ProcExtTest.new - - assert_equal :test, t.test - assert_equal :mruby, t.mruby -end - -assert('mrb_cfunc_env_get') do - ProcExtTest.mrb_cfunc_env_get :get_int, [0, 1, 2] - - t = ProcExtTest.new - - assert_raise(TypeError) { t.cfunc_without_env } - - assert_raise(IndexError) { t.get_int(-1) } - assert_raise(IndexError) { t.get_int(3) } - - assert_equal 1, t.get_int(1) -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-random') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Random class' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/src/mt19937ar.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/src/mt19937ar.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/src/mt19937ar.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/src/mt19937ar.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,197 +0,0 @@ -/* -** mt19937ar.c - MT Random functions -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mt19937ar.h" - -/* Period parameters */ -/* #define N 624 */ -#define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ - -#if 0 /* dead_code */ -static unsigned long mt[N]; /* the array for the state vector */ -static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ -#endif /* dead_code */ - -void mrb_random_init_genrand(mt_state *t, unsigned long s) -{ - t->mt[0]= s & 0xffffffffUL; - for (t->mti=1; t->mtimti++) { - t->mt[t->mti] = - (1812433253UL * (t->mt[t->mti-1] ^ (t->mt[t->mti-1] >> 30)) + t->mti); - t->mt[t->mti] &= 0xffffffffUL; - } -} - -unsigned long mrb_random_genrand_int32(mt_state *t) -{ - unsigned long y; - static const unsigned long mag01[2]={0x0UL, MATRIX_A}; - /* mag01[x] = x * MATRIX_A for x=0,1 */ - - if (t->mti >= N) { /* generate N words at one time */ - int kk; - - if (t->mti == N+1) /* if init_genrand() has not been called, */ - mrb_random_init_genrand(t, 5489UL); /* a default initial seed is used */ - - for (kk=0;kkmt[kk]&UPPER_MASK)|(t->mt[kk+1]&LOWER_MASK); - t->mt[kk] = t->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL]; - } - for (;kkmt[kk]&UPPER_MASK)|(t->mt[kk+1]&LOWER_MASK); - t->mt[kk] = t->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; - } - y = (t->mt[N-1]&UPPER_MASK)|(t->mt[0]&LOWER_MASK); - t->mt[N-1] = t->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; - - t->mti = 0; - } - - y = t->mt[t->mti++]; - - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); - - t->gen.int_ = y; - - return y; -} - -double mrb_random_genrand_real1(mt_state *t) -{ - mrb_random_genrand_int32(t); - t->gen.double_ = t->gen.int_*(1.0/4294967295.0); - return t->gen.double_; - /* divided by 2^32-1 */ -} - -#if 0 /* dead_code */ -/* initializes mt[N] with a seed */ -void init_genrand(unsigned long s) -{ - mt[0]= s & 0xffffffffUL; - for (mti=1; mti> 30)) + mti); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array mt[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - mt[mti] &= 0xffffffffUL; - /* for >32 bit machines */ - } -} - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void init_by_array(unsigned long init_key[], int key_length) -{ - int i, j, k; - init_genrand(19650218UL); - i=1; j=0; - k = (N>key_length ? N : key_length); - for (; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) - + init_key[j] + j; /* non linear */ - mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; j++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - if (j>=key_length) j=0; - } - for (k=N-1; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - - i; /* non linear */ - mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - } - - mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ -} - -/* generates a random number on [0,0xffffffff]-interval */ -unsigned long genrand_int32(void) -{ - unsigned long y; - static const unsigned long mag01[2]={0x0UL, MATRIX_A}; - /* mag01[x] = x * MATRIX_A for x=0,1 */ - - if (mti >= N) { /* generate N words at one time */ - int kk; - - if (mti == N+1) /* if init_genrand() has not been called, */ - init_genrand(5489UL); /* a default initial seed is used */ - - for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; - } - for (;kk> 1) ^ mag01[y & 0x1UL]; - } - y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; - - mti = 0; - } - - y = mt[mti++]; - - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); - - return y; -} - -/* generates a random number on [0,0x7fffffff]-interval */ -long genrand_int31(void) -{ - return (long)(genrand_int32()>>1); -} - -/* generates a random number on [0,1]-real-interval */ -double genrand_real1(void) -{ - return genrand_int32()*(1.0/4294967295.0); - /* divided by 2^32-1 */ -} - -/* generates a random number on [0,1)-real-interval */ -double genrand_real2(void) -{ - return genrand_int32()*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/* generates a random number on (0,1)-real-interval */ -double genrand_real3(void) -{ - return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void) -{ - unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; - return(a*67108864.0+b)*(1.0/9007199254740992.0); -} -/* These real versions are due to Isaku Wada, 2002/01/09 added */ -#endif /* dead_code */ diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/src/mt19937ar.h nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/src/mt19937ar.h --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/src/mt19937ar.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/src/mt19937ar.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* -** mt19937ar.h - MT Random functions -** -** See Copyright Notice in mruby.h -*/ - -#define N 624 - -typedef struct { - unsigned long mt[N]; - int mti; - union { - unsigned long int_; - double double_; - } gen; - - mrb_int seed; - mrb_bool has_seed : 1; -} mt_state; - -void mrb_random_init_genrand(mt_state *, unsigned long); -unsigned long mrb_random_genrand_int32(mt_state *); -double mrb_random_genrand_real1(mt_state *t); - -/* initializes mt[N] with a seed */ -void init_genrand(unsigned long s); - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void init_by_array(unsigned long init_key[], int key_length); - -/* generates a random number on [0,0xffffffff]-interval */ -unsigned long genrand_int32(void); - -/* generates a random number on [0,0x7fffffff]-interval */ -long genrand_int31(void); - -/* These real versions are due to Isaku Wada, 2002/01/09 added */ -/* generates a random number on [0,1]-real-interval */ -double genrand_real1(void); - -/* generates a random number on [0,1)-real-interval */ -double genrand_real2(void); - -/* generates a random number on (0,1)-real-interval */ -double genrand_real3(void); - -/* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void); diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/src/random.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/src/random.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/src/random.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/src/random.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,345 +0,0 @@ -/* -** random.c - Random module -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/variable.h" -#include "mruby/class.h" -#include "mruby/data.h" -#include "mruby/array.h" -#include "mt19937ar.h" - -#include - -static char const MT_STATE_KEY[] = "$mrb_i_mt_state"; - -static const struct mrb_data_type mt_state_type = { - MT_STATE_KEY, mrb_free, -}; - -static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self); -static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self); - -static void -mt_srand(mt_state *t, unsigned long seed) -{ - mrb_random_init_genrand(t, seed); -} - -static unsigned long -mt_rand(mt_state *t) -{ - return mrb_random_genrand_int32(t); -} - -static double -mt_rand_real(mt_state *t) -{ - return mrb_random_genrand_real1(t); -} - -static mrb_value -mrb_random_mt_srand(mrb_state *mrb, mt_state *t, mrb_value seed) -{ - if (mrb_nil_p(seed)) { - seed = mrb_fixnum_value((mrb_int)(time(NULL) + mt_rand(t))); - if (mrb_fixnum(seed) < 0) { - seed = mrb_fixnum_value(0 - mrb_fixnum(seed)); - } - } - - mt_srand(t, (unsigned) mrb_fixnum(seed)); - - return seed; -} - -static mrb_value -mrb_random_mt_rand(mrb_state *mrb, mt_state *t, mrb_value max) -{ - mrb_value value; - - if (mrb_fixnum(max) == 0) { - value = mrb_float_value(mrb, mt_rand_real(t)); - } - else { - value = mrb_fixnum_value(mt_rand(t) % mrb_fixnum(max)); - } - - return value; -} - -static mrb_value -get_opt(mrb_state* mrb) -{ - mrb_value arg; - - arg = mrb_nil_value(); - mrb_get_args(mrb, "|o", &arg); - - if (!mrb_nil_p(arg)) { - if (!mrb_fixnum_p(arg)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type"); - } - arg = mrb_check_convert_type(mrb, arg, MRB_TT_FIXNUM, "Fixnum", "to_int"); - if (mrb_fixnum(arg) < 0) { - arg = mrb_fixnum_value(0 - mrb_fixnum(arg)); - } - } - return arg; -} - -static mrb_value -get_random(mrb_state *mrb) { - return mrb_const_get(mrb, - mrb_obj_value(mrb_class_get(mrb, "Random")), - mrb_intern_lit(mrb, "DEFAULT")); -} - -static mt_state * -get_random_state(mrb_state *mrb) -{ - mrb_value random_val = get_random(mrb); - return DATA_GET_PTR(mrb, random_val, &mt_state_type, mt_state); -} - -static mrb_value -mrb_random_g_rand(mrb_state *mrb, mrb_value self) -{ - mrb_value random = get_random(mrb); - return mrb_random_rand(mrb, random); -} - -static mrb_value -mrb_random_g_srand(mrb_state *mrb, mrb_value self) -{ - mrb_value random = get_random(mrb); - return mrb_random_srand(mrb, random); -} - -static mrb_value -mrb_random_init(mrb_state *mrb, mrb_value self) -{ - mrb_value seed; - mt_state *t; - - /* avoid memory leaks */ - t = (mt_state*)DATA_PTR(self); - if (t) { - mrb_free(mrb, t); - } - mrb_data_init(self, NULL, &mt_state_type); - - t = (mt_state *)mrb_malloc(mrb, sizeof(mt_state)); - t->mti = N + 1; - - seed = get_opt(mrb); - seed = mrb_random_mt_srand(mrb, t, seed); - if (mrb_nil_p(seed)) { - t->has_seed = FALSE; - } - else { - mrb_assert(mrb_fixnum_p(seed)); - t->has_seed = TRUE; - t->seed = mrb_fixnum(seed); - } - - mrb_data_init(self, t, &mt_state_type); - - return self; -} - -static void -mrb_random_rand_seed(mrb_state *mrb, mt_state *t) -{ - if (!t->has_seed) { - mrb_random_mt_srand(mrb, t, mrb_nil_value()); - } -} - -static mrb_value -mrb_random_rand(mrb_state *mrb, mrb_value self) -{ - mrb_value max; - mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state); - - max = get_opt(mrb); - mrb_random_rand_seed(mrb, t); - return mrb_random_mt_rand(mrb, t, max); -} - -static mrb_value -mrb_random_srand(mrb_state *mrb, mrb_value self) -{ - mrb_value seed; - mrb_value old_seed; - mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state); - - seed = get_opt(mrb); - seed = mrb_random_mt_srand(mrb, t, seed); - old_seed = t->has_seed? mrb_fixnum_value(t->seed) : mrb_nil_value(); - if (mrb_nil_p(seed)) { - t->has_seed = FALSE; - } - else { - mrb_assert(mrb_fixnum_p(seed)); - t->has_seed = TRUE; - t->seed = mrb_fixnum(seed); - } - - return old_seed; -} - -/* - * call-seq: - * ary.shuffle! -> ary - * - * Shuffles elements in self in place. - */ - -static mrb_value -mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) -{ - mrb_int i; - mt_state *random = NULL; - - if (RARRAY_LEN(ary) > 1) { - mrb_get_args(mrb, "|d", &random, &mt_state_type); - - if (random == NULL) { - random = get_random_state(mrb); - } - mrb_random_rand_seed(mrb, random); - - mrb_ary_modify(mrb, mrb_ary_ptr(ary)); - - for (i = RARRAY_LEN(ary) - 1; i > 0; i--) { - mrb_int j; - mrb_value tmp; - - j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary)))); - - tmp = RARRAY_PTR(ary)[i]; - mrb_ary_ptr(ary)->ptr[i] = RARRAY_PTR(ary)[j]; - mrb_ary_ptr(ary)->ptr[j] = tmp; - } - } - - return ary; -} - -/* - * call-seq: - * ary.shuffle -> new_ary - * - * Returns a new array with elements of self shuffled. - */ - -static mrb_value -mrb_ary_shuffle(mrb_state *mrb, mrb_value ary) -{ - mrb_value new_ary = mrb_ary_new_from_values(mrb, RARRAY_LEN(ary), RARRAY_PTR(ary)); - mrb_ary_shuffle_bang(mrb, new_ary); - - return new_ary; -} - -/* - * call-seq: - * ary.sample -> obj - * ary.sample(n) -> new_ary - * - * Choose a random element or +n+ random elements from the array. - * - * The elements are chosen by using random and unique indices into the array - * in order to ensure that an element doesn't repeat itself unless the array - * already contained duplicate elements. - * - * If the array is empty the first form returns +nil+ and the second form - * returns an empty array. - */ - -static mrb_value -mrb_ary_sample(mrb_state *mrb, mrb_value ary) -{ - mrb_int n = 0; - mrb_bool given; - mt_state *random = NULL; - mrb_int len = RARRAY_LEN(ary); - - mrb_get_args(mrb, "|i?d", &n, &given, &random, &mt_state_type); - if (random == NULL) { - random = get_random_state(mrb); - } - mrb_random_rand_seed(mrb, random); - mt_rand(random); - if (!given) { /* pick one element */ - switch (len) { - case 0: - return mrb_nil_value(); - case 1: - return RARRAY_PTR(ary)[0]; - default: - return RARRAY_PTR(ary)[mt_rand(random) % len]; - } - } - else { - mrb_value result; - mrb_int i, j; - - if (n < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "negative sample number"); - if (n > len) n = len; - result = mrb_ary_new_capa(mrb, n); - for (i=0; iarray_class; - - mrb_define_method(mrb, mrb->kernel_module, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, mrb->kernel_module, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1)); - - random = mrb_define_class(mrb, "Random", mrb->object_class); - MRB_SET_INSTANCE_TT(random, MRB_TT_DATA); - mrb_define_class_method(mrb, random, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1)); - mrb_define_class_method(mrb, random, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1)); - - mrb_define_method(mrb, random, "initialize", mrb_random_init, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, random, "rand", mrb_random_rand, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, random, "srand", mrb_random_srand, MRB_ARGS_OPT(1)); - - mrb_define_method(mrb, array, "shuffle", mrb_ary_shuffle, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, array, "shuffle!", mrb_ary_shuffle_bang, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, array, "sample", mrb_ary_sample, MRB_ARGS_OPT(2)); - - mrb_const_set(mrb, mrb_obj_value(random), mrb_intern_lit(mrb, "DEFAULT"), - mrb_obj_new(mrb, random, 0, NULL)); -} - -void mrb_mruby_random_gem_final(mrb_state *mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/src/random.h nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/src/random.h --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/src/random.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/src/random.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -/* -** random.h - Random module -** -** See Copyright Notice in mruby.h -*/ - -#ifndef RANDOM_H -#define RANDOM_H - -void mrb_mruby_random_gem_init(mrb_state *mrb); - -#endif diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/test/random.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/test/random.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-random/test/random.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-random/test/random.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,76 +0,0 @@ -## -# Random Test - -assert("Random#srand") do - r1 = Random.new(123) - r2 = Random.new(123) - r1.rand == r2.rand -end - -assert("Kernel::srand") do - srand(234) - r1 = rand - srand(234) - r2 = rand - r1 == r2 -end - -assert("Random::srand") do - Random.srand(345) - r1 = rand - srand(345) - r2 = Random.rand - r1 == r2 -end - -assert("fixnum") do - rand(3).class == Fixnum -end - -assert("float") do - rand.class == Float -end - -assert("Array#shuffle") do - ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - shuffled = ary.shuffle - - ary == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and shuffled != ary and 10.times { |x| ary.include? x } -end - -assert('Array#shuffle!') do - ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - ary.shuffle! - - ary != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary.include? x } -end - -assert("Array#shuffle(random)") do - assert_raise(TypeError) do - # this will cause an exception due to the wrong argument - [1, 2].shuffle "Not a Random instance" - end - - # verify that the same seed causes the same results - ary1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - shuffle1 = ary1.shuffle Random.new 345 - ary2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - shuffle2 = ary2.shuffle Random.new 345 - - ary1 != shuffle1 and 10.times { |x| shuffle1.include? x } and shuffle1 == shuffle2 -end - -assert('Array#shuffle!(random)') do - assert_raise(TypeError) do - # this will cause an exception due to the wrong argument - [1, 2].shuffle! "Not a Random instance" - end - - # verify that the same seed causes the same results - ary1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - ary1.shuffle! Random.new 345 - ary2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - ary2.shuffle! Random.new 345 - - ary1 != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary1.include? x } and ary1 == ary2 -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-range-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-range-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-range-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-range-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-range-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Range class extension' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-range-ext/src/range.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-range-ext/src/range.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-range-ext/src/range.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-range-ext/src/range.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,191 +0,0 @@ -#include "mruby.h" -#include "mruby/range.h" -#include - -static mrb_bool -r_le(mrb_state *mrb, mrb_value a, mrb_value b) -{ - mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ - /* output :a < b => -1, a = b => 0, a > b => +1 */ - - if (mrb_fixnum_p(r)) { - mrb_int c = mrb_fixnum(r); - if (c == 0 || c == -1) return TRUE; - } - - return FALSE; -} - -static mrb_bool -r_lt(mrb_state *mrb, mrb_value a, mrb_value b) -{ - mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); - /* output :a < b => -1, a = b => 0, a > b => +1 */ - - return mrb_fixnum_p(r) && mrb_fixnum(r) == -1; -} - -/* - * call-seq: - * rng.cover?(obj) -> true or false - * - * Returns true if +obj+ is between the begin and end of - * the range. - * - * This tests begin <= obj <= end when #exclude_end? is +false+ - * and begin <= obj < end when #exclude_end? is +true+. - * - * ("a".."z").cover?("c") #=> true - * ("a".."z").cover?("5") #=> false - * ("a".."z").cover?("cc") #=> true - */ -static mrb_value -mrb_range_cover(mrb_state *mrb, mrb_value range) -{ - mrb_value val; - struct RRange *r = mrb_range_ptr(range); - mrb_value beg, end; - - mrb_get_args(mrb, "o", &val); - - beg = r->edges->beg; - end = r->edges->end; - - if (r_le(mrb, beg, val)) { - if (r->excl) { - if (r_lt(mrb, val, end)) - return mrb_true_value(); - } - else { - if (r_le(mrb, val, end)) - return mrb_true_value(); - } - } - - return mrb_false_value(); -} - -/* - * call-seq: - * rng.first -> obj - * rng.first(n) -> an_array - * - * Returns the first object in the range, or an array of the first +n+ - * elements. - * - * (10..20).first #=> 10 - * (10..20).first(3) #=> [10, 11, 12] - */ -static mrb_value -mrb_range_first(mrb_state *mrb, mrb_value range) -{ - mrb_int num; - mrb_value array; - struct RRange *r = mrb_range_ptr(range); - - if (mrb_get_args(mrb, "|i", &num) == 0) { - return r->edges->beg; - } - - array = mrb_funcall(mrb, range, "to_a", 0); - return mrb_funcall(mrb, array, "first", 1, mrb_fixnum_value(num)); -} - -/* - * call-seq: - * rng.last -> obj - * rng.last(n) -> an_array - * - * Returns the last object in the range, - * or an array of the last +n+ elements. - * - * Note that with no arguments +last+ will return the object that defines - * the end of the range even if #exclude_end? is +true+. - * - * (10..20).last #=> 20 - * (10...20).last #=> 20 - * (10..20).last(3) #=> [18, 19, 20] - * (10...20).last(3) #=> [17, 18, 19] - */ -static mrb_value -mrb_range_last(mrb_state *mrb, mrb_value range) -{ - mrb_value num; - mrb_value array; - struct RRange *r = mrb_range_ptr(range); - - if (mrb_get_args(mrb, "|o", &num) == 0) { - return r->edges->end; - } - - array = mrb_funcall(mrb, range, "to_a", 0); - return mrb_funcall(mrb, array, "last", 1, mrb_to_int(mrb, num)); -} - -/* - * call-seq: - * rng.size -> num - * - * Returns the number of elements in the range. Both the begin and the end of - * the Range must be Numeric, otherwise nil is returned. - * - * (10..20).size #=> 11 - * ('a'..'z').size #=> nil - */ - -static mrb_value -mrb_range_size(mrb_state *mrb, mrb_value range) -{ - struct RRange *r = mrb_range_ptr(range); - mrb_value beg, end; - double beg_f, end_f; - mrb_bool num_p = TRUE; - - beg = r->edges->beg; - end = r->edges->end; - if (mrb_fixnum_p(beg)) { - beg_f = (double)mrb_fixnum(beg); - } - else if (mrb_float_p(beg)) { - beg_f = mrb_float(beg); - } - else { - num_p = FALSE; - } - if (mrb_fixnum_p(end)) { - end_f = (double)mrb_fixnum(end); - } - else if (mrb_float_p(end)) { - end_f = mrb_float(end); - } - else { - num_p = FALSE; - } - if (num_p) { - double f; - - if (beg_f > end_f) return mrb_fixnum_value(0); - f = end_f - beg_f; - if (!r->excl) { - return mrb_fixnum_value((mrb_int)ceil(f + 1)); - } - return mrb_fixnum_value((mrb_int)ceil(f)); - } - return mrb_nil_value(); -} - -void -mrb_mruby_range_ext_gem_init(mrb_state* mrb) -{ - struct RClass * s = mrb_class_get(mrb, "Range"); - - mrb_define_method(mrb, s, "cover?", mrb_range_cover, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, s, "first", mrb_range_first, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, s, "last", mrb_range_last, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, s, "size", mrb_range_size, MRB_ARGS_NONE()); -} - -void -mrb_mruby_range_ext_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-range-ext/test/range.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-range-ext/test/range.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-range-ext/test/range.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-range-ext/test/range.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -## -# Range(Ext) Test - -assert('Range#cover?') do - assert_true ("a".."z").cover?("c") - assert_true !("a".."z").cover?("5") - assert_true ("a".."z").cover?("cc") -end - -assert('Range#first') do - assert_equal 10, (10..20).first - assert_equal [10, 11, 12], (10..20).first(3) -end - -assert('Range#last') do - assert_equal 20, (10..20).last - assert_equal 20, (10...20).last - assert_equal [18, 19, 20], (10..20).last(3) - assert_equal [17, 18, 19], (10...20).last(3) -end - -assert('Range#size') do - assert_equal 42, (1..42).size - assert_equal 41, (1...42).size - assert_equal 6, (1...6.3).size - assert_equal 5, (1...6.0).size - assert_equal 5, (1.1...6).size - assert_nil ('a'..'z').size -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-sprintf/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-sprintf/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-sprintf/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-sprintf/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-sprintf') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'standard Kernel#sprintf method' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-sprintf/mrblib/string.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-sprintf/mrblib/string.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-sprintf/mrblib/string.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-sprintf/mrblib/string.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -class String - def %(args) - if args.is_a? Array - sprintf(self, *args) - else - sprintf(self, args) - end - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-sprintf/src/kernel.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-sprintf/src/kernel.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-sprintf/src/kernel.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-sprintf/src/kernel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -/* -** kernel.c - Kernel module suppliment -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" - -mrb_value mrb_f_sprintf(mrb_state *mrb, mrb_value obj); /* in sprintf.c */ - -void -mrb_mruby_sprintf_gem_init(mrb_state* mrb) -{ - struct RClass *krn; - - if (mrb->kernel_module == NULL) { - mrb->kernel_module = mrb_define_module(mrb, "Kernel"); /* Might be PARANOID. */ - } - krn = mrb->kernel_module; - - mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, MRB_ARGS_ANY()); - mrb_define_method(mrb, krn, "format", mrb_f_sprintf, MRB_ARGS_ANY()); -} - -void -mrb_mruby_sprintf_gem_final(mrb_state* mrb) -{ - /* nothing to do. */ -} - diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-sprintf/src/sprintf.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-sprintf/src/sprintf.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-sprintf/src/sprintf.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-sprintf/src/sprintf.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1104 +0,0 @@ -/* -** sprintf.c - Kernel.#sprintf -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" - -#include -#include -#include -#include "mruby/string.h" -#include "mruby/hash.h" -#include "mruby/numeric.h" -#include -#include - -#define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */ -#define BITSPERDIG MRB_INT_BIT -#define EXTENDSIGN(n, l) (((~0 << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0 << (n))) - -mrb_value mrb_str_format(mrb_state *, int, const mrb_value *, mrb_value); -static void fmt_setup(char*,size_t,int,int,mrb_int,mrb_int); - -static char* -remove_sign_bits(char *str, int base) -{ - char *t; - - t = str; - if (base == 16) { - while (*t == 'f') { - t++; - } - } - else if (base == 8) { - *t |= EXTENDSIGN(3, strlen(t)); - while (*t == '7') { - t++; - } - } - else if (base == 2) { - while (*t == '1') { - t++; - } - } - - return t; -} - -static char -sign_bits(int base, const char *p) -{ - char c; - - switch (base) { - case 16: - if (*p == 'X') c = 'F'; - else c = 'f'; - break; - case 8: - c = '7'; break; - case 2: - c = '1'; break; - default: - c = '.'; break; - } - return c; -} - -static mrb_value -mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) -{ - char buf[64], *b = buf + sizeof buf; - mrb_int num = mrb_fixnum(x); - uint64_t val = (uint64_t)num; - char d; - - if (base != 2) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base)); - } - - if (val >= (1 << 10)) - val &= 0x3ff; - - if (val == 0) { - return mrb_str_new_lit(mrb, "0"); - } - *--b = '\0'; - do { - *--b = mrb_digitmap[(int)(val % base)]; - } while (val /= base); - - if (num < 0) { - b = remove_sign_bits(b, base); - switch (base) { - case 16: d = 'f'; break; - case 8: d = '7'; break; - case 2: d = '1'; break; - default: d = 0; break; - } - - if (d && *b != d) { - *--b = d; - } - } - - return mrb_str_new_cstr(mrb, b); -} - -#define FNONE 0 -#define FSHARP 1 -#define FMINUS 2 -#define FPLUS 4 -#define FZERO 8 -#define FSPACE 16 -#define FWIDTH 32 -#define FPREC 64 -#define FPREC0 128 - -#define CHECK(l) do {\ -/* int cr = ENC_CODERANGE(result);*/\ - while (blen + (l) >= bsiz) {\ - bsiz*=2;\ - }\ - mrb_str_resize(mrb, result, bsiz);\ -/* ENC_CODERANGE_SET(result, cr);*/\ - buf = RSTRING_PTR(result);\ -} while (0) - -#define PUSH(s, l) do { \ - CHECK(l);\ - memcpy(&buf[blen], s, l);\ - blen += (l);\ -} while (0) - -#define FILL(c, l) do { \ - CHECK(l);\ - memset(&buf[blen], c, l);\ - blen += (l);\ -} while (0) - -#define GETARG() (!mrb_undef_p(nextvalue) ? nextvalue : \ - posarg == -1 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with numbered", mrb_fixnum_value(nextarg)), mrb_undef_value()) : \ - posarg == -2 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with named", mrb_fixnum_value(nextarg)), mrb_undef_value()) : \ - (posarg = nextarg++, GETNTHARG(posarg))) - -#define GETPOSARG(n) (posarg > 0 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after unnumbered(%S)", mrb_fixnum_value(n), mrb_fixnum_value(posarg)), mrb_undef_value()) : \ - posarg == -2 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after named", mrb_fixnum_value(n)), mrb_undef_value()) : \ - ((n < 1) ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid index - %S$", mrb_fixnum_value(n)), mrb_undef_value()) : \ - (posarg = -1, GETNTHARG(n)))) - -#define GETNTHARG(nth) \ - ((nth >= argc) ? (mrb_raise(mrb, E_ARGUMENT_ERROR, "too few arguments"), mrb_undef_value()) : argv[nth]) - -#define GETNAMEARG(id, name, len) ( \ - posarg > 0 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after unnumbered(%S)", mrb_str_new(mrb, (name), (len)), mrb_fixnum_value(posarg)), mrb_undef_value()) : \ - posarg == -1 ? \ - (mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after numbered", mrb_str_new(mrb, (name), (len))), mrb_undef_value()) : \ - (posarg = -2, mrb_hash_fetch(mrb, get_hash(mrb, &hash, argc, argv), id, mrb_undef_value()))) - -#define GETNUM(n, val) \ - for (; p < end && ISDIGIT(*p); p++) {\ - int next_n = 10 * n + (*p - '0'); \ - if (next_n / 10 != n) {\ - mrb_raise(mrb, E_ARGUMENT_ERROR, #val " too big"); \ - } \ - n = next_n; \ - } \ - if (p >= end) { \ - mrb_raise(mrb, E_ARGUMENT_ERROR, "malformed format string - %*[0-9]"); \ - } - -#define GETASTER(num) do { \ - mrb_value tmp_v; \ - t = p++; \ - n = 0; \ - GETNUM(n, val); \ - if (*p == '$') { \ - tmp_v = GETPOSARG(n); \ - } \ - else { \ - tmp_v = GETARG(); \ - p = t; \ - } \ - num = mrb_fixnum(tmp_v); \ -} while (0) - -static mrb_value -get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) -{ - mrb_value tmp; - - if (!mrb_undef_p(*hash)) return *hash; - if (argc != 2) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required"); - } - tmp = mrb_check_convert_type(mrb, argv[1], MRB_TT_HASH, "Hash", "to_hash"); - if (mrb_nil_p(tmp)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required"); - } - return (*hash = tmp); -} - -/* - * call-seq: - * format(format_string [, arguments...] ) -> string - * sprintf(format_string [, arguments...] ) -> string - * - * Returns the string resulting from applying format_string to - * any additional arguments. Within the format string, any characters - * other than format sequences are copied to the result. - * - * The syntax of a format sequence is follows. - * - * %[flags][width][.precision]type - * - * A format - * sequence consists of a percent sign, followed by optional flags, - * width, and precision indicators, then terminated with a field type - * character. The field type controls how the corresponding - * sprintf argument is to be interpreted, while the flags - * modify that interpretation. - * - * The field type characters are: - * - * Field | Integer Format - * ------+-------------------------------------------------------------- - * b | Convert argument as a binary number. - * | Negative numbers will be displayed as a two's complement - * | prefixed with '..1'. - * B | Equivalent to 'b', but uses an uppercase 0B for prefix - * | in the alternative format by #. - * d | Convert argument as a decimal number. - * i | Identical to 'd'. - * o | Convert argument as an octal number. - * | Negative numbers will be displayed as a two's complement - * | prefixed with '..7'. - * u | Identical to 'd'. - * x | Convert argument as a hexadecimal number. - * | Negative numbers will be displayed as a two's complement - * | prefixed with '..f' (representing an infinite string of - * | leading 'ff's). - * X | Equivalent to 'x', but uses uppercase letters. - * - * Field | Float Format - * ------+-------------------------------------------------------------- - * e | Convert floating point argument into exponential notation - * | with one digit before the decimal point as [-]d.dddddde[+-]dd. - * | The precision specifies the number of digits after the decimal - * | point (defaulting to six). - * E | Equivalent to 'e', but uses an uppercase E to indicate - * | the exponent. - * f | Convert floating point argument as [-]ddd.dddddd, - * | where the precision specifies the number of digits after - * | the decimal point. - * g | Convert a floating point number using exponential form - * | if the exponent is less than -4 or greater than or - * | equal to the precision, or in dd.dddd form otherwise. - * | The precision specifies the number of significant digits. - * G | Equivalent to 'g', but use an uppercase 'E' in exponent form. - * a | Convert floating point argument as [-]0xh.hhhhp[+-]dd, - * | which is consisted from optional sign, "0x", fraction part - * | as hexadecimal, "p", and exponential part as decimal. - * A | Equivalent to 'a', but use uppercase 'X' and 'P'. - * - * Field | Other Format - * ------+-------------------------------------------------------------- - * c | Argument is the numeric code for a single character or - * | a single character string itself. - * p | The valuing of argument.inspect. - * s | Argument is a string to be substituted. If the format - * | sequence contains a precision, at most that many characters - * | will be copied. - * % | A percent sign itself will be displayed. No argument taken. - * - * The flags modifies the behavior of the formats. - * The flag characters are: - * - * Flag | Applies to | Meaning - * ---------+---------------+----------------------------------------- - * space | bBdiouxX | Leave a space at the start of - * | aAeEfgG | non-negative numbers. - * | (numeric fmt) | For 'o', 'x', 'X', 'b' and 'B', use - * | | a minus sign with absolute value for - * | | negative values. - * ---------+---------------+----------------------------------------- - * (digit)$ | all | Specifies the absolute argument number - * | | for this field. Absolute and relative - * | | argument numbers cannot be mixed in a - * | | sprintf string. - * ---------+---------------+----------------------------------------- - * # | bBoxX | Use an alternative format. - * | aAeEfgG | For the conversions 'o', increase the precision - * | | until the first digit will be '0' if - * | | it is not formatted as complements. - * | | For the conversions 'x', 'X', 'b' and 'B' - * | | on non-zero, prefix the result with "0x", - * | | "0X", "0b" and "0B", respectively. - * | | For 'a', 'A', 'e', 'E', 'f', 'g', and 'G', - * | | force a decimal point to be added, - * | | even if no digits follow. - * | | For 'g' and 'G', do not remove trailing zeros. - * ---------+---------------+----------------------------------------- - * + | bBdiouxX | Add a leading plus sign to non-negative - * | aAeEfgG | numbers. - * | (numeric fmt) | For 'o', 'x', 'X', 'b' and 'B', use - * | | a minus sign with absolute value for - * | | negative values. - * ---------+---------------+----------------------------------------- - * - | all | Left-justify the result of this conversion. - * ---------+---------------+----------------------------------------- - * 0 (zero) | bBdiouxX | Pad with zeros, not spaces. - * | aAeEfgG | For 'o', 'x', 'X', 'b' and 'B', radix-1 - * | (numeric fmt) | is used for negative numbers formatted as - * | | complements. - * ---------+---------------+----------------------------------------- - * * | all | Use the next argument as the field width. - * | | If negative, left-justify the result. If the - * | | asterisk is followed by a number and a dollar - * | | sign, use the indicated argument as the width. - * - * Examples of flags: - * - * # '+' and space flag specifies the sign of non-negative numbers. - * sprintf("%d", 123) #=> "123" - * sprintf("%+d", 123) #=> "+123" - * sprintf("% d", 123) #=> " 123" - * - * # '#' flag for 'o' increases number of digits to show '0'. - * # '+' and space flag changes format of negative numbers. - * sprintf("%o", 123) #=> "173" - * sprintf("%#o", 123) #=> "0173" - * sprintf("%+o", -123) #=> "-173" - * sprintf("%o", -123) #=> "..7605" - * sprintf("%#o", -123) #=> "..7605" - * - * # '#' flag for 'x' add a prefix '0x' for non-zero numbers. - * # '+' and space flag disables complements for negative numbers. - * sprintf("%x", 123) #=> "7b" - * sprintf("%#x", 123) #=> "0x7b" - * sprintf("%+x", -123) #=> "-7b" - * sprintf("%x", -123) #=> "..f85" - * sprintf("%#x", -123) #=> "0x..f85" - * sprintf("%#x", 0) #=> "0" - * - * # '#' for 'X' uses the prefix '0X'. - * sprintf("%X", 123) #=> "7B" - * sprintf("%#X", 123) #=> "0X7B" - * - * # '#' flag for 'b' add a prefix '0b' for non-zero numbers. - * # '+' and space flag disables complements for negative numbers. - * sprintf("%b", 123) #=> "1111011" - * sprintf("%#b", 123) #=> "0b1111011" - * sprintf("%+b", -123) #=> "-1111011" - * sprintf("%b", -123) #=> "..10000101" - * sprintf("%#b", -123) #=> "0b..10000101" - * sprintf("%#b", 0) #=> "0" - * - * # '#' for 'B' uses the prefix '0B'. - * sprintf("%B", 123) #=> "1111011" - * sprintf("%#B", 123) #=> "0B1111011" - * - * # '#' for 'e' forces to show the decimal point. - * sprintf("%.0e", 1) #=> "1e+00" - * sprintf("%#.0e", 1) #=> "1.e+00" - * - * # '#' for 'f' forces to show the decimal point. - * sprintf("%.0f", 1234) #=> "1234" - * sprintf("%#.0f", 1234) #=> "1234." - * - * # '#' for 'g' forces to show the decimal point. - * # It also disables stripping lowest zeros. - * sprintf("%g", 123.4) #=> "123.4" - * sprintf("%#g", 123.4) #=> "123.400" - * sprintf("%g", 123456) #=> "123456" - * sprintf("%#g", 123456) #=> "123456." - * - * The field width is an optional integer, followed optionally by a - * period and a precision. The width specifies the minimum number of - * characters that will be written to the result for this field. - * - * Examples of width: - * - * # padding is done by spaces, width=20 - * # 0 or radix-1. <------------------> - * sprintf("%20d", 123) #=> " 123" - * sprintf("%+20d", 123) #=> " +123" - * sprintf("%020d", 123) #=> "00000000000000000123" - * sprintf("%+020d", 123) #=> "+0000000000000000123" - * sprintf("% 020d", 123) #=> " 0000000000000000123" - * sprintf("%-20d", 123) #=> "123 " - * sprintf("%-+20d", 123) #=> "+123 " - * sprintf("%- 20d", 123) #=> " 123 " - * sprintf("%020x", -123) #=> "..ffffffffffffffff85" - * - * For - * numeric fields, the precision controls the number of decimal places - * displayed. For string fields, the precision determines the maximum - * number of characters to be copied from the string. (Thus, the format - * sequence %10.10s will always contribute exactly ten - * characters to the result.) - * - * Examples of precisions: - * - * # precision for 'd', 'o', 'x' and 'b' is - * # minimum number of digits <------> - * sprintf("%20.8d", 123) #=> " 00000123" - * sprintf("%20.8o", 123) #=> " 00000173" - * sprintf("%20.8x", 123) #=> " 0000007b" - * sprintf("%20.8b", 123) #=> " 01111011" - * sprintf("%20.8d", -123) #=> " -00000123" - * sprintf("%20.8o", -123) #=> " ..777605" - * sprintf("%20.8x", -123) #=> " ..ffff85" - * sprintf("%20.8b", -11) #=> " ..110101" - * - * # "0x" and "0b" for '#x' and '#b' is not counted for - * # precision but "0" for '#o' is counted. <------> - * sprintf("%#20.8d", 123) #=> " 00000123" - * sprintf("%#20.8o", 123) #=> " 00000173" - * sprintf("%#20.8x", 123) #=> " 0x0000007b" - * sprintf("%#20.8b", 123) #=> " 0b01111011" - * sprintf("%#20.8d", -123) #=> " -00000123" - * sprintf("%#20.8o", -123) #=> " ..777605" - * sprintf("%#20.8x", -123) #=> " 0x..ffff85" - * sprintf("%#20.8b", -11) #=> " 0b..110101" - * - * # precision for 'e' is number of - * # digits after the decimal point <------> - * sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03" - * - * # precision for 'f' is number of - * # digits after the decimal point <------> - * sprintf("%20.8f", 1234.56789) #=> " 1234.56789000" - * - * # precision for 'g' is number of - * # significant digits <-------> - * sprintf("%20.8g", 1234.56789) #=> " 1234.5679" - * - * # <-------> - * sprintf("%20.8g", 123456789) #=> " 1.2345679e+08" - * - * # precision for 's' is - * # maximum number of characters <------> - * sprintf("%20.8s", "string test") #=> " string t" - * - * Examples: - * - * sprintf("%d %04x", 123, 123) #=> "123 007b" - * sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'" - * sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello" - * sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8" - * sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23" - * sprintf("%u", -123) #=> "-123" - * - * For more complex formatting, Ruby supports a reference by name. - * %s style uses format style, but %{name} style doesn't. - * - * Exapmles: - * sprintf("%d : %f", { :foo => 1, :bar => 2 }) - * #=> 1 : 2.000000 - * sprintf("%{foo}f", { :foo => 1 }) - * # => "1f" - */ - -mrb_value -mrb_f_sprintf(mrb_state *mrb, mrb_value obj) -{ - mrb_int argc; - mrb_value *argv; - - mrb_get_args(mrb, "*", &argv, &argc); - - if (argc <= 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "too few arguments"); - return mrb_nil_value(); - } - else { - return mrb_str_format(mrb, argc - 1, argv + 1, argv[0]); - } -} - -mrb_value -mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt) -{ - const char *p, *end; - char *buf; - mrb_int blen; - mrb_int bsiz; - mrb_value result; - mrb_int n; - mrb_int width; - mrb_int prec; - int flags = FNONE; - int nextarg = 1; - int posarg = 0; - mrb_value nextvalue; - mrb_value str; - mrb_value hash = mrb_undef_value(); - -#define CHECK_FOR_WIDTH(f) \ - if ((f) & FWIDTH) { \ - mrb_raise(mrb, E_ARGUMENT_ERROR, "width given twice"); \ - } \ - if ((f) & FPREC0) { \ - mrb_raise(mrb, E_ARGUMENT_ERROR, "width after precision"); \ - } -#define CHECK_FOR_FLAGS(f) \ - if ((f) & FWIDTH) { \ - mrb_raise(mrb, E_ARGUMENT_ERROR, "flag after width"); \ - } \ - if ((f) & FPREC0) { \ - mrb_raise(mrb, E_ARGUMENT_ERROR, "flag after precision"); \ - } - - ++argc; - --argv; - fmt = mrb_str_to_str(mrb, fmt); - p = RSTRING_PTR(fmt); - end = p + RSTRING_LEN(fmt); - blen = 0; - bsiz = 120; - result = mrb_str_buf_new(mrb, bsiz); - buf = RSTRING_PTR(result); - memset(buf, 0, bsiz); - - for (; p < end; p++) { - const char *t; - mrb_sym id = 0; - - for (t = p; t < end && *t != '%'; t++) ; - PUSH(p, t - p); - if (t >= end) - goto sprint_exit; /* end of fmt string */ - - p = t + 1; /* skip '%' */ - - width = prec = -1; - nextvalue = mrb_undef_value(); - -retry: - switch (*p) { - default: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - \\%%S", mrb_str_new(mrb, p, 1)); - break; - - case ' ': - CHECK_FOR_FLAGS(flags); - flags |= FSPACE; - p++; - goto retry; - - case '#': - CHECK_FOR_FLAGS(flags); - flags |= FSHARP; - p++; - goto retry; - - case '+': - CHECK_FOR_FLAGS(flags); - flags |= FPLUS; - p++; - goto retry; - - case '-': - CHECK_FOR_FLAGS(flags); - flags |= FMINUS; - p++; - goto retry; - - case '0': - CHECK_FOR_FLAGS(flags); - flags |= FZERO; - p++; - goto retry; - - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - n = 0; - GETNUM(n, width); - if (*p == '$') { - if (!mrb_undef_p(nextvalue)) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "value given twice - %S$", mrb_fixnum_value(n)); - } - nextvalue = GETPOSARG(n); - p++; - goto retry; - } - CHECK_FOR_WIDTH(flags); - width = n; - flags |= FWIDTH; - goto retry; - - case '<': - case '{': { - const char *start = p; - char term = (*p == '<') ? '>' : '}'; - mrb_value symname; - - for (; p < end && *p != term; ) - p++; - if (id) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "name%S after <%S>", - mrb_str_new(mrb, start, p - start + 1), mrb_sym2str(mrb, id)); - } - symname = mrb_str_new(mrb, start + 1, p - start - 1); - id = mrb_intern_str(mrb, symname); - nextvalue = GETNAMEARG(mrb_symbol_value(id), start, (int)(p - start + 1)); - if (mrb_undef_p(nextvalue)) { - mrb_raisef(mrb, E_KEY_ERROR, "key%S not found", mrb_str_new(mrb, start, p - start + 1)); - } - if (term == '}') goto format_s; - p++; - goto retry; - } - - case '*': - CHECK_FOR_WIDTH(flags); - flags |= FWIDTH; - GETASTER(width); - if (width < 0) { - flags |= FMINUS; - width = -width; - } - p++; - goto retry; - - case '.': - if (flags & FPREC0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "precision given twice"); - } - flags |= FPREC|FPREC0; - - prec = 0; - p++; - if (*p == '*') { - GETASTER(prec); - if (prec < 0) { /* ignore negative precision */ - flags &= ~FPREC; - } - p++; - goto retry; - } - - GETNUM(prec, precision); - goto retry; - - case '\n': - case '\0': - p--; - /* fallthrough */ - case '%': - if (flags != FNONE) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format character - %"); - } - PUSH("%", 1); - break; - - case 'c': { - mrb_value val = GETARG(); - mrb_value tmp; - char *c; - - tmp = mrb_check_string_type(mrb, val); - if (!mrb_nil_p(tmp)) { - if (mrb_fixnum(mrb_funcall(mrb, tmp, "size", 0)) != 1 ) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "%c requires a character"); - } - } - else if (mrb_fixnum_p(val)) { - tmp = mrb_funcall(mrb, val, "chr", 0); - } - else { - mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character"); - } - c = RSTRING_PTR(tmp); - n = RSTRING_LEN(tmp); - if (!(flags & FWIDTH)) { - CHECK(n); - memcpy(buf+blen, c, n); - blen += n; - } - else if ((flags & FMINUS)) { - CHECK(n); - memcpy(buf+blen, c, n); - blen += n; - FILL(' ', width-1); - } - else { - FILL(' ', width-1); - CHECK(n); - memcpy(buf+blen, c, n); - blen += n; - } - } - break; - - case 's': - case 'p': - format_s: - { - mrb_value arg = GETARG(); - mrb_int len; - mrb_int slen; - - if (*p == 'p') arg = mrb_inspect(mrb, arg); - str = mrb_obj_as_string(mrb, arg); - len = RSTRING_LEN(str); - if (RSTRING(result)->flags & MRB_STR_EMBED) { - mrb_int tmp_n = len; - RSTRING(result)->flags &= ~MRB_STR_EMBED_LEN_MASK; - RSTRING(result)->flags |= tmp_n << MRB_STR_EMBED_LEN_SHIFT; - } else { - RSTRING(result)->as.heap.len = blen; - } - if (flags&(FPREC|FWIDTH)) { - slen = RSTRING_LEN(str); - if (slen < 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid mbstring sequence"); - } - if ((flags&FPREC) && (prec < slen)) { - char *p = RSTRING_PTR(str) + prec; - slen = prec; - len = p - RSTRING_PTR(str); - } - /* need to adjust multi-byte string pos */ - if ((flags&FWIDTH) && (width > slen)) { - width -= (int)slen; - if (!(flags&FMINUS)) { - CHECK(width); - while (width--) { - buf[blen++] = ' '; - } - } - CHECK(len); - memcpy(&buf[blen], RSTRING_PTR(str), len); - blen += len; - if (flags&FMINUS) { - CHECK(width); - while (width--) { - buf[blen++] = ' '; - } - } - break; - } - } - PUSH(RSTRING_PTR(str), len); - } - break; - - case 'd': - case 'i': - case 'o': - case 'x': - case 'X': - case 'b': - case 'B': - case 'u': { - mrb_value val = GETARG(); - char fbuf[32], nbuf[64], *s; - const char *prefix = NULL; - int sign = 0, dots = 0; - char sc = 0; - mrb_int v = 0, org_v = 0; - int base; - mrb_int len; - - switch (*p) { - case 'd': - case 'i': - case 'u': - sign = 1; break; - case 'o': - case 'x': - case 'X': - case 'b': - case 'B': - if (flags&(FPLUS|FSPACE)) sign = 1; - break; - default: - break; - } - if (flags & FSHARP) { - switch (*p) { - case 'o': prefix = "0"; break; - case 'x': prefix = "0x"; break; - case 'X': prefix = "0X"; break; - case 'b': prefix = "0b"; break; - case 'B': prefix = "0B"; break; - default: break; - } - } - - bin_retry: - switch (mrb_type(val)) { - case MRB_TT_FLOAT: - if (FIXABLE(mrb_float(val))) { - val = mrb_fixnum_value((mrb_int)mrb_float(val)); - goto bin_retry; - } - val = mrb_flo_to_fixnum(mrb, val); - if (mrb_fixnum_p(val)) goto bin_retry; - break; - case MRB_TT_STRING: - val = mrb_str_to_inum(mrb, val, 0, TRUE); - goto bin_retry; - case MRB_TT_FIXNUM: - v = mrb_fixnum(val); - break; - default: - val = mrb_Integer(mrb, val); - goto bin_retry; - } - - switch (*p) { - case 'o': - base = 8; break; - case 'x': - case 'X': - base = 16; break; - case 'b': - case 'B': - base = 2; break; - case 'u': - case 'd': - case 'i': - default: - base = 10; break; - } - - if (base == 2) { - org_v = v; - if (v < 0 && !sign) { - val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base); - dots = 1; - } - else { - val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base); - } - v = mrb_fixnum(mrb_str_to_inum(mrb, val, 10, FALSE)); - } - if (sign) { - char c = *p; - if (c == 'i') c = 'd'; /* %d and %i are identical */ - if (base == 2) c = 'd'; - if (v < 0) { - v = -v; - sc = '-'; - width--; - } - else if (flags & FPLUS) { - sc = '+'; - width--; - } - else if (flags & FSPACE) { - sc = ' '; - width--; - } - snprintf(fbuf, sizeof(fbuf), "%%l%c", c); - snprintf(nbuf, sizeof(nbuf), fbuf, v); - s = nbuf; - } - else { - char c = *p; - if (c == 'X') c = 'x'; - if (base == 2) c = 'd'; - s = nbuf; - if (v < 0) { - dots = 1; - } - snprintf(fbuf, sizeof(fbuf), "%%l%c", c); - snprintf(++s, sizeof(nbuf) - 1, fbuf, v); - if (v < 0) { - char d; - - s = remove_sign_bits(s, base); - switch (base) { - case 16: d = 'f'; break; - case 8: d = '7'; break; - case 2: d = '1'; break; - default: d = 0; break; - } - - if (d && *s != d) { - *--s = d; - } - } - } - { - size_t size; - size = strlen(s); - /* PARANOID: assert(size <= MRB_INT_MAX) */ - len = (mrb_int)size; - } - - if (dots) { - prec -= 2; - width -= 2; - } - - if (*p == 'X') { - char *pp = s; - int c; - while ((c = (int)(unsigned char)*pp) != 0) { - *pp = toupper(c); - pp++; - } - } - - if (prefix && !prefix[1]) { /* octal */ - if (dots) { - prefix = NULL; - } - else if (len == 1 && *s == '0') { - len = 0; - if (flags & FPREC) prec--; - } - else if ((flags & FPREC) && (prec > len)) { - prefix = NULL; - } - } - else if (len == 1 && *s == '0') { - prefix = NULL; - } - - if (prefix) { - size_t size; - size = strlen(prefix); - /* PARANOID: assert(size <= MRB_INT_MAX). - * this check is absolutely paranoid. */ - width -= (mrb_int)size; - } - - if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) { - prec = width; - width = 0; - } - else { - if (prec < len) { - if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0; - prec = len; - } - width -= prec; - } - - if (!(flags&FMINUS)) { - CHECK(width); - while (width-- > 0) { - buf[blen++] = ' '; - } - } - - if (sc) PUSH(&sc, 1); - - if (prefix) { - int plen = (int)strlen(prefix); - PUSH(prefix, plen); - } - CHECK(prec - len); - if (dots) PUSH("..", 2); - - if (v < 0 || (base == 2 && org_v < 0)) { - char c = sign_bits(base, p); - while (len < prec--) { - buf[blen++] = c; - } - } - else if ((flags & (FMINUS|FPREC)) != FMINUS) { - char c = '0'; - while (len < prec--) { - buf[blen++] = c; - } - } - - PUSH(s, len); - CHECK(width); - while (width-- > 0) { - buf[blen++] = ' '; - } - } - break; - - case 'f': - case 'g': - case 'G': - case 'e': - case 'E': - case 'a': - case 'A': { - mrb_value val = GETARG(); - double fval; - int i, need = 6; - char fbuf[32]; - - fval = mrb_float(mrb_Float(mrb, val)); - if (!isfinite(fval)) { - const char *expr; - const int elen = 3; - - if (isnan(fval)) { - expr = "NaN"; - } - else { - expr = "Inf"; - } - need = elen; - if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS)) - need++; - if ((flags & FWIDTH) && need < width) - need = width; - - CHECK(need + 1); - snprintf(&buf[blen], need + 1, "%*s", need, ""); - if (flags & FMINUS) { - if (!isnan(fval) && fval < 0.0) - buf[blen++] = '-'; - else if (flags & FPLUS) - buf[blen++] = '+'; - else if (flags & FSPACE) - blen++; - memcpy(&buf[blen], expr, elen); - } - else { - if (!isnan(fval) && fval < 0.0) - buf[blen + need - elen - 1] = '-'; - else if (flags & FPLUS) - buf[blen + need - elen - 1] = '+'; - else if ((flags & FSPACE) && need > width) - blen++; - memcpy(&buf[blen + need - elen], expr, elen); - } - blen += strlen(&buf[blen]); - break; - } - - fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec); - need = 0; - if (*p != 'e' && *p != 'E') { - i = INT_MIN; - frexp(fval, &i); - if (i > 0) - need = BIT_DIGITS(i); - } - need += (flags&FPREC) ? prec : 6; - if ((flags&FWIDTH) && need < width) - need = width; - need += 20; - - CHECK(need); - n = snprintf(&buf[blen], need, fbuf, fval); - blen += n; - } - break; - } - flags = FNONE; - } - - sprint_exit: -#if 0 - /* XXX - We cannot validate the number of arguments if (digit)$ style used. - */ - if (posarg >= 0 && nextarg < argc) { - const char *mesg = "too many arguments for format string"; - if (mrb_test(ruby_debug)) mrb_raise(mrb, E_ARGUMENT_ERROR, mesg); - if (mrb_test(ruby_verbose)) mrb_warn(mrb, "%S", mrb_str_new_cstr(mrb, mesg)); - } -#endif - mrb_str_resize(mrb, result, blen); - - return result; -} - -static void -fmt_setup(char *buf, size_t size, int c, int flags, mrb_int width, mrb_int prec) -{ - char *end = buf + size; - int n; - - *buf++ = '%'; - if (flags & FSHARP) *buf++ = '#'; - if (flags & FPLUS) *buf++ = '+'; - if (flags & FMINUS) *buf++ = '-'; - if (flags & FZERO) *buf++ = '0'; - if (flags & FSPACE) *buf++ = ' '; - - if (flags & FWIDTH) { - n = snprintf(buf, end - buf, "%d", (int)width); - buf += n; - } - - if (flags & FPREC) { - n = snprintf(buf, end - buf, ".%d", (int)prec); - buf += n; - } - - *buf++ = c; - *buf = '\0'; -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-sprintf/test/sprintf.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-sprintf/test/sprintf.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-sprintf/test/sprintf.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-sprintf/test/sprintf.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -#assert('Kernel.sprintf') do -#end - -assert('String#%') do - assert_equal "one=1", "one=%d" % 1 - assert_equal "1 one 1.0", "%d %s %3.1f" % [ 1, "one", 1.01 ] - assert_equal "123 < 456", "%{num} < %s" % { num: 123, str: "456" } -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-string-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-string-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-string-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-string-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-string-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'String class extension' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-string-ext/mrblib/string.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-string-ext/mrblib/string.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-string-ext/mrblib/string.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-string-ext/mrblib/string.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,339 +0,0 @@ -class String - - ## - # call-seq: - # string.clear -> string - # - # Makes string empty. - # - # a = "abcde" - # a.clear #=> "" - # - def clear - self.replace("") - end - - ## - # call-seq: - # str.lstrip -> new_str - # - # Returns a copy of str with leading whitespace removed. See also - # String#rstrip and String#strip. - # - # " hello ".lstrip #=> "hello " - # "hello".lstrip #=> "hello" - # - def lstrip - a = 0 - z = self.size - 1 - a += 1 while " \f\n\r\t\v".include?(self[a]) and a <= z - (z >= 0) ? self[a..z] : "" - end - - ## - # call-seq: - # str.rstrip -> new_str - # - # Returns a copy of str with trailing whitespace removed. See also - # String#lstrip and String#strip. - # - # " hello ".rstrip #=> " hello" - # "hello".rstrip #=> "hello" - # - def rstrip - a = 0 - z = self.size - 1 - z -= 1 while " \f\n\r\t\v\0".include?(self[z]) and a <= z - (z >= 0) ? self[a..z] : "" - end - - ## - # call-seq: - # str.strip -> new_str - # - # Returns a copy of str with leading and trailing whitespace removed. - # - # " hello ".strip #=> "hello" - # "\tgoodbye\r\n".strip #=> "goodbye" - # - def strip - a = 0 - z = self.size - 1 - a += 1 while " \f\n\r\t\v".include?(self[a]) and a <= z - z -= 1 while " \f\n\r\t\v\0".include?(self[z]) and a <= z - (z >= 0) ? self[a..z] : "" - end - - ## - # call-seq: - # str.lstrip! -> self or nil - # - # Removes leading whitespace from str, returning nil if no - # change was made. See also String#rstrip! and - # String#strip!. - # - # " hello ".lstrip #=> "hello " - # "hello".lstrip! #=> nil - # - def lstrip! - s = self.lstrip - (s == self) ? nil : self.replace(s) - end - - ## - # call-seq: - # str.rstrip! -> self or nil - # - # Removes trailing whitespace from str, returning nil if - # no change was made. See also String#lstrip! and - # String#strip!. - # - # " hello ".rstrip #=> " hello" - # "hello".rstrip! #=> nil - # - def rstrip! - s = self.rstrip - (s == self) ? nil : self.replace(s) - end - - ## - # call-seq: - # str.strip! -> str or nil - # - # Removes leading and trailing whitespace from str. Returns - # nil if str was not altered. - # - def strip! - s = self.strip - (s == self) ? nil : self.replace(s) - end - - ## - # call-seq: - # str.casecmp(other_str) -> -1, 0, +1 or nil - # - # Case-insensitive version of String#<=>. - # - # "abcdef".casecmp("abcde") #=> 1 - # "aBcDeF".casecmp("abcdef") #=> 0 - # "abcdef".casecmp("abcdefg") #=> -1 - # "abcdef".casecmp("ABCDEF") #=> 0 - # - def casecmp(str) - self.downcase <=> str.to_str.downcase - rescue NoMethodError - raise TypeError, "no implicit conversion of #{str.class} into String" - end - - def partition(sep) - raise TypeError, "type mismatch: #{sep.class} given" unless sep.is_a? String - n = index(sep) - unless n.nil? - m = n + sep.size - [ slice(0, n), sep, slice(m, size - m) ] - else - [ self, "", "" ] - end - end - - def rpartition(sep) - raise TypeError, "type mismatch: #{sep.class} given" unless sep.is_a? String - n = rindex(sep) - unless n.nil? - m = n + sep.size - [ slice(0, n), sep, slice(m, size - m) ] - else - [ "", "", self ] - end - end - - ## - # call-seq: - # str.slice!(fixnum) -> new_str or nil - # str.slice!(fixnum, fixnum) -> new_str or nil - # str.slice!(range) -> new_str or nil - # str.slice!(other_str) -> new_str or nil - # - # Deletes the specified portion from str, and returns the portion - # deleted. - # - # string = "this is a string" - # string.slice!(2) #=> "i" - # string.slice!(3..6) #=> " is " - # string.slice!("r") #=> "r" - # string #=> "thsa sting" - # - def slice!(arg1, arg2=nil) - raise "wrong number of arguments (for 1..2)" if arg1.nil? && arg2.nil? - - if !arg1.nil? && !arg2.nil? - idx = arg1 - idx += self.size if arg1 < 0 - if idx >= 0 && idx <= self.size && arg2 > 0 - str = self[idx, arg2] - else - return nil - end - else - validated = false - if arg1.kind_of?(Range) - beg = arg1.begin - ed = arg1.end - beg += self.size if beg < 0 - ed += self.size if ed < 0 - ed -= 1 if arg1.exclude_end? - validated = true - elsif arg1.kind_of?(String) - validated = true - else - idx = arg1 - idx += self.size if arg1 < 0 - validated = true if idx >=0 && arg1 < self.size - end - if validated - str = self[arg1] - else - return nil - end - end - unless str.nil? || str == "" - if !arg1.nil? && !arg2.nil? - idx = arg1 >= 0 ? arg1 : self.size+arg1 - str2 = self[0...idx] + self[idx+arg2..-1].to_s - else - if arg1.kind_of?(Range) - idx = beg >= 0 ? beg : self.size+beg - idx2 = ed>= 0 ? ed : self.size+ed - str2 = self[0...idx] + self[idx2+1..-1].to_s - elsif arg1.kind_of?(String) - idx = self.index(arg1) - str2 = self[0...idx] + self[idx+arg1.size..-1] unless idx.nil? - else - idx = arg1 >= 0 ? arg1 : self.size+arg1 - str2 = self[0...idx] + self[idx+1..-1].to_s - end - end - self.replace(str2) unless str2.nil? - end - str - end - - ## - # call-seq: - # str.insert(index, other_str) -> str - # - # Inserts other_str before the character at the given - # index, modifying str. Negative indices count from the - # end of the string, and insert after the given character. - # The intent is insert aString so that it starts at the given - # index. - # - # "abcd".insert(0, 'X') #=> "Xabcd" - # "abcd".insert(3, 'X') #=> "abcXd" - # "abcd".insert(4, 'X') #=> "abcdX" - # "abcd".insert(-3, 'X') #=> "abXcd" - # "abcd".insert(-1, 'X') #=> "abcdX" - # - def insert(idx, str) - pos = idx.to_i - pos += self.size + 1 if pos < 0 - - raise IndexError, "index #{idx.to_i} out of string" if pos < 0 || pos > self.size - - return self + str if pos == -1 - return str + self if pos == 0 - return self[0..pos - 1] + str + self[pos..-1] - end - - ## - # call-seq: - # str.ljust(integer, padstr=' ') -> new_str - # - # If integer is greater than the length of str, returns a new - # String of length integer with str left justified - # and padded with padstr; otherwise, returns str. - # - # "hello".ljust(4) #=> "hello" - # "hello".ljust(20) #=> "hello " - # "hello".ljust(20, '1234') #=> "hello123412341234123" - def ljust(idx, padstr = ' ') - if idx <= self.size - return self - end - newstr = self.dup - newstr << padstr - while newstr.size <= idx - newstr << padstr - end - return newstr.slice(0,idx) - end - - # str.upto(other_str, exclusive=false) {|s| block } -> str - # str.upto(other_str, exclusive=false) -> an_enumerator - # - # Iterates through successive values, starting at str and - # ending at other_str inclusive, passing each value in turn to - # the block. The String#succ method is used to generate - # each value. If optional second argument exclusive is omitted or is false, - # the last value will be included; otherwise it will be excluded. - # - # If no block is given, an enumerator is returned instead. - # - # "a8".upto("b6") {|s| print s, ' ' } - # for s in "a8".."b6" - # print s, ' ' - # end - # - # produces: - # - # a8 a9 b0 b1 b2 b3 b4 b5 b6 - # a8 a9 b0 b1 b2 b3 b4 b5 b6 - # - # If str and other_str contains only ascii numeric characters, - # both are recognized as decimal numbers. In addition, the width of - # string (e.g. leading zeros) is handled appropriately. - # - # "9".upto("11").to_a #=> ["9", "10", "11"] - # "25".upto("5").to_a #=> [] - # "07".upto("11").to_a #=> ["07", "08", "09", "10", "11"] - # - def upto(other_str, excl=false, &block) - return to_enum :upto, other_str, excl unless block - - str = self - n = self.<=>other_str - return self if n > 0 || (self == other_str && excl) - while true - block.call(str) - return self if !excl && str == other_str - str = str.succ - return self if excl && str == other_str - end - end - - def chars(&block) - if block_given? - self.split('').map do |i| - block.call(i) - end - self - else - self.split('') - end - end - alias each_char chars - - def codepoints(&block) - len = self.size - - if block_given? - self.split('').map do|x| - block.call(x.ord) - end - self - else - self.split('').map{|x| x.ord} - end - end - alias each_codepoint codepoints -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-string-ext/src/string.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-string-ext/src/string.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-string-ext/src/string.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-string-ext/src/string.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,568 +0,0 @@ -#include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/string.h" -#include "mruby/range.h" - -static mrb_value -mrb_str_getbyte(mrb_state *mrb, mrb_value str) -{ - mrb_int pos; - mrb_get_args(mrb, "i", &pos); - - if (pos < 0) - pos += RSTRING_LEN(str); - if (pos < 0 || RSTRING_LEN(str) <= pos) - return mrb_nil_value(); - - return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[pos]); -} - -static mrb_value -mrb_str_setbyte(mrb_state *mrb, mrb_value str) -{ - mrb_int pos, byte; - long len = RSTRING_LEN(str); - - mrb_get_args(mrb, "ii", &pos, &byte); - - if (pos < -len || len <= pos) - mrb_raisef(mrb, E_INDEX_ERROR, "index %S is out of array", mrb_fixnum_value(pos)); - if (pos < 0) - pos += len; - - mrb_str_modify(mrb, mrb_str_ptr(str)); - byte &= 0xff; - RSTRING_PTR(str)[pos] = byte; - return mrb_fixnum_value((unsigned char)byte); -} - -static mrb_value -mrb_str_byteslice(mrb_state *mrb, mrb_value str) -{ - mrb_value a1; - mrb_int len; - int argc; - - argc = mrb_get_args(mrb, "o|i", &a1, &len); - if (argc == 2) { - return mrb_str_substr(mrb, str, mrb_fixnum(a1), len); - } - switch (mrb_type(a1)) { - case MRB_TT_RANGE: - { - mrb_int beg; - - len = RSTRING_LEN(str); - if (mrb_range_beg_len(mrb, a1, &beg, &len, len)) { - return mrb_str_substr(mrb, str, beg, len); - } - return mrb_nil_value(); - } - case MRB_TT_FLOAT: - a1 = mrb_fixnum_value((mrb_int)mrb_float(a1)); - /* fall through */ - case MRB_TT_FIXNUM: - return mrb_str_substr(mrb, str, mrb_fixnum(a1), 1); - default: - mrb_raise(mrb, E_TYPE_ERROR, "wrong type of argument"); - } - /* not reached */ - return mrb_nil_value(); -} - -/* - * call-seq: - * str.swapcase! -> str or nil - * - * Equivalent to String#swapcase, but modifies the receiver in - * place, returning str, or nil if no changes were made. - * Note: case conversion is effective only in ASCII region. - */ -static mrb_value -mrb_str_swapcase_bang(mrb_state *mrb, mrb_value str) -{ - char *p, *pend; - int modify = 0; - struct RString *s = mrb_str_ptr(str); - - mrb_str_modify(mrb, s); - p = RSTRING_PTR(str); - pend = p + RSTRING_LEN(str); - while (p < pend) { - if (ISUPPER(*p)) { - *p = TOLOWER(*p); - modify = 1; - } - else if (ISLOWER(*p)) { - *p = TOUPPER(*p); - modify = 1; - } - p++; - } - - if (modify) return str; - return mrb_nil_value(); -} - -/* - * call-seq: - * str.swapcase -> new_str - * - * Returns a copy of str with uppercase alphabetic characters converted - * to lowercase and lowercase characters converted to uppercase. - * Note: case conversion is effective only in ASCII region. - * - * "Hello".swapcase #=> "hELLO" - * "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11" - */ -static mrb_value -mrb_str_swapcase(mrb_state *mrb, mrb_value self) -{ - mrb_value str; - - str = mrb_str_dup(mrb, self); - mrb_str_swapcase_bang(mrb, str); - return str; -} - -/* - * call-seq: - * str << integer -> str - * str.concat(integer) -> str - * str << obj -> str - * str.concat(obj) -> str - * - * Append---Concatenates the given object to str. If the object is a - * Integer, it is considered as a codepoint, and is converted - * to a character before concatenation. - * - * a = "hello " - * a << "world" #=> "hello world" - * a.concat(33) #=> "hello world!" - */ -static mrb_value -mrb_str_concat2(mrb_state *mrb, mrb_value self) -{ - mrb_value str; - mrb_get_args(mrb, "S", &str); - mrb_str_concat(mrb, self, str); - return self; -} - -/* - * call-seq: - * str.start_with?([prefixes]+) -> true or false - * - * Returns true if +str+ starts with one of the +prefixes+ given. - * - * "hello".start_with?("hell") #=> true - * - * # returns true if one of the prefixes matches. - * "hello".start_with?("heaven", "hell") #=> true - * "hello".start_with?("heaven", "paradise") #=> false - * "h".start_with?("heaven", "hell") #=> false - */ -static mrb_value -mrb_str_start_with(mrb_state *mrb, mrb_value self) -{ - mrb_value *argv, sub; - mrb_int argc, i; - mrb_get_args(mrb, "*", &argv, &argc); - - for (i = 0; i < argc; i++) { - size_t len_l, len_r; - int ai = mrb_gc_arena_save(mrb); - sub = mrb_string_type(mrb, argv[i]); - mrb_gc_arena_restore(mrb, ai); - len_l = RSTRING_LEN(self); - len_r = RSTRING_LEN(sub); - if (len_l >= len_r) { - if (memcmp(RSTRING_PTR(self), RSTRING_PTR(sub), len_r) == 0) { - return mrb_true_value(); - } - } - } - return mrb_false_value(); -} - -/* - * call-seq: - * str.end_with?([suffixes]+) -> true or false - * - * Returns true if +str+ ends with one of the +suffixes+ given. - */ -static mrb_value -mrb_str_end_with(mrb_state *mrb, mrb_value self) -{ - mrb_value *argv, sub; - mrb_int argc, i; - mrb_get_args(mrb, "*", &argv, &argc); - - for (i = 0; i < argc; i++) { - size_t len_l, len_r; - int ai = mrb_gc_arena_save(mrb); - sub = mrb_string_type(mrb, argv[i]); - mrb_gc_arena_restore(mrb, ai); - len_l = RSTRING_LEN(self); - len_r = RSTRING_LEN(sub); - if (len_l >= len_r) { - if (memcmp(RSTRING_PTR(self) + (len_l - len_r), - RSTRING_PTR(sub), - len_r) == 0) { - return mrb_true_value(); - } - } - } - return mrb_false_value(); -} - -static mrb_value -mrb_str_hex(mrb_state *mrb, mrb_value self) -{ - return mrb_str_to_inum(mrb, self, 16, FALSE); -} - -static mrb_value -mrb_str_oct(mrb_state *mrb, mrb_value self) -{ - return mrb_str_to_inum(mrb, self, 8, FALSE); -} - -/* - * call-seq: - * string.chr -> string - * - * Returns a one-character string at the beginning of the string. - * - * a = "abcde" - * a.chr #=> "a" - */ -static mrb_value -mrb_str_chr(mrb_state *mrb, mrb_value self) -{ - return mrb_str_substr(mrb, self, 0, 1); -} - -static mrb_value -mrb_fixnum_chr(mrb_state *mrb, mrb_value num) -{ - mrb_int cp = mrb_fixnum(num); -#ifdef MRB_UTF8_STRING - char utf8[4]; - mrb_int len; - - if (cp < 0 || 0x10FFFF < cp) { - mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num); - } - if (cp < 0x80) { - utf8[0] = (char)cp; - len = 1; - } - else if (cp < 0x800) { - utf8[0] = (char)(0xC0 | (cp >> 6)); - utf8[1] = (char)(0x80 | (cp & 0x3F)); - len = 2; - } - else if (cp < 0x10000) { - utf8[0] = (char)(0xE0 | (cp >> 12)); - utf8[1] = (char)(0x80 | ((cp >> 6) & 0x3F)); - utf8[2] = (char)(0x80 | ( cp & 0x3F)); - len = 3; - } - else { - utf8[0] = (char)(0xF0 | (cp >> 18)); - utf8[1] = (char)(0x80 | ((cp >> 12) & 0x3F)); - utf8[2] = (char)(0x80 | ((cp >> 6) & 0x3F)); - utf8[3] = (char)(0x80 | ( cp & 0x3F)); - len = 4; - } - return mrb_str_new(mrb, utf8, len); -#else - char c; - - if (cp < 0 || 0xff < cp) { - mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num); - } - c = (char)cp; - return mrb_str_new(mrb, &c, 1); -#endif -} - -/* - * call-seq: - * string.lines -> array of string - * - * Returns strings per line; - * - * a = "abc\ndef" - * a.lines #=> ["abc\n", "def"] - */ -static mrb_value -mrb_str_lines(mrb_state *mrb, mrb_value self) -{ - mrb_value result; - mrb_value blk; - int ai; - mrb_int len; - mrb_value arg; - char *p = RSTRING_PTR(self), *t; - char *e = p + RSTRING_LEN(self); - - mrb_get_args(mrb, "&", &blk); - - result = mrb_ary_new(mrb); - - if (!mrb_nil_p(blk)) { - while (p < e) { - t = p; - while (p < e && *p != '\n') p++; - if (*p == '\n') p++; - len = (mrb_int) (p - t); - arg = mrb_str_new(mrb, t, len); - mrb_yield_argv(mrb, blk, 1, &arg); - } - return self; - } - while (p < e) { - ai = mrb_gc_arena_save(mrb); - t = p; - while (p < e && *p != '\n') p++; - if (*p == '\n') p++; - len = (mrb_int) (p - t); - mrb_ary_push(mrb, result, mrb_str_new(mrb, t, len)); - mrb_gc_arena_restore(mrb, ai); - } - return result; -} - -/* - * call-seq: - * string.succ -> string - * - * Returns next sequence of the string; - * - * a = "abc" - * a.succ #=> "abd" - */ -static mrb_value -mrb_str_succ_bang(mrb_state *mrb, mrb_value self) -{ - mrb_value result; - unsigned char *p, *e, *b, *t; - const char *prepend; - struct RString *s = mrb_str_ptr(self); - size_t l; - - if (RSTRING_LEN(self) == 0) - return self; - - mrb_str_modify(mrb, s); - l = RSTRING_LEN(self); - b = p = (unsigned char*) RSTRING_PTR(self); - t = e = p + l; - *(e--) = 0; - - // find trailing ascii/number - while (e >= b) { - if (ISALNUM(*e)) - break; - e--; - } - if (e < b) { - e = p + l - 1; - result = mrb_str_new_lit(mrb, ""); - } else { - // find leading letter of the ascii/number - b = e; - while (b > p) { - if (!ISALNUM(*b) || (ISALNUM(*b) && *b != '9' && *b != 'z' && *b != 'Z')) - break; - b--; - } - if (!ISALNUM(*b)) - b++; - result = mrb_str_new(mrb, (char*) p, b - p); - } - - while (e >= b) { - if (!ISALNUM(*e)) { - if (*e == 0xff) { - mrb_str_cat_lit(mrb, result, "\x01"); - (*e) = 0; - } else - (*e)++; - break; - } - prepend = NULL; - if (*e == '9') { - if (e == b) prepend = "1"; - *e = '0'; - } else if (*e == 'z') { - if (e == b) prepend = "a"; - *e = 'a'; - } else if (*e == 'Z') { - if (e == b) prepend = "A"; - *e = 'A'; - } else { - (*e)++; - break; - } - if (prepend) mrb_str_cat_cstr(mrb, result, prepend); - e--; - } - result = mrb_str_cat(mrb, result, (char*) b, t - b); - l = RSTRING_LEN(result); - mrb_str_resize(mrb, self, l); - memcpy(RSTRING_PTR(self), RSTRING_PTR(result), l); - return self; -} - -static mrb_value -mrb_str_succ(mrb_state *mrb, mrb_value self) -{ - mrb_value str; - - str = mrb_str_dup(mrb, self); - mrb_str_succ_bang(mrb, str); - return str; -} - -/* - * call-seq: - * str.prepend(other_str) -> str - * - * Prepend---Prepend the given string to str. - * - * a = "world" - * a.prepend("hello ") #=> "hello world" - * a #=> "hello world" - */ -static mrb_value -mrb_str_prepend(mrb_state *mrb, mrb_value self) -{ - struct RString *s1 = mrb_str_ptr(self), *s2, *temp_s; - mrb_int len; - mrb_value other, temp_str; - - mrb_get_args(mrb, "S", &other); - - mrb_str_modify(mrb, s1); - if (!mrb_string_p(other)) { - other = mrb_str_to_str(mrb, other); - } - s2 = mrb_str_ptr(other); - len = RSTR_LEN(s1) + RSTR_LEN(s2); - temp_str = mrb_str_new(mrb, NULL, RSTR_LEN(s1)); - temp_s = mrb_str_ptr(temp_str); - memcpy(RSTR_PTR(temp_s), RSTR_PTR(s1), RSTR_LEN(s1)); - if (RSTRING_CAPA(self) < len) { - mrb_str_resize(mrb, self, len); - } - memcpy(RSTR_PTR(s1), RSTR_PTR(s2), RSTR_LEN(s2)); - memcpy(RSTR_PTR(s1) + RSTR_LEN(s2), RSTR_PTR(temp_s), RSTR_LEN(temp_s)); - RSTR_SET_LEN(s1, len); - RSTR_PTR(s1)[len] = '\0'; - return self; -} - -#ifdef MRB_UTF8_STRING -static const char utf8len_codepage_zero[256] = -{ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, -}; - -static mrb_int -utf8code(unsigned char* p) -{ - mrb_int len; - - if (p[0] < 0x80) - return p[0]; - - len = utf8len_codepage_zero[p[0]]; - if (len > 1 && (p[1] & 0xc0) == 0x80) { - if (len == 2) - return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f); - if ((p[2] & 0xc0) == 0x80) { - if (len == 3) - return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) - + (p[2] & 0x3f); - if ((p[3] & 0xc0) == 0x80) { - if (len == 4) - return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12) - + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f); - if ((p[4] & 0xc0) == 0x80) { - if (len == 5) - return ((p[0] & 0x03) << 24) + ((p[1] & 0x3f) << 18) - + ((p[2] & 0x3f) << 12) + ((p[3] & 0x3f) << 6) - + (p[4] & 0x3f); - if ((p[5] & 0xc0) == 0x80 && len == 6) - return ((p[0] & 0x01) << 30) + ((p[1] & 0x3f) << 24) - + ((p[2] & 0x3f) << 18) + ((p[3] & 0x3f) << 12) - + ((p[4] & 0x3f) << 6) + (p[5] & 0x3f); - } - } - } - } - return p[0]; -} - -static mrb_value -mrb_str_ord(mrb_state* mrb, mrb_value str) -{ - if (RSTRING_LEN(str) == 0) - mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string"); - return mrb_fixnum_value(utf8code((unsigned char*) RSTRING_PTR(str))); -} -#else -static mrb_value -mrb_str_ord(mrb_state* mrb, mrb_value str) -{ - if (RSTRING_LEN(str) == 0) - mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string"); - return mrb_fixnum_value(RSTRING_PTR(str)[0]); -} -#endif - -void -mrb_mruby_string_ext_gem_init(mrb_state* mrb) -{ - struct RClass * s = mrb->string_class; - - mrb_define_method(mrb, s, "dump", mrb_str_dump, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "getbyte", mrb_str_getbyte, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, s, "setbyte", mrb_str_setbyte, MRB_ARGS_REQ(2)); - mrb_define_method(mrb, s, "byteslice", mrb_str_byteslice, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); - mrb_define_method(mrb, s, "swapcase!", mrb_str_swapcase_bang, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "swapcase", mrb_str_swapcase, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "concat", mrb_str_concat2, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, s, "<<", mrb_str_concat2, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, s, "start_with?", mrb_str_start_with, MRB_ARGS_REST()); - mrb_define_method(mrb, s, "end_with?", mrb_str_end_with, MRB_ARGS_REST()); - mrb_define_method(mrb, s, "hex", mrb_str_hex, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "oct", mrb_str_oct, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "chr", mrb_str_chr, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "lines", mrb_str_lines, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "succ", mrb_str_succ, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "prepend", mrb_str_prepend, MRB_ARGS_REQ(1)); - mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ")); - mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!")); - mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE()); - - mrb_define_method(mrb, mrb->fixnum_class, "chr", mrb_fixnum_chr, MRB_ARGS_NONE()); -} - -void -mrb_mruby_string_ext_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-string-ext/test/string.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-string-ext/test/string.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-string-ext/test/string.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-string-ext/test/string.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,570 +0,0 @@ -## -# String(Ext) Test - -UTF8STRING = ("\343\201\202".size == 1) - -assert('String#getbyte') do - str1 = "hello" - bytes1 = [104, 101, 108, 108, 111] - assert_equal bytes1[0], str1.getbyte(0) - assert_equal bytes1[-1], str1.getbyte(-1) - assert_equal bytes1[6], str1.getbyte(6) - - str2 = "\xFF" - bytes2 = [0xFF] - assert_equal bytes2[0], str2.getbyte(0) -end - -assert('String#setbyte') do - str1 = "hello" - h = "H".getbyte(0) - str1.setbyte(0, h) - assert_equal(h, str1.getbyte(0)) - assert_equal("Hello", str1) -end - -assert('String#byteslice') do - str1 = "hello" - assert_equal("e", str1.byteslice(1)) - assert_equal("o", str1.byteslice(-1)) - assert_equal("ell", str1.byteslice(1..3)) - assert_equal("el", str1.byteslice(1...3)) -end - -assert('String#dump') do - ("\1" * 100).dump # should not raise an exception - regress #1210 - "\0".inspect == "\"\\000\"" and - "foo".dump == "\"foo\"" -end - -assert('String#strip') do - s = " abc " - "".strip == "" and " \t\r\n\f\v".strip == "" and - "\0a\0".strip == "\0a" and - "abc".strip == "abc" and - " abc".strip == "abc" and - "abc ".strip == "abc" and - " abc ".strip == "abc" and - s == " abc " -end - -assert('String#lstrip') do - s = " abc " - s.lstrip - "".lstrip == "" and " \t\r\n\f\v".lstrip == "" and - "\0a\0".lstrip == "\0a\0" and - "abc".lstrip == "abc" and - " abc".lstrip == "abc" and - "abc ".lstrip == "abc " and - " abc ".lstrip == "abc " and - s == " abc " -end - -assert('String#rstrip') do - s = " abc " - s.rstrip - "".rstrip == "" and " \t\r\n\f\v".rstrip == "" and - "\0a\0".rstrip == "\0a" and - "abc".rstrip == "abc" and - " abc".rstrip == " abc" and - "abc ".rstrip == "abc" and - " abc ".rstrip == " abc" and - s == " abc " -end - -assert('String#strip!') do - s = " abc " - t = "abc" - s.strip! == "abc" and s == "abc" and t.strip! == nil -end - -assert('String#lstrip!') do - s = " abc " - t = "abc " - s.lstrip! == "abc " and s == "abc " and t.lstrip! == nil -end - -assert('String#rstrip!') do - s = " abc " - t = " abc" - s.rstrip! == " abc" and s == " abc" and t.rstrip! == nil -end - -assert('String#swapcase') do - assert_equal "hELLO", "Hello".swapcase - assert_equal "CyBeR_pUnK11", "cYbEr_PuNk11".swapcase -end - -assert('String#swapcase!') do - s = "Hello" - t = s.clone - t.swapcase! - assert_equal s.swapcase, t -end - -assert('String#concat') do - s = "Hello " - s.concat "World!" - t = "Hello " - t << "World!" - assert_equal "Hello World!", t - assert_equal "Hello World!", s -end - -assert('String#casecmp') do - assert_equal 1, "abcdef".casecmp("abcde") - assert_equal 0, "aBcDeF".casecmp("abcdef") - assert_equal(-1, "abcdef".casecmp("abcdefg")) - assert_equal 0, "abcdef".casecmp("ABCDEF") - o = Object.new - def o.to_str - "ABCDEF" - end - assert_equal 0, "abcdef".casecmp(o) -end - -assert('String#start_with?') do - assert_true "hello".start_with?("heaven", "hell") - assert_true !"hello".start_with?("heaven", "paradise") - assert_true !"h".start_with?("heaven", "hell") - assert_raise TypeError do "hello".start_with?(true) end -end - -assert('String#end_with?') do - assert_true "string".end_with?("ing", "mng") - assert_true !"string".end_with?("str", "tri") - assert_true !"ng".end_with?("ing", "mng") - assert_raise TypeError do "hello".end_with?(true) end -end - -assert('String#partition') do - assert_equal ["a", "x", "axa"], "axaxa".partition("x") - assert_equal ["aaaaa", "", ""], "aaaaa".partition("x") - assert_equal ["", "", "aaaaa"], "aaaaa".partition("") - assert_equal ["", "a", "aaaa"], "aaaaa".partition("a") - assert_equal ["aaaa", "b", ""], "aaaab".partition("b") - assert_equal ["", "b", "aaaa"], "baaaa".partition("b") - assert_equal ["", "", ""], "".partition("a") -end - -assert('String#rpartition') do - assert_equal ["axa", "x", "a"], "axaxa".rpartition("x") - assert_equal ["", "", "aaaaa"], "aaaaa".rpartition("x") - assert_equal ["aaaaa", "", ""], "aaaaa".rpartition("") - assert_equal ["aaaa", "a", ""], "aaaaa".rpartition("a") - assert_equal ["aaaa", "b", ""], "aaaab".rpartition("b") - assert_equal ["", "b", "aaaa"], "baaaa".rpartition("b") - assert_equal ["", "", ""], "".rpartition("a") -end - -assert('String#hex') do - assert_equal 16, "10".hex - assert_equal 255, "ff".hex - assert_equal 16, "0x10".hex - assert_equal (-16), "-0x10".hex - assert_equal 0, "xyz".hex - assert_equal 16, "10z".hex - assert_equal 16, "1_0".hex - assert_equal 0, "".hex -end - -assert('String#oct') do - assert_equal 8, "10".oct - assert_equal 7, "7".oct - assert_equal 0, "8".oct - assert_equal 0, "9".oct - assert_equal 0, "xyz".oct - assert_equal 8, "10z".oct - assert_equal 8, "1_0".oct - assert_equal 8, "010".oct - assert_equal (-8), "-10".oct -end - -assert('String#chr') do - assert_equal "a", "abcde".chr - # test Fixnum#chr as well - assert_equal "a", 97.chr -end - -assert('String#lines') do - assert_equal ["Hel\n", "lo\n", "World!"], "Hel\nlo\nWorld!".lines - assert_equal ["Hel\n", "lo\n", "World!\n"], "Hel\nlo\nWorld!\n".lines - assert_equal ["\n", "\n", "\n"], "\n\n\n".lines - assert_equal [], "".lines -end - -assert('String#clear') do - # embed string - s = "foo" - assert_equal("", s.clear) - assert_equal("", s) - - # not embed string and not shared string - s = "foo" * 100 - a = s - assert_equal("", s.clear) - assert_equal("", s) - assert_equal("", a) - - # shared string - s = "foo" * 100 - a = s[10, 90] # create shared string - assert_equal("", s.clear) # clear - assert_equal("", s) # s is cleared - assert_not_equal("", a) # a should not be affected -end - -assert('String#slice!') do - a = "AooBar" - b = a.dup - assert_equal "A", a.slice!(0) - assert_equal "AooBar", b - - a = "FooBar" - assert_equal "r", a.slice!(-1) - assert_equal "FooBa", a - - a = "FooBar" - assert_nil a.slice!(6) - assert_nil a.slice!(-7) - assert_equal "FooBar", a - - a = "FooBar" - assert_equal "Foo", a.slice!(0, 3) - assert_equal "Bar", a - - a = "FooBar" - assert_equal "Bar", a.slice!(-3, 3) - assert_equal "Foo", a - - a = "FooBar" - assert_equal "", a.slice!(6, 2) - assert_equal "FooBar", a - - a = "FooBar" - assert_nil a.slice!(-7,10) - assert_equal "FooBar", a - - a = "FooBar" - assert_equal "Foo", a.slice!(0..2) - assert_equal "Bar", a - - a = "FooBar" - assert_equal "Bar", a.slice!(-3..-1) - assert_equal "Foo", a - - a = "FooBar" - assert_equal "", a.slice!(6..2) - assert_equal "FooBar", a - - a = "FooBar" - assert_nil a.slice!(-10..-7) - assert_equal "FooBar", a - - a = "FooBar" - assert_equal "Foo", a.slice!("Foo") - assert_equal "Bar", a - - a = "FooBar" - assert_nil a.slice!("xyzzy") - assert_equal "FooBar", a - - assert_raise(ArgumentError) { "foo".slice! } -end - -assert('String#succ') do - assert_equal "", "".succ - assert_equal "1", "0".succ - assert_equal "10", "9".succ - assert_equal "01", "00".succ - assert_equal "a1", "a0".succ - assert_equal "A1", "A0".succ - assert_equal "10", "09".succ - assert_equal "b0", "a9".succ - assert_equal "B0", "A9".succ - - assert_equal "b", "a".succ - assert_equal "aa", "z".succ - assert_equal "ab", "aa".succ - assert_equal "Ab", "Aa".succ - assert_equal "0b", "0a".succ - assert_equal "ba", "az".succ - assert_equal "Ba", "Az".succ - assert_equal "1a", "0z".succ - - assert_equal "B", "A".succ - assert_equal "AA", "Z".succ - assert_equal "AB", "AA".succ - assert_equal "aB", "aA".succ - assert_equal "0B", "0A".succ - assert_equal "BA", "AZ".succ - assert_equal "bA", "aZ".succ - assert_equal "1A", "0Z".succ - - assert_equal ".", "-".succ - assert_equal "\x01\x00", "\xff".succ - assert_equal "-b", "-a".succ - assert_equal "-aa", "-z".succ - assert_equal "-a-b-", "-a-a-".succ - assert_equal "-b-", "-a-".succ - assert_equal "-aa-", "-z-".succ - assert_equal "あb", "あa".succ - assert_equal "あba", "あaz".succ - - a = ""; a.succ! - assert_equal "", a - a = "0"; a.succ! - assert_equal "1", a - a = "9"; a.succ! - assert_equal "10", a - a = "00"; a.succ! - assert_equal "01", a - a = "a0"; a.succ! - assert_equal "a1", a - a = "A0"; a.succ! - assert_equal "A1", a - a = "09"; a.succ! - assert_equal "10", a - a = "a9"; a.succ! - assert_equal "b0", a - a = "A9"; a.succ! - assert_equal "B0", a - - a = "a"; a.succ! - assert_equal "b", a - a = "z"; a.succ! - assert_equal "aa", a - a = "aa"; a.succ! - assert_equal "ab", a - a = "Aa"; a.succ! - assert_equal "Ab", a - a = "0a"; a.succ! - assert_equal "0b", a - a = "az"; a.succ! - assert_equal "ba", a - a = "Az"; a.succ! - assert_equal "Ba", a - a = "0z"; a.succ! - assert_equal "1a", a - - a = "A"; a.succ! - assert_equal "B", a - a = "Z"; a.succ! - assert_equal "AA", a - a = "AA"; a.succ! - assert_equal "AB", a - a = "aA"; a.succ! - assert_equal "aB", a - a = "0A"; a.succ! - assert_equal "0B", a - a = "AZ"; a.succ! - assert_equal "BA", a - a = "aZ"; a.succ! - assert_equal "bA", a - a = "0Z"; a.succ! - assert_equal "1A", a - - a = "-"; a.succ! - assert_equal ".", a - a = "\xff"; a.succ! - assert_equal "\x01\x00", a - a = "-a"; a.succ! - assert_equal "-b", a - a = "-z"; a.succ! - assert_equal "-aa", a - a = "-a-a-"; a.succ! - assert_equal "-a-b-", a - a = "-a-"; a.succ! - assert_equal "-b-", a - a = "-z-"; a.succ! - assert_equal "-aa-", a - a = "あb"; a.succ! - assert_equal "あc", a - a = "あaz"; a.succ! - assert_equal "あba", a -end - -assert('String#next') do - assert_equal "01", "00".next - - a = "00"; a.next! - assert_equal "01", a -end - -assert('String#insert') do - assert_equal "Xabcd", "abcd".insert(0, 'X') - assert_equal "abcXd", "abcd".insert(3, 'X') - assert_equal "abcdX", "abcd".insert(4, 'X') - assert_equal "abXcd", "abcd".insert(-3, 'X') - assert_equal "abcdX", "abcd".insert(-1, 'X') - assert_raise(IndexError) { "abcd".insert(5, 'X') } - assert_raise(IndexError) { "abcd".insert(-6, 'X') } -end - -assert('String#prepend') do - a = "world" - assert_equal "hello world", a.prepend("hello ") - assert_equal "hello world", a -end - -assert('String#ljust') do - assert_equal "hello", "hello".ljust(4) - assert_equal "hello ", "hello".ljust(20) - assert_equal "hello123412341234123", "hello".ljust(20, '1234') - assert_equal "hello", "hello".ljust(-3) -end - -assert('String#upto') do - a = "aa" - start = "aa" - count = 0 - assert_equal("aa", a.upto("zz") {|s| - assert_equal(start, s) - start.succ! - count += 1 - }) - assert_equal(676, count) - - a = "a" - start = "a" - count = 0 - assert_equal("a", a.upto("a") {|s| - assert_equal(start, s) - start.succ! - count += 1 - }) - assert_equal(1, count) - - a = "a" - start = "a" - count = 0 - assert_equal("a", a.upto("b", true) {|s| - assert_equal(start, s) - start.succ! - count += 1 - }) - assert_equal(1, count) - - a = "0" - start = "0" - count = 0 - assert_equal("0", a.upto("0") {|s| - assert_equal(start, s) - start.succ! - count += 1 - }) - assert_equal(1, count) - - a = "0" - start = "0" - count = 0 - assert_equal("0", a.upto("-1") {|s| - assert_equal(start, s) - start.succ! - count += 1 - }) - assert_equal(0, count) - - a = "-1" - start = "-1" - count = 0 - assert_equal("-1", a.upto("-2") {|s| - assert_equal(start, s) - start.succ! - count += 1 - }) - assert_equal(2, count) -end - -assert('String#ord') do - got = "hello!".split('').map {|x| x.ord} - expect = [104, 101, 108, 108, 111, 33] - assert_equal expect, got -end - -assert('String#ord(UTF-8)') do - got = "こんにちは世界!".split('').map {|x| x.ord} - expect = [0x3053,0x3093,0x306b,0x3061,0x306f,0x4e16,0x754c,0x21] - assert_equal expect, got -end if UTF8STRING - -assert('String#chr') do - assert_equal "h", "hello!".chr -end -assert('String#chr(UTF-8)') do - assert_equal "こ", "こんにちは世界!".chr -end if UTF8STRING - -assert('String#chars') do - expect = ["h", "e", "l", "l", "o", "!"] - assert_equal expect, "hello!".chars - s = "" - "hello!".chars do |x| - s += x - end - assert_equal "hello!", s -end - -assert('String#chars(UTF-8)') do - expect = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'] - assert_equal expect, "こんにちは世界!".chars - s = "" - "こんにちは世界!".chars do |x| - s += x - end - assert_equal "こんにちは世界!", s -end if UTF8STRING - -assert('String#each_char') do - s = "" - "hello!".each_char do |x| - s += x - end - assert_equal "hello!", s -end - -assert('String#each_char(UTF-8)') do - s = "" - "こんにちは世界!".each_char do |x| - s += x - end - assert_equal "こんにちは世界!", s -end if UTF8STRING - -assert('String#codepoints') do - expect = [104, 101, 108, 108, 111, 33] - assert_equal expect, "hello!".codepoints - cp = [] - "hello!".codepoints do |x| - cp << x - end - assert_equal expect, cp -end - -assert('String#codepoints(UTF-8)') do - expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33] - assert_equal expect, "こんにちは世界!".codepoints - cp = [] - "こんにちは世界!".codepoints do |x| - cp << x - end - assert_equal expect, cp -end if UTF8STRING - -assert('String#each_codepoint') do - expect = [104, 101, 108, 108, 111, 33] - cp = [] - "hello!".each_codepoint do |x| - cp << x - end - assert_equal expect, cp -end - -assert('String#each_codepoint(UTF-8)') do - expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33] - cp = [] - "こんにちは世界!".each_codepoint do |x| - cp << x - end - assert_equal expect, cp -end if UTF8STRING diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-struct/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-struct/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-struct/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-struct/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-struct') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'standard Struct class' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-struct/mrblib/struct.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-struct/mrblib/struct.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-struct/mrblib/struct.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-struct/mrblib/struct.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -## -# Struct -# -# ISO 15.2.18 - -if Object.const_defined?(:Struct) - class Struct - - ## - # Calls the given block for each element of +self+ - # and pass the respective element. - # - # ISO 15.2.18.4.4 - def each(&block) - self.class.members.each{|field| - block.call(self[field]) - } - self - end - - ## - # Calls the given block for each element of +self+ - # and pass the name and value of the respectiev - # element. - # - # ISO 15.2.18.4.5 - def each_pair(&block) - self.class.members.each{|field| - block.call(field.to_sym, self[field]) - } - self - end - - ## - # Calls the given block for each element of +self+ - # and returns an array with all elements of which - # block is not false. - # - # ISO 15.2.18.4.7 - def select(&block) - ary = [] - self.class.members.each{|field| - val = self[field] - ary.push(val) if block.call(val) - } - ary - end - - def _inspect - name = self.class.to_s - if name[0] == "#" - str = "#" - end - - ## - # call-seq: - # struct.to_s -> string - # struct.inspect -> string - # - # Describe the contents of this struct in a string. - # - # 15.2.18.4.10(x) - # - def inspect - begin - self._inspect - rescue SystemStackError - "#" - end - end - - ## - # 15.2.18.4.11(x) - # - alias to_s inspect - end -end - diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-struct/src/struct.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-struct/src/struct.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-struct/src/struct.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-struct/src/struct.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,785 +0,0 @@ -/* -** struct.c - Struct class -** -** See Copyright Notice in mruby.h -*/ - -#include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/string.h" -#include "mruby/class.h" -#include "mruby/variable.h" -#include "mruby/hash.h" -#include "mruby/range.h" - -#define RSTRUCT_LEN(st) mrb_ary_ptr(st)->len -#define RSTRUCT_PTR(st) mrb_ary_ptr(st)->ptr - -static struct RClass * -struct_class(mrb_state *mrb) -{ - return mrb_class_get(mrb, "Struct"); -} - -static inline mrb_value -struct_ivar_get(mrb_state *mrb, mrb_value c, mrb_sym id) -{ - struct RClass* kclass; - struct RClass* sclass = struct_class(mrb); - mrb_value ans; - - for (;;) { - ans = mrb_iv_get(mrb, c, id); - if (!mrb_nil_p(ans)) return ans; - kclass = RCLASS_SUPER(c); - if (kclass == 0 || kclass == sclass) - return mrb_nil_value(); - c = mrb_obj_value(kclass); - } -} - -static mrb_value -struct_s_members(mrb_state *mrb, struct RClass *klass) -{ - mrb_value members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern_lit(mrb, "__members__")); - - if (mrb_nil_p(members)) { - mrb_raise(mrb, E_TYPE_ERROR, "uninitialized struct"); - } - if (!mrb_array_p(members)) { - mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct"); - } - return members; -} - -static mrb_value -struct_members(mrb_state *mrb, mrb_value s) -{ - mrb_value members = struct_s_members(mrb, mrb_obj_class(mrb, s)); - if (!mrb_array_p(s)) { - mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct"); - } - if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { - mrb_raisef(mrb, E_TYPE_ERROR, - "struct size differs (%S required %S given)", - mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s))); - } - return members; -} - -static mrb_value -mrb_struct_s_members_m(mrb_state *mrb, mrb_value klass) -{ - mrb_value members, ary; - - members = struct_s_members(mrb, mrb_class_ptr(klass)); - ary = mrb_ary_new_capa(mrb, RARRAY_LEN(members)); - mrb_ary_replace(mrb, ary, members); - return ary; -} - -/* 15.2.18.4.6 */ -/* - * call-seq: - * struct.members -> array - * - * Returns an array of strings representing the names of the instance - * variables. - * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * joe.members #=> [:name, :address, :zip] - */ - -static mrb_value -mrb_struct_members(mrb_state *mrb, mrb_value obj) -{ - return mrb_struct_s_members_m(mrb, mrb_obj_value(mrb_obj_class(mrb, obj))); -} - -static mrb_value -mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id) -{ - mrb_value members, slot, *ptr; - const mrb_value *ptr_members; - mrb_int i, len; - - ptr = RSTRUCT_PTR(obj); - members = struct_members(mrb, obj); - ptr_members = RARRAY_PTR(members); - slot = mrb_symbol_value(id); - len = RARRAY_LEN(members); - for (i=0; ic->ci->mid); -} - -static mrb_value mrb_struct_ref0(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[0];} -static mrb_value mrb_struct_ref1(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[1];} -static mrb_value mrb_struct_ref2(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[2];} -static mrb_value mrb_struct_ref3(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[3];} -static mrb_value mrb_struct_ref4(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[4];} -static mrb_value mrb_struct_ref5(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[5];} -static mrb_value mrb_struct_ref6(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[6];} -static mrb_value mrb_struct_ref7(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[7];} -static mrb_value mrb_struct_ref8(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[8];} -static mrb_value mrb_struct_ref9(mrb_state* mrb, mrb_value obj) {return RSTRUCT_PTR(obj)[9];} - -#define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) -#define N_REF_FUNC numberof(ref_func) - -static const mrb_func_t ref_func[] = { - mrb_struct_ref0, - mrb_struct_ref1, - mrb_struct_ref2, - mrb_struct_ref3, - mrb_struct_ref4, - mrb_struct_ref5, - mrb_struct_ref6, - mrb_struct_ref7, - mrb_struct_ref8, - mrb_struct_ref9, -}; - -static mrb_sym -mrb_id_attrset(mrb_state *mrb, mrb_sym id) -{ - const char *name; - char *buf; - mrb_int len; - mrb_sym mid; - - name = mrb_sym2name_len(mrb, id, &len); - buf = (char *)mrb_malloc(mrb, (size_t)len+2); - memcpy(buf, name, (size_t)len); - buf[len] = '='; - buf[len+1] = '\0'; - - mid = mrb_intern(mrb, buf, len+1); - mrb_free(mrb, buf); - return mid; -} - -static mrb_value -mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val) -{ - const char *name; - mrb_int i, len, slen; - mrb_sym mid; - mrb_value members, slot, *ptr; - const mrb_value *ptr_members; - - /* get base id */ - name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen); - mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */ - - members = struct_members(mrb, obj); - ptr_members = RARRAY_PTR(members); - len = RARRAY_LEN(members); - ptr = RSTRUCT_PTR(obj); - for (i=0; ibasic.c->super = c->c; */ - make_struct_define_accessors(mrb, members, c); - return nstr; -} - -/* 15.2.18.3.1 */ -/* - * call-seq: - * Struct.new( [aString] [, aSym]+> ) -> StructClass - * StructClass.new(arg, ...) -> obj - * StructClass[arg, ...] -> obj - * - * Creates a new class, named by aString, containing accessor - * methods for the given symbols. If the name aString is - * omitted, an anonymous structure class will be created. Otherwise, - * the name of this struct will appear as a constant in class - * Struct, so it must be unique for all - * Structs in the system and should start with a capital - * letter. Assigning a structure class to a constant effectively gives - * the class the name of the constant. - * - * Struct::new returns a new Class object, - * which can then be used to create specific instances of the new - * structure. The number of actual parameters must be - * less than or equal to the number of attributes defined for this - * class; unset parameters default to nil. Passing too many - * parameters will raise an ArgumentError. - * - * The remaining methods listed in this section (class and instance) - * are defined for this generated class. - * - * # Create a structure with a name in Struct - * Struct.new("Customer", :name, :address) #=> Struct::Customer - * Struct::Customer.new("Dave", "123 Main") #=> # - * - * # Create a structure named by its constant - * Customer = Struct.new(:name, :address) #=> Customer - * Customer.new("Dave", "123 Main") #=> # - */ -static mrb_value -mrb_struct_s_def(mrb_state *mrb, mrb_value klass) -{ - mrb_value name, rest; - mrb_value *pargv; - mrb_int argcnt; - mrb_int i; - mrb_value b, st; - mrb_sym id; - mrb_value *argv; - mrb_int argc; - - name = mrb_nil_value(); - rest = mrb_nil_value(); - mrb_get_args(mrb, "*&", &argv, &argc, &b); - if (argc == 0) { /* special case to avoid crash */ - rest = mrb_ary_new(mrb); - } - else { - if (argc > 0) name = argv[0]; - if (argc > 1) rest = argv[1]; - if (mrb_array_p(rest)) { - if (!mrb_nil_p(name) && mrb_symbol_p(name)) { - /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ - mrb_ary_unshift(mrb, rest, name); - name = mrb_nil_value(); - } - } - else { - pargv = &argv[1]; - argcnt = argc-1; - if (!mrb_nil_p(name) && mrb_symbol_p(name)) { - /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */ - name = mrb_nil_value(); - pargv = &argv[0]; - argcnt++; - } - rest = mrb_ary_new_from_values(mrb, argcnt, pargv); - } - for (i=0; i anObject - * struct[fixnum] -> anObject - * - * Attribute Reference---Returns the value of the instance variable - * named by symbol, or indexed (0..length-1) by - * fixnum. Will raise NameError if the named - * variable does not exist, or IndexError if the index is - * out of range. - * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * - * joe["name"] #=> "Joe Smith" - * joe[:name] #=> "Joe Smith" - * joe[0] #=> "Joe Smith" - */ -static mrb_value -mrb_struct_aref(mrb_state *mrb, mrb_value s) -{ - mrb_value idx; - - mrb_get_args(mrb, "o", &idx); - if (mrb_string_p(idx)) { - mrb_value sym = mrb_check_intern_str(mrb, idx); - - if (mrb_nil_p(sym)) { - mrb_raisef(mrb, E_INDEX_ERROR, "no member '%S' in struct", idx); - } - idx = sym; - } - if (mrb_symbol_p(idx)) { - return struct_aref_sym(mrb, s, mrb_symbol(idx)); - } - return struct_aref_int(mrb, s, mrb_int(mrb, idx)); -} - -static mrb_value -mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) -{ - mrb_value members, *ptr; - const mrb_value *ptr_members; - mrb_int i, len; - - members = struct_members(mrb, s); - len = RARRAY_LEN(members); - if (RSTRUCT_LEN(s) != len) { - mrb_raisef(mrb, E_TYPE_ERROR, - "struct size differs (%S required %S given)", - mrb_fixnum_value(len), mrb_fixnum_value(RSTRUCT_LEN(s))); - } - ptr = RSTRUCT_PTR(s); - ptr_members = RARRAY_PTR(members); - for (i=0; i obj - * struct[fixnum] = obj -> obj - * - * Attribute Assignment---Assigns to the instance variable named by - * symbol or fixnum the value obj and - * returns it. Will raise a NameError if the named - * variable does not exist, or an IndexError if the index - * is out of range. - * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * - * joe["name"] = "Luke" - * joe[:zip] = "90210" - * - * joe.name #=> "Luke" - * joe.zip #=> "90210" - */ - -static mrb_value -mrb_struct_aset(mrb_state *mrb, mrb_value s) -{ - mrb_int i; - mrb_value idx; - mrb_value val; - - mrb_get_args(mrb, "oo", &idx, &val); - - if (mrb_string_p(idx)) { - mrb_value sym = mrb_check_intern_str(mrb, idx); - - if (mrb_nil_p(sym)) { - mrb_raisef(mrb, E_INDEX_ERROR, "no member '%S' in struct", idx); - } - idx = sym; - } - if (mrb_symbol_p(idx)) { - return mrb_struct_aset_sym(mrb, s, mrb_symbol(idx), val); - } - - i = mrb_int(mrb, idx); - if (i < 0) i = RSTRUCT_LEN(s) + i; - if (i < 0) { - mrb_raisef(mrb, E_INDEX_ERROR, - "offset %S too small for struct(size:%S)", - mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); - } - if (RSTRUCT_LEN(s) <= i) { - mrb_raisef(mrb, E_INDEX_ERROR, - "offset %S too large for struct(size:%S)", - mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s))); - } - return RSTRUCT_PTR(s)[i] = val; -} - -/* 15.2.18.4.1 */ -/* - * call-seq: - * struct == other_struct -> true or false - * - * Equality---Returns true if other_struct is - * equal to this one: they must be of the same class as generated by - * Struct::new, and the values of all instance variables - * must be equal (according to Object#==). - * - * Customer = Struct.new(:name, :address, :zip) - * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345) - * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345) - * joe == joejr #=> true - * joe == jane #=> false - */ - -static mrb_value -mrb_struct_equal(mrb_state *mrb, mrb_value s) -{ - mrb_value s2; - mrb_value *ptr, *ptr2; - mrb_int i, len; - - mrb_get_args(mrb, "o", &s2); - if (mrb_obj_equal(mrb, s, s2)) { - return mrb_true_value(); - } - if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) { - return mrb_false_value(); - } - if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { - mrb_bug(mrb, "inconsistent struct"); /* should never happen */ - } - ptr = RSTRUCT_PTR(s); - ptr2 = RSTRUCT_PTR(s2); - len = RSTRUCT_LEN(s); - for (i=0; i true or false - * - * Two structures are equal if they are the same object, or if all their - * fields are equal (using eql?). - */ -static mrb_value -mrb_struct_eql(mrb_state *mrb, mrb_value s) -{ - mrb_value s2; - mrb_value *ptr, *ptr2; - mrb_int i, len; - - mrb_get_args(mrb, "o", &s2); - if (mrb_obj_equal(mrb, s, s2)) { - return mrb_true_value(); - } - if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) { - return mrb_false_value(); - } - if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { - mrb_bug(mrb, "inconsistent struct"); /* should never happen */ - } - ptr = RSTRUCT_PTR(s); - ptr2 = RSTRUCT_PTR(s2); - len = RSTRUCT_LEN(s); - for (i=0; i Fixnum - * struct.size -> Fixnum - * - * Returns number of struct members. - */ -static mrb_value -mrb_struct_len(mrb_state *mrb, mrb_value self) -{ - return mrb_fixnum_value(RSTRUCT_LEN(self)); -} - -/* - * call-seq: - * struct.to_a -> array - * struct.values -> array - * - * Create an array from struct values. - */ -static mrb_value -mrb_struct_to_a(mrb_state *mrb, mrb_value self) -{ - return mrb_ary_new_from_values(mrb, RSTRUCT_LEN(self), RSTRUCT_PTR(self)); -} - -/* - * call-seq: - * struct.to_h -> hash - * - * Create a hash from member names and struct values. - */ -static mrb_value -mrb_struct_to_h(mrb_state *mrb, mrb_value self) -{ - mrb_value members, ret; - mrb_int i; - - members = struct_s_members(mrb, mrb_class(mrb, self)); - ret = mrb_hash_new_capa(mrb, RARRAY_LEN(members)); - - for (i = 0; i < RARRAY_LEN(members); ++i) { - mrb_hash_set(mrb, ret, RARRAY_PTR(members)[i], RSTRUCT_PTR(self)[i]); - } - - return ret; -} - -static mrb_value -mrb_struct_values_at(mrb_state *mrb, mrb_value self) -{ - mrb_int argc; - mrb_value *argv; - - mrb_get_args(mrb, "*", &argv, &argc); - - return mrb_get_values_at(mrb, self, RSTRUCT_LEN(self), argc, argv, struct_aref_int); -} - -/* - * A Struct is a convenient way to bundle a number of - * attributes together, using accessor methods, without having to write - * an explicit class. - * - * The Struct class is a generator of specific classes, - * each one of which is defined to hold a set of variables and their - * accessors. In these examples, we'll call the generated class - * "CustomerClass," and we'll show an example instance of that - * class as "CustomerInst." - * - * In the descriptions that follow, the parameter symbol refers - * to a symbol, which is either a quoted string or a - * Symbol (such as :name). - */ -void -mrb_mruby_struct_gem_init(mrb_state* mrb) -{ - struct RClass *st; - st = mrb_define_class(mrb, "Struct", mrb->object_class); - - mrb_define_class_method(mrb, st, "new", mrb_struct_s_def, MRB_ARGS_ANY()); /* 15.2.18.3.1 */ - - mrb_define_method(mrb, st, "==", mrb_struct_equal, MRB_ARGS_REQ(1)); /* 15.2.18.4.1 */ - mrb_define_method(mrb, st, "[]", mrb_struct_aref, MRB_ARGS_REQ(1)); /* 15.2.18.4.2 */ - mrb_define_method(mrb, st, "[]=", mrb_struct_aset, MRB_ARGS_REQ(2)); /* 15.2.18.4.3 */ - mrb_define_method(mrb, st, "members", mrb_struct_members, MRB_ARGS_NONE()); /* 15.2.18.4.6 */ - mrb_define_method(mrb, st, "initialize", mrb_struct_initialize, MRB_ARGS_ANY()); /* 15.2.18.4.8 */ - mrb_define_method(mrb, st, "initialize_copy", mrb_struct_init_copy, MRB_ARGS_REQ(1)); /* 15.2.18.4.9 */ - mrb_define_method(mrb, st, "eql?", mrb_struct_eql, MRB_ARGS_REQ(1)); /* 15.2.18.4.12(x) */ - - mrb_define_method(mrb, st, "size", mrb_struct_len, MRB_ARGS_NONE()); - mrb_define_method(mrb, st, "length", mrb_struct_len, MRB_ARGS_NONE()); - mrb_define_method(mrb, st, "to_a", mrb_struct_to_a, MRB_ARGS_NONE()); - mrb_define_method(mrb, st, "values", mrb_struct_to_a, MRB_ARGS_NONE()); - mrb_define_method(mrb, st, "to_h", mrb_struct_to_h, MRB_ARGS_NONE()); - mrb_define_method(mrb, st, "values_at", mrb_struct_values_at, MRB_ARGS_NONE()); -} - -void -mrb_mruby_struct_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-struct/test/struct.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-struct/test/struct.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-struct/test/struct.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-struct/test/struct.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,131 +0,0 @@ -## -# Struct ISO Test - -assert('Struct', '15.2.18') do - Struct.class == Class -end - -assert('Struct.new', '15.2.18.3.1') do - c = Struct.new(:m1, :m2) - c.superclass == Struct and - c.members == [:m1,:m2] -end - -# Check crash bug with Struc.new and no params. -assert('Struct.new', '15.2.18.3.1') do - c = Struct.new() - c.superclass == Struct and c.members == [] -end - -assert('Struct#==', '15.2.18.4.1') do - c = Struct.new(:m1, :m2) - cc1 = c.new(1,2) - cc2 = c.new(1,2) - cc1 == cc2 -end - -assert('Struct#[]', '15.2.18.4.2') do - c = Struct.new(:m1, :m2) - cc = c.new(1,2) - cc[:m1] == 1 and cc["m2"] == 2 -end - -assert('Struct#[]=', '15.2.18.4.3') do - c = Struct.new(:m1, :m2) - cc = c.new(1,2) - cc[:m1] = 3 - cc[:m1] == 3 - cc["m2"] = 3 - assert_equal 3, cc["m2"] - assert_raise(TypeError) { cc[[]] = 3 } -end - -assert('Struct#each', '15.2.18.4.4') do - c = Struct.new(:m1, :m2) - cc = c.new(1,2) - a = [] - cc.each{|x| - a << x - } - a[0] == 1 and a[1] == 2 -end - -assert('Struct#each_pair', '15.2.18.4.5') do - c = Struct.new(:m1, :m2) - cc = c.new(1,2) - a = [] - cc.each_pair{|k,v| - a << [k,v] - } - a[0] == [:m1, 1] and a[1] == [:m2, 2] -end - -assert('Struct#members', '15.2.18.4.6') do - c = Struct.new(:m1, :m2) - cc = c.new(1,2) - cc.members == [:m1,:m2] -end - -assert('Struct#select', '15.2.18.4.7') do - c = Struct.new(:m1, :m2) - cc = c.new(1,2) - cc.select{|v| v % 2 == 0} == [2] -end - -assert('large struct') do - c = Struct.new(:m1, :m2, :m3, :m4, :m5, :m6, :m7, :m8, :m9, :m10, :m11, :m12, :m13) - cc = c.new(1,2,3,4,5,6,7,8,9,10,11,12,13) - assert_equal 1, cc.m1 - assert_equal 2, cc.m2 - assert_equal 3, cc.m3 - assert_equal 4, cc.m4 - assert_equal 5, cc.m5 - assert_equal 6, cc.m6 - assert_equal 7, cc.m7 - assert_equal 8, cc.m8 - assert_equal 9, cc.m9 - assert_equal 10, cc.m10 - assert_equal 13, cc.m13 - - cc.m13 = 'test' - assert_equal 'test', cc.m13 - - assert_raise(NoMethodError) { cc.m14 } -end - -assert('wrong struct arg count') do - c = Struct.new(:m1) - assert_raise ArgumentError do - cc = c.new(1,2,3) - end -end - -assert('struct inspect') do - c = Struct.new(:m1, :m2, :m3, :m4, :m5) - cc = c.new(1,2,3,4,5) - assert_equal "#", cc.inspect -end - -assert('Struct#length, Struct#size') do - s = Struct.new(:f1, :f2).new(0, 1) - assert_equal 2, s.size - assert_equal 2, s.length -end - -assert('Struct#to_a, Struct#values') do - s = Struct.new(:mem1, :mem2).new('a', 'b') - assert_equal ['a', 'b'], s.to_a - assert_equal ['a', 'b'], s.values -end - -assert('Struct#to_h') do - s = Struct.new(:white, :red, :green).new('ruuko', 'yuzuki', 'hitoe') - assert_equal(:white => 'ruuko', :red => 'yuzuki', :green => 'hitoe') { s.to_h } -end - -assert('Struct#values_at') do - a = Struct.new(:blue, :purple).new('aki', 'io') - assert_equal ['aki'], a.values_at(0) - assert_equal ['io', 'aki'], a.values_at(1, 0) - assert_raise(IndexError) { a.values_at 2 } -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-symbol-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Symbol class extension' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -class Symbol - include Comparable - - alias intern to_sym - - def to_proc - ->(obj,*args,&block) do - obj.__send__(self, *args, &block) - end - end - - ## - # call-seq: - # sym.capitalize -> symbol - # - # Same as sym.to_s.capitalize.intern. - - def capitalize - (self.to_s.capitalize! || self).to_sym - end - - ## - # call-seq: - # sym.downcase -> symbol - # - # Same as sym.to_s.downcase.intern. - - def downcase - (self.to_s.downcase! || self).to_sym - end - - ## - # call-seq: - # sym.upcase -> symbol - # - # Same as sym.to_s.upcase.intern. - - def upcase - (self.to_s.upcase! || self).to_sym - end - - ## - # call-seq: - # sym.casecmp(other) -> -1, 0, +1 or nil - # - # Case-insensitive version of Symbol#<=>. - - def casecmp(other) - return nil unless other.kind_of?(Symbol) - lhs = self.to_s; lhs.upcase! - rhs = other.to_s; rhs.upcase! - lhs <=> rhs - end - - # - # call-seq: - # sym.empty? -> true or false - # - # Returns that _sym_ is :"" or not. - - def empty? - self.length == 0 - end - -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-symbol-ext/src/symbol.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-symbol-ext/src/symbol.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-symbol-ext/src/symbol.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-symbol-ext/src/symbol.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -#include "mruby.h" -#include "mruby/khash.h" -#include "mruby/array.h" - -typedef struct symbol_name { - size_t len; - const char *name; -} symbol_name; - -/* - * call-seq: - * Symbol.all_symbols => array - * - * Returns an array of all the symbols currently in Ruby's symbol - * table. - * - * Symbol.all_symbols.size #=> 903 - * Symbol.all_symbols[1,20] #=> [:floor, :ARGV, :Binding, :symlink, - * :chown, :EOFError, :$;, :String, - * :LOCK_SH, :"setuid?", :$<, - * :default_proc, :compact, :extend, - * :Tms, :getwd, :$=, :ThreadGroup, - * :wait2, :$>] - */ -static mrb_value -mrb_sym_all_symbols(mrb_state *mrb, mrb_value self) -{ - mrb_sym i, lim; - mrb_value ary = mrb_ary_new_capa(mrb, mrb->symidx); - - for (i=1, lim=mrb->symidx+1; i integer - * - * Same as sym.to_s.length. - */ -static mrb_value -mrb_sym_length(mrb_state *mrb, mrb_value self) -{ - mrb_int len; - mrb_sym2name_len(mrb, mrb_symbol(self), &len); - return mrb_fixnum_value(len); -} - -void -mrb_mruby_symbol_ext_gem_init(mrb_state* mrb) -{ - struct RClass *s = mrb->symbol_class; - mrb_define_class_method(mrb, s, "all_symbols", mrb_sym_all_symbols, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "length", mrb_sym_length, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "size", mrb_sym_length, MRB_ARGS_NONE()); -} - -void -mrb_mruby_symbol_ext_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -## -# Symbol(Ext) Test - -assert('Symbol#to_proc') do - assert_equal 5, :abs.to_proc[-5] -end - -assert('Symbol.all_symbols') do - foo = [:__symbol_test_1, :__symbol_test_2, :__symbol_test_3].sort - symbols = Symbol.all_symbols.select{|sym|sym.to_s.include? '__symbol_test'}.sort - assert_equal foo, symbols -end - -assert("Symbol#length") do - assert_equal 5, :hello.size - assert_equal 5, :mruby.length -end - -assert("Symbol#capitalize") do - assert_equal :Hello, :hello.capitalize - assert_equal :Hello, :HELLO.capitalize - assert_equal :Hello, :Hello.capitalize -end - -assert("Symbol#downcase") do - assert_equal :hello, :hEllO.downcase - assert_equal :hello, :hello.downcase -end - -assert("Symbol#upcase") do - assert_equal :HELLO, :hEllO.upcase - assert_equal :HELLO, :HELLO.upcase -end - -assert("Symbol#casecmp") do - assert_equal 0, :HELLO.casecmp(:hEllO) - assert_equal 1, :HELLO.casecmp(:hEllN) - assert_equal(-1, :HELLO.casecmp(:hEllP)) - assert_nil :HELLO.casecmp("hEllO") -end - -assert("Symbol#empty?") do - assert_true :''.empty? -end - -assert('Symbol#intern') do - assert_equal :test, :test.intern -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-test/driver.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-test/driver.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-test/driver.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-test/driver.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,166 +0,0 @@ -/* -** mrbtest - Test for Embeddable Ruby -** -** This program runs Ruby test programs in test/t directory -** against the current mruby implementation. -*/ - - -#include -#include -#include - -#include "mruby.h" -#include "mruby/proc.h" -#include "mruby/data.h" -#include "mruby/compile.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/array.h" - -void -mrb_init_mrbtest(mrb_state *); - -/* Print a short remark for the user */ -static void -print_hint(void) -{ - printf("mrbtest - Embeddable Ruby Test\n\n"); -} - -static int -check_error(mrb_state *mrb) -{ - /* Error check */ - /* $ko_test and $kill_test should be 0 */ - mrb_value ko_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$ko_test")); - mrb_value kill_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$kill_test")); - - return mrb_fixnum_p(ko_test) && mrb_fixnum(ko_test) == 0 && mrb_fixnum_p(kill_test) && mrb_fixnum(kill_test) == 0; -} - -static int -eval_test(mrb_state *mrb) -{ - /* evaluate the test */ - mrb_funcall(mrb, mrb_top_self(mrb), "report", 0); - /* did an exception occur? */ - if (mrb->exc) { - mrb_print_error(mrb); - mrb->exc = 0; - return EXIT_FAILURE; - } - else if (!check_error(mrb)) { - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - -static void -t_printstr(mrb_state *mrb, mrb_value obj) -{ - char *s; - int len; - - if (mrb_string_p(obj)) { - s = RSTRING_PTR(obj); - len = RSTRING_LEN(obj); - fwrite(s, len, 1, stdout); - } -} - -mrb_value -mrb_t_printstr(mrb_state *mrb, mrb_value self) -{ - mrb_value argv; - - mrb_get_args(mrb, "o", &argv); - t_printstr(mrb, argv); - - return argv; -} - -void -mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose) -{ - struct RClass *krn, *mrbtest; - - krn = mrb->kernel_module; - mrb_define_method(mrb, krn, "__t_printstr__", mrb_t_printstr, MRB_ARGS_REQ(1)); - - mrbtest = mrb_define_module(mrb, "Mrbtest"); - - mrb_define_const(mrb, mrbtest, "FIXNUM_MAX", mrb_fixnum_value(MRB_INT_MAX)); - mrb_define_const(mrb, mrbtest, "FIXNUM_MIN", mrb_fixnum_value(MRB_INT_MIN)); - mrb_define_const(mrb, mrbtest, "FIXNUM_BIT", mrb_fixnum_value(MRB_INT_BIT)); - - if (verbose) { - mrb_gv_set(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"), mrb_true_value()); - } -} - -void -mrb_t_pass_result(mrb_state *mrb_dst, mrb_state *mrb_src) -{ - mrb_value res_src; - - if (mrb_src->exc) { - mrb_print_error(mrb_src); - exit(EXIT_FAILURE); - } - -#define TEST_COUNT_PASS(name) \ - do { \ - res_src = mrb_gv_get(mrb_src, mrb_intern_lit(mrb_src, "$" #name)); \ - if (mrb_fixnum_p(res_src)) { \ - mrb_value res_dst = mrb_gv_get(mrb_dst, mrb_intern_lit(mrb_dst, "$" #name)); \ - mrb_gv_set(mrb_dst, mrb_intern_lit(mrb_dst, "$" #name), mrb_fixnum_value(mrb_fixnum(res_dst) + mrb_fixnum(res_src))); \ - } \ - } while (FALSE) \ - - TEST_COUNT_PASS(ok_test); - TEST_COUNT_PASS(ko_test); - TEST_COUNT_PASS(kill_test); - -#undef TEST_COUNT_PASS - - res_src = mrb_gv_get(mrb_src, mrb_intern_lit(mrb_src, "$asserts")); - - if (mrb_array_p(res_src)) { - mrb_int i; - mrb_value res_dst = mrb_gv_get(mrb_dst, mrb_intern_lit(mrb_dst, "$asserts")); - for (i = 0; i < RARRAY_LEN(res_src); ++i) { - mrb_value val_src = RARRAY_PTR(res_src)[i]; - mrb_ary_push(mrb_dst, res_dst, mrb_str_new(mrb_dst, RSTRING_PTR(val_src), RSTRING_LEN(val_src))); - } - } -} - -int -main(int argc, char **argv) -{ - mrb_state *mrb; - int ret; - mrb_bool verbose = FALSE; - - print_hint(); - - /* new interpreter instance */ - mrb = mrb_open(); - if (mrb == NULL) { - fprintf(stderr, "Invalid mrb_state, exiting test driver"); - return EXIT_FAILURE; - } - - if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'v') { - printf("verbose mode: enable\n\n"); - verbose = TRUE; - } - - mrb_init_test_driver(mrb, verbose); - mrb_init_mrbtest(mrb); - ret = eval_test(mrb); - mrb_close(mrb); - - return ret; -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-test/init_mrbtest.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-test/init_mrbtest.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-test/init_mrbtest.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-test/init_mrbtest.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -#include -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/variable.h" - -extern const uint8_t mrbtest_assert_irep[]; -extern const uint8_t mrbtest_irep[]; - -void mrbgemtest_init(mrb_state* mrb); -void mrb_init_test_driver(mrb_state* mrb, mrb_bool verbose); -void mrb_t_pass_result(mrb_state *mrb_dst, mrb_state *mrb_src); - -void -mrb_init_mrbtest(mrb_state *mrb) -{ - mrb_state *core_test; - - mrb_load_irep(mrb, mrbtest_assert_irep); - - core_test = mrb_open_core(mrb_default_allocf, NULL); - if (core_test == NULL) { - fprintf(stderr, "Invalid mrb_state, exiting %s", __FUNCTION__); - exit(EXIT_FAILURE); - } - mrb_init_test_driver(core_test, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose")))); - mrb_load_irep(core_test, mrbtest_assert_irep); - mrb_load_irep(core_test, mrbtest_irep); - mrb_t_pass_result(mrb, core_test); - -#ifndef DISABLE_GEMS - mrbgemtest_init(mrb); -#endif - - if (mrb->exc) { - mrb_print_error(mrb); - exit(EXIT_FAILURE); - } - mrb_close(core_test); -} - diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-test/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-test/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-test/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-test/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,174 +0,0 @@ -MRuby::Gem::Specification.new('mruby-test') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'mruby test' - - build.bins << 'mrbtest' - spec.add_dependency('mruby-compiler', :core => 'mruby-compiler') - - clib = "#{build_dir}/mrbtest.c" - mlib = clib.ext(exts.object) - mrbs = Dir.glob("#{MRUBY_ROOT}/test/t/*.rb") - exec = exefile("#{build.build_dir}/bin/mrbtest") - - libmruby = libfile("#{build.build_dir}/lib/libmruby") - libmruby_core = libfile("#{build.build_dir}/lib/libmruby_core") - - mrbtest_lib = libfile("#{build_dir}/mrbtest") - mrbtest_objs = [] - - driver_obj = objfile("#{build_dir}/driver") - driver = "#{spec.dir}/driver.c" - - assert_c = "#{build_dir}/assert.c" - assert_rb = "#{MRUBY_ROOT}/test/assert.rb" - assert_lib = assert_c.ext(exts.object) - mrbtest_objs << assert_lib - - file assert_lib => assert_c - file assert_c => [build.mrbcfile, assert_rb] do |t| - open(t.name, 'w') do |f| - mrbc.run f, assert_rb, 'mrbtest_assert_irep' - end - end - - gem_table = build.gems.generate_gem_table build - - build.gems.each do |g| - test_rbobj = g.test_rbireps.ext(exts.object) - g.test_objs << test_rbobj - dep_list = build.gems.tsort_dependencies(g.test_dependencies, gem_table).select(&:generate_functions) - - file test_rbobj => g.test_rbireps - file g.test_rbireps => [g.test_rbfiles].flatten + [File.join(g.dir, 'mrbgem.rake'), g.build.mrbcfile, "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake"] do |t| - FileUtils.mkdir_p File.dirname(t.name) - open(t.name, 'w') do |f| - g.print_gem_test_header(f) - test_preload = g.test_preload and [g.dir, MRUBY_ROOT].map {|dir| - File.expand_path(g.test_preload, dir) - }.find {|file| File.exist?(file) } - - f.puts %Q[/*] - f.puts %Q[ * This file contains a test code for #{g.name} gem.] - f.puts %Q[ *] - f.puts %Q[ * IMPORTANT:] - f.puts %Q[ * This file was generated!] - f.puts %Q[ * All manual changes will get lost.] - f.puts %Q[ */] - if test_preload.nil? - f.puts %Q[extern const uint8_t mrbtest_assert_irep[];] - else - g.build.mrbc.run f, test_preload, "gem_test_irep_#{g.funcname}_preload" - end - g.test_rbfiles.flatten.each_with_index do |rbfile, i| - g.build.mrbc.run f, rbfile, "gem_test_irep_#{g.funcname}_#{i}" - end - f.puts %Q[void mrb_#{g.funcname}_gem_test(mrb_state *mrb);] unless g.test_objs.empty? - dep_list.each do |d| - f.puts %Q[void GENERATED_TMP_mrb_#{d.funcname}_gem_init(mrb_state *mrb);] - f.puts %Q[void GENERATED_TMP_mrb_#{d.funcname}_gem_final(mrb_state *mrb);] - end - f.puts %Q[void mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose);] - f.puts %Q[void mrb_t_pass_result(mrb_state *dst, mrb_state *src);] - f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb) {] - unless g.test_rbfiles.empty? - f.puts %Q[ mrb_state *mrb2;] - unless g.test_args.empty? - f.puts %Q[ mrb_value test_args_hash;] - end - f.puts %Q[ int ai;] - g.test_rbfiles.count.times do |i| - f.puts %Q[ ai = mrb_gc_arena_save(mrb);] - f.puts %Q[ mrb2 = mrb_open_core(mrb_default_allocf, NULL);] - f.puts %Q[ if (mrb2 == NULL) {] - f.puts %Q[ fprintf(stderr, "Invalid mrb_state, exiting \%s", __FUNCTION__);] - f.puts %Q[ exit(EXIT_FAILURE);] - f.puts %Q[ }] - dep_list.each do |d| - f.puts %Q[ GENERATED_TMP_mrb_#{d.funcname}_gem_init(mrb2);] - f.puts %Q[ mrb_state_atexit(mrb2, GENERATED_TMP_mrb_#{d.funcname}_gem_final);] - end - f.puts %Q[ mrb_init_test_driver(mrb2, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"))));] - if test_preload.nil? - f.puts %Q[ mrb_load_irep(mrb2, mrbtest_assert_irep);] - else - f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_preload);] - end - f.puts %Q[ if (mrb2->exc) {] - f.puts %Q[ mrb_print_error(mrb2);] - f.puts %Q[ exit(EXIT_FAILURE);] - f.puts %Q[ }] - f.puts %Q[ mrb_const_set(mrb2, mrb_obj_value(mrb2->object_class), mrb_intern_lit(mrb2, "GEMNAME"), mrb_str_new(mrb2, "#{g.name}", #{g.name.length}));] - - unless g.test_args.empty? - f.puts %Q[ test_args_hash = mrb_hash_new_capa(mrb, #{g.test_args.length}); ] - g.test_args.each do |arg_name, arg_value| - escaped_arg_name = arg_name.gsub('\\', '\\\\\\\\').gsub('"', '\"') - escaped_arg_value = arg_value.gsub('\\', '\\\\\\\\').gsub('"', '\"') - f.puts %Q[ mrb_hash_set(mrb2, test_args_hash, mrb_str_new(mrb2, "#{escaped_arg_name.to_s}", #{escaped_arg_name.to_s.length}), mrb_str_new(mrb2, "#{escaped_arg_value.to_s}", #{escaped_arg_value.to_s.length})); ] - end - f.puts %Q[ mrb_const_set(mrb2, mrb_obj_value(mrb2->object_class), mrb_intern_lit(mrb2, "TEST_ARGS"), test_args_hash); ] - end - - f.puts %Q[ mrb_#{g.funcname}_gem_test(mrb2);] if g.custom_test_init? - - f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_#{i});] - f.puts %Q[ ] - - f.puts %Q[ mrb_t_pass_result(mrb, mrb2);] - f.puts %Q[ mrb_close(mrb2);] - f.puts %Q[ mrb_gc_arena_restore(mrb, ai);] - end - end - f.puts %Q[}] - end - end - end - - build.gems.each do |v| - mrbtest_objs.concat v.test_objs - end - - file mrbtest_lib => mrbtest_objs do |t| - build.archiver.run t.name, t.prerequisites - end - - unless build.build_mrbtest_lib_only? - file exec => [driver_obj, mlib, mrbtest_lib, libmruby_core, libmruby] do |t| - gem_flags = build.gems.map { |g| g.linker.flags } - gem_flags_before_libraries = build.gems.map { |g| g.linker.flags_before_libraries } - gem_flags_after_libraries = build.gems.map { |g| g.linker.flags_after_libraries } - gem_libraries = build.gems.map { |g| g.linker.libraries } - gem_library_paths = build.gems.map { |g| g.linker.library_paths } - build.linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries - end - end - - init = "#{spec.dir}/init_mrbtest.c" - file mlib => clib - file clib => [build.mrbcfile, init] + mrbs do |t| - _pp "GEN", "*.rb", "#{clib.relative_path}" - FileUtils.mkdir_p File.dirname(clib) - open(clib, 'w') do |f| - f.puts %Q[/*] - f.puts %Q[ * This file contains a list of all] - f.puts %Q[ * test functions.] - f.puts %Q[ *] - f.puts %Q[ * IMPORTANT:] - f.puts %Q[ * This file was generated!] - f.puts %Q[ * All manual changes will get lost.] - f.puts %Q[ */] - f.puts %Q[] - f.puts IO.read(init) - mrbc.run f, mrbs, 'mrbtest_irep' - build.gems.each do |g| - f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb);] - end - f.puts %Q[void mrbgemtest_init(mrb_state* mrb) {] - build.gems.each do |g| - f.puts %Q[ GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb);] - end - f.puts %Q[}] - end - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-test/README.md nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-test/README.md --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-test/README.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-test/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -Running Tests -============= - -To run the tests, execute the following from the project's root directory. - - $ make test - diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-time/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-time/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-time/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-time/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-time') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'standard Time class' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-time/mrblib/time.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-time/mrblib/time.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-time/mrblib/time.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-time/mrblib/time.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -class Time - def sunday?; wday == 0 end - def monday?; wday == 1 end - def tuesday?; wday == 2 end - def wednesday?; wday == 3 end - def thursday?; wday == 4 end - def friday?; wday == 5 end - def saturday?; wday == 6 end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-time/src/time.c nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-time/src/time.c --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-time/src/time.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-time/src/time.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,800 +0,0 @@ -/* -** time.c - Time class -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/data.h" - -#if !defined(__MINGW64__) && defined(_WIN32) -# define llround(x) round(x) -#endif - -#if defined(__MINGW64__) || defined(__MINGW32__) -# include -#endif - -/** Time class configuration */ - -/* gettimeofday(2) */ -/* C99 does not have gettimeofday that is required to retrieve microseconds */ -/* uncomment following macro on platforms without gettimeofday(2) */ -/* #define NO_GETTIMEOFDAY */ - -/* gmtime(3) */ -/* C99 does not have reentrant gmtime_r() so it might cause troubles under */ -/* multi-threading environment. undef following macro on platforms that */ -/* does not have gmtime_r() and localtime_r(). */ -/* #define NO_GMTIME_R */ - -#ifdef _WIN32 -#if _MSC_VER -/* Win32 platform do not provide gmtime_r/localtime_r; emulate them using gmtime_s/localtime_s */ -#define gmtime_r(tp, tm) ((gmtime_s((tm), (tp)) == 0) ? (tm) : NULL) -#define localtime_r(tp, tm) ((localtime_s((tm), (tp)) == 0) ? (tm) : NULL) -#else -#define NO_GMTIME_R -#endif -#endif - -/* timegm(3) */ -/* mktime() creates tm structure for localtime; timegm() is for UTC time */ -/* define following macro to use probably faster timegm() on the platform */ -/* #define USE_SYSTEM_TIMEGM */ - -/** end of Time class configuration */ - -#ifndef NO_GETTIMEOFDAY -# ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN /* don't include winsock.h */ -# include -# define gettimeofday my_gettimeofday - -# ifdef _MSC_VER -# define UI64(x) x##ui64 -# else -# define UI64(x) x##ull -# endif - -typedef long suseconds_t; - -# if (!defined __MINGW64__) && (!defined __MINGW32__) -struct timeval { - time_t tv_sec; - suseconds_t tv_usec; -}; -# endif - -static int -gettimeofday(struct timeval *tv, void *tz) -{ - if (tz) { - mrb_assert(0); /* timezone is not supported */ - } - if (tv) { - union { - FILETIME ft; - unsigned __int64 u64; - } t; - GetSystemTimeAsFileTime(&t.ft); /* 100 ns intervals since Windows epoch */ - t.u64 -= UI64(116444736000000000); /* Unix epoch bias */ - t.u64 /= 10; /* to microseconds */ - tv->tv_sec = (time_t)(t.u64 / (1000 * 1000)); - tv->tv_usec = t.u64 % (1000 * 1000); - } - return 0; -} -# else -# include -# endif -#endif -#ifdef NO_GMTIME_R -#define gmtime_r(t,r) gmtime(t) -#define localtime_r(t,r) localtime(t) -#endif - -#ifndef USE_SYSTEM_TIMEGM -#define timegm my_timgm - -static unsigned int -is_leapyear(unsigned int y) -{ - return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0); -} - -static time_t -timegm(struct tm *tm) -{ - static const unsigned int ndays[2][12] = { - {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} - }; - time_t r = 0; - int i; - unsigned int *nday = (unsigned int*) ndays[is_leapyear(tm->tm_year+1900)]; - - for (i = 70; i < tm->tm_year; ++i) - r += is_leapyear(i+1900) ? 366*24*60*60 : 365*24*60*60; - for (i = 0; i < tm->tm_mon; ++i) - r += nday[i] * 24 * 60 * 60; - r += (tm->tm_mday - 1) * 24 * 60 * 60; - r += tm->tm_hour * 60 * 60; - r += tm->tm_min * 60; - r += tm->tm_sec; - return r; -} -#endif - -/* Since we are limited to using ISO C99, this implementation is based -* on time_t. That means the resolution of time is only precise to the -* second level. Also, there are only 2 timezones, namely UTC and LOCAL. -*/ - -enum mrb_timezone { - MRB_TIMEZONE_NONE = 0, - MRB_TIMEZONE_UTC = 1, - MRB_TIMEZONE_LOCAL = 2, - MRB_TIMEZONE_LAST = 3 -}; - -typedef struct mrb_timezone_name { - const char name[8]; - size_t len; -} mrb_timezone_name; - -static const mrb_timezone_name timezone_names[] = { - { "none", sizeof("none") - 1 }, - { "UTC", sizeof("UTC") - 1 }, - { "LOCAL", sizeof("LOCAL") - 1 }, -}; - -static const char mon_names[12][4] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", -}; - -static const char wday_names[7][4] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", -}; - -struct mrb_time { - time_t sec; - time_t usec; - enum mrb_timezone timezone; - struct tm datetime; -}; - -static const struct mrb_data_type mrb_time_type = { "Time", mrb_free }; - -/** Updates the datetime of a mrb_time based on it's timezone and -seconds setting. Returns self on success, NULL of failure. */ -static struct mrb_time* -mrb_time_update_datetime(struct mrb_time *self) -{ - struct tm *aid; - - if (self->timezone == MRB_TIMEZONE_UTC) { - aid = gmtime_r(&self->sec, &self->datetime); - } - else { - aid = localtime_r(&self->sec, &self->datetime); - } - if (!aid) return NULL; -#ifdef NO_GMTIME_R - self->datetime = *aid; /* copy data */ -#endif - - return self; -} - -static mrb_value -mrb_time_wrap(mrb_state *mrb, struct RClass *tc, struct mrb_time *tm) -{ - return mrb_obj_value(Data_Wrap_Struct(mrb, tc, &mrb_time_type, tm)); -} - - -/* Allocates a mrb_time object and initializes it. */ -static struct mrb_time* -time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone) -{ - struct mrb_time *tm; - - tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time)); - if (sizeof(time_t) == 4 && (sec > (double)INT32_MAX || (double)INT32_MIN > sec)) { - goto out_of_range; - } - if (sizeof(time_t) == 8 && (sec > (double)INT64_MAX || (double)INT64_MIN > sec)) { - goto out_of_range; - } - tm->sec = (time_t)sec; - if ((sec > 0 && tm->sec < 0) || (sec < 0 && (double)tm->sec > sec)) { - out_of_range: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, sec)); - } - tm->usec = (time_t)llround((sec - tm->sec) * 1.0e6 + usec); - while (tm->usec < 0) { - tm->sec--; - tm->usec += 1000000; - } - while (tm->usec >= 1000000) { - tm->sec++; - tm->usec -= 1000000; - } - tm->timezone = timezone; - mrb_time_update_datetime(tm); - - return tm; -} - -static mrb_value -mrb_time_make(mrb_state *mrb, struct RClass *c, double sec, double usec, enum mrb_timezone timezone) -{ - return mrb_time_wrap(mrb, c, time_alloc(mrb, sec, usec, timezone)); -} - -static struct mrb_time* -current_mrb_time(mrb_state *mrb) -{ - struct mrb_time *tm; - - tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); -#if defined(TIME_UTC) - { - struct timespec ts; - if (timespec_get(&ts, TIME_UTC) == 0) { - mrb_free(mrb, tm); - mrb_raise(mrb, E_RUNTIME_ERROR, "timespec_get() failed for unknown reasons"); - } - tm->sec = ts.tv_sec; - tm->usec = ts.tv_nsec / 1000; - } -#elif defined(NO_GETTIMEOFDAY) - { - static time_t last_sec = 0, last_usec = 0; - - tm->sec = time(NULL); - if (tm->sec != last_sec) { - last_sec = tm->sec; - last_usec = 0; - } - else { - /* add 1 usec to differentiate two times */ - last_usec += 1; - } - tm->usec = last_usec; - } -#else - { - struct timeval tv; - - gettimeofday(&tv, NULL); - tm->sec = tv.tv_sec; - tm->usec = tv.tv_usec; - } -#endif - tm->timezone = MRB_TIMEZONE_LOCAL; - mrb_time_update_datetime(tm); - - return tm; -} - -/* Allocates a new Time object with given millis value. */ -static mrb_value -mrb_time_now(mrb_state *mrb, mrb_value self) -{ - return mrb_time_wrap(mrb, mrb_class_ptr(self), current_mrb_time(mrb)); -} - -/* 15.2.19.6.1 */ -/* Creates an instance of time at the given time in seconds, etc. */ -static mrb_value -mrb_time_at(mrb_state *mrb, mrb_value self) -{ - mrb_float f, f2 = 0; - - mrb_get_args(mrb, "f|f", &f, &f2); - return mrb_time_make(mrb, mrb_class_ptr(self), f, f2, MRB_TIMEZONE_LOCAL); -} - -static struct mrb_time* -time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday, - mrb_int ahour, mrb_int amin, mrb_int asec, mrb_int ausec, - enum mrb_timezone timezone) -{ - time_t nowsecs; - struct tm nowtime = { 0 }; - - nowtime.tm_year = (int)ayear - 1900; - nowtime.tm_mon = (int)amonth - 1; - nowtime.tm_mday = (int)aday; - nowtime.tm_hour = (int)ahour; - nowtime.tm_min = (int)amin; - nowtime.tm_sec = (int)asec; - nowtime.tm_isdst = -1; - if (timezone == MRB_TIMEZONE_UTC) { - nowsecs = timegm(&nowtime); - } - else { - nowsecs = mktime(&nowtime); - } - if (nowsecs == (time_t)-1) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time."); - } - - return time_alloc(mrb, (double)nowsecs, ausec, timezone); -} - -/* 15.2.19.6.2 */ -/* Creates an instance of time at the given time in UTC. */ -static mrb_value -mrb_time_gm(mrb_state *mrb, mrb_value self) -{ - mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0, amin = 0, asec = 0, ausec = 0; - - mrb_get_args(mrb, "i|iiiiii", - &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); - return mrb_time_wrap(mrb, mrb_class_ptr(self), - time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_UTC)); -} - - -/* 15.2.19.6.3 */ -/* Creates an instance of time at the given time in local time zone. */ -static mrb_value -mrb_time_local(mrb_state *mrb, mrb_value self) -{ - mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0, amin = 0, asec = 0, ausec = 0; - - mrb_get_args(mrb, "i|iiiiii", - &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); - return mrb_time_wrap(mrb, mrb_class_ptr(self), - time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL)); -} - - -static mrb_value -mrb_time_eq(mrb_state *mrb, mrb_value self) -{ - mrb_value other; - struct mrb_time *tm1, *tm2; - mrb_bool eq_p; - - mrb_get_args(mrb, "o", &other); - tm1 = DATA_CHECK_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time); - eq_p = tm1 && tm2 && tm1->sec == tm2->sec && tm1->usec == tm2->usec; - - return mrb_bool_value(eq_p); -} - -static mrb_value -mrb_time_cmp(mrb_state *mrb, mrb_value self) -{ - mrb_value other; - struct mrb_time *tm1, *tm2; - - mrb_get_args(mrb, "o", &other); - tm1 = DATA_CHECK_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time); - if (!tm1 || !tm2) return mrb_nil_value(); - if (tm1->sec > tm2->sec) { - return mrb_fixnum_value(1); - } - else if (tm1->sec < tm2->sec) { - return mrb_fixnum_value(-1); - } - /* tm1->sec == tm2->sec */ - if (tm1->usec > tm2->usec) { - return mrb_fixnum_value(1); - } - else if (tm1->usec < tm2->usec) { - return mrb_fixnum_value(-1); - } - return mrb_fixnum_value(0); -} - -static mrb_value -mrb_time_plus(mrb_state *mrb, mrb_value self) -{ - mrb_float f; - struct mrb_time *tm; - - mrb_get_args(mrb, "f", &f); - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, (double)tm->usec, tm->timezone); -} - -static mrb_value -mrb_time_minus(mrb_state *mrb, mrb_value self) -{ - mrb_float f; - mrb_value other; - struct mrb_time *tm, *tm2; - - mrb_get_args(mrb, "o", &other); - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - - tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time); - if (tm2) { - f = (mrb_float)(tm->sec - tm2->sec) - + (mrb_float)(tm->usec - tm2->usec) / 1.0e6; - return mrb_float_value(mrb, f); - } - else { - mrb_get_args(mrb, "f", &f); - return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec-f, (double)tm->usec, tm->timezone); - } -} - -/* 15.2.19.7.30 */ -/* Returns week day number of time. */ -static mrb_value -mrb_time_wday(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_fixnum_value(tm->datetime.tm_wday); -} - -/* 15.2.19.7.31 */ -/* Returns year day number of time. */ -static mrb_value -mrb_time_yday(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_fixnum_value(tm->datetime.tm_yday + 1); -} - -/* 15.2.19.7.32 */ -/* Returns year of time. */ -static mrb_value -mrb_time_year(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_fixnum_value(tm->datetime.tm_year + 1900); -} - -/* 15.2.19.7.33 */ -/* Returns name of time's timezone. */ -static mrb_value -mrb_time_zone(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - if (tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value(); - if (tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value(); - return mrb_str_new_static(mrb, - timezone_names[tm->timezone].name, - timezone_names[tm->timezone].len); -} - -/* 15.2.19.7.4 */ -/* Returns a string that describes the time. */ -static mrb_value -mrb_time_asctime(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - struct tm *d; - char buf[256]; - int len; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - d = &tm->datetime; - len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d", - wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday, - d->tm_hour, d->tm_min, d->tm_sec, - tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "", - d->tm_year + 1900); - return mrb_str_new(mrb, buf, len); -} - -/* 15.2.19.7.6 */ -/* Returns the day in the month of the time. */ -static mrb_value -mrb_time_day(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - if (!tm) return mrb_nil_value(); - return mrb_fixnum_value(tm->datetime.tm_mday); -} - - -/* 15.2.19.7.7 */ -/* Returns true if daylight saving was applied for this time. */ -static mrb_value -mrb_time_dst_p(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_bool_value(tm->datetime.tm_isdst); -} - -/* 15.2.19.7.8 */ -/* 15.2.19.7.10 */ -/* Returns the Time object of the UTC(GMT) timezone. */ -static mrb_value -mrb_time_getutc(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm, *tm2; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); - *tm2 = *tm; - tm2->timezone = MRB_TIMEZONE_UTC; - mrb_time_update_datetime(tm2); - return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2); -} - -/* 15.2.19.7.9 */ -/* Returns the Time object of the LOCAL timezone. */ -static mrb_value -mrb_time_getlocal(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm, *tm2; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm)); - *tm2 = *tm; - tm2->timezone = MRB_TIMEZONE_LOCAL; - mrb_time_update_datetime(tm2); - return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2); -} - -/* 15.2.19.7.15 */ -/* Returns hour of time. */ -static mrb_value -mrb_time_hour(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_fixnum_value(tm->datetime.tm_hour); -} - -/* 15.2.19.7.16 */ -/* Initializes a time by setting the amount of milliseconds since the epoch.*/ -static mrb_value -mrb_time_initialize(mrb_state *mrb, mrb_value self) -{ - mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0, - amin = 0, asec = 0, ausec = 0; - int n; - struct mrb_time *tm; - - tm = (struct mrb_time*)DATA_PTR(self); - if (tm) { - mrb_free(mrb, tm); - } - mrb_data_init(self, NULL, &mrb_time_type); - - n = mrb_get_args(mrb, "|iiiiiii", - &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec); - if (n == 0) { - tm = current_mrb_time(mrb); - } - else { - tm = time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL); - } - mrb_data_init(self, tm, &mrb_time_type); - return self; -} - -/* 15.2.19.7.17(x) */ -/* Initializes a copy of this time object. */ -static mrb_value -mrb_time_initialize_copy(mrb_state *mrb, mrb_value copy) -{ - mrb_value src; - - mrb_get_args(mrb, "o", &src); - if (mrb_obj_equal(mrb, copy, src)) return copy; - if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) { - mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class"); - } - if (!DATA_PTR(copy)) { - mrb_data_init(copy, mrb_malloc(mrb, sizeof(struct mrb_time)), &mrb_time_type); - } - *(struct mrb_time *)DATA_PTR(copy) = *(struct mrb_time *)DATA_PTR(src); - return copy; -} - -/* 15.2.19.7.18 */ -/* Sets the timezone attribute of the Time object to LOCAL. */ -static mrb_value -mrb_time_localtime(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - tm->timezone = MRB_TIMEZONE_LOCAL; - mrb_time_update_datetime(tm); - return self; -} - -/* 15.2.19.7.19 */ -/* Returns day of month of time. */ -static mrb_value -mrb_time_mday(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_fixnum_value(tm->datetime.tm_mday); -} - -/* 15.2.19.7.20 */ -/* Returns minutes of time. */ -static mrb_value -mrb_time_min(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_fixnum_value(tm->datetime.tm_min); -} - -/* 15.2.19.7.21 and 15.2.19.7.22 */ -/* Returns month of time. */ -static mrb_value -mrb_time_mon(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_fixnum_value(tm->datetime.tm_mon + 1); -} - -/* 15.2.19.7.23 */ -/* Returns seconds in minute of time. */ -static mrb_value -mrb_time_sec(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_fixnum_value(tm->datetime.tm_sec); -} - - -/* 15.2.19.7.24 */ -/* Returns a Float with the time since the epoch in seconds. */ -static mrb_value -mrb_time_to_f(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_float_value(mrb, (mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6); -} - -/* 15.2.19.7.25 */ -/* Returns a Fixnum with the time since the epoch in seconds. */ -static mrb_value -mrb_time_to_i(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - if (tm->sec > MRB_INT_MAX || tm->sec < MRB_INT_MIN) { - return mrb_float_value(mrb, (mrb_float)tm->sec); - } - return mrb_fixnum_value((mrb_int)tm->sec); -} - -/* 15.2.19.7.26 */ -/* Returns a Float with the time since the epoch in microseconds. */ -static mrb_value -mrb_time_usec(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - if (tm->usec > MRB_INT_MAX || tm->usec < MRB_INT_MIN) { - return mrb_float_value(mrb, (mrb_float)tm->usec); - } - return mrb_fixnum_value((mrb_int)tm->usec); -} - -/* 15.2.19.7.27 */ -/* Sets the timezone attribute of the Time object to UTC. */ -static mrb_value -mrb_time_utc(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - tm->timezone = MRB_TIMEZONE_UTC; - mrb_time_update_datetime(tm); - return self; -} - -/* 15.2.19.7.28 */ -/* Returns true if this time is in the UTC timezone false if not. */ -static mrb_value -mrb_time_utc_p(mrb_state *mrb, mrb_value self) -{ - struct mrb_time *tm; - - tm = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time); - return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC); -} - - -void -mrb_mruby_time_gem_init(mrb_state* mrb) -{ - struct RClass *tc; - /* ISO 15.2.19.2 */ - tc = mrb_define_class(mrb, "Time", mrb->object_class); - MRB_SET_INSTANCE_TT(tc, MRB_TT_DATA); - mrb_include_module(mrb, tc, mrb_module_get(mrb, "Comparable")); - mrb_define_class_method(mrb, tc, "at", mrb_time_at, MRB_ARGS_ARG(1, 1)); /* 15.2.19.6.1 */ - mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.2 */ - mrb_define_class_method(mrb, tc, "local", mrb_time_local, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.3 */ - mrb_define_class_method(mrb, tc, "mktime", mrb_time_local, MRB_ARGS_ARG(1,6));/* 15.2.19.6.4 */ - mrb_define_class_method(mrb, tc, "now", mrb_time_now, MRB_ARGS_NONE()); /* 15.2.19.6.5 */ - mrb_define_class_method(mrb, tc, "utc", mrb_time_gm, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.6 */ - - mrb_define_method(mrb, tc, "==" , mrb_time_eq , MRB_ARGS_REQ(1)); - mrb_define_method(mrb, tc, "<=>" , mrb_time_cmp , MRB_ARGS_REQ(1)); /* 15.2.19.7.1 */ - mrb_define_method(mrb, tc, "+" , mrb_time_plus , MRB_ARGS_REQ(1)); /* 15.2.19.7.2 */ - mrb_define_method(mrb, tc, "-" , mrb_time_minus , MRB_ARGS_REQ(1)); /* 15.2.19.7.3 */ - mrb_define_method(mrb, tc, "to_s" , mrb_time_asctime, MRB_ARGS_NONE()); - mrb_define_method(mrb, tc, "inspect", mrb_time_asctime, MRB_ARGS_NONE()); - mrb_define_method(mrb, tc, "asctime", mrb_time_asctime, MRB_ARGS_NONE()); /* 15.2.19.7.4 */ - mrb_define_method(mrb, tc, "ctime" , mrb_time_asctime, MRB_ARGS_NONE()); /* 15.2.19.7.5 */ - mrb_define_method(mrb, tc, "day" , mrb_time_day , MRB_ARGS_NONE()); /* 15.2.19.7.6 */ - mrb_define_method(mrb, tc, "dst?" , mrb_time_dst_p , MRB_ARGS_NONE()); /* 15.2.19.7.7 */ - mrb_define_method(mrb, tc, "getgm" , mrb_time_getutc , MRB_ARGS_NONE()); /* 15.2.19.7.8 */ - mrb_define_method(mrb, tc, "getlocal",mrb_time_getlocal,MRB_ARGS_NONE()); /* 15.2.19.7.9 */ - mrb_define_method(mrb, tc, "getutc" , mrb_time_getutc , MRB_ARGS_NONE()); /* 15.2.19.7.10 */ - mrb_define_method(mrb, tc, "gmt?" , mrb_time_utc_p , MRB_ARGS_NONE()); /* 15.2.19.7.11 */ - mrb_define_method(mrb, tc, "gmtime" , mrb_time_utc , MRB_ARGS_NONE()); /* 15.2.19.7.13 */ - mrb_define_method(mrb, tc, "hour" , mrb_time_hour, MRB_ARGS_NONE()); /* 15.2.19.7.15 */ - mrb_define_method(mrb, tc, "localtime", mrb_time_localtime, MRB_ARGS_NONE()); /* 15.2.19.7.18 */ - mrb_define_method(mrb, tc, "mday" , mrb_time_mday, MRB_ARGS_NONE()); /* 15.2.19.7.19 */ - mrb_define_method(mrb, tc, "min" , mrb_time_min, MRB_ARGS_NONE()); /* 15.2.19.7.20 */ - - mrb_define_method(mrb, tc, "mon" , mrb_time_mon, MRB_ARGS_NONE()); /* 15.2.19.7.21 */ - mrb_define_method(mrb, tc, "month", mrb_time_mon, MRB_ARGS_NONE()); /* 15.2.19.7.22 */ - - mrb_define_method(mrb, tc, "sec" , mrb_time_sec, MRB_ARGS_NONE()); /* 15.2.19.7.23 */ - mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, MRB_ARGS_NONE()); /* 15.2.19.7.25 */ - mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, MRB_ARGS_NONE()); /* 15.2.19.7.24 */ - mrb_define_method(mrb, tc, "usec", mrb_time_usec, MRB_ARGS_NONE()); /* 15.2.19.7.26 */ - mrb_define_method(mrb, tc, "utc" , mrb_time_utc, MRB_ARGS_NONE()); /* 15.2.19.7.27 */ - mrb_define_method(mrb, tc, "utc?", mrb_time_utc_p,MRB_ARGS_NONE()); /* 15.2.19.7.28 */ - mrb_define_method(mrb, tc, "wday", mrb_time_wday, MRB_ARGS_NONE()); /* 15.2.19.7.30 */ - mrb_define_method(mrb, tc, "yday", mrb_time_yday, MRB_ARGS_NONE()); /* 15.2.19.7.31 */ - mrb_define_method(mrb, tc, "year", mrb_time_year, MRB_ARGS_NONE()); /* 15.2.19.7.32 */ - mrb_define_method(mrb, tc, "zone", mrb_time_zone, MRB_ARGS_NONE()); /* 15.2.19.7.33 */ - - mrb_define_method(mrb, tc, "initialize", mrb_time_initialize, MRB_ARGS_REQ(1)); /* 15.2.19.7.16 */ - mrb_define_method(mrb, tc, "initialize_copy", mrb_time_initialize_copy, MRB_ARGS_REQ(1)); /* 15.2.19.7.17 */ - - /* - methods not available: - gmt_offset(15.2.19.7.12) - gmtoff(15.2.19.7.14) - utc_offset(15.2.19.7.29) - */ -} - -void -mrb_mruby_time_gem_final(mrb_state* mrb) -{ -} diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-time/test/time.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-time/test/time.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-time/test/time.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-time/test/time.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,213 +0,0 @@ -## -# Time ISO Test - -assert('Time.new', '15.2.3.3.3') do - Time.new.class == Time -end - -assert('Time', '15.2.19') do - Time.class == Class -end - -assert('Time.at', '15.2.19.6.1') do - Time.at(1300000000.0) -end - -assert('Time.gm', '15.2.19.6.2') do - Time.gm(2012, 12, 23) -end - -assert('Time.local', '15.2.19.6.3') do - Time.local(2012, 12, 23) -end - -assert('Time.mktime', '15.2.19.6.4') do - Time.mktime(2012, 12, 23) -end - -assert('Time.now', '15.2.19.6.5') do - Time.now.class == Time -end - -assert('Time.utc', '15.2.19.6.6') do - Time.utc(2012, 12, 23) -end - -assert('Time#+', '15.2.19.7.1') do - t1 = Time.at(1300000000.0) - t2 = t1.+(60) - - t2.utc.asctime == "Sun Mar 13 07:07:40 UTC 2011" -end - -assert('Time#-', '15.2.19.7.2') do - t1 = Time.at(1300000000.0) - t2 = t1.-(60) - - t2.utc.asctime == "Sun Mar 13 07:05:40 UTC 2011" -end - -assert('Time#<=>', '15.2.19.7.3') do - t1 = Time.at(1300000000.0) - t2 = Time.at(1400000000.0) - t3 = Time.at(1500000000.0) - - t2.<=>(t1) == 1 and - t2.<=>(t2) == 0 and - t2.<=>(t3) == -1 and - t2.<=>(nil) == nil -end - -assert('Time#asctime', '15.2.19.7.4') do - Time.at(1300000000.0).utc.asctime == "Sun Mar 13 07:06:40 UTC 2011" -end - -assert('Time#ctime', '15.2.19.7.5') do - Time.at(1300000000.0).utc.ctime == "Sun Mar 13 07:06:40 UTC 2011" -end - -assert('Time#day', '15.2.19.7.6') do - Time.gm(2012, 12, 23).day == 23 -end - -assert('Time#dst?', '15.2.19.7.7') do - not Time.gm(2012, 12, 23).utc.dst? -end - -assert('Time#getgm', '15.2.19.7.8') do - Time.at(1300000000.0).getgm.asctime == "Sun Mar 13 07:06:40 UTC 2011" -end - -assert('Time#getlocal', '15.2.19.7.9') do - t1 = Time.at(1300000000.0) - t2 = Time.at(1300000000.0) - t3 = t1.getlocal - - t1 == t3 and t3 == t2.getlocal -end - -assert('Time#getutc', '15.2.19.7.10') do - Time.at(1300000000.0).getutc.asctime == "Sun Mar 13 07:06:40 UTC 2011" -end - -assert('Time#gmt?', '15.2.19.7.11') do - Time.at(1300000000.0).utc.gmt? -end - -# ATM not implemented -# assert('Time#gmt_offset', '15.2.19.7.12') do - -assert('Time#gmtime', '15.2.19.7.13') do - Time.at(1300000000.0).gmtime -end - -# ATM not implemented -# assert('Time#gmtoff', '15.2.19.7.14') do - -assert('Time#hour', '15.2.19.7.15') do - Time.gm(2012, 12, 23, 7, 6).hour == 7 -end - -# ATM doesn't really work -# assert('Time#initialize', '15.2.19.7.16') do - -assert('Time#initialize_copy', '15.2.19.7.17') do - time_tmp_2 = Time.at(7.0e6) - time_tmp_2.clone == time_tmp_2 -end - -assert('Time#localtime', '15.2.19.7.18') do - t1 = Time.at(1300000000.0) - t2 = Time.at(1300000000.0) - - t1.localtime - t1 == t2.getlocal -end - -assert('Time#mday', '15.2.19.7.19') do - Time.gm(2012, 12, 23).mday == 23 -end - -assert('Time#min', '15.2.19.7.20') do - Time.gm(2012, 12, 23, 7, 6).min == 6 -end - -assert('Time#mon', '15.2.19.7.21') do - Time.gm(2012, 12, 23).mon == 12 -end - -assert('Time#month', '15.2.19.7.22') do - Time.gm(2012, 12, 23).month == 12 -end - -assert('Times#sec', '15.2.19.7.23') do - Time.gm(2012, 12, 23, 7, 6, 40).sec == 40 -end - -assert('Time#to_f', '15.2.19.7.24') do - Time.at(1300000000.0).to_f == 1300000000.0 -end - -assert('Time#to_i', '15.2.19.7.25') do - Time.at(1300000000.0).to_i == 1300000000 -end - -assert('Time#usec', '15.2.19.7.26') do - Time.at(1300000000.0).usec == 0 -end - -assert('Time#utc', '15.2.19.7.27') do - Time.at(1300000000.0).utc -end - -assert('Time#utc?', '15.2.19.7.28') do - Time.at(1300000000.0).utc.utc? -end - -# ATM not implemented -# assert('Time#utc_offset', '15.2.19.7.29') do - -assert('Time#wday', '15.2.19.7.30') do - Time.gm(2012, 12, 23).wday == 0 -end - -assert('Time#yday', '15.2.19.7.31') do - Time.gm(2012, 12, 23).yday == 358 -end - -assert('Time#year', '15.2.19.7.32') do - Time.gm(2012, 12, 23).year == 2012 -end - -assert('Time#zone', '15.2.19.7.33') do - Time.at(1300000000.0).utc.zone == 'UTC' -end - -# Not ISO specified - -assert('Time#to_s') do - Time.at(1300000000.0).utc.to_s == "Sun Mar 13 07:06:40 UTC 2011" -end - -assert('Time#inspect') do - Time.at(1300000000.0).utc.inspect == "Sun Mar 13 07:06:40 UTC 2011" -end - -assert('day of week methods') do - t = Time.gm(2012, 12, 24) - assert_false t.sunday? - assert_true t.monday? - assert_false t.tuesday? - assert_false t.wednesday? - assert_false t.thursday? - assert_false t.friday? - assert_false t.saturday? -end - -assert('2000 times 500us make a second') do - t = Time.utc 2015 - 2000.times do - t += 0.0005 - end - t.usec == 0 -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -MRuby::Gem::Specification.new('mruby-toplevel-ext') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'toplevel object (main) methods extension' -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ - -def self.include (*modules) - self.class.include(*modules) -end - -def self.private(*methods) -end -def self.protected(*methods) -end -def self.public(*methods) -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb --- nghttp2-1.13.0/third-party/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -## -# Toplevel Self(Ext) Test - -assert('Toplevel#include') do - module ToplevelTestModule1 - def method_foo - :foo - end - - CONST_BAR = :bar - end - - module ToplevelTestModule2 - CONST_BAR = :bar2 - end - - self.include ToplevelTestModule2, ToplevelTestModule1 - - assert_true self.class.included_modules.include?( ToplevelTestModule1 ) - assert_true self.class.included_modules.include?( ToplevelTestModule2 ) - assert_equal :foo, method_foo - assert_equal :bar2, CONST_BAR -end - diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/array.rb nghttp2-0.6.7/third-party/mruby/mrblib/array.rb --- nghttp2-1.13.0/third-party/mruby/mrblib/array.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/array.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,206 +0,0 @@ -## -# Array -# -# ISO 15.2.12 -class Array - - ## - # Calls the given block for each element of +self+ - # and pass the respective element. - # - # ISO 15.2.12.5.10 - def each(&block) - return to_enum :each unless block_given? - - idx, length = -1, self.length-1 - while idx < length and length <= self.length and length = self.length-1 - elm = self[idx += 1] - unless elm - if elm.nil? and length >= self.length - break - end - end - block.call(elm) - end - self - end - - ## - # Calls the given block for each element of +self+ - # and pass the index of the respective element. - # - # ISO 15.2.12.5.11 - def each_index(&block) - return to_enum :each_index unless block_given? - - idx = 0 - while idx < length - block.call(idx) - idx += 1 - end - self - end - - ## - # Calls the given block for each element of +self+ - # and pass the respective element. Each element will - # be replaced by the resulting values. - # - # ISO 15.2.12.5.7 - def collect!(&block) - return to_enum :collect! unless block_given? - - self.each_index { |idx| self[idx] = block.call(self[idx]) } - self - end - - ## - # Alias for collect! - # - # ISO 15.2.12.5.20 - alias map! collect! - - ## - # Private method for Array creation. - # - # ISO 15.2.12.5.15 - def initialize(size=0, obj=nil, &block) - raise TypeError, "expected Integer for 1st argument" unless size.kind_of? Integer - raise ArgumentError, "negative array size" if size < 0 - - self.clear - if size > 0 - self[size - 1] = nil # allocate - - idx = 0 - while idx < size - self[idx] = (block)? block.call(idx): obj - idx += 1 - end - end - - self - end - - def _inspect - return "[]" if self.size == 0 - "["+self.map{|x|x.inspect}.join(", ")+"]" - end - ## - # Return the contents of this array as a string. - # - # ISO 15.2.12.5.31 (x) - def inspect - begin - self._inspect - rescue SystemStackError - "[...]" - end - end - # ISO 15.2.12.5.32 (x) - alias to_s inspect - - ## - # Equality---Two arrays are equal if they contain the same number - # of elements and if each element is equal to (according to - # Object.==) the corresponding element in the other array. - # - # ISO 15.2.12.5.33 (x) - def ==(other) - other = self.__ary_eq(other) - return false if other == false - return true if other == true - len = self.size - i = 0 - while i < len - return false if self[i] != other[i] - i += 1 - end - return true - end - - ## - # Returns true if +self+ and _other_ are the same object, - # or are both arrays with the same content. - # - # ISO 15.2.12.5.34 (x) - def eql?(other) - other = self.__ary_eq(other) - return false if other == false - return true if other == true - len = self.size - i = 0 - while i < len - return false unless self[i].eql?(other[i]) - i += 1 - end - return true - end - - ## - # Comparison---Returns an integer (-1, 0, or +1) - # if this array is less than, equal to, or greater than other_ary. - # Each object in each array is compared (using <=>). If any value isn't - # equal, then that inequality is the return value. If all the - # values found are equal, then the return is based on a - # comparison of the array lengths. Thus, two arrays are - # "equal" according to Array#<=> if and only if they have - # the same length and the value of each element is equal to the - # value of the corresponding element in the other array. - # - # ISO 15.2.12.5.36 (x) - def <=>(other) - other = self.__ary_cmp(other) - return 0 if 0 == other - return nil if nil == other - - len = self.size - n = other.size - len = n if len > n - i = 0 - while i < len - n = (self[i] <=> other[i]) - return n if n.nil? || n != 0 - i += 1 - end - len = self.size - other.size - if len == 0 - 0 - elsif len > 0 - 1 - else - -1 - end - end - - ## - # Delete element with index +key+ - def delete(key, &block) - while i = self.index(key) - self.delete_at(i) - ret = key - end - return block.call if ret.nil? && block - ret - end - - # internal method to convert multi-value to single value - def __svalue - return self.first if self.size < 2 - self - end -end - -## -# Array is enumerable -class Array - # ISO 15.2.12.3 - include Enumerable - - ## - # Sort all elements and replace +self+ with these - # elements. - def sort!(&block) - self.replace(self.sort(&block)) - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/class.rb nghttp2-0.6.7/third-party/mruby/mrblib/class.rb --- nghttp2-1.13.0/third-party/mruby/mrblib/class.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/class.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -class Module - # 15.2.2.4.12 - def attr_accessor(*names) - attr_reader(*names) - attr_writer(*names) - end - # 15.2.2.4.11 - def attr(name) - attr_reader(name) - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/compar.rb nghttp2-0.6.7/third-party/mruby/mrblib/compar.rb --- nghttp2-1.13.0/third-party/mruby/mrblib/compar.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/compar.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -## -# Comparable -# -# ISO 15.3.3 -module Comparable - - ## - # Return true if +self+ is less - # than +other+. Otherwise return - # false. - # - # ISO 15.3.3.2.1 - def < other - cmp = self <=> other - if cmp.nil? - raise ArgumentError, "comparison of #{self.class} with #{other.class} failed" - end - cmp < 0 - end - - ## - # Return true if +self+ is less - # than or equal to +other+. - # Otherwise return false. - # - # ISO 15.3.3.2.2 - def <= other - cmp = self <=> other - if cmp.nil? - raise ArgumentError, "comparison of #{self.class} with #{other.class} failed" - end - cmp <= 0 - end - - ## - # Return true if +self+ is equal - # to +other+. Otherwise return - # false. - # - # ISO 15.3.3.2.3 - def == other - cmp = self <=> other - cmp == 0 - end - - ## - # Return true if +self+ is greater - # than +other+. Otherwise return - # false. - # - # ISO 15.3.3.2.4 - def > other - cmp = self <=> other - if cmp.nil? - raise ArgumentError, "comparison of #{self.class} with #{other.class} failed" - end - cmp > 0 - end - - ## - # Return true if +self+ is greater - # than or equal to +other+. - # Otherwise return false. - # - # ISO 15.3.3.2.5 - def >= other - cmp = self <=> other - if cmp.nil? - raise ArgumentError, "comparison of #{self.class} with #{other.class} failed" - end - cmp >= 0 - end - - ## - # Return true if +self+ is greater - # than or equal to +min+ and - # less than or equal to +max+. - # Otherwise return false. - # - # ISO 15.3.3.2.6 - def between?(min, max) - self >= min and self <= max - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/enum.rb nghttp2-0.6.7/third-party/mruby/mrblib/enum.rb --- nghttp2-1.13.0/third-party/mruby/mrblib/enum.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/enum.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,392 +0,0 @@ -## -# Enumerable -# -# The Enumerable mixin provides collection classes with -# several traversal and searching methods, and with the ability to -# sort. The class must provide a method `each`, which -# yields successive members of the collection. If -# {Enumerable#max}, {#min}, or -# {#sort} is used, the objects in the collection must also -# implement a meaningful `<=>` operator, as these methods -# rely on an ordering between members of the collection. -# -# @ISO 15.3.2 -module Enumerable - - ## - # Call the given block for each element - # which is yield by +each+. Return false - # if one block value is false. Otherwise - # return true. If no block is given and - # +self+ is false return false. - # - # ISO 15.3.2.2.1 - def all?(&block) - if block - self.each{|*val| return false unless block.call(*val)} - else - self.each{|*val| return false unless val.__svalue} - end - true - end - - ## - # Call the given block for each element - # which is yield by +each+. Return true - # if one block value is true. Otherwise - # return false. If no block is given and - # +self+ is true object return true. - # - # ISO 15.3.2.2.2 - def any?(&block) - if block - self.each{|*val| return true if block.call(*val)} - else - self.each{|*val| return true if val.__svalue} - end - false - end - - ## - # Call the given block for each element - # which is yield by +each+. Append all - # values of each block together and - # return this value. - # - # ISO 15.3.2.2.3 - def collect(&block) - return to_enum :collect unless block - - ary = [] - self.each{|*val| ary.push(block.call(*val))} - ary - end - - ## - # Call the given block for each element - # which is yield by +each+. Return - # +ifnone+ if no block value was true. - # Otherwise return the first block value - # which had was true. - # - # ISO 15.3.2.2.4 - def detect(ifnone=nil, &block) - ret = ifnone - self.each{|*val| - if block.call(*val) - ret = val.__svalue - break - end - } - ret - end - - ## - # Call the given block for each element - # which is yield by +each+. Pass an - # index to the block which starts at 0 - # and increase by 1 for each element. - # - # ISO 15.3.2.2.5 - def each_with_index(&block) - return to_enum :each_with_index unless block - - i = 0 - self.each{|*val| - block.call(val.__svalue, i) - i += 1 - } - self - end - - ## - # Return an array of all elements which - # are yield by +each+. - # - # ISO 15.3.2.2.6 - def entries - ary = [] - self.each{|*val| - # __svalue is an internal method - ary.push val.__svalue - } - ary - end - - ## - # Alias for find - # - # ISO 15.3.2.2.7 - alias find detect - - ## - # Call the given block for each element - # which is yield by +each+. Return an array - # which contains all elements whose block - # value was true. - # - # ISO 15.3.2.2.8 - def find_all(&block) - return to_enum :find_all unless block - - ary = [] - self.each{|*val| - ary.push(val.__svalue) if block.call(*val) - } - ary - end - - ## - # Call the given block for each element - # which is yield by +each+ and which return - # value was true when invoking === with - # +pattern+. Return an array with all - # elements or the respective block values. - # - # ISO 15.3.2.2.9 - def grep(pattern, &block) - ary = [] - self.each{|*val| - sv = val.__svalue - if pattern === sv - ary.push((block)? block.call(*val): sv) - end - } - ary - end - - ## - # Return true if at least one element which - # is yield by +each+ returns a true value - # by invoking == with +obj+. Otherwise return - # false. - # - # ISO 15.3.2.2.10 - def include?(obj) - self.each{|*val| - return true if val.__svalue == obj - } - false - end - - ## - # Call the given block for each element - # which is yield by +each+. Return value - # is the sum of all block values. Pass - # to each block the current sum and the - # current element. - # - # ISO 15.3.2.2.11 - def inject(*args, &block) - raise ArgumentError, "too many arguments" if args.size > 2 - if Symbol === args[-1] - sym = args[-1] - block = ->(x,y){x.__send__(sym,y)} - args.pop - end - if args.empty? - flag = true # no initial argument - result = nil - else - flag = false - result = args[0] - end - self.each{|*val| - val = val.__svalue - if flag - # push first element as initial - flag = false - result = val - else - result = block.call(result, val) - end - } - result - end - alias reduce inject - - ## - # Alias for collect - # - # ISO 15.3.2.2.12 - alias map collect - - ## - # Return the maximum value of all elements - # yield by +each+. If no block is given <=> - # will be invoked to define this value. If - # a block is given it will be used instead. - # - # ISO 15.3.2.2.13 - def max(&block) - flag = true # 1st element? - result = nil - self.each{|*val| - val = val.__svalue - if flag - # 1st element - result = val - flag = false - else - if block - result = val if block.call(val, result) > 0 - else - result = val if (val <=> result) > 0 - end - end - } - result - end - - ## - # Return the minimum value of all elements - # yield by +each+. If no block is given <=> - # will be invoked to define this value. If - # a block is given it will be used instead. - # - # ISO 15.3.2.2.14 - def min(&block) - flag = true # 1st element? - result = nil - self.each{|*val| - val = val.__svalue - if flag - # 1st element - result = val - flag = false - else - if block - result = val if block.call(val, result) < 0 - else - result = val if (val <=> result) < 0 - end - end - } - result - end - - ## - # Alias for include? - # - # ISO 15.3.2.2.15 - alias member? include? - - ## - # Call the given block for each element - # which is yield by +each+. Return an - # array which contains two arrays. The - # first array contains all elements - # whose block value was true. The second - # array contains all elements whose - # block value was false. - # - # ISO 15.3.2.2.16 - def partition(&block) - ary_T = [] - ary_F = [] - self.each{|*val| - if block.call(*val) - ary_T.push(val.__svalue) - else - ary_F.push(val.__svalue) - end - } - [ary_T, ary_F] - end - - ## - # Call the given block for each element - # which is yield by +each+. Return an - # array which contains only the elements - # whose block value was false. - # - # ISO 15.3.2.2.17 - def reject(&block) - ary = [] - self.each{|*val| - ary.push(val.__svalue) unless block.call(*val) - } - ary - end - - ## - # Alias for find_all. - # - # ISO 15.3.2.2.18 - alias select find_all - - ## - # TODO - # Does this OK? Please test it. - def __sort_sub__(sorted, work, src_ary, head, tail, &block) - if head == tail - sorted[head] = work[head] if src_ary == 1 - return - end - - # on current step, which is a src ary? - if src_ary == 0 - src, dst = sorted, work - else - src, dst = work, sorted - end - - key = src[head] # key value for dividing values - i, j = head, tail # position to store on the dst ary - - (head + 1).upto(tail){|idx| - if ((block)? block.call(src[idx], key): (src[idx] <=> key)) > 0 - # larger than key - dst[j] = src[idx] - j -= 1 - else - dst[i] = src[idx] - i += 1 - end - } - - sorted[i] = key - - # sort each sub-array - src_ary = (src_ary + 1) % 2 # exchange a src ary - __sort_sub__(sorted, work, src_ary, head, i - 1, &block) if i > head - __sort_sub__(sorted, work, src_ary, i + 1, tail, &block) if i < tail - end -# private :__sort_sub__ - - ## - # Return a sorted array of all elements - # which are yield by +each+. If no block - # is given <=> will be invoked on each - # element to define the order. Otherwise - # the given block will be used for - # sorting. - # - # ISO 15.3.2.2.19 - def sort(&block) - ary = [] - self.each{|*val| ary.push(val.__svalue)} - if ary.size > 1 - __sort_sub__(ary, ::Array.new(ary.size), 0, 0, ary.size - 1, &block) - end - ary - end - - ## - # Alias for entries. - # - # ISO 15.3.2.2.20 - alias to_a entries - - # redefine #hash 15.3.1.3.15 - def hash - h = 12347 - i = 0 - self.each do |e| - n = e.hash << (i % 16) - h ^= n - i += 1 - end - h - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/error.rb nghttp2-0.6.7/third-party/mruby/mrblib/error.rb --- nghttp2-1.13.0/third-party/mruby/mrblib/error.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/error.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -# ISO 15.2.24 -class ArgumentError < StandardError -end - -# ISO 15.2.25 -class LocalJumpError < StandardError -end - -# ISO 15.2.26 -class RangeError < StandardError -end - -class FloatDomainError < RangeError -end - -# ISO 15.2.26 -class RegexpError < StandardError -end - -# ISO 15.2.29 -class TypeError < StandardError -end - -# ISO 15.2.31 -class NameError < StandardError - attr_accessor :name - - def initialize(message=nil, name=nil) - @name = name - super(message) - end -end - -# ISO 15.2.32 -class NoMethodError < NameError - attr_reader :args - - def initialize(message=nil, name=nil, args=nil) - @args = args - super message, name - end -end - -# ISO 15.2.33 -class IndexError < StandardError -end - -class KeyError < IndexError -end - -class NotImplementedError < ScriptError -end - -class StopIteration < IndexError - attr_accessor :result -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/hash.rb nghttp2-0.6.7/third-party/mruby/mrblib/hash.rb --- nghttp2-1.13.0/third-party/mruby/mrblib/hash.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/hash.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,357 +0,0 @@ -## -# Hash -# -# ISO 15.2.13 -class Hash - ## - # Equality---Two hashes are equal if they each contain the same number - # of keys and if each key-value pair is equal to (according to - # Object#==) the corresponding elements in the other - # hash. - # - # ISO 15.2.13.4.1 - def ==(hash) - return true if self.equal?(hash) - begin - hash = hash.to_hash - rescue NoMethodError - return false - end - return false if self.size != hash.size - self.each do |k,v| - return false unless hash.key?(k) - return false unless self[k] == hash[k] - end - return true - end - - ## - # Returns true if hash and other are - # both hashes with the same content compared by eql?. - # - # ISO 15.2.13.4.32 (x) - def eql?(hash) - return true if self.equal?(hash) - begin - hash = hash.to_hash - rescue NoMethodError - return false - end - return false if self.size != hash.size - self.each do |k,v| - return false unless hash.key?(k) - return false unless self[k].eql?(hash[k]) - end - return true - end - - ## - # Delete the element with the key +key+. - # Return the value of the element if +key+ - # was found. Return nil if nothing was - # found. If a block is given, call the - # block with the value of the element. - # - # ISO 15.2.13.4.8 - def delete(key, &block) - if block && !self.has_key?(key) - block.call(key) - else - self.__delete(key) - end - end - - ## - # Calls the given block for each element of +self+ - # and pass the key and value of each element. - # - # call-seq: - # hsh.each {| key, value | block } -> hsh - # hsh.each_pair {| key, value | block } -> hsh - # hsh.each -> an_enumerator - # hsh.each_pair -> an_enumerator - # - # - # If no block is given, an enumerator is returned instead. - # - # h = { "a" => 100, "b" => 200 } - # h.each {|key, value| puts "#{key} is #{value}" } - # - # produces: - # - # a is 100 - # b is 200 - # - # ISO 15.2.13.4.9 - def each(&block) - return to_enum :each unless block_given? - - keys = self.keys - vals = self.values - len = self.size - i = 0 - while i < len - block.call [keys[i], vals[i]] - i += 1 - end - self - end - - ## - # Calls the given block for each element of +self+ - # and pass the key of each element. - # - # call-seq: - # hsh.each_key {| key | block } -> hsh - # hsh.each_key -> an_enumerator - # - # If no block is given, an enumerator is returned instead. - # - # h = { "a" => 100, "b" => 200 } - # h.each_key {|key| puts key } - # - # produces: - # - # a - # b - # - # ISO 15.2.13.4.10 - def each_key(&block) - return to_enum :each_key unless block_given? - - self.keys.each{|k| block.call(k)} - self - end - - ## - # Calls the given block for each element of +self+ - # and pass the value of each element. - # - # call-seq: - # hsh.each_value {| value | block } -> hsh - # hsh.each_value -> an_enumerator - # - # If no block is given, an enumerator is returned instead. - # - # h = { "a" => 100, "b" => 200 } - # h.each_value {|value| puts value } - # - # produces: - # - # 100 - # 200 - # - # ISO 15.2.13.4.11 - def each_value(&block) - return to_enum :each_value unless block_given? - - self.keys.each{|k| block.call(self[k])} - self - end - - ## - # Replaces the contents of hsh with the contents of other hash - # - # ISO 15.2.13.4.23 - def replace(hash) - self.clear - hash = hash.to_hash - hash.each_key{|k| - self[k] = hash[k] - } - if hash.default_proc - self.default_proc = hash.default_proc - else - self.default = hash.default - end - self - end - # ISO 15.2.13.4.17 - alias initialize_copy replace - - ## - # Return a hash which contains the content of - # +self+ and +other+. If a block is given - # it will be called for each element with - # a duplicate key. The value of the block - # will be the final value of this element. - # - # ISO 15.2.13.4.22 - def merge(other, &block) - h = {} - raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash) - other = other.to_hash - self.each_key{|k| h[k] = self[k]} - if block - other.each_key{|k| - h[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k] - } - else - other.each_key{|k| h[k] = other[k]} - end - h - end - - # internal method for Hash inspection - def _inspect - return "{}" if self.size == 0 - "{"+self.map {|k,v| - k._inspect + "=>" + v._inspect - }.join(", ")+"}" - end - ## - # Return the contents of this hash as a string. - # - # ISO 15.2.13.4.30 (x) - def inspect - begin - self._inspect - rescue SystemStackError - "{...}" - end - end - # ISO 15.2.13.4.31 (x) - alias to_s inspect - - ## - # call-seq: - # hsh.reject! {| key, value | block } -> hsh or nil - # hsh.reject! -> an_enumerator - # - # Equivalent to Hash#delete_if, but returns - # nil if no changes were made. - # - # 1.8/1.9 Hash#reject! returns Hash; ISO says nothing. - # - def reject!(&b) - return to_enum :reject! unless block_given? - - keys = [] - self.each{|k,v| - if b.call([k, v]) - keys.push(k) - end - } - return nil if keys.size == 0 - keys.each{|k| - self.delete(k) - } - self - end - - ## - # call-seq: - # hsh.reject {|key, value| block} -> a_hash - # hsh.reject -> an_enumerator - # - # Returns a new hash consisting of entries for which the block returns false. - # - # If no block is given, an enumerator is returned instead. - # - # h = { "a" => 100, "b" => 200, "c" => 300 } - # h.reject {|k,v| k < "b"} #=> {"b" => 200, "c" => 300} - # h.reject {|k,v| v > 100} #=> {"a" => 100} - # - # 1.8/1.9 Hash#reject returns Hash; ISO says nothing. - # - def reject(&b) - return to_enum :reject unless block_given? - - h = {} - self.each{|k,v| - unless b.call([k, v]) - h[k] = v - end - } - h - end - - ## - # call-seq: - # hsh.select! {| key, value | block } -> hsh or nil - # hsh.select! -> an_enumerator - # - # Equivalent to Hash#keep_if, but returns - # nil if no changes were made. - # - # 1.9 Hash#select! returns Hash; ISO says nothing. - # - def select!(&b) - return to_enum :select! unless block_given? - - keys = [] - self.each{|k,v| - unless b.call([k, v]) - keys.push(k) - end - } - return nil if keys.size == 0 - keys.each{|k| - self.delete(k) - } - self - end - - ## - # call-seq: - # hsh.select {|key, value| block} -> a_hash - # hsh.select -> an_enumerator - # - # Returns a new hash consisting of entries for which the block returns true. - # - # If no block is given, an enumerator is returned instead. - # - # h = { "a" => 100, "b" => 200, "c" => 300 } - # h.select {|k,v| k > "a"} #=> {"b" => 200, "c" => 300} - # h.select {|k,v| v < 200} #=> {"a" => 100} - # - # 1.9 Hash#select returns Hash; ISO says nothing - # - def select(&b) - return to_enum :select unless block_given? - - h = {} - self.each{|k,v| - if b.call([k, v]) - h[k] = v - end - } - h - end - - ## - # call-seq: - # hsh.rehash -> hsh - # - # Rebuilds the hash based on the current hash values for each key. If - # values of key objects have changed since they were inserted, this - # method will reindex hsh. - # - # h = {"AAA" => "b"} - # h.keys[0].chop! - # h #=> {"AA"=>"b"} - # h["AA"] #=> nil - # h.rehash #=> {"AA"=>"b"} - # h["AA"] #=> "b" - # - def rehash - h = {} - self.each{|k,v| - h[k] = v - } - self.replace(h) - end - - def __update(h) - h.each_key{|k| self[k] = h[k]} - self - end -end - -## -# Hash is enumerable -# -# ISO 15.2.13.3 -class Hash - include Enumerable -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/init_mrblib.c nghttp2-0.6.7/third-party/mruby/mrblib/init_mrblib.c --- nghttp2-1.13.0/third-party/mruby/mrblib/init_mrblib.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/init_mrblib.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#include "mruby.h" -#include "mruby/irep.h" - -extern const uint8_t mrblib_irep[]; - -void -mrb_init_mrblib(mrb_state *mrb) -{ - mrb_load_irep(mrb, mrblib_irep); -} - diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/kernel.rb nghttp2-0.6.7/third-party/mruby/mrblib/kernel.rb --- nghttp2-1.13.0/third-party/mruby/mrblib/kernel.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/kernel.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -## -# Kernel -# -# ISO 15.3.1 -module Kernel - - # 15.3.1.2.1 Kernel.` - # provided by Kernel#` - # 15.3.1.3.5 - def `(s) - raise NotImplementedError.new("backquotes not implemented") - end - - ## - # 15.3.1.2.3 Kernel.eval - # 15.3.1.3.12 Kernel#eval - # NotImplemented by mruby core; use mruby-eval gem - - ## - # ISO 15.3.1.2.8 Kernel.loop - # provided by Kernel#loop - - ## - # Calls the given block repetitively. - # - # ISO 15.3.1.3.29 - def loop(&block) - return to_enum :loop unless block - - while true - yield - end - rescue StopIteration => e - e.result - end - - # 11.4.4 Step c) - def !~(y) - !(self =~ y) - end - - # internal method for inspect - def _inspect - self.inspect - end - - def to_enum(*a) - raise NotImplementedError.new("fiber required for enumerator") - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/mrblib.rake nghttp2-0.6.7/third-party/mruby/mrblib/mrblib.rake --- nghttp2-1.13.0/third-party/mruby/mrblib/mrblib.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/mrblib.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -MRuby.each_target do - current_dir = File.dirname(__FILE__) - relative_from_root = File.dirname(__FILE__).relative_path_from(MRUBY_ROOT) - current_build_dir = "#{build_dir}/#{relative_from_root}" - - self.libmruby << objfile("#{current_build_dir}/mrblib") - - file objfile("#{current_build_dir}/mrblib") => "#{current_build_dir}/mrblib.c" - file "#{current_build_dir}/mrblib.c" => [mrbcfile, __FILE__] + Dir.glob("#{current_dir}/*.rb").sort do |t| - _, _, *rbfiles = t.prerequisites - FileUtils.mkdir_p File.dirname(t.name) - open(t.name, 'w') do |f| - _pp "GEN", "*.rb", "#{t.name.relative_path}" - f.puts File.read("#{current_dir}/init_mrblib.c") - mrbc.run f, rbfiles, 'mrblib_irep' - end - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/numeric.rb nghttp2-0.6.7/third-party/mruby/mrblib/numeric.rb --- nghttp2-1.13.0/third-party/mruby/mrblib/numeric.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/numeric.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,194 +0,0 @@ -## -# Numeric -# -# ISO 15.2.7 -class Numeric - include Comparable - ## - # Returns the receiver simply. - # - # ISO 15.2.7.4.1 - def +@ - self - end - - ## - # Returns the receiver's value, negated. - # - # ISO 15.2.7.4.2 - def -@ - 0 - self - end - - ## - # Returns the absolute value of the receiver. - # - # ISO 15.2.7.4.3 - def abs - if self < 0 - -self - else - self - end - end -end - -## -# Integral -# -# mruby special - module to share methods between Floats and Integers -# to make them compatible -module Integral - ## - # Calls the given block once for each Integer - # from +self+ downto +num+. - # - # ISO 15.2.8.3.15 - def downto(num, &block) - return to_enum(:downto, num) unless block_given? - - i = self.to_i - while i >= num - block.call(i) - i -= 1 - end - self - end - - ## - # Returns self + 1 - # - # ISO 15.2.8.3.19 - def next - self + 1 - end - # ISO 15.2.8.3.21 - alias succ next - - ## - # Calls the given block +self+ times. - # - # ISO 15.2.8.3.22 - def times &block - return to_enum :times unless block_given? - - i = 0 - while i < self - block.call i - i += 1 - end - self - end - - ## - # Calls the given block once for each Integer - # from +self+ upto +num+. - # - # ISO 15.2.8.3.27 - def upto(num, &block) - return to_enum(:upto, num) unless block_given? - - i = self.to_i - while i <= num - block.call(i) - i += 1 - end - self - end - - ## - # Calls the given block from +self+ to +num+ - # incremented by +step+ (default 1). - # - def step(num, step = 1, &block) - raise ArgumentError, "step can't be 0" if step == 0 - return to_enum(:step, num, step) unless block_given? - - i = if num.kind_of? Float then self.to_f else self end - if step > 0 - while i <= num - block.call(i) - i += step - end - else - while i >= num - block.call(i) - i += step - end - end - self - end -end - -## -# Integer -# -# ISO 15.2.8 -class Integer - include Integral - ## - # Returns the receiver simply. - # - # ISO 15.2.8.3.14 - def ceil - self - end - - ## - # Returns the receiver simply. - # - # ISO 15.2.8.3.17 - def floor - self - end - - ## - # Returns the receiver simply. - # - # ISO 15.2.8.3.24 - alias round floor - - ## - # Returns the receiver simply. - # - # ISO 15.2.8.3.26 - alias truncate floor -end - -## -# Float -# -# ISO 15.2.9 -class Float - include Integral - # mruby special - since mruby integers may be upgraded to floats, - # floats should be compatible to integers. - def >> other - n = self.to_i - other = other.to_i - if other < 0 - n << -other - else - other.times { n /= 2 } - if n.abs < 1 - if n >= 0 - 0 - else - -1 - end - else - n.to_i - end - end - end - def << other - n = self.to_i - other = other.to_i - if other < 0 - n >> -other - else - other.times { n *= 2 } - n - end - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/range.rb nghttp2-0.6.7/third-party/mruby/mrblib/range.rb --- nghttp2-1.13.0/third-party/mruby/mrblib/range.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/range.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -## -# Range -# -# ISO 15.2.14 -class Range - - ## - # Calls the given block for each element of +self+ - # and pass the respective element. - # - # ISO 15.2.14.4.4 - def each(&block) - return to_enum :each unless block_given? - - val = self.first - last = self.last - - if val.kind_of?(Fixnum) && last.kind_of?(Fixnum) # fixnums are special - lim = last - lim += 1 unless exclude_end? - i = val - while i < lim - block.call(i) - i += 1 - end - return self - end - - raise TypeError, "can't iterate" unless val.respond_to? :succ - - return self if (val <=> last) > 0 - - while (val <=> last) < 0 - block.call(val) - val = val.succ - end - - block.call(val) if !exclude_end? && (val <=> last) == 0 - self - end - - # redefine #hash 15.3.1.3.15 - def hash - h = first.hash ^ last.hash - h += 1 if self.exclude_end? - h - end -end - -## -# Range is enumerable -# -# ISO 15.2.14.3 -class Range - include Enumerable -end diff -Nru nghttp2-1.13.0/third-party/mruby/mrblib/string.rb nghttp2-0.6.7/third-party/mruby/mrblib/string.rb --- nghttp2-1.13.0/third-party/mruby/mrblib/string.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mrblib/string.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,230 +0,0 @@ -## -# String -# -# ISO 15.2.10 -class String - include Comparable - ## - # Calls the given block for each line - # and pass the respective line. - # - # ISO 15.2.10.5.15 - def each_line(&block) - offset = 0 - while pos = self.index("\n", offset) - block.call(self[offset, pos + 1 - offset]) - offset = pos + 1 - end - block.call(self[offset, self.size - offset]) if self.size > offset - self - end - - # private method for gsub/sub - def __sub_replace(pre, m, post) - s = "" - i = 0 - while j = index("\\", i) - break if j == length-1 - t = case self[j+1] - when "\\" - "\\" - when "`" - pre - when "&", "0" - m - when "'" - post - else - self[j, 2] - end - s += self[i, j-i] + t - i = j + 2 - end - s + self[i, length-i] - end - - ## - # Replace all matches of +pattern+ with +replacement+. - # Call block (if given) for each match and replace - # +pattern+ with the value of the block. Return the - # final value. - # - # ISO 15.2.10.5.18 - def gsub(*args, &block) - if args.size == 2 - s = "" - i = 0 - while j = index(args[0], i) - seplen = args[0].length - k = j + seplen - pre = self[0, j] - post = self[k, length-k] - s += self[i, j-i] + args[1].__sub_replace(pre, args[0], post) - i = k - end - s + self[i, length-i] - elsif args.size == 1 && block - split(args[0], -1).join(block.call(args[0])) - else - raise ArgumentError, "wrong number of arguments" - end - end - - ## - # Replace all matches of +pattern+ with +replacement+. - # Call block (if given) for each match and replace - # +pattern+ with the value of the block. Modify - # +self+ with the final value. - # - # ISO 15.2.10.5.19 - def gsub!(*args, &block) - str = self.gsub(*args, &block) - return nil if str == self - self.replace(str) - end - - ## - # Calls the given block for each match of +pattern+ - # If no block is given return an array with all - # matches of +pattern+. - # - # ISO 15.2.10.5.32 - def scan(reg, &block) - ### *** TODO *** ### - unless Object.const_defined?(:Regexp) - raise NotImplementedError, "scan not available (yet)" - end - end - - ## - # Replace only the first match of +pattern+ with - # +replacement+. Call block (if given) for each - # match and replace +pattern+ with the value of the - # block. Return the final value. - # - # ISO 15.2.10.5.36 - def sub(*args, &block) - if args.size == 2 - pre, post = split(args[0], 2) - return self unless post # The sub target wasn't found in the string - pre + args[1].__sub_replace(pre, args[0], post) + post - elsif args.size == 1 && block - split(args[0], 2).join(block.call(args[0])) - else - raise ArgumentError, "wrong number of arguments" - end - end - - ## - # Replace only the first match of +pattern+ with - # +replacement+. Call block (if given) for each - # match and replace +pattern+ with the value of the - # block. Modify +self+ with the final value. - # - # ISO 15.2.10.5.37 - def sub!(*args, &block) - str = self.sub(*args, &block) - return nil if str == self - self.replace(str) - end - - ## - # Call the given block for each character of - # +self+. - def each_char(&block) - pos = 0 - while pos < self.size - block.call(self[pos]) - pos += 1 - end - self - end - - ## - # Call the given block for each byte of +self+. - def each_byte(&block) - bytes = self.bytes - pos = 0 - while pos < bytes.size - block.call(bytes[pos]) - pos += 1 - end - self - end - - ## - # Modify +self+ by replacing the content of +self+. - # The portion of the string affected is determined using the same criteria as +String#[]+. - def []=(*args) - anum = args.size - if anum == 2 - pos, value = args - if pos.kind_of? String - posnum = self.index(pos) - if posnum - b = self[0, posnum.to_i] - a = self[(posnum + pos.length)..-1] - self.replace([b, value, a].join('')) - return value - else - raise IndexError, "string not matched" - end - else - pos += self.length if pos < 0 - if pos < 0 || pos > self.length - raise IndexError, "index #{args[0]} out of string" - end - b = self[0, pos.to_i] - a = self[pos + 1..-1] - self.replace([b, value, a].join('')) - return value - end - elsif anum == 3 - pos, len, value = args - pos += self.length if pos < 0 - if pos < 0 || pos > self.length - raise IndexError, "index #{args[0]} out of string" - end - if len < 0 - raise IndexError, "negative length #{len}" - end - b = self[0, pos.to_i] - a = self[pos + len..-1] - self.replace([b, value, a].join('')) - return value - else - raise ArgumentError, "wrong number of arguments (#{anum} for 2..3)" - end - end - - ## - # ISO 15.2.10.5.3 - def =~(re) - raise TypeError, "type mismatch: String given" if re.respond_to? :to_str - re =~ self - end - - ## - # ISO 15.2.10.5.27 - def match(re, &block) - if re.respond_to? :to_str - if Object.const_defined?(:Regexp) - r = Regexp.new(re) - r.match(self, &block) - else - raise NotImplementedError, "String#match needs Regexp class" - end - else - re.match(self, &block) - end - end -end - -## -# String is comparable -# -# ISO 15.2.10.3 -module Comparable; end -class String - include Comparable -end diff -Nru nghttp2-1.13.0/third-party/mruby/mruby-source.gemspec nghttp2-0.6.7/third-party/mruby/mruby-source.gemspec --- nghttp2-1.13.0/third-party/mruby/mruby-source.gemspec 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/mruby-source.gemspec 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -# coding: utf-8 -lib = File.expand_path('../lib', __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'mruby/source' - -Gem::Specification.new do |spec| - spec.name = "mruby-source" - spec.version = MRuby::Source::MRUBY_VERSION - spec.authors = [ MRuby::Source::MRUBY_AUTHOR ] - - spec.summary = %q{MRuby source code wrapper.} - spec.description = %q{MRuby source code wrapper for use with Ruby libs.} - spec.homepage = "http://www.mruby.org/" - spec.license = "MIT" - - spec.files = `git ls-files -z`.split("\x0") - spec.require_paths = ["lib"] -end diff -Nru nghttp2-1.13.0/third-party/mruby/NEWS nghttp2-0.6.7/third-party/mruby/NEWS --- nghttp2-1.13.0/third-party/mruby/NEWS 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/NEWS 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -* NEWS - -This document is a list of user visible feature changes made between -releases except for bug fixes. - -Note that each entry is kept so brief that no reason behind or -reference information is supplied with. For a full list of changes -with all sufficient information, see the ChangeLog file. - - -** Information about first release v1.0.0 - - diff -Nru nghttp2-1.13.0/third-party/mruby/Rakefile nghttp2-0.6.7/third-party/mruby/Rakefile --- nghttp2-1.13.0/third-party/mruby/Rakefile 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/Rakefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,148 +0,0 @@ -# encoding: utf-8 -# Build description. -# basic build file for mruby -MRUBY_ROOT = File.dirname(File.expand_path(__FILE__)) -MRUBY_BUILD_HOST_IS_CYGWIN = RUBY_PLATFORM.include?('cygwin') -MRUBY_BUILD_HOST_IS_OPENBSD = RUBY_PLATFORM.include?('openbsd') - -# load build systems -load "#{MRUBY_ROOT}/tasks/ruby_ext.rake" -load "#{MRUBY_ROOT}/tasks/mruby_build.rake" -load "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake" - -# load configuration file -MRUBY_CONFIG = (ENV['MRUBY_CONFIG'] && ENV['MRUBY_CONFIG'] != '') ? ENV['MRUBY_CONFIG'] : "#{MRUBY_ROOT}/build_config.rb" -load MRUBY_CONFIG - -# load basic rules -MRuby.each_target do |build| - build.define_rules -end - -# load custom rules -load "#{MRUBY_ROOT}/src/mruby_core.rake" -load "#{MRUBY_ROOT}/mrblib/mrblib.rake" - -load "#{MRUBY_ROOT}/tasks/mrbgems.rake" -load "#{MRUBY_ROOT}/tasks/libmruby.rake" - -load "#{MRUBY_ROOT}/tasks/benchmark.rake" - -############################## -# generic build targets, rules -task :default => :all - -bin_path = ENV['INSTALL_DIR'] || "#{MRUBY_ROOT}/bin" -FileUtils.mkdir_p bin_path, { :verbose => $verbose } - -depfiles = MRuby.targets['host'].bins.map do |bin| - install_path = MRuby.targets['host'].exefile("#{bin_path}/#{bin}") - source_path = MRuby.targets['host'].exefile("#{MRuby.targets['host'].build_dir}/bin/#{bin}") - - file install_path => source_path do |t| - FileUtils.rm_f t.name, { :verbose => $verbose } - FileUtils.cp t.prerequisites.first, t.name, { :verbose => $verbose } - end - - install_path -end - -MRuby.each_target do |target| - gems.map do |gem| - current_dir = gem.dir.relative_path_from(Dir.pwd) - relative_from_root = gem.dir.relative_path_from(MRUBY_ROOT) - current_build_dir = File.expand_path "#{build_dir}/#{relative_from_root}" - - if current_build_dir !~ /^#{build_dir}/ - current_build_dir = "#{build_dir}/mrbgems/#{gem.name}" - end - - gem.bins.each do |bin| - exec = exefile("#{build_dir}/bin/#{bin}") - objs = Dir.glob("#{current_dir}/tools/#{bin}/*.{c,cpp,cxx,cc}").map { |f| objfile(f.pathmap("#{current_build_dir}/tools/#{bin}/%n")) } - - file exec => objs + [libfile("#{build_dir}/lib/libmruby")] do |t| - gem_flags = gems.map { |g| g.linker.flags } - gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries } - gem_flags_after_libraries = gems.map { |g| g.linker.flags_after_libraries } - gem_libraries = gems.map { |g| g.linker.libraries } - gem_library_paths = gems.map { |g| g.linker.library_paths } - linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries, gem_flags_after_libraries - end - - if target == MRuby.targets['host'] - install_path = MRuby.targets['host'].exefile("#{bin_path}/#{bin}") - - file install_path => exec do |t| - FileUtils.rm_f t.name, { :verbose => $verbose } - FileUtils.cp t.prerequisites.first, t.name, { :verbose => $verbose } - end - depfiles += [ install_path ] - elsif target == MRuby.targets['host-debug'] - unless MRuby.targets['host'].gems.map {|g| g.bins}.include?([bin]) - install_path = MRuby.targets['host-debug'].exefile("#{bin_path}/#{bin}") - - file install_path => exec do |t| - FileUtils.rm_f t.name, { :verbose => $verbose } - FileUtils.cp t.prerequisites.first, t.name, { :verbose => $verbose } - end - depfiles += [ install_path ] - end - else - depfiles += [ exec ] - end - end - end -end - -depfiles += MRuby.targets.map { |n, t| - [t.libfile("#{t.build_dir}/lib/libmruby")] -}.flatten - -depfiles += MRuby.targets.reject { |n, t| n == 'host' }.map { |n, t| - t.bins.map { |bin| t.exefile("#{t.build_dir}/bin/#{bin}") } -}.flatten - -desc "build all targets, install (locally) in-repo" -task :all => depfiles do - puts - puts "Build summary:" - puts - MRuby.each_target do - print_build_summary - end -end - -desc "run all mruby tests" -task :test => ["all"] do - MRuby.each_target do - run_test if test_enabled? - end -end - -desc "clean all built and in-repo installed artifacts" -task :clean do - MRuby.each_target do |t| - FileUtils.rm_rf t.build_dir, { :verbose => $verbose } - end - FileUtils.rm_f depfiles, { :verbose => $verbose } - puts "Cleaned up target build folder" -end - -desc "clean everything!" -task :deep_clean => ["clean"] do - MRuby.each_target do |t| - FileUtils.rm_rf t.gem_clone_dir, { :verbose => $verbose } - end - puts "Cleaned up mrbgems build folder" -end - -desc 'generate document' -task :doc do - begin - sh "mrbdoc" - rescue - puts "ERROR: To generate documents, you should install yard-mruby gem." - puts " $ gem install yard-mruby" - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/README.md nghttp2-0.6.7/third-party/mruby/README.md --- nghttp2-1.13.0/third-party/mruby/README.md 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -[![Build Status][build-status-img]][travis-ci] - -## What is mruby - -mruby is the lightweight implementation of the Ruby language complying to (part -of) the [ISO standard][ISO-standard]. Its syntax is Ruby 1.9 compatible. - -mruby can be linked and embedded within your application. We provide the -interpreter program "mruby" and the interactive mruby shell "mirb" as examples. -You can also compile Ruby programs into compiled byte code using the mruby -compiler "mrbc". All those tools reside in the "bin" directory. "mrbc" is -also able to generate compiled byte code in a C source file, see the "mrbtest" -program under the "test" directory for an example. - -This achievement was sponsored by the Regional Innovation Creation R&D Programs -of the Ministry of Economy, Trade and Industry of Japan. - -## How to get mruby - -The stable version 1.2.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/1.2.0.zip](https://github.com/mruby/mruby/archive/1.2.0.zip) - -The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master) - -The trunk of the mruby source tree can be checked out with the -following command: - - $ git clone https://github.com/mruby/mruby.git - -## mruby home-page - -The URL of the mruby home-page is: [http://www.mruby.org](http://www.mruby.org). - -## Mailing list - -We don't have mailing list, but you can use [GitHub issues](https://github.com/mruby/mruby). - -## How to compile and install (mruby and gems) - -See the [doc/guides/compile.md](doc/guides/compile.md) file. - -## Running Tests - -To run the tests, execute the following from the project's root directory. - - $ make test - -Or - - $ ruby ./minirake test - -## How to customize mruby (mrbgems) - -mruby contains a package manager called *mrbgems*. To create extensions -in C and/or Ruby you should create a *GEM*. For a documentation of how to -use mrbgems consult the file [doc/mrbgems/README.md](doc/mrbgems/README.md). For example code of -how to use mrbgems look into the folder *examples/mrbgems/*. - -## License - -mruby is released under the [MIT License](MITL). - -## Note for License - -mruby has chosen a MIT License due to its permissive license allowing -developers to target various environments such as embedded systems. -However, the license requires the display of the copyright notice and license -information in manuals for instance. Doing so for big projects can be -complicated or troublesome. This is why mruby has decided to display "mruby -developers" as the copyright name to make it simple conventionally. -In the future, mruby might ask you to distribute your new code -(that you will commit,) under the MIT License as a member of -"mruby developers" but contributors will keep their copyright. -(We did not intend for contributors to transfer or waive their copyrights, -Actual copyright holder name (contributors) will be listed in the AUTHORS -file.) - -Please ask us if you want to distribute your code under another license. - -## How to Contribute - -See the [contribution guidelines][contribution-guidelines], and then send a pull -request to . We consider you have granted -non-exclusive right to your contributed code under MIT license. If you want to -be named as one of mruby developers, please include an update to the AUTHORS -file in your pull request. - -[ISO-standard]: http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579 -[build-status-img]: https://travis-ci.org/mruby/mruby.svg?branch=master -[contribution-guidelines]: CONTRIBUTING.md -[travis-ci]: https://travis-ci.org/mruby/mruby diff -Nru nghttp2-1.13.0/third-party/mruby/src/array.c nghttp2-0.6.7/third-party/mruby/src/array.c --- nghttp2-1.13.0/third-party/mruby/src/array.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/array.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1105 +0,0 @@ -/* -** array.c - Array class -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/string.h" -#include "mruby/range.h" -#include "value_array.h" - -#define ARY_DEFAULT_LEN 4 -#define ARY_SHRINK_RATIO 5 /* must be larger than 2 */ -#define ARY_C_MAX_SIZE (SIZE_MAX / sizeof(mrb_value)) -#define ARY_MAX_SIZE ((ARY_C_MAX_SIZE < (size_t)MRB_INT_MAX) ? (mrb_int)ARY_C_MAX_SIZE : MRB_INT_MAX-1) - -static inline mrb_value -ary_elt(mrb_value ary, mrb_int offset) -{ - if (offset < 0 || RARRAY_LEN(ary) <= offset) { - return mrb_nil_value(); - } - return RARRAY_PTR(ary)[offset]; -} - -static struct RArray* -ary_new_capa(mrb_state *mrb, mrb_int capa) -{ - struct RArray *a; - mrb_int blen; - - if (capa > ARY_MAX_SIZE) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); - } - blen = capa * sizeof(mrb_value); - if (blen < capa) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); - } - - a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); - a->ptr = (mrb_value *)mrb_malloc(mrb, blen); - a->aux.capa = capa; - a->len = 0; - - return a; -} - -MRB_API mrb_value -mrb_ary_new_capa(mrb_state *mrb, mrb_int capa) -{ - struct RArray *a = ary_new_capa(mrb, capa); - return mrb_obj_value(a); -} - -MRB_API mrb_value -mrb_ary_new(mrb_state *mrb) -{ - return mrb_ary_new_capa(mrb, 0); -} - -/* - * to copy array, use this instead of memcpy because of portability - * * gcc on ARM may fail optimization of memcpy - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3934.html - * * gcc on MIPS also fail - * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39755 - * * memcpy doesn't exist on freestanding environment - * - * If you optimize for binary size, use memcpy instead of this at your own risk - * of above portability issue. - * - * see also http://togetter.com/li/462898 - * - */ -static inline void -array_copy(mrb_value *dst, const mrb_value *src, mrb_int size) -{ - mrb_int i; - - for (i = 0; i < size; i++) { - dst[i] = src[i]; - } -} - -MRB_API mrb_value -mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals) -{ - struct RArray *a = ary_new_capa(mrb, size); - - array_copy(a->ptr, vals, size); - a->len = size; - - return mrb_obj_value(a); -} - -MRB_API mrb_value -mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr) -{ - struct RArray *a; - - a = ary_new_capa(mrb, 2); - a->ptr[0] = car; - a->ptr[1] = cdr; - a->len = 2; - return mrb_obj_value(a); -} - -static void -ary_fill_with_nil(mrb_value *ptr, mrb_int size) -{ - mrb_value nil = mrb_nil_value(); - - while (size--) { - *ptr++ = nil; - } -} - -static void -ary_modify(mrb_state *mrb, struct RArray *a) -{ - if (ARY_SHARED_P(a)) { - mrb_shared_array *shared = a->aux.shared; - - if (shared->refcnt == 1 && a->ptr == shared->ptr) { - a->ptr = shared->ptr; - a->aux.capa = a->len; - mrb_free(mrb, shared); - } - else { - mrb_value *ptr, *p; - mrb_int len; - - p = a->ptr; - len = a->len * sizeof(mrb_value); - ptr = (mrb_value *)mrb_malloc(mrb, len); - if (p) { - array_copy(ptr, p, a->len); - } - a->ptr = ptr; - a->aux.capa = a->len; - mrb_ary_decref(mrb, shared); - } - ARY_UNSET_SHARED_FLAG(a); - } -} - -MRB_API void -mrb_ary_modify(mrb_state *mrb, struct RArray* a) -{ - mrb_write_barrier(mrb, (struct RBasic*)a); - ary_modify(mrb, a); -} - -static void -ary_make_shared(mrb_state *mrb, struct RArray *a) -{ - if (!ARY_SHARED_P(a)) { - mrb_shared_array *shared = (mrb_shared_array *)mrb_malloc(mrb, sizeof(mrb_shared_array)); - - shared->refcnt = 1; - if (a->aux.capa > a->len) { - a->ptr = shared->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*a->len+1); - } - else { - shared->ptr = a->ptr; - } - shared->len = a->len; - a->aux.shared = shared; - ARY_SET_SHARED_FLAG(a); - } -} - -static void -ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len) -{ - mrb_int capa = a->aux.capa; - - if (len > ARY_MAX_SIZE) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); - } - - if (capa == 0) { - capa = ARY_DEFAULT_LEN; - } - while (capa < len) { - capa *= 2; - } - - if (capa > ARY_MAX_SIZE) capa = ARY_MAX_SIZE; /* len <= capa <= ARY_MAX_SIZE */ - - if (capa > a->aux.capa) { - mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa); - - a->aux.capa = capa; - a->ptr = expanded_ptr; - } -} - -static void -ary_shrink_capa(mrb_state *mrb, struct RArray *a) -{ - mrb_int capa = a->aux.capa; - - if (capa < ARY_DEFAULT_LEN * 2) return; - if (capa <= a->len * ARY_SHRINK_RATIO) return; - - do { - capa /= 2; - if (capa < ARY_DEFAULT_LEN) { - capa = ARY_DEFAULT_LEN; - break; - } - } while (capa > a->len * ARY_SHRINK_RATIO); - - if (capa > a->len && capa < a->aux.capa) { - a->aux.capa = capa; - a->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa); - } -} - -MRB_API mrb_value -mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len) -{ - mrb_int old_len; - struct RArray *a = mrb_ary_ptr(ary); - - ary_modify(mrb, a); - old_len = RARRAY_LEN(ary); - if (old_len != new_len) { - a->len = new_len; - if (new_len < old_len) { - ary_shrink_capa(mrb, a); - } - else { - ary_expand_capa(mrb, a, new_len); - ary_fill_with_nil(a->ptr + old_len, new_len - old_len); - } - } - - return ary; -} - -static mrb_value -mrb_ary_s_create(mrb_state *mrb, mrb_value self) -{ - mrb_value *vals; - mrb_int len; - - mrb_get_args(mrb, "*", &vals, &len); - - return mrb_ary_new_from_values(mrb, len, vals); -} - -static void -ary_concat(mrb_state *mrb, struct RArray *a, mrb_value *ptr, mrb_int blen) -{ - mrb_int len = a->len + blen; - - ary_modify(mrb, a); - if (a->aux.capa < len) ary_expand_capa(mrb, a, len); - array_copy(a->ptr+a->len, ptr, blen); - mrb_write_barrier(mrb, (struct RBasic*)a); - a->len = len; -} - -MRB_API void -mrb_ary_concat(mrb_state *mrb, mrb_value self, mrb_value other) -{ - struct RArray *a2 = mrb_ary_ptr(other); - - ary_concat(mrb, mrb_ary_ptr(self), a2->ptr, a2->len); -} - -static mrb_value -mrb_ary_concat_m(mrb_state *mrb, mrb_value self) -{ - mrb_value *ptr; - mrb_int blen; - - mrb_get_args(mrb, "a", &ptr, &blen); - ary_concat(mrb, mrb_ary_ptr(self), ptr, blen); - return self; -} - -static mrb_value -mrb_ary_plus(mrb_state *mrb, mrb_value self) -{ - struct RArray *a1 = mrb_ary_ptr(self); - struct RArray *a2; - mrb_value *ptr; - mrb_int blen; - - mrb_get_args(mrb, "a", &ptr, &blen); - if (ARY_MAX_SIZE - blen < a1->len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); - } - a2 = ary_new_capa(mrb, a1->len + blen); - array_copy(a2->ptr, a1->ptr, a1->len); - array_copy(a2->ptr + a1->len, ptr, blen); - a2->len = a1->len + blen; - - return mrb_obj_value(a2); -} - -static void -ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, mrb_int len) -{ - ary_modify(mrb, a); - if (a->aux.capa < len) - ary_expand_capa(mrb, a, len); - array_copy(a->ptr, argv, len); - mrb_write_barrier(mrb, (struct RBasic*)a); - a->len = len; -} - -MRB_API void -mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other) -{ - struct RArray *a2 = mrb_ary_ptr(other); - - ary_replace(mrb, mrb_ary_ptr(self), a2->ptr, a2->len); -} - -static mrb_value -mrb_ary_replace_m(mrb_state *mrb, mrb_value self) -{ - mrb_value other; - - mrb_get_args(mrb, "A", &other); - mrb_ary_replace(mrb, self, other); - - return self; -} - -static mrb_value -mrb_ary_times(mrb_state *mrb, mrb_value self) -{ - struct RArray *a1 = mrb_ary_ptr(self); - struct RArray *a2; - mrb_value *ptr; - mrb_int times; - - mrb_get_args(mrb, "i", ×); - if (times < 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument"); - } - if (times == 0) return mrb_ary_new(mrb); - if (ARY_MAX_SIZE / times < a1->len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); - } - a2 = ary_new_capa(mrb, a1->len * times); - ptr = a2->ptr; - while (times--) { - array_copy(ptr, a1->ptr, a1->len); - ptr += a1->len; - a2->len += a1->len; - } - - return mrb_obj_value(a2); -} - -static mrb_value -mrb_ary_reverse_bang(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self); - - if (a->len > 1) { - mrb_value *p1, *p2; - - ary_modify(mrb, a); - p1 = a->ptr; - p2 = a->ptr + a->len - 1; - - while (p1 < p2) { - mrb_value tmp = *p1; - *p1++ = *p2; - *p2-- = tmp; - } - } - return self; -} - -static mrb_value -mrb_ary_reverse(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self), *b = ary_new_capa(mrb, a->len); - - if (a->len > 0) { - mrb_value *p1, *p2, *e; - - p1 = a->ptr; - e = p1 + a->len; - p2 = b->ptr + a->len - 1; - while (p1 < e) { - *p2-- = *p1++; - } - b->len = a->len; - } - return mrb_obj_value(b); -} - -MRB_API void -mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem) -{ - struct RArray *a = mrb_ary_ptr(ary); - - ary_modify(mrb, a); - if (a->len == a->aux.capa) - ary_expand_capa(mrb, a, a->len + 1); - a->ptr[a->len++] = elem; - mrb_field_write_barrier_value(mrb, (struct RBasic*)a, elem); -} - -static mrb_value -mrb_ary_push_m(mrb_state *mrb, mrb_value self) -{ - mrb_value *argv; - mrb_int len; - - mrb_get_args(mrb, "*", &argv, &len); - while (len--) { - mrb_ary_push(mrb, self, *argv++); - } - - return self; -} - -MRB_API mrb_value -mrb_ary_pop(mrb_state *mrb, mrb_value ary) -{ - struct RArray *a = mrb_ary_ptr(ary); - - if (a->len == 0) return mrb_nil_value(); - return a->ptr[--a->len]; -} - -#define ARY_SHIFT_SHARED_MIN 10 - -MRB_API mrb_value -mrb_ary_shift(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self); - mrb_value val; - - if (a->len == 0) return mrb_nil_value(); - if (ARY_SHARED_P(a)) { - L_SHIFT: - val = a->ptr[0]; - a->ptr++; - a->len--; - return val; - } - if (a->len > ARY_SHIFT_SHARED_MIN) { - ary_make_shared(mrb, a); - goto L_SHIFT; - } - else { - mrb_value *ptr = a->ptr; - mrb_int size = a->len; - - val = *ptr; - while (--size) { - *ptr = *(ptr+1); - ++ptr; - } - --a->len; - } - return val; -} - -/* self = [1,2,3] - item = 0 - self.unshift item - p self #=> [0, 1, 2, 3] */ -MRB_API mrb_value -mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item) -{ - struct RArray *a = mrb_ary_ptr(self); - - if (ARY_SHARED_P(a) - && a->aux.shared->refcnt == 1 /* shared only referenced from this array */ - && a->ptr - a->aux.shared->ptr >= 1) /* there's room for unshifted item */ { - a->ptr--; - a->ptr[0] = item; - } - else { - ary_modify(mrb, a); - if (a->aux.capa < a->len + 1) - ary_expand_capa(mrb, a, a->len + 1); - value_move(a->ptr + 1, a->ptr, a->len); - a->ptr[0] = item; - } - a->len++; - mrb_field_write_barrier_value(mrb, (struct RBasic*)a, item); - - return self; -} - -static mrb_value -mrb_ary_unshift_m(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self); - mrb_value *vals; - mrb_int len; - - mrb_get_args(mrb, "*", &vals, &len); - if (ARY_SHARED_P(a) - && a->aux.shared->refcnt == 1 /* shared only referenced from this array */ - && a->ptr - a->aux.shared->ptr >= len) /* there's room for unshifted item */ { - a->ptr -= len; - } - else { - ary_modify(mrb, a); - if (len == 0) return self; - if (a->aux.capa < a->len + len) - ary_expand_capa(mrb, a, a->len + len); - value_move(a->ptr + len, a->ptr, a->len); - } - array_copy(a->ptr, vals, len); - a->len += len; - while (len--) { - mrb_field_write_barrier_value(mrb, (struct RBasic*)a, vals[len]); - } - - return self; -} - -MRB_API mrb_value -mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n) -{ - struct RArray *a = mrb_ary_ptr(ary); - - /* range check */ - if (n < 0) n += a->len; - if (n < 0 || a->len <= n) return mrb_nil_value(); - - return a->ptr[n]; -} - -MRB_API void -mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) -{ - struct RArray *a = mrb_ary_ptr(ary); - - ary_modify(mrb, a); - /* range check */ - if (n < 0) { - n += a->len; - if (n < 0) { - mrb_raisef(mrb, E_INDEX_ERROR, "index %S out of array", mrb_fixnum_value(n - a->len)); - } - } - if (a->len <= n) { - if (a->aux.capa <= n) - ary_expand_capa(mrb, a, n + 1); - ary_fill_with_nil(a->ptr + a->len, n + 1 - a->len); - a->len = n + 1; - } - - a->ptr[n] = val; - mrb_field_write_barrier_value(mrb, (struct RBasic*)a, val); -} - -MRB_API mrb_value -mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_value rpl) -{ - struct RArray *a = mrb_ary_ptr(ary); - mrb_int tail, size; - const mrb_value *argv; - mrb_int i, argc; - - ary_modify(mrb, a); - - /* len check */ - if (len < 0) mrb_raisef(mrb, E_INDEX_ERROR, "negative length (%S)", mrb_fixnum_value(len)); - - /* range check */ - if (head < 0) { - head += a->len; - if (head < 0) { - mrb_raise(mrb, E_INDEX_ERROR, "index is out of array"); - } - } - if (a->len < len || a->len < head + len) { - len = a->len - head; - } - tail = head + len; - - /* size check */ - if (mrb_array_p(rpl)) { - argc = RARRAY_LEN(rpl); - argv = RARRAY_PTR(rpl); - } - else { - argc = 1; - argv = &rpl; - } - size = head + argc; - - if (tail < a->len) size += a->len - tail; - if (size > a->aux.capa) - ary_expand_capa(mrb, a, size); - - if (head > a->len) { - ary_fill_with_nil(a->ptr + a->len, head - a->len); - } - else if (head < a->len) { - value_move(a->ptr + head + argc, a->ptr + tail, a->len - tail); - } - - for (i = 0; i < argc; i++) { - *(a->ptr + head + i) = *(argv + i); - mrb_field_write_barrier_value(mrb, (struct RBasic*)a, argv[i]); - } - - a->len = size; - - return ary; -} - -void -mrb_ary_decref(mrb_state *mrb, mrb_shared_array *shared) -{ - shared->refcnt--; - if (shared->refcnt == 0) { - mrb_free(mrb, shared->ptr); - mrb_free(mrb, shared); - } -} - -static mrb_value -ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len) -{ - struct RArray *b; - - ary_make_shared(mrb, a); - b = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); - b->ptr = a->ptr + beg; - b->len = len; - b->aux.shared = a->aux.shared; - b->aux.shared->refcnt++; - ARY_SET_SHARED_FLAG(b); - - return mrb_obj_value(b); -} - -static mrb_int -aget_index(mrb_state *mrb, mrb_value index) -{ - if (mrb_fixnum_p(index)) { - return mrb_fixnum(index); - } - else if (mrb_float_p(index)) { - return (mrb_int)mrb_float(index); - } - else { - mrb_int i, argc; - mrb_value *argv; - - mrb_get_args(mrb, "i*", &i, &argv, &argc); - return i; - } -} - -/* - * call-seq: - * ary[index] -> obj or nil - * ary[start, length] -> new_ary or nil - * ary[range] -> new_ary or nil - * ary.slice(index) -> obj or nil - * ary.slice(start, length) -> new_ary or nil - * ary.slice(range) -> new_ary or nil - * - * Element Reference --- Returns the element at +index+, or returns a - * subarray starting at the +start+ index and continuing for +length+ - * elements, or returns a subarray specified by +range+ of indices. - * - * Negative indices count backward from the end of the array (-1 is the last - * element). For +start+ and +range+ cases the starting index is just before - * an element. Additionally, an empty array is returned when the starting - * index for an element range is at the end of the array. - * - * Returns +nil+ if the index (or starting index) are out of range. - * - * a = [ "a", "b", "c", "d", "e" ] - * a[1] => "b" - * a[1,2] => ["b", "c"] - * a[1..-2] => ["b", "c", "d"] - * - */ - -static mrb_value -mrb_ary_aget(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self); - mrb_int i, len; - mrb_value index; - - if (mrb_get_args(mrb, "o|i", &index, &len) == 1) { - switch (mrb_type(index)) { - /* a[n..m] */ - case MRB_TT_RANGE: - if (mrb_range_beg_len(mrb, index, &i, &len, a->len)) { - return ary_subseq(mrb, a, i, len); - } - else { - return mrb_nil_value(); - } - case MRB_TT_FIXNUM: - return mrb_ary_ref(mrb, self, mrb_fixnum(index)); - default: - return mrb_ary_ref(mrb, self, aget_index(mrb, index)); - } - } - - i = aget_index(mrb, index); - if (i < 0) i += a->len; - if (i < 0 || a->len < i) return mrb_nil_value(); - if (len < 0) return mrb_nil_value(); - if (a->len == i) return mrb_ary_new(mrb); - if (len > a->len - i) len = a->len - i; - - return ary_subseq(mrb, a, i, len); -} - -/* - * call-seq: - * ary[index] = obj -> obj - * ary[start, length] = obj or other_ary or nil -> obj or other_ary or nil - * ary[range] = obj or other_ary or nil -> obj or other_ary or nil - * - * Element Assignment --- Sets the element at +index+, or replaces a subarray - * from the +start+ index for +length+ elements, or replaces a subarray - * specified by the +range+ of indices. - * - * If indices are greater than the current capacity of the array, the array - * grows automatically. Elements are inserted into the array at +start+ if - * +length+ is zero. - * - * Negative indices will count backward from the end of the array. For - * +start+ and +range+ cases the starting index is just before an element. - * - * An IndexError is raised if a negative index points past the beginning of - * the array. - * - * See also Array#push, and Array#unshift. - * - * a = Array.new - * a[4] = "4"; #=> [nil, nil, nil, nil, "4"] - * a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"] - * a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"] - * a[0, 2] = "?" #=> ["?", 2, nil, "4"] - * a[0..2] = "A" #=> ["A", "4"] - * a[-1] = "Z" #=> ["A", "Z"] - * a[1..-1] = nil #=> ["A", nil] - * a[1..-1] = [] #=> ["A"] - * a[0, 0] = [ 1, 2 ] #=> [1, 2, "A"] - * a[3, 0] = "B" #=> [1, 2, "A", "B"] - */ - -static mrb_value -mrb_ary_aset(mrb_state *mrb, mrb_value self) -{ - mrb_value v1, v2, v3; - mrb_int i, len; - - if (mrb_get_args(mrb, "oo|o", &v1, &v2, &v3) == 2) { - switch (mrb_type(v1)) { - /* a[n..m] = v */ - case MRB_TT_RANGE: - if (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self))) { - mrb_ary_splice(mrb, self, i, len, v2); - } - break; - /* a[n] = v */ - case MRB_TT_FIXNUM: - mrb_ary_set(mrb, self, mrb_fixnum(v1), v2); - break; - default: - mrb_ary_set(mrb, self, aget_index(mrb, v1), v2); - break; - } - return v2; - } - - /* a[n,m] = v */ - mrb_ary_splice(mrb, self, aget_index(mrb, v1), aget_index(mrb, v2), v3); - return v3; -} - -static mrb_value -mrb_ary_delete_at(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self); - mrb_int index; - mrb_value val; - mrb_value *ptr; - mrb_int len; - - mrb_get_args(mrb, "i", &index); - if (index < 0) index += a->len; - if (index < 0 || a->len <= index) return mrb_nil_value(); - - ary_modify(mrb, a); - val = a->ptr[index]; - - ptr = a->ptr + index; - len = a->len - index; - while (--len) { - *ptr = *(ptr+1); - ++ptr; - } - --a->len; - - ary_shrink_capa(mrb, a); - - return val; -} - -static mrb_value -mrb_ary_first(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self); - mrb_int size; - - if (mrb_get_args(mrb, "|i", &size) == 0) { - return (a->len > 0)? a->ptr[0]: mrb_nil_value(); - } - if (size < 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size"); - } - - if (size > a->len) size = a->len; - if (ARY_SHARED_P(a)) { - return ary_subseq(mrb, a, 0, size); - } - return mrb_ary_new_from_values(mrb, size, a->ptr); -} - -static mrb_value -mrb_ary_last(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self); - mrb_int size; - - if (mrb_get_args(mrb, "|i", &size) == 0) - return (a->len > 0)? a->ptr[a->len - 1]: mrb_nil_value(); - - if (size < 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size"); - } - if (size > a->len) size = a->len; - if (ARY_SHARED_P(a) || size > ARY_DEFAULT_LEN) { - return ary_subseq(mrb, a, a->len - size, size); - } - return mrb_ary_new_from_values(mrb, size, a->ptr + a->len - size); -} - -static mrb_value -mrb_ary_index_m(mrb_state *mrb, mrb_value self) -{ - mrb_value obj; - mrb_int i; - - mrb_get_args(mrb, "o", &obj); - for (i = 0; i < RARRAY_LEN(self); i++) { - if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) { - return mrb_fixnum_value(i); - } - } - return mrb_nil_value(); -} - -static mrb_value -mrb_ary_rindex_m(mrb_state *mrb, mrb_value self) -{ - mrb_value obj; - mrb_int i; - - mrb_get_args(mrb, "o", &obj); - for (i = RARRAY_LEN(self) - 1; i >= 0; i--) { - if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) { - return mrb_fixnum_value(i); - } - } - return mrb_nil_value(); -} - -MRB_API mrb_value -mrb_ary_splat(mrb_state *mrb, mrb_value v) -{ - if (mrb_array_p(v)) { - return v; - } - if (mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) { - return mrb_funcall(mrb, v, "to_a", 0); - } - else { - return mrb_ary_new_from_values(mrb, 1, &v); - } -} - -static mrb_value -mrb_ary_size(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self); - - return mrb_fixnum_value(a->len); -} - -MRB_API mrb_value -mrb_ary_clear(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self); - - if (ARY_SHARED_P(a)) { - mrb_ary_decref(mrb, a->aux.shared); - ARY_UNSET_SHARED_FLAG(a); - } - else { - mrb_free(mrb, a->ptr); - } - a->len = 0; - a->aux.capa = 0; - a->ptr = 0; - - return self; -} - -static mrb_value -mrb_ary_empty_p(mrb_state *mrb, mrb_value self) -{ - struct RArray *a = mrb_ary_ptr(self); - - return mrb_bool_value(a->len == 0); -} - -MRB_API mrb_value -mrb_check_array_type(mrb_state *mrb, mrb_value ary) -{ - return mrb_check_convert_type(mrb, ary, MRB_TT_ARRAY, "Array", "to_ary"); -} - -MRB_API mrb_value -mrb_ary_entry(mrb_value ary, mrb_int offset) -{ - if (offset < 0) { - offset += RARRAY_LEN(ary); - } - return ary_elt(ary, offset); -} - -static mrb_value -join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list) -{ - mrb_int i; - mrb_value result, val, tmp; - - /* check recursive */ - for (i=0; i 0 && !mrb_nil_p(sep)) { - mrb_str_cat_str(mrb, result, sep); - } - - val = RARRAY_PTR(ary)[i]; - switch (mrb_type(val)) { - case MRB_TT_ARRAY: - ary_join: - val = join_ary(mrb, val, sep, list); - /* fall through */ - - case MRB_TT_STRING: - str_join: - mrb_str_cat_str(mrb, result, val); - break; - - default: - tmp = mrb_check_string_type(mrb, val); - if (!mrb_nil_p(tmp)) { - val = tmp; - goto str_join; - } - tmp = mrb_check_convert_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary"); - if (!mrb_nil_p(tmp)) { - val = tmp; - goto ary_join; - } - val = mrb_obj_as_string(mrb, val); - goto str_join; - } - } - - mrb_ary_pop(mrb, list); - - return result; -} - -MRB_API mrb_value -mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep) -{ - sep = mrb_obj_as_string(mrb, sep); - return join_ary(mrb, ary, sep, mrb_ary_new(mrb)); -} - -/* - * call-seq: - * ary.join(sep="") -> str - * - * Returns a string created by converting each element of the array to - * a string, separated by sep. - * - * [ "a", "b", "c" ].join #=> "abc" - * [ "a", "b", "c" ].join("-") #=> "a-b-c" - */ - -static mrb_value -mrb_ary_join_m(mrb_state *mrb, mrb_value ary) -{ - mrb_value sep = mrb_nil_value(); - - mrb_get_args(mrb, "|S!", &sep); - return mrb_ary_join(mrb, ary, sep); -} - -static mrb_value -mrb_ary_eq(mrb_state *mrb, mrb_value ary1) -{ - mrb_value ary2; - - mrb_get_args(mrb, "o", &ary2); - if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value(); - if (!mrb_array_p(ary2)) { - return mrb_false_value(); - } - if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); - - return ary2; -} - -static mrb_value -mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) -{ - mrb_value ary2; - - mrb_get_args(mrb, "o", &ary2); - if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_fixnum_value(0); - if (!mrb_array_p(ary2)) { - return mrb_nil_value(); - } - - return ary2; -} - -void -mrb_init_array(mrb_state *mrb) -{ - struct RClass *a; - - mrb->array_class = a = mrb_define_class(mrb, "Array", mrb->object_class); /* 15.2.12 */ - MRB_SET_INSTANCE_TT(a, MRB_TT_ARRAY); - - mrb_define_class_method(mrb, a, "[]", mrb_ary_s_create, MRB_ARGS_ANY()); /* 15.2.12.4.1 */ - - mrb_define_method(mrb, a, "+", mrb_ary_plus, MRB_ARGS_REQ(1)); /* 15.2.12.5.1 */ - mrb_define_method(mrb, a, "*", mrb_ary_times, MRB_ARGS_REQ(1)); /* 15.2.12.5.2 */ - mrb_define_method(mrb, a, "<<", mrb_ary_push_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.3 */ - mrb_define_method(mrb, a, "[]", mrb_ary_aget, MRB_ARGS_ANY()); /* 15.2.12.5.4 */ - mrb_define_method(mrb, a, "[]=", mrb_ary_aset, MRB_ARGS_ANY()); /* 15.2.12.5.5 */ - mrb_define_method(mrb, a, "clear", mrb_ary_clear, MRB_ARGS_NONE()); /* 15.2.12.5.6 */ - mrb_define_method(mrb, a, "concat", mrb_ary_concat_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.8 */ - mrb_define_method(mrb, a, "delete_at", mrb_ary_delete_at, MRB_ARGS_REQ(1)); /* 15.2.12.5.9 */ - mrb_define_method(mrb, a, "empty?", mrb_ary_empty_p, MRB_ARGS_NONE()); /* 15.2.12.5.12 */ - mrb_define_method(mrb, a, "first", mrb_ary_first, MRB_ARGS_OPT(1)); /* 15.2.12.5.13 */ - mrb_define_method(mrb, a, "index", mrb_ary_index_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.14 */ - mrb_define_method(mrb, a, "initialize_copy", mrb_ary_replace_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.16 */ - mrb_define_method(mrb, a, "join", mrb_ary_join_m, MRB_ARGS_ANY()); /* 15.2.12.5.17 */ - mrb_define_method(mrb, a, "last", mrb_ary_last, MRB_ARGS_ANY()); /* 15.2.12.5.18 */ - mrb_define_method(mrb, a, "length", mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.19 */ - mrb_define_method(mrb, a, "pop", mrb_ary_pop, MRB_ARGS_NONE()); /* 15.2.12.5.21 */ - mrb_define_method(mrb, a, "push", mrb_ary_push_m, MRB_ARGS_ANY()); /* 15.2.12.5.22 */ - mrb_define_method(mrb, a, "replace", mrb_ary_replace_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.23 */ - mrb_define_method(mrb, a, "reverse", mrb_ary_reverse, MRB_ARGS_NONE()); /* 15.2.12.5.24 */ - mrb_define_method(mrb, a, "reverse!", mrb_ary_reverse_bang, MRB_ARGS_NONE()); /* 15.2.12.5.25 */ - mrb_define_method(mrb, a, "rindex", mrb_ary_rindex_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.26 */ - mrb_define_method(mrb, a, "shift", mrb_ary_shift, MRB_ARGS_NONE()); /* 15.2.12.5.27 */ - mrb_define_method(mrb, a, "size", mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.28 */ - mrb_define_method(mrb, a, "slice", mrb_ary_aget, MRB_ARGS_ANY()); /* 15.2.12.5.29 */ - mrb_define_method(mrb, a, "unshift", mrb_ary_unshift_m, MRB_ARGS_ANY()); /* 15.2.12.5.30 */ - - mrb_define_method(mrb, a, "__ary_eq", mrb_ary_eq, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, a, "__ary_cmp", mrb_ary_cmp, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, a, "__ary_index", mrb_ary_index_m, MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */ -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/backtrace.c nghttp2-0.6.7/third-party/mruby/src/backtrace.c --- nghttp2-1.13.0/third-party/mruby/src/backtrace.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/backtrace.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,217 +0,0 @@ -/* -** backtrace.c - -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/variable.h" -#include "mruby/proc.h" -#include "mruby/array.h" -#include "mruby/string.h" -#include "mruby/class.h" -#include "mruby/debug.h" -#include "mruby/error.h" -#include "mruby/numeric.h" - -struct backtrace_location { - int i; - int lineno; - const char *filename; - const char *method; - const char *sep; - const char *class_name; -}; - -typedef void (*output_stream_func)(mrb_state*, struct backtrace_location*, void*); - -#ifndef MRB_DISABLE_STDIO - -struct print_backtrace_args { - FILE *stream; - int tracehead; -}; - -static void -print_backtrace_i(mrb_state *mrb, struct backtrace_location *loc, void *data) -{ - struct print_backtrace_args *args; - - args = (struct print_backtrace_args*)data; - - if (args->tracehead) { - fprintf(args->stream, "trace:\n"); - args->tracehead = FALSE; - } - - fprintf(args->stream, "\t[%d] %s:%d", loc->i, loc->filename, loc->lineno); - - if (loc->method) { - if (loc->class_name) { - fprintf(args->stream, ":in %s%s%s", loc->class_name, loc->sep, loc->method); - } - else { - fprintf(args->stream, ":in %s", loc->method); - } - } - - fprintf(args->stream, "\n"); -} - -#endif - -static void -get_backtrace_i(mrb_state *mrb, struct backtrace_location *loc, void *data) -{ - mrb_value ary, str; - int ai; - - ai = mrb_gc_arena_save(mrb); - ary = mrb_obj_value((struct RArray*)data); - - str = mrb_str_new_cstr(mrb, loc->filename); - mrb_str_cat_lit(mrb, str, ":"); - mrb_str_concat(mrb, str, mrb_fixnum_to_str(mrb, mrb_fixnum_value(loc->lineno), 10)); - - if (loc->method) { - mrb_str_cat_lit(mrb, str, ":in "); - - if (loc->class_name) { - mrb_str_cat_cstr(mrb, str, loc->class_name); - mrb_str_cat_cstr(mrb, str, loc->sep); - } - - mrb_str_cat_cstr(mrb, str, loc->method); - } - - mrb_ary_push(mrb, ary, str); - mrb_gc_arena_restore(mrb, ai); -} - -static void -output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_func func, void *data) -{ - int i; - - if (ciidx >= mrb->c->ciend - mrb->c->cibase) - ciidx = 10; /* ciidx is broken... */ - - for (i = ciidx; i >= 0; i--) { - struct backtrace_location loc; - mrb_callinfo *ci; - mrb_irep *irep; - mrb_code *pc; - - ci = &mrb->c->cibase[i]; - - if (!ci->proc) continue; - if (MRB_PROC_CFUNC_P(ci->proc)) continue; - - irep = ci->proc->body.irep; - - if (mrb->c->cibase[i].err) { - pc = mrb->c->cibase[i].err; - } - else if (i+1 <= ciidx) { - pc = mrb->c->cibase[i+1].pc - 1; - } - else { - pc = pc0; - } - loc.filename = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq)); - loc.lineno = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq)); - - if (loc.lineno == -1) continue; - - if (ci->target_class == ci->proc->target_class) { - loc.sep = "."; - } - else { - loc.sep = "#"; - } - - if (!loc.filename) { - loc.filename = "(unknown)"; - } - - loc.method = mrb_sym2name(mrb, ci->mid); - loc.class_name = mrb_class_name(mrb, ci->proc->target_class); - loc.i = i; - func(mrb, &loc, data); - } -} - -static void -exc_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func func, void *stream) -{ - mrb_value lastpc; - mrb_code *code; - - lastpc = mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "lastpc")); - if (mrb_nil_p(lastpc)) { - code = NULL; - } else { - code = (mrb_code*)mrb_cptr(lastpc); - } - - output_backtrace(mrb, mrb_fixnum(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "ciidx"))), - code, func, stream); -} - -/* mrb_print_backtrace/mrb_get_backtrace: - - function to retrieve backtrace information from the exception. - note that if you call method after the exception, call stack will be - overwritten. So invoke these functions just after detecting exceptions. -*/ - -#ifndef MRB_DISABLE_STDIO - -MRB_API void -mrb_print_backtrace(mrb_state *mrb) -{ - struct print_backtrace_args args; - - if (!mrb->exc || mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), E_SYSSTACK_ERROR)) { - return; - } - - args.stream = stderr; - args.tracehead = TRUE; - exc_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)&args); -} - -#else - -MRB_API void -mrb_print_backtrace(mrb_state *mrb) -{ -} - -#endif - -MRB_API mrb_value -mrb_exc_backtrace(mrb_state *mrb, mrb_value self) -{ - mrb_value ary; - - ary = mrb_ary_new(mrb); - exc_output_backtrace(mrb, mrb_obj_ptr(self), get_backtrace_i, (void*)mrb_ary_ptr(ary)); - - return ary; -} - -MRB_API mrb_value -mrb_get_backtrace(mrb_state *mrb) -{ - mrb_value ary; - mrb_callinfo *ci = mrb->c->ci; - mrb_code *pc = ci->pc; - mrb_int ciidx = (mrb_int)(ci - mrb->c->cibase - 1); - - if (ciidx < 0) ciidx = 0; - ary = mrb_ary_new(mrb); - output_backtrace(mrb, ciidx, pc, get_backtrace_i, (void*)mrb_ary_ptr(ary)); - - return ary; -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/class.c nghttp2-0.6.7/third-party/mruby/src/class.c --- nghttp2-1.13.0/third-party/mruby/src/class.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/class.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,2278 +0,0 @@ -/* -** class.c - Class class -** -** See Copyright Notice in mruby.h -*/ - -#include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/numeric.h" -#include "mruby/proc.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/error.h" -#include "mruby/data.h" - -KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal) - -void -mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c) -{ - khiter_t k; - khash_t(mt) *h = c->mt; - - if (!h) return; - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)) { - struct RProc *m = kh_value(h, k); - if (m) { - mrb_gc_mark(mrb, (struct RBasic*)m); - } - } - } -} - -size_t -mrb_gc_mark_mt_size(mrb_state *mrb, struct RClass *c) -{ - khash_t(mt) *h = c->mt; - - if (!h) return 0; - return kh_size(h); -} - -void -mrb_gc_free_mt(mrb_state *mrb, struct RClass *c) -{ - kh_destroy(mt, mrb, c->mt); -} - -static void -name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) -{ - mrb_obj_iv_set(mrb, (struct RObject*)c, - mrb_intern_lit(mrb, "__classid__"), mrb_symbol_value(name)); -} - -static void -setup_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id) -{ - name_class(mrb, c, id); - mrb_obj_iv_set(mrb, (struct RObject*)outer, id, mrb_obj_value(c)); - if (outer != mrb->object_class) { - mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"), - mrb_obj_value(outer)); - } -} - -#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c)) - -static void -prepare_singleton_class(mrb_state *mrb, struct RBasic *o) -{ - struct RClass *sc, *c; - - if (o->c->tt == MRB_TT_SCLASS) return; - sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class); - sc->mt = kh_init(mt, mrb); - sc->iv = 0; - if (o->tt == MRB_TT_CLASS) { - c = (struct RClass*)o; - if (!c->super) { - sc->super = mrb->class_class; - } - else { - sc->super = c->super->c; - } - } - else if (o->tt == MRB_TT_SCLASS) { - c = (struct RClass*)o; - while (c->super->tt == MRB_TT_ICLASS) - c = c->super; - make_metaclass(mrb, c->super); - sc->super = c->super->c; - } - else { - sc->super = o->c; - } - o->c = sc; - mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc); - mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o); - mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o)); -} - -static struct RClass * -class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id) -{ - mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id); - - mrb_check_type(mrb, c, MRB_TT_CLASS); - return mrb_class_ptr(c); -} - -static struct RClass * -module_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id) -{ - mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id); - - mrb_check_type(mrb, c, MRB_TT_MODULE); - return mrb_class_ptr(c); -} - -MRB_API struct RClass* -mrb_class_outer_module(mrb_state *mrb, struct RClass *c) -{ - mrb_value outer; - - outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__")); - if (mrb_nil_p(outer)) return NULL; - return mrb_class_ptr(outer); -} - -static void -check_if_class_or_module(mrb_state *mrb, mrb_value obj) -{ - switch (mrb_type(obj)) { - case MRB_TT_CLASS: - case MRB_TT_SCLASS: - case MRB_TT_MODULE: - return; - default: - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_inspect(mrb, obj)); - } -} - -static struct RClass* -define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer) -{ - struct RClass *m; - - if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) { - return module_from_sym(mrb, outer, name); - } - m = mrb_module_new(mrb); - setup_class(mrb, outer, m, name); - - return m; -} - -MRB_API struct RClass* -mrb_define_module_id(mrb_state *mrb, mrb_sym name) -{ - return define_module(mrb, name, mrb->object_class); -} - -MRB_API struct RClass* -mrb_define_module(mrb_state *mrb, const char *name) -{ - return define_module(mrb, mrb_intern_cstr(mrb, name), mrb->object_class); -} - -MRB_API struct RClass* -mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id) -{ - check_if_class_or_module(mrb, outer); - return define_module(mrb, id, mrb_class_ptr(outer)); -} - -MRB_API struct RClass* -mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name) -{ - mrb_sym id = mrb_intern_cstr(mrb, name); - struct RClass * c = define_module(mrb, id, outer); - - setup_class(mrb, outer, c, id); - return c; -} - -static struct RClass* -find_origin(struct RClass *c) -{ - MRB_CLASS_ORIGIN(c); - return c; -} - -static struct RClass* -define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *outer) -{ - struct RClass * c; - - if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) { - c = class_from_sym(mrb, outer, name); - MRB_CLASS_ORIGIN(c); - if (super && mrb_class_real(c->super) != super) { - mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)", - mrb_sym2str(mrb, name), - mrb_obj_value(c->super), mrb_obj_value(super)); - } - return c; - } - - c = mrb_class_new(mrb, super); - setup_class(mrb, outer, c, name); - - return c; -} - -MRB_API struct RClass* -mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super) -{ - if (!super) { - mrb_warn(mrb, "no super class for '%S', Object assumed", mrb_sym2str(mrb, name)); - } - return define_class(mrb, name, super, mrb->object_class); -} - -MRB_API struct RClass* -mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super) -{ - return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super); -} - -static void -mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass) -{ - if (!super) - super = mrb->object_class; - mrb_funcall(mrb, mrb_obj_value(super), "inherited", 1, mrb_obj_value(klass)); -} - -MRB_API struct RClass* -mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id) -{ - struct RClass *s; - struct RClass *c; - - if (!mrb_nil_p(super)) { - if (mrb_type(super) != MRB_TT_CLASS) { - mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", super); - } - s = mrb_class_ptr(super); - } - else { - s = 0; - } - check_if_class_or_module(mrb, outer); - c = define_class(mrb, id, s, mrb_class_ptr(outer)); - mrb_class_inherited(mrb, mrb_class_real(c->super), c); - - return c; -} - -MRB_API mrb_bool -mrb_class_defined(mrb_state *mrb, const char *name) -{ - mrb_value sym = mrb_check_intern_cstr(mrb, name); - if (mrb_nil_p(sym)) { - return FALSE; - } - return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_symbol(sym)); -} - -MRB_API struct RClass * -mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name) -{ - return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name)); -} - -MRB_API struct RClass * -mrb_class_get(mrb_state *mrb, const char *name) -{ - return mrb_class_get_under(mrb, mrb->object_class, name); -} - -MRB_API struct RClass * -mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name) -{ - return module_from_sym(mrb, outer, mrb_intern_cstr(mrb, name)); -} - -MRB_API struct RClass * -mrb_module_get(mrb_state *mrb, const char *name) -{ - return mrb_module_get_under(mrb, mrb->object_class, name); -} - -/*! - * Defines a class under the namespace of \a outer. - * \param outer a class which contains the new class. - * \param id name of the new class - * \param super a class from which the new class will derive. - * NULL means \c Object class. - * \return the created class - * \throw TypeError if the constant name \a name is already taken but - * the constant is not a \c Class. - * \throw NameError if the class is already defined but the class can not - * be reopened because its superclass is not \a super. - * \post top-level constant named \a name refers the returned class. - * - * \note if a class named \a name is already defined and its superclass is - * \a super, the function just returns the defined class. - */ -MRB_API struct RClass * -mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super) -{ - mrb_sym id = mrb_intern_cstr(mrb, name); - struct RClass * c; - -#if 0 - if (!super) { - mrb_warn(mrb, "no super class for '%S::%S', Object assumed", - mrb_obj_value(outer), mrb_sym2str(mrb, id)); - } -#endif - c = define_class(mrb, id, super, outer); - setup_class(mrb, outer, c, id); - return c; -} - -MRB_API void -mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RProc *p) -{ - khash_t(mt) *h; - khiter_t k; - MRB_CLASS_ORIGIN(c); - h = c->mt; - - if (!h) h = c->mt = kh_init(mt, mrb); - k = kh_put(mt, mrb, h, mid); - kh_value(h, k) = p; - if (p) { - mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p); - } -} - -MRB_API void -mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec) -{ - struct RProc *p; - int ai = mrb_gc_arena_save(mrb); - - p = mrb_proc_new_cfunc(mrb, func); - p->target_class = c; - mrb_define_method_raw(mrb, c, mid, p); - mrb_gc_arena_restore(mrb, ai); -} - -MRB_API void -mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) -{ - mrb_define_method_id(mrb, c, mrb_intern_cstr(mrb, name), func, aspec); -} - -/* a function to raise NotImplementedError with current method name */ -MRB_API void -mrb_notimplement(mrb_state *mrb) -{ - const char *str; - mrb_int len; - mrb_callinfo *ci = mrb->c->ci; - - if (ci->mid) { - str = mrb_sym2name_len(mrb, ci->mid, &len); - mrb_raisef(mrb, E_NOTIMP_ERROR, - "%S() function is unimplemented on this machine", - mrb_str_new_static(mrb, str, (size_t)len)); - } -} - -/* a function to be replacement of unimplemented method */ -MRB_API mrb_value -mrb_notimplement_m(mrb_state *mrb, mrb_value self) -{ - mrb_notimplement(mrb); - /* not reached */ - return mrb_nil_value(); -} - -static mrb_value -check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const char *m) -{ - mrb_value tmp; - - tmp = mrb_check_convert_type(mrb, val, t, c, m); - if (mrb_nil_p(tmp)) { - mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_cstr(mrb, c)); - } - return tmp; -} - -static mrb_value -to_str(mrb_state *mrb, mrb_value val) -{ - return check_type(mrb, val, MRB_TT_STRING, "String", "to_str"); -} - -static mrb_value -to_ary(mrb_state *mrb, mrb_value val) -{ - return check_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary"); -} - -static mrb_value -to_hash(mrb_state *mrb, mrb_value val) -{ - return check_type(mrb, val, MRB_TT_HASH, "Hash", "to_hash"); -} - -static mrb_sym -to_sym(mrb_state *mrb, mrb_value ss) -{ - if (mrb_type(ss) == MRB_TT_SYMBOL) { - return mrb_symbol(ss); - } - else if (mrb_string_p(ss)) { - return mrb_intern_str(mrb, to_str(mrb, ss)); - } - else { - mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0); - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj); - } -} - -/* - retrieve arguments from mrb_state. - - mrb_get_args(mrb, format, ...) - - returns number of arguments parsed. - - format specifiers: - - string mruby type C type note - ---------------------------------------------------------------------------------------------- - o: Object [mrb_value] - C: class/module [mrb_value] - S: String [mrb_value] when ! follows, the value may be nil - A: Array [mrb_value] when ! follows, the value may be nil - H: Hash [mrb_value] when ! follows, the value may be nil - s: String [char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil - z: String [char*] NUL terminated string; z! gives NULL for nil - a: Array [mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil - f: Float [mrb_float] - i: Integer [mrb_int] - b: Boolean [mrb_bool] - n: Symbol [mrb_sym] - d: Data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified - &: Block [mrb_value] - *: rest argument [mrb_value*,mrb_int] Receive the rest of the arguments as an array. - |: optional Next argument of '|' and later are optional. - ?: optional given [mrb_bool] true if preceding argument (optional) is given. - */ -MRB_API mrb_int -mrb_get_args(mrb_state *mrb, const char *format, ...) -{ - char c; - int i = 0; - mrb_value *sp = mrb->c->stack + 1; - va_list ap; - int argc = mrb->c->ci->argc; - mrb_bool opt = FALSE; - mrb_bool given = TRUE; - - va_start(ap, format); - if (argc < 0) { - struct RArray *a = mrb_ary_ptr(mrb->c->stack[1]); - - argc = a->len; - sp = a->ptr; - } - while ((c = *format++)) { - switch (c) { - case '|': case '*': case '&': case '?': - break; - default: - if (argc <= i) { - if (opt) { - given = FALSE; - } - else { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); - } - } - break; - } - - switch (c) { - case 'o': - { - mrb_value *p; - - p = va_arg(ap, mrb_value*); - if (i < argc) { - *p = *sp++; - i++; - } - } - break; - case 'C': - { - mrb_value *p; - - p = va_arg(ap, mrb_value*); - if (i < argc) { - mrb_value ss; - - ss = *sp++; - switch (mrb_type(ss)) { - case MRB_TT_CLASS: - case MRB_TT_MODULE: - case MRB_TT_SCLASS: - break; - default: - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not class/module", ss); - break; - } - *p = ss; - i++; - } - } - break; - case 'S': - { - mrb_value *p; - - p = va_arg(ap, mrb_value*); - if (*format == '!') { - format++; - if (i < argc && mrb_nil_p(*sp)) { - *p = *sp++; - i++; - break; - } - } - if (i < argc) { - *p = to_str(mrb, *sp++); - i++; - } - } - break; - case 'A': - { - mrb_value *p; - - p = va_arg(ap, mrb_value*); - if (*format == '!') { - format++; - if (i < argc && mrb_nil_p(*sp)) { - *p = *sp++; - i++; - break; - } - } - if (i < argc) { - *p = to_ary(mrb, *sp++); - i++; - } - } - break; - case 'H': - { - mrb_value *p; - - p = va_arg(ap, mrb_value*); - if (*format == '!') { - format++; - if (i < argc && mrb_nil_p(*sp)) { - *p = *sp++; - i++; - break; - } - } - if (i < argc) { - *p = to_hash(mrb, *sp++); - i++; - } - } - break; - case 's': - { - mrb_value ss; - char **ps = 0; - mrb_int *pl = 0; - - ps = va_arg(ap, char**); - pl = va_arg(ap, mrb_int*); - if (*format == '!') { - format++; - if (i < argc && mrb_nil_p(*sp)) { - *ps = NULL; - *pl = 0; - i++; - break; - } - } - if (i < argc) { - ss = to_str(mrb, *sp++); - *ps = RSTRING_PTR(ss); - *pl = RSTRING_LEN(ss); - i++; - } - } - break; - case 'z': - { - mrb_value ss; - const char **ps; - - ps = va_arg(ap, const char**); - if (*format == '!') { - format++; - if (i < argc && mrb_nil_p(*sp)) { - *ps = NULL; - i++; sp++; - break; - } - } - if (i < argc) { - ss = to_str(mrb, *sp++); - *ps = mrb_string_value_cstr(mrb, &ss); - i++; - } - } - break; - case 'a': - { - mrb_value aa; - struct RArray *a; - mrb_value **pb; - mrb_int *pl; - - pb = va_arg(ap, mrb_value**); - pl = va_arg(ap, mrb_int*); - if (*format == '!') { - format++; - if (i < argc && mrb_nil_p(*sp)) { - *pb = 0; - *pl = 0; - i++; sp++; - break; - } - } - if (i < argc) { - aa = to_ary(mrb, *sp++); - a = mrb_ary_ptr(aa); - *pb = a->ptr; - *pl = a->len; - i++; - } - } - break; - case 'f': - { - mrb_float *p; - - p = va_arg(ap, mrb_float*); - if (i < argc) { - *p = mrb_to_flo(mrb, *sp); - sp++; - i++; - } - } - break; - case 'i': - { - mrb_int *p; - - p = va_arg(ap, mrb_int*); - if (i < argc) { - switch (mrb_type(*sp)) { - case MRB_TT_FIXNUM: - *p = mrb_fixnum(*sp); - break; - case MRB_TT_FLOAT: - { - mrb_float f = mrb_float(*sp); - - if (!FIXABLE(f)) { - mrb_raise(mrb, E_RANGE_ERROR, "float too big for int"); - } - *p = (mrb_int)f; - } - break; - case MRB_TT_STRING: - mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer"); - break; - default: - *p = mrb_fixnum(mrb_Integer(mrb, *sp)); - break; - } - sp++; - i++; - } - } - break; - case 'b': - { - mrb_bool *boolp = va_arg(ap, mrb_bool*); - - if (i < argc) { - mrb_value b = *sp++; - *boolp = mrb_test(b); - i++; - } - } - break; - case 'n': - { - mrb_sym *symp; - - symp = va_arg(ap, mrb_sym*); - if (i < argc) { - mrb_value ss; - - ss = *sp++; - *symp = to_sym(mrb, ss); - i++; - } - } - break; - case 'd': - { - void** datap; - struct mrb_data_type const* type; - - datap = va_arg(ap, void**); - type = va_arg(ap, struct mrb_data_type const*); - if (*format == '!') { - format++; - if (i < argc && mrb_nil_p(*sp)) { - *datap = 0; - i++; sp++; - break; - } - } - if (i < argc) { - *datap = mrb_data_get_ptr(mrb, *sp++, type); - ++i; - } - } - break; - - case '&': - { - mrb_value *p, *bp; - - p = va_arg(ap, mrb_value*); - if (mrb->c->ci->argc < 0) { - bp = mrb->c->stack + 2; - } - else { - bp = mrb->c->stack + mrb->c->ci->argc + 1; - } - *p = *bp; - } - break; - case '|': - opt = TRUE; - break; - case '?': - { - mrb_bool *p; - - p = va_arg(ap, mrb_bool*); - *p = given; - } - break; - - case '*': - { - mrb_value **var; - mrb_int *pl; - - var = va_arg(ap, mrb_value**); - pl = va_arg(ap, mrb_int*); - if (argc > i) { - *pl = argc-i; - if (*pl > 0) { - *var = sp; - } - i = argc; - sp += *pl; - } - else { - *pl = 0; - *var = NULL; - } - } - break; - default: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %S", mrb_str_new(mrb, &c, 1)); - break; - } - } - if (!c && argc > i) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); - } - va_end(ap); - return i; -} - -static struct RClass* -boot_defclass(mrb_state *mrb, struct RClass *super) -{ - struct RClass *c; - - c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class); - if (super) { - c->super = super; - mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super); - } - else { - c->super = mrb->object_class; - } - c->mt = kh_init(mt, mrb); - return c; -} - -static void -boot_initmod(mrb_state *mrb, struct RClass *mod) -{ - mod->mt = kh_init(mt, mrb); -} - -static struct RClass* -include_class_new(mrb_state *mrb, struct RClass *m, struct RClass *super) -{ - struct RClass *ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class); - if (m->tt == MRB_TT_ICLASS) { - m = m->c; - } - MRB_CLASS_ORIGIN(m); - ic->iv = m->iv; - ic->mt = m->mt; - ic->super = super; - if (m->tt == MRB_TT_ICLASS) { - ic->c = m->c; - } else { - ic->c = m; - } - return ic; -} - -static int -include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super) -{ - struct RClass *p, *ic; - void *klass_mt = find_origin(c)->mt; - - while (m) { - int superclass_seen = 0; - - if (m->flags & MRB_FLAG_IS_PREPENDED) - goto skip; - - if (klass_mt && klass_mt == m->mt) - return -1; - - p = c->super; - while(p) { - if (p->tt == MRB_TT_ICLASS) { - if (p->mt == m->mt) { - if (!superclass_seen) { - ins_pos = p; // move insert point - } - goto skip; - } - } else if (p->tt == MRB_TT_CLASS) { - if (!search_super) break; - superclass_seen = 1; - } - p = p->super; - } - - ic = include_class_new(mrb, m, ins_pos->super); - ins_pos->super = ic; - mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ins_pos->super); - ins_pos = ic; - skip: - m = m->super; - } - return 0; -} - -MRB_API void -mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) -{ - int changed = include_module_at(mrb, c, find_origin(c), m, 1); - if (changed < 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected"); - } -} - -MRB_API void -mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) -{ - struct RClass *origin; - int changed = 0; - - if (!(c->flags & MRB_FLAG_IS_PREPENDED)) { - origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c); - origin->flags |= MRB_FLAG_IS_ORIGIN; - origin->super = c->super; - c->super = origin; - origin->mt = c->mt; - c->mt = kh_init(mt, mrb); - mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)origin); - c->flags |= MRB_FLAG_IS_PREPENDED; - } - changed = include_module_at(mrb, c, c, m, 0); - if (changed < 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic prepend detected"); - } -} - -static mrb_value -mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod) -{ - mrb_value klass; - - mrb_check_type(mrb, mod, MRB_TT_MODULE); - mrb_get_args(mrb, "C", &klass); - mrb_prepend_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); - return mod; -} - -static mrb_value -mrb_mod_prepend(mrb_state *mrb, mrb_value klass) -{ - mrb_value *argv; - mrb_int argc, i; - - mrb_get_args(mrb, "*", &argv, &argc); - for (i=0; i true or false - * - * Returns true if module is included in - * mod or one of mod's ancestors. - * - * module A - * end - * class B - * include A - * end - * class C < B - * end - * B.include?(A) #=> true - * C.include?(A) #=> true - * A.include?(A) #=> false - */ -static mrb_value -mrb_mod_include_p(mrb_state *mrb, mrb_value mod) -{ - mrb_value mod2; - struct RClass *c = mrb_class_ptr(mod); - - mrb_get_args(mrb, "C", &mod2); - mrb_check_type(mrb, mod2, MRB_TT_MODULE); - - while (c) { - if (c->tt == MRB_TT_ICLASS) { - if (c->c == mrb_class_ptr(mod2)) return mrb_true_value(); - } - c = c->super; - } - return mrb_false_value(); -} - -static mrb_value -mrb_mod_ancestors(mrb_state *mrb, mrb_value self) -{ - mrb_value result; - struct RClass *c = mrb_class_ptr(self); - result = mrb_ary_new(mrb); - while (c) { - if (c->tt == MRB_TT_ICLASS) { - mrb_ary_push(mrb, result, mrb_obj_value(c->c)); - } - else if (!(c->flags & MRB_FLAG_IS_PREPENDED)) { - mrb_ary_push(mrb, result, mrb_obj_value(c)); - } - c = c->super; - } - - return result; -} - -static mrb_value -mrb_mod_extend_object(mrb_state *mrb, mrb_value mod) -{ - mrb_value obj; - - mrb_check_type(mrb, mod, MRB_TT_MODULE); - mrb_get_args(mrb, "o", &obj); - mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod)); - return mod; -} - -static mrb_value -mrb_mod_included_modules(mrb_state *mrb, mrb_value self) -{ - mrb_value result; - struct RClass *c = mrb_class_ptr(self); - struct RClass *origin = c; - - MRB_CLASS_ORIGIN(origin); - result = mrb_ary_new(mrb); - while (c) { - if (c != origin && c->tt == MRB_TT_ICLASS) { - if (c->c->tt == MRB_TT_MODULE) { - mrb_ary_push(mrb, result, mrb_obj_value(c->c)); - } - } - c = c->super; - } - - return result; -} - -static mrb_value -mrb_mod_initialize(mrb_state *mrb, mrb_value mod) -{ - mrb_value b; - struct RClass *m = mrb_class_ptr(mod); - boot_initmod(mrb, m); // bootstrap a newly initialized module - mrb_get_args(mrb, "|&", &b); - if (!mrb_nil_p(b)) { - mrb_yield_with_class(mrb, b, 1, &mod, mod, m); - } - return mod; -} - -mrb_value mrb_class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int); - -/* 15.2.2.4.33 */ -/* - * call-seq: - * mod.instance_methods(include_super=true) -> array - * - * Returns an array containing the names of the public and protected instance - * methods in the receiver. For a module, these are the public and protected methods; - * for a class, they are the instance (not singleton) methods. With no - * argument, or with an argument that is false, the - * instance methods in mod are returned, otherwise the methods - * in mod and mod's superclasses are returned. - * - * module A - * def method1() end - * end - * class B - * def method2() end - * end - * class C < B - * def method3() end - * end - * - * A.instance_methods #=> [:method1] - * B.instance_methods(false) #=> [:method2] - * C.instance_methods(false) #=> [:method3] - * C.instance_methods(true).length #=> 43 - */ - -static mrb_value -mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod) -{ - struct RClass *c = mrb_class_ptr(mod); - mrb_bool recur = TRUE; - mrb_get_args(mrb, "|b", &recur); - return mrb_class_instance_method_list(mrb, recur, c, 0); -} - -/* implementation of module_eval/class_eval */ -mrb_value mrb_mod_module_eval(mrb_state*, mrb_value); - -static mrb_value -mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod) -{ - return mod; -} - -MRB_API mrb_value -mrb_singleton_class(mrb_state *mrb, mrb_value v) -{ - struct RBasic *obj; - - switch (mrb_type(v)) { - case MRB_TT_FALSE: - if (mrb_nil_p(v)) - return mrb_obj_value(mrb->nil_class); - return mrb_obj_value(mrb->false_class); - case MRB_TT_TRUE: - return mrb_obj_value(mrb->true_class); - case MRB_TT_CPTR: - return mrb_obj_value(mrb->object_class); - case MRB_TT_SYMBOL: - case MRB_TT_FIXNUM: - case MRB_TT_FLOAT: - mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton"); - return mrb_nil_value(); /* not reached */ - default: - break; - } - obj = mrb_basic_ptr(v); - prepare_singleton_class(mrb, obj); - if (mrb->c && mrb->c->ci && mrb->c->ci->target_class) { - mrb_obj_iv_set(mrb, (struct RObject*)obj->c, mrb_intern_lit(mrb, "__outer__"), - mrb_obj_value(mrb->c->ci->target_class)); - } - return mrb_obj_value(obj->c); -} - -MRB_API void -mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, mrb_aspec aspec) -{ - prepare_singleton_class(mrb, (struct RBasic*)o); - mrb_define_method_id(mrb, o->c, mrb_intern_cstr(mrb, name), func, aspec); -} - -MRB_API void -mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) -{ - mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec); -} - -MRB_API void -mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) -{ - mrb_define_class_method(mrb, c, name, func, aspec); - mrb_define_method(mrb, c, name, func, aspec); -} - -MRB_API struct RProc* -mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid) -{ - khiter_t k; - struct RProc *m; - struct RClass *c = *cp; - - while (c) { - khash_t(mt) *h = c->mt; - - if (h) { - k = kh_get(mt, mrb, h, mid); - if (k != kh_end(h)) { - m = kh_value(h, k); - if (!m) break; - *cp = c; - return m; - } - } - c = c->super; - } - return NULL; /* no method */ -} - -MRB_API struct RProc* -mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid) -{ - struct RProc *m; - - m = mrb_method_search_vm(mrb, &c, mid); - if (!m) { - mrb_value inspect = mrb_funcall(mrb, mrb_obj_value(c), "inspect", 0); - if (mrb_string_p(inspect) && RSTRING_LEN(inspect) > 64) { - inspect = mrb_any_to_s(mrb, mrb_obj_value(c)); - } - mrb_name_error(mrb, mid, "undefined method '%S' for class %S", - mrb_sym2str(mrb, mid), inspect); - } - return m; -} - -static mrb_value -attr_reader(mrb_state *mrb, mrb_value obj) -{ - mrb_value name = mrb_proc_cfunc_env_get(mrb, 0); - return mrb_iv_get(mrb, obj, to_sym(mrb, name)); -} - -static mrb_value -mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod) -{ - struct RClass *c = mrb_class_ptr(mod); - mrb_value *argv; - mrb_int argc, i; - int ai; - - mrb_get_args(mrb, "*", &argv, &argc); - ai = mrb_gc_arena_save(mrb); - for (i=0; i obj - * - * Creates a new object of class's class, then - * invokes that object's initialize method, - * passing it args. This is the method that ends - * up getting called whenever an object is constructed using - * `.new`. - * - */ - -MRB_API mrb_value -mrb_instance_new(mrb_state *mrb, mrb_value cv) -{ - mrb_value obj, blk; - mrb_value *argv; - mrb_int argc; - - mrb_get_args(mrb, "*&", &argv, &argc, &blk); - obj = mrb_instance_alloc(mrb, cv); - mrb_funcall_with_block(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv, blk); - - return obj; -} - -MRB_API mrb_value -mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv) -{ - mrb_value obj; - - obj = mrb_instance_alloc(mrb, mrb_obj_value(c)); - mrb_funcall_argv(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv); - - return obj; -} - -static mrb_value -mrb_class_initialize(mrb_state *mrb, mrb_value c) -{ - mrb_value a, b; - - mrb_get_args(mrb, "|C&", &a, &b); - if (!mrb_nil_p(b)) { - mrb_yield_with_class(mrb, b, 1, &c, c, mrb_class_ptr(c)); - } - return c; -} - -static mrb_value -mrb_class_new_class(mrb_state *mrb, mrb_value cv) -{ - mrb_int n; - mrb_value super, blk; - mrb_value new_class; - - n = mrb_get_args(mrb, "|C&", &super, &blk); - if (n == 0) { - super = mrb_obj_value(mrb->object_class); - } - new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super))); - mrb_funcall_with_block(mrb, new_class, mrb_intern_lit(mrb, "initialize"), n, &super, blk); - mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class)); - return new_class; -} - -static mrb_value -mrb_class_superclass(mrb_state *mrb, mrb_value klass) -{ - struct RClass *c; - - c = mrb_class_ptr(klass); - c = find_origin(c)->super; - while (c && c->tt == MRB_TT_ICLASS) { - c = find_origin(c)->super; - } - if (!c) return mrb_nil_value(); - return mrb_obj_value(c); -} - -static mrb_value -mrb_bob_init(mrb_state *mrb, mrb_value cv) -{ - return mrb_nil_value(); -} - -static mrb_value -mrb_bob_not(mrb_state *mrb, mrb_value cv) -{ - return mrb_bool_value(!mrb_test(cv)); -} - -void -mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args) -{ - mrb_sym inspect; - mrb_value repr; - - inspect = mrb_intern_lit(mrb, "inspect"); - if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { - /* method missing in inspect; avoid recursion */ - repr = mrb_any_to_s(mrb, self); - } - else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) { - repr = mrb_funcall_argv(mrb, self, inspect, 0, 0); - if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) { - repr = mrb_any_to_s(mrb, self); - } - } - else { - repr = mrb_any_to_s(mrb, self); - } - - mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S", - mrb_sym2str(mrb, name), repr); -} - -/* 15.3.1.3.30 */ -/* - * call-seq: - * obj.method_missing(symbol [, *args] ) -> result - * - * Invoked by Ruby when obj is sent a message it cannot handle. - * symbol is the symbol for the method called, and args - * are any arguments that were passed to it. By default, the interpreter - * raises an error when this method is called. However, it is possible - * to override the method to provide more dynamic behavior. - * If it is decided that a particular method should not be handled, then - * super should be called, so that ancestors can pick up the - * missing method. - * The example below creates - * a class Roman, which responds to methods with names - * consisting of roman numerals, returning the corresponding integer - * values. - * - * class Roman - * def romanToInt(str) - * # ... - * end - * def method_missing(methId) - * str = methId.id2name - * romanToInt(str) - * end - * end - * - * r = Roman.new - * r.iv #=> 4 - * r.xxiii #=> 23 - * r.mm #=> 2000 - */ -static mrb_value -mrb_bob_missing(mrb_state *mrb, mrb_value mod) -{ - mrb_sym name; - mrb_value *a; - mrb_int alen; - - mrb_get_args(mrb, "n*", &name, &a, &alen); - mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a)); - /* not reached */ - return mrb_nil_value(); -} - -MRB_API mrb_bool -mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid) -{ - khiter_t k; - - while (c) { - khash_t(mt) *h = c->mt; - - if (h) { - k = kh_get(mt, mrb, h, mid); - if (k != kh_end(h)) { - if (kh_value(h, k)) { - return TRUE; /* method exists */ - } - else { - return FALSE; /* undefined method */ - } - } - } - c = c->super; - } - return FALSE; /* no method */ -} - -MRB_API mrb_bool -mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid) -{ - return mrb_obj_respond_to(mrb, mrb_class(mrb, obj), mid); -} - -MRB_API mrb_value -mrb_class_path(mrb_state *mrb, struct RClass *c) -{ - mrb_value path; - const char *name; - mrb_sym classpath = mrb_intern_lit(mrb, "__classpath__"); - - path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath); - if (mrb_nil_p(path)) { - struct RClass *outer = mrb_class_outer_module(mrb, c); - mrb_sym sym = mrb_class_sym(mrb, c, outer); - mrb_int len; - - if (sym == 0) { - return mrb_nil_value(); - } - else if (outer && outer != mrb->object_class) { - mrb_value base = mrb_class_path(mrb, outer); - path = mrb_str_buf_new(mrb, 0); - if (mrb_nil_p(base)) { - mrb_str_cat_lit(mrb, path, "#"); - } - else { - mrb_str_concat(mrb, path, base); - } - mrb_str_cat_lit(mrb, path, "::"); - name = mrb_sym2name_len(mrb, sym, &len); - mrb_str_cat(mrb, path, name, len); - } - else { - name = mrb_sym2name_len(mrb, sym, &len); - path = mrb_str_new(mrb, name, len); - } - mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path); - } - return path; -} - -MRB_API struct RClass * -mrb_class_real(struct RClass* cl) -{ - if (cl == 0) - return NULL; - while ((cl->tt == MRB_TT_SCLASS) || (cl->tt == MRB_TT_ICLASS)) { - cl = cl->super; - } - return cl; -} - -MRB_API const char* -mrb_class_name(mrb_state *mrb, struct RClass* c) -{ - mrb_value path = mrb_class_path(mrb, c); - if (mrb_nil_p(path)) { - path = mrb_str_new_lit(mrb, "#"); - } - return RSTRING_PTR(path); -} - -MRB_API const char* -mrb_obj_classname(mrb_state *mrb, mrb_value obj) -{ - return mrb_class_name(mrb, mrb_obj_class(mrb, obj)); -} - -/*! - * Ensures a class can be derived from super. - * - * \param super a reference to an object. - * \exception TypeError if \a super is not a Class or \a super is a singleton class. - */ -static void -mrb_check_inheritable(mrb_state *mrb, struct RClass *super) -{ - if (super->tt != MRB_TT_CLASS) { - mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", mrb_obj_value(super)); - } - if (super->tt == MRB_TT_SCLASS) { - mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of singleton class"); - } - if (super == mrb->class_class) { - mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of Class"); - } -} - -/*! - * Creates a new class. - * \param super a class from which the new class derives. - * \exception TypeError \a super is not inheritable. - * \exception TypeError \a super is the Class class. - */ -MRB_API struct RClass* -mrb_class_new(mrb_state *mrb, struct RClass *super) -{ - struct RClass *c; - - if (super) { - mrb_check_inheritable(mrb, super); - } - c = boot_defclass(mrb, super); - if (super) { - MRB_SET_INSTANCE_TT(c, MRB_INSTANCE_TT(super)); - } - make_metaclass(mrb, c); - - return c; -} - -/*! - * Creates a new module. - */ -MRB_API struct RClass* -mrb_module_new(mrb_state *mrb) -{ - struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class); - boot_initmod(mrb, m); - return m; -} - -/* - * call-seq: - * obj.class => class - * - * Returns the class of obj, now preferred over - * Object#type, as an object's type in Ruby is only - * loosely tied to that object's class. This method must always be - * called with an explicit receiver, as class is also a - * reserved word in Ruby. - * - * 1.class #=> Fixnum - * self.class #=> Object - */ - -MRB_API struct RClass* -mrb_obj_class(mrb_state *mrb, mrb_value obj) -{ - return mrb_class_real(mrb_class(mrb, obj)); -} - -MRB_API void -mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b) -{ - struct RProc *m = mrb_method_search(mrb, c, b); - - mrb_define_method_raw(mrb, c, a, m); -} - -/*! - * Defines an alias of a method. - * \param klass the class which the original method belongs to - * \param name1 a new name for the method - * \param name2 the original name of the method - */ -MRB_API void -mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2) -{ - mrb_alias_method(mrb, klass, mrb_intern_cstr(mrb, name1), mrb_intern_cstr(mrb, name2)); -} - -/* - * call-seq: - * mod.to_s -> string - * - * Return a string representing this module or class. For basic - * classes and modules, this is the name. For singletons, we - * show information on the thing we're attached to as well. - */ - -static mrb_value -mrb_mod_to_s(mrb_state *mrb, mrb_value klass) -{ - mrb_value str; - - if (mrb_type(klass) == MRB_TT_SCLASS) { - mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__")); - - str = mrb_str_new_lit(mrb, "#"); - } - else { - struct RClass *c; - mrb_value path; - - str = mrb_str_buf_new(mrb, 32); - c = mrb_class_ptr(klass); - path = mrb_class_path(mrb, c); - - if (mrb_nil_p(path)) { - switch (mrb_type(klass)) { - case MRB_TT_CLASS: - mrb_str_cat_lit(mrb, str, "#"); - } - else { - return path; - } - } -} - -static mrb_value -mrb_mod_alias(mrb_state *mrb, mrb_value mod) -{ - struct RClass *c = mrb_class_ptr(mod); - mrb_sym new_name, old_name; - - mrb_get_args(mrb, "nn", &new_name, &old_name); - mrb_alias_method(mrb, c, new_name, old_name); - return mrb_nil_value(); -} - -static void -undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) -{ - if (!mrb_obj_respond_to(mrb, c, a)) { - mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c)); - } - else { - mrb_define_method_raw(mrb, c, a, NULL); - } -} - -MRB_API void -mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name) -{ - undef_method(mrb, c, mrb_intern_cstr(mrb, name)); -} - -MRB_API void -mrb_undef_class_method(mrb_state *mrb, struct RClass *c, const char *name) -{ - mrb_undef_method(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name); -} - -static mrb_value -mrb_mod_undef(mrb_state *mrb, mrb_value mod) -{ - struct RClass *c = mrb_class_ptr(mod); - mrb_int argc; - mrb_value *argv; - - mrb_get_args(mrb, "*", &argv, &argc); - while (argc--) { - undef_method(mrb, c, mrb_symbol(*argv)); - argv++; - } - return mrb_nil_value(); -} - -static mrb_value -mod_define_method(mrb_state *mrb, mrb_value self) -{ - struct RClass *c = mrb_class_ptr(self); - struct RProc *p; - mrb_sym mid; - mrb_value blk; - - mrb_get_args(mrb, "n&", &mid, &blk); - if (mrb_nil_p(blk)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); - } - p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); - mrb_proc_copy(p, mrb_proc_ptr(blk)); - p->flags |= MRB_PROC_STRICT; - mrb_define_method_raw(mrb, c, mid, p); - return mrb_symbol_value(mid); -} - -static void -check_cv_name_str(mrb_state *mrb, mrb_value str) -{ - const char *s = RSTRING_PTR(str); - mrb_int len = RSTRING_LEN(str); - - if (len < 3 || !(s[0] == '@' && s[1] == '@')) { - mrb_name_error(mrb, mrb_intern_str(mrb, str), "'%S' is not allowed as a class variable name", str); - } -} - -static void -check_cv_name_sym(mrb_state *mrb, mrb_sym id) -{ - check_cv_name_str(mrb, mrb_sym2str(mrb, id)); -} - -/* 15.2.2.4.16 */ -/* - * call-seq: - * obj.class_variable_defined?(symbol) -> true or false - * - * Returns true if the given class variable is defined - * in obj. - * - * class Fred - * @@foo = 99 - * end - * Fred.class_variable_defined?(:@@foo) #=> true - * Fred.class_variable_defined?(:@@bar) #=> false - */ - -static mrb_value -mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod) -{ - mrb_sym id; - - mrb_get_args(mrb, "n", &id); - check_cv_name_sym(mrb, id); - return mrb_bool_value(mrb_cv_defined(mrb, mod, id)); -} - -/* 15.2.2.4.17 */ -/* - * call-seq: - * mod.class_variable_get(symbol) -> obj - * - * Returns the value of the given class variable (or throws a - * NameError exception). The @@ part of the - * variable name should be included for regular class variables - * - * class Fred - * @@foo = 99 - * end - * Fred.class_variable_get(:@@foo) #=> 99 - */ - -static mrb_value -mrb_mod_cvar_get(mrb_state *mrb, mrb_value mod) -{ - mrb_sym id; - - mrb_get_args(mrb, "n", &id); - check_cv_name_sym(mrb, id); - return mrb_cv_get(mrb, mod, id); -} - -/* 15.2.2.4.18 */ -/* - * call-seq: - * obj.class_variable_set(symbol, obj) -> obj - * - * Sets the class variable names by symbol to - * object. - * - * class Fred - * @@foo = 99 - * def foo - * @@foo - * end - * end - * Fred.class_variable_set(:@@foo, 101) #=> 101 - * Fred.new.foo #=> 101 - */ - -static mrb_value -mrb_mod_cvar_set(mrb_state *mrb, mrb_value mod) -{ - mrb_value value; - mrb_sym id; - - mrb_get_args(mrb, "no", &id, &value); - check_cv_name_sym(mrb, id); - mrb_cv_set(mrb, mod, id, value); - return value; -} - -/* 15.2.2.4.39 */ -/* - * call-seq: - * remove_class_variable(sym) -> obj - * - * Removes the definition of the sym, returning that - * constant's value. - * - * class Dummy - * @@var = 99 - * puts @@var - * p class_variables - * remove_class_variable(:@@var) - * p class_variables - * end - * - * produces: - * - * 99 - * [:@@var] - * [] - */ - -static mrb_value -mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod) -{ - mrb_value val; - mrb_sym id; - - mrb_get_args(mrb, "n", &id); - check_cv_name_sym(mrb, id); - - val = mrb_iv_remove(mrb, mod, id); - if (!mrb_undef_p(val)) return val; - - if (mrb_cv_defined(mrb, mod, id)) { - mrb_name_error(mrb, id, "cannot remove %S for %S", - mrb_sym2str(mrb, id), mod); - } - - mrb_name_error(mrb, id, "class variable %S not defined for %S", - mrb_sym2str(mrb, id), mod); - - /* not reached */ - return mrb_nil_value(); -} - -/* 15.2.2.4.34 */ -/* - * call-seq: - * mod.method_defined?(symbol) -> true or false - * - * Returns +true+ if the named method is defined by - * _mod_ (or its included modules and, if _mod_ is a class, - * its ancestors). Public and protected methods are matched. - * - * module A - * def method1() end - * end - * class B - * def method2() end - * end - * class C < B - * include A - * def method3() end - * end - * - * A.method_defined? :method1 #=> true - * C.method_defined? "method1" #=> true - * C.method_defined? "method2" #=> true - * C.method_defined? "method3" #=> true - * C.method_defined? "method4" #=> false - */ - -static mrb_value -mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) -{ - mrb_sym id; - - mrb_get_args(mrb, "n", &id); - return mrb_bool_value(mrb_obj_respond_to(mrb, mrb_class_ptr(mod), id)); -} - -static void -remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid) -{ - struct RClass *c = mrb_class_ptr(mod); - khash_t(mt) *h = find_origin(c)->mt; - khiter_t k; - - if (h) { - k = kh_get(mt, mrb, h, mid); - if (k != kh_end(h)) { - kh_del(mt, mrb, h, k); - mrb_funcall(mrb, mod, "method_removed", 1, mrb_symbol_value(mid)); - return; - } - } - - mrb_name_error(mrb, mid, "method '%S' not defined in %S", - mrb_sym2str(mrb, mid), mod); -} - -/* 15.2.2.4.41 */ -/* - * call-seq: - * remove_method(symbol) -> self - * - * Removes the method identified by _symbol_ from the current - * class. For an example, see Module.undef_method. - */ - -static mrb_value -mrb_mod_remove_method(mrb_state *mrb, mrb_value mod) -{ - mrb_int argc; - mrb_value *argv; - - mrb_get_args(mrb, "*", &argv, &argc); - while (argc--) { - remove_method(mrb, mod, mrb_symbol(*argv)); - argv++; - } - return mod; -} - - - -static void -check_const_name_str(mrb_state *mrb, mrb_value str) -{ - if (RSTRING_LEN(str) < 1 || !ISUPPER(*RSTRING_PTR(str))) { - mrb_name_error(mrb, mrb_intern_str(mrb, str), "wrong constant name %S", str); - } -} - -static void -check_const_name_sym(mrb_state *mrb, mrb_sym id) -{ - check_const_name_str(mrb, mrb_sym2str(mrb, id)); -} - -static mrb_value -const_defined(mrb_state *mrb, mrb_value mod, mrb_sym id, mrb_bool inherit) -{ - if (inherit) { - return mrb_bool_value(mrb_const_defined(mrb, mod, id)); - } - return mrb_bool_value(mrb_const_defined_at(mrb, mod, id)); -} - -static mrb_value -mrb_mod_const_defined(mrb_state *mrb, mrb_value mod) -{ - mrb_sym id; - mrb_bool inherit = TRUE; - - mrb_get_args(mrb, "n|b", &id, &inherit); - check_const_name_sym(mrb, id); - return const_defined(mrb, mod, id, inherit); -} - -static mrb_value -mrb_mod_const_get(mrb_state *mrb, mrb_value mod) -{ - mrb_sym id; - - mrb_get_args(mrb, "n", &id); - check_const_name_sym(mrb, id); - return mrb_const_get(mrb, mod, id); -} - -static mrb_value -mrb_mod_const_set(mrb_state *mrb, mrb_value mod) -{ - mrb_sym id; - mrb_value value; - - mrb_get_args(mrb, "no", &id, &value); - check_const_name_sym(mrb, id); - mrb_const_set(mrb, mod, id, value); - return value; -} - -static mrb_value -mrb_mod_remove_const(mrb_state *mrb, mrb_value mod) -{ - mrb_sym id; - mrb_value val; - - mrb_get_args(mrb, "n", &id); - check_const_name_sym(mrb, id); - val = mrb_iv_remove(mrb, mod, id); - if (mrb_undef_p(val)) { - mrb_name_error(mrb, id, "constant %S not defined", mrb_sym2str(mrb, id)); - } - return val; -} - -static mrb_value -mrb_mod_const_missing(mrb_state *mrb, mrb_value mod) -{ - mrb_sym sym; - - mrb_get_args(mrb, "n", &sym); - - if (mrb_class_real(mrb_class_ptr(mod)) != mrb->object_class) { - mrb_name_error(mrb, sym, "uninitialized constant %S::%S", - mod, - mrb_sym2str(mrb, sym)); - } - else { - mrb_name_error(mrb, sym, "uninitialized constant %S", - mrb_sym2str(mrb, sym)); - } - /* not reached */ - return mrb_nil_value(); -} - -static mrb_value -mrb_mod_s_constants(mrb_state *mrb, mrb_value mod) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Module.constants not implemented"); - return mrb_nil_value(); /* not reached */ -} - -static mrb_value -mrb_mod_eqq(mrb_state *mrb, mrb_value mod) -{ - mrb_value obj; - mrb_bool eqq; - - mrb_get_args(mrb, "o", &obj); - eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod)); - - return mrb_bool_value(eqq); -} - -MRB_API mrb_value -mrb_mod_module_function(mrb_state *mrb, mrb_value mod) -{ - mrb_value *argv; - mrb_int argc, i; - mrb_sym mid; - struct RProc *method_rproc; - struct RClass *rclass; - int ai; - - mrb_check_type(mrb, mod, MRB_TT_MODULE); - - mrb_get_args(mrb, "*", &argv, &argc); - if(argc == 0) { - /* set MODFUNC SCOPE if implemented */ - return mod; - } - - /* set PRIVATE method visibility if implemented */ - /* mrb_mod_dummy_visibility(mrb, mod); */ - - for (i=0; ic, mid, method_rproc); - mrb_gc_arena_restore(mrb, ai); - } - - return mod; -} - -void -mrb_init_class(mrb_state *mrb) -{ - struct RClass *bob; /* BasicObject */ - struct RClass *obj; /* Object */ - struct RClass *mod; /* Module */ - struct RClass *cls; /* Class */ - - /* boot class hierarchy */ - bob = boot_defclass(mrb, 0); - obj = boot_defclass(mrb, bob); mrb->object_class = obj; - mod = boot_defclass(mrb, obj); mrb->module_class = mod;/* obj -> mod */ - cls = boot_defclass(mrb, mod); mrb->class_class = cls; /* obj -> cls */ - /* fix-up loose ends */ - bob->c = obj->c = mod->c = cls->c = cls; - make_metaclass(mrb, bob); - make_metaclass(mrb, obj); - make_metaclass(mrb, mod); - make_metaclass(mrb, cls); - - /* name basic classes */ - mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob)); - mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value(bob)); - mrb_define_const(mrb, obj, "Object", mrb_obj_value(obj)); - mrb_define_const(mrb, obj, "Module", mrb_obj_value(mod)); - mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls)); - - /* name each classes */ - name_class(mrb, bob, mrb_intern_lit(mrb, "BasicObject")); - name_class(mrb, obj, mrb_intern_lit(mrb, "Object")); /* 15.2.1 */ - name_class(mrb, mod, mrb_intern_lit(mrb, "Module")); /* 15.2.2 */ - name_class(mrb, cls, mrb_intern_lit(mrb, "Class")); /* 15.2.3 */ - - mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); /* 15.2.17 */ - MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC); - - MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS); - mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE()); - mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); - mrb_define_method(mrb, bob, "method_missing", mrb_bob_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */ - - mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */ - mrb_define_method(mrb, cls, "new", mrb_instance_new, MRB_ARGS_ANY()); /* 15.2.3.3.3 */ - mrb_define_method(mrb, cls, "initialize", mrb_class_initialize, MRB_ARGS_OPT(1)); /* 15.2.3.3.1 */ - mrb_define_method(mrb, cls, "inherited", mrb_bob_init, MRB_ARGS_REQ(1)); - - MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE); - mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.16 */ - mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.17 */ - mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.18 */ - mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */ - mrb_define_method(mrb, mod, "extended", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */ - mrb_define_method(mrb, mod, "prepend", mrb_mod_prepend, MRB_ARGS_ANY()); - mrb_define_method(mrb, mod, "prepended", mrb_bob_init, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mod, "prepend_features", mrb_mod_prepend_features, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mod, "include", mrb_mod_include, MRB_ARGS_ANY()); /* 15.2.2.4.27 */ - mrb_define_method(mrb, mod, "include?", mrb_mod_include_p, MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */ - mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */ - mrb_define_method(mrb, mod, "class_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.15 */ - mrb_define_method(mrb, mod, "included", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */ - mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, MRB_ARGS_NONE()); /* 15.2.2.4.30 */ - mrb_define_method(mrb, mod, "initialize", mrb_mod_initialize, MRB_ARGS_NONE()); /* 15.2.2.4.31 */ - mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, MRB_ARGS_ANY()); /* 15.2.2.4.33 */ - mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */ - mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.35 */ - mrb_define_method(mrb, mod, "module_function", mrb_mod_module_function, MRB_ARGS_ANY()); - mrb_define_method(mrb, mod, "private", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.36 */ - mrb_define_method(mrb, mod, "protected", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.37 */ - mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */ - mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */ - mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */ - mrb_define_method(mrb, mod, "method_removed", mrb_bob_init, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mod, "attr_reader", mrb_mod_attr_reader, MRB_ARGS_ANY()); /* 15.2.2.4.13 */ - mrb_define_method(mrb, mod, "attr_writer", mrb_mod_attr_writer, MRB_ARGS_ANY()); /* 15.2.2.4.14 */ - mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, mod, "inspect", mrb_mod_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, MRB_ARGS_ANY()); /* 15.2.2.4.8 */ - mrb_define_method(mrb, mod, "ancestors", mrb_mod_ancestors, MRB_ARGS_NONE()); /* 15.2.2.4.9 */ - mrb_define_method(mrb, mod, "undef_method", mrb_mod_undef, MRB_ARGS_ANY()); /* 15.2.2.4.41 */ - mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, MRB_ARGS_ARG(1,1)); /* 15.2.2.4.20 */ - mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.21 */ - mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */ - mrb_define_method(mrb, mod, "constants", mrb_mod_constants, MRB_ARGS_OPT(1)); /* 15.2.2.4.24 */ - mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */ - mrb_define_method(mrb, mod, "const_missing", mrb_mod_const_missing, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_NONE()); /* 15.2.2.4.19 */ - mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, mod, "constants", mrb_mod_s_constants, MRB_ARGS_ANY()); /* 15.2.2.3.1 */ - - mrb_undef_method(mrb, cls, "append_features"); - mrb_undef_method(mrb, cls, "extend_object"); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/codedump.c nghttp2-0.6.7/third-party/mruby/src/codedump.c --- nghttp2-1.13.0/third-party/mruby/src/codedump.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/codedump.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,453 +0,0 @@ -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/debug.h" -#include "mruby/opcode.h" -#include "mruby/string.h" -#include "mruby/proc.h" - -#ifndef MRB_DISABLE_STDIO -static int -print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre) -{ - size_t i; - - if (n == 0) return 0; - - for (i=0; i+1nlocals; i++) { - if (irep->lv[i].r == n) { - mrb_sym sym = irep->lv[i].name; - if (pre) printf(" "); - printf("R%d:%s", (int)n, mrb_sym2name(mrb, sym)); - return 1; - } - } - return 0; -} - -#define RA 1 -#define RB 2 -#define RAB 3 - -static void -print_lv(mrb_state *mrb, mrb_irep *irep, mrb_code c, int r) -{ - int pre = 0; - - if (!irep->lv - || ((!(r & RA) || GETARG_A(c) >= irep->nlocals) - && (!(r & RB) || GETARG_B(c) >= irep->nlocals))) { - printf("\n"); - return; - } - printf("\t; "); - if (r & RA) { - pre = print_r(mrb, irep, GETARG_A(c), 0); - } - if (r & RB) { - print_r(mrb, irep, GETARG_B(c), pre); - } - printf("\n"); -} -#endif - -static void -codedump(mrb_state *mrb, mrb_irep *irep) -{ -#ifndef MRB_DISABLE_STDIO - int i; - int ai; - mrb_code c; - const char *file = NULL, *next_file; - int32_t line; - - if (!irep) return; - printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", (void*)irep, - irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen); - - for (i = 0; i < (int)irep->ilen; i++) { - ai = mrb_gc_arena_save(mrb); - - next_file = mrb_debug_get_filename(irep, i); - if (next_file && file != next_file) { - printf("file: %s\n", next_file); - file = next_file; - } - line = mrb_debug_get_line(irep, i); - if (line < 0) { - printf(" "); - } - else { - printf("%5d ", line); - } - - printf("%03d ", i); - c = irep->iseq[i]; - switch (GET_OPCODE(c)) { - case OP_NOP: - printf("OP_NOP\n"); - break; - case OP_MOVE: - printf("OP_MOVE\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); - break; - case OP_LOADL: - { - mrb_value v = irep->pool[GETARG_Bx(c)]; - mrb_value s = mrb_inspect(mrb, v); - printf("OP_LOADL\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s)); - } - print_lv(mrb, irep, c, RA); - break; - case OP_LOADI: - printf("OP_LOADI\tR%d\t%d\t", GETARG_A(c), GETARG_sBx(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADSYM: - printf("OP_LOADSYM\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADNIL: - printf("OP_LOADNIL\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADSELF: - printf("OP_LOADSELF\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADT: - printf("OP_LOADT\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADF: - printf("OP_LOADF\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETGLOBAL: - printf("OP_GETGLOBAL\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_SETGLOBAL: - printf("OP_SETGLOBAL\t:%s\tR%d\t", - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), - GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETCONST: - printf("OP_GETCONST\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_SETCONST: - printf("OP_SETCONST\t:%s\tR%d\t", - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), - GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETMCNST: - printf("OP_GETMCNST\tR%d\tR%d::%s", GETARG_A(c), GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RAB); - break; - case OP_SETMCNST: - printf("OP_SETMCNST\tR%d::%s\tR%d", GETARG_A(c)+1, - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), - GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETIV: - printf("OP_GETIV\tR%d\t%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_SETIV: - printf("OP_SETIV\t%s\tR%d", - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), - GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETUPVAR: - printf("OP_GETUPVAR\tR%d\t%d\t%d", - GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_SETUPVAR: - printf("OP_SETUPVAR\tR%d\t%d\t%d", - GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETCV: - printf("OP_GETCV\tR%d\t%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_SETCV: - printf("OP_SETCV\t%s\tR%d", - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), - GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_JMP: - printf("OP_JMP\t%03d\n", i+GETARG_sBx(c)); - break; - case OP_JMPIF: - printf("OP_JMPIF\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c)); - break; - case OP_JMPNOT: - printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c)); - break; - case OP_SEND: - printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_SENDB: - printf("OP_SENDB\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_TAILCALL: - printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_SUPER: - printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c), - GETARG_C(c)); - break; - case OP_ARGARY: - printf("OP_ARGARY\tR%d\t%d:%d:%d:%d", GETARG_A(c), - (GETARG_Bx(c)>>10)&0x3f, - (GETARG_Bx(c)>>9)&0x1, - (GETARG_Bx(c)>>4)&0x1f, - (GETARG_Bx(c)>>0)&0xf); - print_lv(mrb, irep, c, RA); - break; - - case OP_ENTER: - printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n", - (GETARG_Ax(c)>>18)&0x1f, - (GETARG_Ax(c)>>13)&0x1f, - (GETARG_Ax(c)>>12)&0x1, - (GETARG_Ax(c)>>7)&0x1f, - (GETARG_Ax(c)>>2)&0x1f, - (GETARG_Ax(c)>>1)&0x1, - GETARG_Ax(c) & 0x1); - break; - case OP_RETURN: - printf("OP_RETURN\tR%d", GETARG_A(c)); - switch (GETARG_B(c)) { - case OP_R_NORMAL: - case OP_R_RETURN: - printf("\treturn\t"); break; - case OP_R_BREAK: - printf("\tbreak\t"); break; - default: - printf("\tbroken\t"); break; - break; - } - print_lv(mrb, irep, c, RA); - break; - case OP_BLKPUSH: - printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", GETARG_A(c), - (GETARG_Bx(c)>>10)&0x3f, - (GETARG_Bx(c)>>9)&0x1, - (GETARG_Bx(c)>>4)&0x1f, - (GETARG_Bx(c)>>0)&0xf); - print_lv(mrb, irep, c, RA); - break; - - case OP_LAMBDA: - printf("OP_LAMBDA\tR%d\tI(%+d)\t%d", GETARG_A(c), GETARG_b(c)+1, GETARG_c(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_RANGE: - printf("OP_RANGE\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RAB); - break; - case OP_METHOD: - printf("OP_METHOD\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); - print_lv(mrb, irep, c, RA); - break; - - case OP_ADD: - printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_ADDI: - printf("OP_ADDI\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_SUB: - printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_SUBI: - printf("OP_SUBI\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_MUL: - printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_DIV: - printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_LT: - printf("OP_LT\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_LE: - printf("OP_LE\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_GT: - printf("OP_GT\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_GE: - printf("OP_GE\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_EQ: - printf("OP_EQ\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - - case OP_STOP: - printf("OP_STOP\n"); - break; - - case OP_ARRAY: - printf("OP_ARRAY\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RAB); - break; - case OP_ARYCAT: - printf("OP_ARYCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); - break; - case OP_ARYPUSH: - printf("OP_ARYPUSH\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); - break; - case OP_AREF: - printf("OP_AREF\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RAB); - break; - case OP_APOST: - printf("OP_APOST\tR%d\t%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_STRING: - { - mrb_value v = irep->pool[GETARG_Bx(c)]; - mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); - printf("OP_STRING\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s)); - } - print_lv(mrb, irep, c, RA); - break; - case OP_STRCAT: - printf("OP_STRCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); - break; - case OP_HASH: - printf("OP_HASH\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RAB); - break; - - case OP_OCLASS: - printf("OP_OCLASS\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_CLASS: - printf("OP_CLASS\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_MODULE: - printf("OP_MODULE\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_EXEC: - printf("OP_EXEC\tR%d\tI(%+d)", GETARG_A(c), GETARG_Bx(c)+1); - print_lv(mrb, irep, c, RA); - break; - case OP_SCLASS: - printf("OP_SCLASS\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); - break; - case OP_TCLASS: - printf("OP_TCLASS\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_ERR: - { - mrb_value v = irep->pool[GETARG_Bx(c)]; - mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); - printf("OP_ERR\t%s\n", RSTRING_PTR(s)); - } - break; - case OP_EPUSH: - printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1); - break; - case OP_ONERR: - printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c)); - break; - case OP_RESCUE: - printf("OP_RESCUE\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_RAISE: - printf("OP_RAISE\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_POPERR: - printf("OP_POPERR\t%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_EPOP: - printf("OP_EPOP\t%d\n", GETARG_A(c)); - break; - - default: - printf("OP_unknown %d\t%d\t%d\t%d\n", GET_OPCODE(c), - GETARG_A(c), GETARG_B(c), GETARG_C(c)); - break; - } - mrb_gc_arena_restore(mrb, ai); - } - printf("\n"); -#endif -} - -static void -codedump_recur(mrb_state *mrb, mrb_irep *irep) -{ - size_t i; - - codedump(mrb, irep); - for (i=0; irlen; i++) { - codedump_recur(mrb, irep->reps[i]); - } -} - -void -mrb_codedump_all(mrb_state *mrb, struct RProc *proc) -{ - codedump_recur(mrb, proc->body.irep); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/compar.c nghttp2-0.6.7/third-party/mruby/src/compar.c --- nghttp2-1.13.0/third-party/mruby/src/compar.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/compar.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -/* -** compar.c - Comparable module -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" - -void -mrb_init_comparable(mrb_state *mrb) -{ - mrb_define_module(mrb, "Comparable"); /* 15.3.3 */ -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/crc.c nghttp2-0.6.7/third-party/mruby/src/crc.c --- nghttp2-1.13.0/third-party/mruby/src/crc.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/crc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* -** crc.c - calculate CRC -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include - -/* Calculate CRC (CRC-16-CCITT) -** -** 0000_0000_0000_0000_0000_0000_0000_0000 -** ^|------- CRC -------|- work --| -** carry -*/ -#define CRC_16_CCITT 0x11021ul /* x^16+x^12+x^5+1 */ -#define CRC_XOR_PATTERN (CRC_16_CCITT << 8) -#define CRC_CARRY_BIT (0x01000000) - -uint16_t -calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc) -{ - size_t ibyte; - uint32_t ibit; - uint32_t crcwk = crc << 8; - - for (ibyte = 0; ibyte < nbytes; ibyte++) { - crcwk |= *src++; - for (ibit = 0; ibit < CHAR_BIT; ibit++) { - crcwk <<= 1; - if (crcwk & CRC_CARRY_BIT) { - crcwk ^= CRC_XOR_PATTERN; - } - } - } - return (uint16_t)(crcwk >> 8); -} - diff -Nru nghttp2-1.13.0/third-party/mruby/src/debug.c nghttp2-0.6.7/third-party/mruby/src/debug.c --- nghttp2-1.13.0/third-party/mruby/src/debug.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/debug.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,215 +0,0 @@ -#include -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/debug.h" - -static mrb_irep_debug_info_file * -get_file(mrb_irep_debug_info *info, uint32_t pc) -{ - mrb_irep_debug_info_file **ret; - int32_t count; - - if (pc >= info->pc_count) { return NULL; } - /* get upper bound */ - ret = info->files; - count = info->flen; - while (count > 0) { - int32_t step = count / 2; - mrb_irep_debug_info_file **it = ret + step; - if (!(pc < (*it)->start_pos)) { - ret = it + 1; - count -= step + 1; - } else { count = step; } - } - - --ret; - - /* check returning file exists inside debug info */ - mrb_assert(info->files <= ret && ret < (info->files + info->flen)); - /* check pc is within the range of returning file */ - mrb_assert((*ret)->start_pos <= pc && - pc < (((ret + 1 - info->files) < info->flen) - ? (*(ret+1))->start_pos : info->pc_count)); - - return *ret; -} - -static mrb_debug_line_type -select_line_type(const uint16_t *lines, size_t lines_len) -{ - size_t line_count = 0; - int prev_line = -1; - size_t i; - for (i = 0; i < lines_len; ++i) { - if (lines[i] != prev_line) { - ++line_count; - } - } - return (sizeof(uint16_t) * lines_len) <= (sizeof(mrb_irep_debug_info_line) * line_count) - ? mrb_debug_line_ary : mrb_debug_line_flat_map; -} - -MRB_API char const* -mrb_debug_get_filename(mrb_irep *irep, uint32_t pc) -{ - if (irep && pc < irep->ilen) { - mrb_irep_debug_info_file* f = NULL; - if (!irep->debug_info) { return irep->filename; } - else if ((f = get_file(irep->debug_info, pc))) { - return f->filename; - } - } - return NULL; -} - -MRB_API int32_t -mrb_debug_get_line(mrb_irep *irep, uint32_t pc) -{ - if (irep && pc < irep->ilen) { - mrb_irep_debug_info_file* f = NULL; - if (!irep->debug_info) { - return irep->lines? irep->lines[pc] : -1; - } - else if ((f = get_file(irep->debug_info, pc))) { - switch (f->line_type) { - case mrb_debug_line_ary: - mrb_assert(f->start_pos <= pc && pc < (f->start_pos + f->line_entry_count)); - return f->lines.ary[pc - f->start_pos]; - - case mrb_debug_line_flat_map: { - /* get upper bound */ - mrb_irep_debug_info_line *ret = f->lines.flat_map; - uint32_t count = f->line_entry_count; - while (count > 0) { - int32_t step = count / 2; - mrb_irep_debug_info_line *it = ret + step; - if (!(pc < it->start_pos)) { - ret = it + 1; - count -= step + 1; - } else { count = step; } - } - - --ret; - - /* check line entry pointer range */ - mrb_assert(f->lines.flat_map <= ret && ret < (f->lines.flat_map + f->line_entry_count)); - /* check pc range */ - mrb_assert(ret->start_pos <= pc && - pc < (((uint32_t)(ret + 1 - f->lines.flat_map) < f->line_entry_count) - ? (ret+1)->start_pos : irep->debug_info->pc_count)); - - return ret->line; - } - } - } - } - return -1; -} - -MRB_API mrb_irep_debug_info * -mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep) -{ - static const mrb_irep_debug_info initial = { 0, 0, NULL }; - mrb_irep_debug_info *ret; - - mrb_assert(!irep->debug_info); - ret = (mrb_irep_debug_info *)mrb_malloc(mrb, sizeof(*ret)); - *ret = initial; - irep->debug_info = ret; - return ret; -} - -MRB_API mrb_irep_debug_info_file * -mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep, - uint32_t start_pos, uint32_t end_pos) -{ - mrb_irep_debug_info *info; - mrb_irep_debug_info_file *ret; - uint32_t file_pc_count; - size_t fn_len; - mrb_int len; - uint32_t i; - - if (!irep->debug_info) { return NULL; } - - mrb_assert(irep->filename); - mrb_assert(irep->lines); - - info = irep->debug_info; - - if (info->flen > 0 && strcmp(irep->filename, info->files[info->flen - 1]->filename) == 0) { - return NULL; - } - - ret = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*ret)); - info->files = - (mrb_irep_debug_info_file**)( - info->files - ? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1)) - : mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*))); - info->files[info->flen++] = ret; - - file_pc_count = end_pos - start_pos; - - ret->start_pos = start_pos; - info->pc_count = end_pos; - - fn_len = strlen(irep->filename); - ret->filename_sym = mrb_intern(mrb, irep->filename, fn_len); - len = 0; - ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len); - - ret->line_type = select_line_type(irep->lines + start_pos, end_pos - start_pos); - ret->lines.ptr = NULL; - - switch (ret->line_type) { - case mrb_debug_line_ary: - ret->line_entry_count = file_pc_count; - ret->lines.ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count); - for (i = 0; i < file_pc_count; ++i) { - ret->lines.ary[i] = irep->lines[start_pos + i]; - } - break; - - case mrb_debug_line_flat_map: { - uint16_t prev_line = 0; - mrb_irep_debug_info_line m; - ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1); - ret->line_entry_count = 0; - for (i = 0; i < file_pc_count; ++i) { - if (irep->lines[start_pos + i] == prev_line) { continue; } - - ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_realloc( - mrb, ret->lines.flat_map, - sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1)); - m.start_pos = start_pos + i; - m.line = irep->lines[start_pos + i]; - ret->lines.flat_map[ret->line_entry_count] = m; - - /* update */ - ++ret->line_entry_count; - prev_line = irep->lines[start_pos + i]; - } - } break; - - default: mrb_assert(0); break; - } - - return ret; -} - -MRB_API void -mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d) -{ - uint32_t i; - - if (!d) { return; } - - for (i = 0; i < d->flen; ++i) { - mrb_assert(d->files[i]); - mrb_free(mrb, d->files[i]->lines.ptr); - mrb_free(mrb, d->files[i]); - } - mrb_free(mrb, d->files); - mrb_free(mrb, d); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/dump.c nghttp2-0.6.7/third-party/mruby/src/dump.c --- nghttp2-1.13.0/third-party/mruby/src/dump.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/dump.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1095 +0,0 @@ -/* -** dump.c - mruby binary dumper (mrbc binary format) -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include "mruby/dump.h" -#include "mruby/string.h" -#include "mruby/irep.h" -#include "mruby/numeric.h" -#include "mruby/debug.h" - -#define FLAG_BYTEORDER_NATIVE 2 -#define FLAG_BYTEORDER_NONATIVE 0 - -#ifdef MRB_USE_FLOAT -#define MRB_FLOAT_FMT "%.8e" -#else -#define MRB_FLOAT_FMT "%.16e" -#endif - -static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep); - -#if UINT32_MAX > SIZE_MAX -# error This code cannot be built on your environment. -#endif - -static size_t -write_padding(uint8_t *buf) -{ - const size_t align = MRB_DUMP_ALIGNMENT; - size_t pad_len = -(intptr_t)buf & (align-1); - if (pad_len > 0) { - memset(buf, 0, pad_len); - } - return pad_len; -} - -static size_t -get_irep_header_size(mrb_state *mrb) -{ - size_t size = 0; - - size += sizeof(uint32_t) * 1; - size += sizeof(uint16_t) * 3; - - return size; -} - -static ptrdiff_t -write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) -{ - uint8_t *cur = buf; - - cur += uint32_to_bin(get_irep_record_size_1(mrb, irep), cur); /* record size */ - cur += uint16_to_bin((uint16_t)irep->nlocals, cur); /* number of local variable */ - cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */ - cur += uint16_to_bin((uint16_t)irep->rlen, cur); /* number of child irep */ - - return cur - buf; -} - - -static size_t -get_iseq_block_size(mrb_state *mrb, mrb_irep *irep) -{ - size_t size = 0; - - size += sizeof(uint32_t); /* ilen */ - size += sizeof(uint32_t); /* max padding */ - size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */ - - return size; -} - -static ptrdiff_t -write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf, uint8_t flags) -{ - uint8_t *cur = buf; - uint32_t iseq_no; - - cur += uint32_to_bin(irep->ilen, cur); /* number of opcode */ - cur += write_padding(cur); - switch (flags & DUMP_ENDIAN_NAT) { - case DUMP_ENDIAN_BIG: - if (bigendian_p()) goto native; - for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) { - cur += uint32_to_bin(irep->iseq[iseq_no], cur); /* opcode */ - } - break; - case DUMP_ENDIAN_LIL: - if (!bigendian_p()) goto native; - for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) { - cur += uint32l_to_bin(irep->iseq[iseq_no], cur); /* opcode */ - } - break; - - native: - case DUMP_ENDIAN_NAT: - memcpy(cur, irep->iseq, irep->ilen * sizeof(mrb_code)); - cur += irep->ilen * sizeof(mrb_code); - break; - } - - return cur - buf; -} - - -static size_t -get_pool_block_size(mrb_state *mrb, mrb_irep *irep) -{ - size_t size = 0; - size_t pool_no; - mrb_value str; - - size += sizeof(uint32_t); /* plen */ - size += irep->plen * (sizeof(uint8_t) + sizeof(uint16_t)); /* len(n) */ - - for (pool_no = 0; pool_no < irep->plen; pool_no++) { - int ai = mrb_gc_arena_save(mrb); - - switch (mrb_type(irep->pool[pool_no])) { - case MRB_TT_FIXNUM: - str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); - { - mrb_int len = RSTRING_LEN(str); - mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - size += (size_t)len; - } - break; - - case MRB_TT_FLOAT: - str = mrb_float_to_str(mrb, irep->pool[pool_no], MRB_FLOAT_FMT); - { - mrb_int len = RSTRING_LEN(str); - mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - size += (size_t)len; - } - break; - - case MRB_TT_STRING: - { - mrb_int len = RSTRING_LEN(irep->pool[pool_no]); - mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - size += (size_t)len; - } - break; - - default: - break; - } - mrb_gc_arena_restore(mrb, ai); - } - - return size; -} - -static ptrdiff_t -write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) -{ - size_t pool_no; - uint8_t *cur = buf; - uint16_t len; - mrb_value str; - const char *char_ptr; - - cur += uint32_to_bin(irep->plen, cur); /* number of pool */ - - for (pool_no = 0; pool_no < irep->plen; pool_no++) { - int ai = mrb_gc_arena_save(mrb); - - switch (mrb_type(irep->pool[pool_no])) { - case MRB_TT_FIXNUM: - cur += uint8_to_bin(IREP_TT_FIXNUM, cur); /* data type */ - str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); - break; - - case MRB_TT_FLOAT: - cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */ - str = mrb_float_to_str(mrb, irep->pool[pool_no], MRB_FLOAT_FMT); - break; - - case MRB_TT_STRING: - cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */ - str = irep->pool[pool_no]; - break; - - default: - continue; - } - - char_ptr = RSTRING_PTR(str); - { - mrb_int tlen = RSTRING_LEN(str); - mrb_assert_int_fit(mrb_int, tlen, uint16_t, UINT16_MAX); - len = (uint16_t)tlen; - } - - cur += uint16_to_bin(len, cur); /* data length */ - memcpy(cur, char_ptr, (size_t)len); - cur += len; - - mrb_gc_arena_restore(mrb, ai); - } - - return cur - buf; -} - - -static size_t -get_syms_block_size(mrb_state *mrb, mrb_irep *irep) -{ - size_t size = 0; - uint32_t sym_no; - mrb_int len; - - size += sizeof(uint32_t); /* slen */ - for (sym_no = 0; sym_no < irep->slen; sym_no++) { - size += sizeof(uint16_t); /* snl(n) */ - if (irep->syms[sym_no] != 0) { - mrb_sym2name_len(mrb, irep->syms[sym_no], &len); - size += len + 1; /* sn(n) + null char */ - } - } - - return size; -} - -static ptrdiff_t -write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) -{ - uint32_t sym_no; - uint8_t *cur = buf; - const char *name; - - cur += uint32_to_bin(irep->slen, cur); /* number of symbol */ - - for (sym_no = 0; sym_no < irep->slen; sym_no++) { - if (irep->syms[sym_no] != 0) { - mrb_int len; - - name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); - - mrb_assert_int_fit(mrb_int, len, uint16_t, UINT16_MAX); - cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */ - memcpy(cur, name, len); /* symbol name */ - cur += (uint16_t)len; - *cur++ = '\0'; - } - else { - cur += uint16_to_bin(MRB_DUMP_NULL_SYM_LEN, cur); /* length of symbol name */ - } - } - - return cur - buf; -} - -static size_t -get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep) -{ - size_t size = 0; - - size += get_irep_header_size(mrb); - size += get_iseq_block_size(mrb, irep); - size += get_pool_block_size(mrb, irep); - size += get_syms_block_size(mrb, irep); - return size; -} - -static size_t -get_irep_record_size(mrb_state *mrb, mrb_irep *irep) -{ - size_t size = 0; - size_t irep_no; - - size = get_irep_record_size_1(mrb, irep); - for (irep_no = 0; irep_no < irep->rlen; irep_no++) { - size += get_irep_record_size(mrb, irep->reps[irep_no]); - } - return size; -} - -static int -write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *irep_record_size, uint8_t flags) -{ - uint32_t i; - uint8_t *src = bin; - - if (irep == NULL) { - return MRB_DUMP_INVALID_IREP; - } - - *irep_record_size = get_irep_record_size_1(mrb, irep); - if (*irep_record_size == 0) { - return MRB_DUMP_GENERAL_FAILURE; - } - - bin += write_irep_header(mrb, irep, bin); - bin += write_iseq_block(mrb, irep, bin, flags); - bin += write_pool_block(mrb, irep, bin); - bin += write_syms_block(mrb, irep, bin); - - for (i = 0; i < irep->rlen; i++) { - int result; - size_t rsize; - - result = write_irep_record(mrb, irep->reps[i], bin, &rsize, flags); - if (result != MRB_DUMP_OK) { - return result; - } - bin += rsize; - } - *irep_record_size = bin - src; - return MRB_DUMP_OK; -} - -static uint32_t -write_footer(mrb_state *mrb, uint8_t *bin) -{ - struct rite_binary_footer footer; - - memcpy(footer.section_ident, RITE_BINARY_EOF, sizeof(footer.section_ident)); - uint32_to_bin(sizeof(struct rite_binary_footer), footer.section_size); - memcpy(bin, &footer, sizeof(struct rite_binary_footer)); - - return sizeof(struct rite_binary_footer); -} - - -static int -write_section_irep_header(mrb_state *mrb, size_t section_size, uint8_t *bin) -{ - struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin; - - memcpy(header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(header->section_ident)); - - mrb_assert_int_fit(size_t, section_size, uint32_t, UINT32_MAX); - uint32_to_bin((uint32_t)section_size, header->section_size); - memcpy(header->rite_version, RITE_VM_VER, sizeof(header->rite_version)); - - return MRB_DUMP_OK; -} - -static int -write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *len_p, uint8_t flags) -{ - int result; - size_t rsize = 0; - uint8_t *cur = bin; - - if (mrb == NULL || bin == NULL) { - return MRB_DUMP_INVALID_ARGUMENT; - } - - cur += sizeof(struct rite_section_irep_header); - - result = write_irep_record(mrb, irep, cur, &rsize, flags); - if (result != MRB_DUMP_OK) { - return result; - } - *len_p = cur - bin + rsize; - write_section_irep_header(mrb, *len_p, bin); - - return MRB_DUMP_OK; -} - -static int -write_section_lineno_header(mrb_state *mrb, size_t section_size, uint8_t *bin) -{ - struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin; - - memcpy(header->section_ident, RITE_SECTION_LINENO_IDENT, sizeof(header->section_ident)); - uint32_to_bin((uint32_t)section_size, header->section_size); - - return MRB_DUMP_OK; -} - -static size_t -get_lineno_record_size(mrb_state *mrb, mrb_irep *irep) -{ - size_t size = 0; - - size += sizeof(uint32_t); /* record size */ - size += sizeof(uint16_t); /* filename size */ - if (irep->filename) { - size += strlen(irep->filename); /* filename */ - } - size += sizeof(uint32_t); /* niseq */ - if (irep->lines) { - size += sizeof(uint16_t) * irep->ilen; /* lineno */ - } - - return size; -} - -static size_t -write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) -{ - uint8_t *cur = bin; - size_t iseq_no; - size_t filename_len; - ptrdiff_t diff; - - cur += sizeof(uint32_t); /* record size */ - - if (irep->filename) { - filename_len = strlen(irep->filename); - } else { - filename_len = 0; - } - mrb_assert_int_fit(size_t, filename_len, uint16_t, UINT16_MAX); - cur += uint16_to_bin((uint16_t)filename_len, cur); /* filename size */ - - if (filename_len) { - memcpy(cur, irep->filename, filename_len); - cur += filename_len; /* filename */ - } - - if (irep->lines) { - mrb_assert_int_fit(size_t, irep->ilen, uint32_t, UINT32_MAX); - cur += uint32_to_bin((uint32_t)(irep->ilen), cur); /* niseq */ - for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) { - cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */ - } - } - else { - cur += uint32_to_bin(0, cur); /* niseq */ - } - - diff = cur - bin; - mrb_assert_int_fit(ptrdiff_t, diff, uint32_t, UINT32_MAX); - - uint32_to_bin((uint32_t)diff, bin); /* record size */ - - mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); - return (size_t)diff; -} - -static size_t -write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) -{ - size_t i; - size_t rlen, size = 0; - - rlen = write_lineno_record_1(mrb, irep, bin); - bin += rlen; - size += rlen; - for (i=0; irlen; i++) { - rlen = write_lineno_record(mrb, irep, bin); - bin += rlen; - size += rlen; - } - return size; -} - -static int -write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) -{ - size_t section_size = 0; - size_t rlen = 0; /* size of irep record */ - uint8_t *cur = bin; - - if (mrb == NULL || bin == NULL) { - return MRB_DUMP_INVALID_ARGUMENT; - } - - cur += sizeof(struct rite_section_lineno_header); - section_size += sizeof(struct rite_section_lineno_header); - - rlen = write_lineno_record(mrb, irep, cur); - section_size += rlen; - - write_section_lineno_header(mrb, section_size, bin); - - return MRB_DUMP_OK; -} - -static size_t -get_debug_record_size(mrb_state *mrb, mrb_irep *irep) -{ - size_t ret = 0; - uint16_t f_idx; - size_t i; - - ret += sizeof(uint32_t); /* record size */ - ret += sizeof(uint16_t); /* file count */ - - for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { - mrb_irep_debug_info_file const* file = irep->debug_info->files[f_idx]; - - ret += sizeof(uint32_t); /* position */ - ret += sizeof(uint16_t); /* filename index */ - - /* lines */ - ret += sizeof(uint32_t); /* entry count */ - ret += sizeof(uint8_t); /* line type */ - switch (file->line_type) { - case mrb_debug_line_ary: - ret += sizeof(uint16_t) * (size_t)(file->line_entry_count); - break; - - case mrb_debug_line_flat_map: - ret += (sizeof(uint32_t) + sizeof(uint16_t)) * (size_t)(file->line_entry_count); - break; - - default: mrb_assert(0); break; - } - } - for (i=0; irlen; i++) { - ret += get_debug_record_size(mrb, irep->reps[i]); - } - - return ret; -} - -static int -find_filename_index(const mrb_sym *ary, int ary_len, mrb_sym s) -{ - int i; - - for (i = 0; i < ary_len; ++i) { - if (ary[i] == s) { return i; } - } - return -1; -} - -static size_t -get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint16_t *lp) -{ - mrb_sym *filenames = *fp; - size_t i, size = 0; - mrb_irep_debug_info *di = irep->debug_info; - - mrb_assert(lp); - for (i = 0; i < di->flen; ++i) { - mrb_irep_debug_info_file *file; - mrb_int filename_len; - - file = di->files[i]; - if (find_filename_index(filenames, *lp, file->filename_sym) == -1) { - /* register filename */ - *lp += 1; - *fp = filenames = (mrb_sym *)mrb_realloc(mrb, filenames, sizeof(mrb_sym) * (*lp)); - filenames[*lp - 1] = file->filename_sym; - - /* filename */ - mrb_sym2name_len(mrb, file->filename_sym, &filename_len); - size += sizeof(uint16_t) + (size_t)filename_len; - } - } - for (i=0; irlen; i++) { - size += get_filename_table_size(mrb, irep->reps[i], fp, lp); - } - return size; -} - -static size_t -write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) -{ - uint8_t *cur; - uint16_t f_idx; - ptrdiff_t ret; - - cur = bin + sizeof(uint32_t); /* skip record size */ - cur += uint16_to_bin(irep->debug_info->flen, cur); /* file count */ - - for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { - int filename_idx; - const mrb_irep_debug_info_file *file = irep->debug_info->files[f_idx]; - - /* position */ - cur += uint32_to_bin(file->start_pos, cur); - - /* filename index */ - filename_idx = find_filename_index(filenames, filenames_len, - file->filename_sym); - mrb_assert_int_fit(int, filename_idx, uint16_t, UINT16_MAX); - cur += uint16_to_bin((uint16_t)filename_idx, cur); - - /* lines */ - cur += uint32_to_bin(file->line_entry_count, cur); - cur += uint8_to_bin(file->line_type, cur); - switch (file->line_type) { - case mrb_debug_line_ary: { - uint32_t l; - for (l = 0; l < file->line_entry_count; ++l) { - cur += uint16_to_bin(file->lines.ary[l], cur); - } - } break; - - case mrb_debug_line_flat_map: { - uint32_t line; - for (line = 0; line < file->line_entry_count; ++line) { - cur += uint32_to_bin(file->lines.flat_map[line].start_pos, cur); - cur += uint16_to_bin(file->lines.flat_map[line].line, cur); - } - } break; - - default: mrb_assert(0); break; - } - } - - ret = cur - bin; - mrb_assert_int_fit(ptrdiff_t, ret, uint32_t, UINT32_MAX); - uint32_to_bin(ret, bin); - - mrb_assert_int_fit(ptrdiff_t, ret, size_t, SIZE_MAX); - return (size_t)ret; -} - -static size_t -write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) -{ - size_t size, len; - size_t irep_no; - - size = len = write_debug_record_1(mrb, irep, bin, filenames, filenames_len); - bin += len; - for (irep_no = 0; irep_no < irep->rlen; irep_no++) { - len = write_debug_record(mrb, irep->reps[irep_no], bin, filenames, filenames_len); - bin += len; - size += len; - } - - mrb_assert(size == get_debug_record_size(mrb, irep)); - return size; -} - -static int -write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur, mrb_sym const *filenames, uint16_t filenames_len) -{ - size_t section_size = 0; - const uint8_t *bin = cur; - struct rite_section_debug_header *header; - size_t dlen; - uint16_t i; - char const *sym; mrb_int sym_len; - - if (mrb == NULL || cur == NULL) { - return MRB_DUMP_INVALID_ARGUMENT; - } - - header = (struct rite_section_debug_header *)bin; - cur += sizeof(struct rite_section_debug_header); - section_size += sizeof(struct rite_section_debug_header); - - /* filename table */ - cur += uint16_to_bin(filenames_len, cur); - section_size += sizeof(uint16_t); - for (i = 0; i < filenames_len; ++i) { - sym = mrb_sym2name_len(mrb, filenames[i], &sym_len); - mrb_assert(sym); - cur += uint16_to_bin(sym_len, cur); - memcpy(cur, sym, sym_len); - cur += sym_len; - section_size += sizeof(uint16_t) + sym_len; - } - - /* debug records */ - dlen = write_debug_record(mrb, irep, cur, filenames, filenames_len); - section_size += dlen; - - memcpy(header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(header->section_ident)); - mrb_assert(section_size <= INT32_MAX); - uint32_to_bin(section_size, header->section_size); - - return MRB_DUMP_OK; -} - -static void -create_lv_sym_table(mrb_state *mrb, const mrb_irep *irep, mrb_sym **syms, uint32_t *syms_len) -{ - size_t i; - - if (*syms == NULL) { - *syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * 1); - } - - for (i = 0; i + 1 < irep->nlocals; ++i) { - mrb_sym const name = irep->lv[i].name; - if (name == 0) continue; - if (find_filename_index(*syms, *syms_len, name) != -1) continue; - - ++(*syms_len); - *syms = (mrb_sym*)mrb_realloc(mrb, *syms, sizeof(mrb_sym) * (*syms_len)); - (*syms)[*syms_len - 1] = name; - } - - for (i = 0; i < irep->rlen; ++i) { - create_lv_sym_table(mrb, irep->reps[i], syms, syms_len); - } -} - -static int -write_lv_sym_table(mrb_state *mrb, uint8_t **start, mrb_sym const *syms, uint32_t syms_len) -{ - uint8_t *cur = *start; - uint32_t i; - const char *str; - mrb_int str_len; - - cur += uint32_to_bin(syms_len, cur); - - for (i = 0; i < syms_len; ++i) { - str = mrb_sym2name_len(mrb, syms[i], &str_len); - cur += uint16_to_bin(str_len, cur); - memcpy(cur, str, str_len); - cur += str_len; - } - - *start = cur; - - return MRB_DUMP_OK; -} - -static int -write_lv_record(mrb_state *mrb, const mrb_irep *irep, uint8_t **start, mrb_sym const *syms, uint32_t syms_len) -{ - uint8_t *cur = *start; - size_t i; - - for (i = 0; i + 1 < irep->nlocals; ++i) { - if (irep->lv[i].name == 0) { - cur += uint16_to_bin(RITE_LV_NULL_MARK, cur); - cur += uint16_to_bin(0, cur); - } - else { - int const sym_idx = find_filename_index(syms, syms_len, irep->lv[i].name); - mrb_assert(sym_idx != -1); /* local variable name must be in syms */ - - cur += uint16_to_bin(sym_idx, cur); - cur += uint16_to_bin(irep->lv[i].r, cur); - } - } - - for (i = 0; i < irep->rlen; ++i) { - write_lv_record(mrb, irep->reps[i], &cur, syms, syms_len); - } - - *start = cur; - - return MRB_DUMP_OK; -} - -static size_t -get_lv_record_size(mrb_state *mrb, mrb_irep *irep) -{ - size_t ret = 0, i; - - ret += (sizeof(uint16_t) + sizeof(uint16_t)) * (irep->nlocals - 1); - - for (i = 0; i < irep->rlen; ++i) { - ret += get_lv_record_size(mrb, irep->reps[i]); - } - - return ret; -} - -static size_t -get_lv_section_size(mrb_state *mrb, mrb_irep *irep, mrb_sym const *syms, uint32_t syms_len) -{ - size_t ret = 0, i; - - ret += sizeof(uint32_t); /* syms_len */ - ret += sizeof(uint16_t) * syms_len; /* symbol name lengths */ - for (i = 0; i < syms_len; ++i) { - mrb_int str_len; - mrb_sym2name_len(mrb, syms[i], &str_len); - ret += str_len; - } - - ret += get_lv_record_size(mrb, irep); - - return ret; -} - -static int -write_section_lv(mrb_state *mrb, mrb_irep *irep, uint8_t *start, mrb_sym const *syms, uint32_t const syms_len) -{ - uint8_t *cur = start; - struct rite_section_lv_header *header; - ptrdiff_t diff; - int result = MRB_DUMP_OK; - - if (mrb == NULL || cur == NULL) { - return MRB_DUMP_INVALID_ARGUMENT; - } - - header = (struct rite_section_lv_header*)cur; - cur += sizeof(struct rite_section_lv_header); - - result = write_lv_sym_table(mrb, &cur, syms, syms_len); - if (result != MRB_DUMP_OK) { - goto lv_section_exit; - } - - result = write_lv_record(mrb, irep, &cur, syms, syms_len); - if (result != MRB_DUMP_OK) { - goto lv_section_exit; - } - - memcpy(header->section_ident, RITE_SECTION_LV_IDENT, sizeof(header->section_ident)); - - diff = cur - start; - mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); - uint32_to_bin(diff, header->section_size); - -lv_section_exit: - return result; -} - -static int -write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8_t flags) -{ - struct rite_binary_header *header = (struct rite_binary_header *)bin; - uint16_t crc; - uint32_t offset; - - switch (flags & DUMP_ENDIAN_NAT) { - endian_big: - case DUMP_ENDIAN_BIG: - memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)); - break; - endian_little: - case DUMP_ENDIAN_LIL: - memcpy(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)); - break; - - case DUMP_ENDIAN_NAT: - if (bigendian_p()) goto endian_big; - goto endian_little; - break; - } - - memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)); - memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name)); - memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version)); - mrb_assert(binary_size <= UINT32_MAX); - uint32_to_bin((uint32_t)binary_size, header->binary_size); - - offset = (&(header->binary_crc[0]) - bin) + sizeof(uint16_t); - crc = calc_crc_16_ccitt(bin + offset, binary_size - offset, 0); - uint16_to_bin(crc, header->binary_crc); - - return MRB_DUMP_OK; -} - -static mrb_bool -is_debug_info_defined(mrb_irep *irep) -{ - size_t i; - - if (!irep->debug_info) return FALSE; - for (i=0; irlen; i++) { - if (!is_debug_info_defined(irep->reps[i])) return FALSE; - } - return TRUE; -} - -static mrb_bool -is_lv_defined(mrb_irep *irep) -{ - size_t i; - - if (irep->lv) { return TRUE; } - - for (i = 0; i < irep->rlen; ++i) { - if (is_lv_defined(irep->reps[i])) { return TRUE; } - } - - return FALSE; -} - -static uint8_t -dump_flags(uint8_t flags, uint8_t native) -{ - if (native == FLAG_BYTEORDER_NATIVE) { - if ((flags & DUMP_ENDIAN_NAT) == 0) { - return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_NAT; - } - return flags; - } - if ((flags & DUMP_ENDIAN_NAT) == 0) { - return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_BIG; - } - return flags; -} - -static int -dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size) -{ - int result = MRB_DUMP_GENERAL_FAILURE; - size_t malloc_size; - size_t section_irep_size; - size_t section_lineno_size = 0, section_lv_size = 0; - uint8_t *cur = NULL; - mrb_bool const debug_info_defined = is_debug_info_defined(irep), lv_defined = is_lv_defined(irep); - mrb_sym *lv_syms = NULL; uint32_t lv_syms_len = 0; - mrb_sym *filenames = NULL; uint16_t filenames_len = 0; - - if (mrb == NULL) { - *bin = NULL; - return MRB_DUMP_GENERAL_FAILURE; - } - - section_irep_size = sizeof(struct rite_section_irep_header); - section_irep_size += get_irep_record_size(mrb, irep); - - /* DEBUG section size */ - if (flags & DUMP_DEBUG_INFO) { - if (debug_info_defined) { - section_lineno_size += sizeof(struct rite_section_debug_header); - /* filename table */ - filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) + 1); - - /* filename table size */ - section_lineno_size += sizeof(uint16_t); - section_lineno_size += get_filename_table_size(mrb, irep, &filenames, &filenames_len); - - section_lineno_size += get_debug_record_size(mrb, irep); - } - else { - section_lineno_size += sizeof(struct rite_section_lineno_header); - section_lineno_size += get_lineno_record_size(mrb, irep); - } - } - - if (lv_defined) { - section_lv_size += sizeof(struct rite_section_lv_header); - create_lv_sym_table(mrb, irep, &lv_syms, &lv_syms_len); - section_lv_size += get_lv_section_size(mrb, irep, lv_syms, lv_syms_len); - } - - malloc_size = sizeof(struct rite_binary_header) + - section_irep_size + section_lineno_size + section_lv_size + - sizeof(struct rite_binary_footer); - cur = *bin = (uint8_t*)mrb_malloc(mrb, malloc_size); - cur += sizeof(struct rite_binary_header); - - result = write_section_irep(mrb, irep, cur, §ion_irep_size, flags); - if (result != MRB_DUMP_OK) { - goto error_exit; - } - cur += section_irep_size; - *bin_size = sizeof(struct rite_binary_header) + - section_irep_size + section_lineno_size + section_lv_size + - sizeof(struct rite_binary_footer); - - /* write DEBUG section */ - if (flags & DUMP_DEBUG_INFO) { - if (debug_info_defined) { - result = write_section_debug(mrb, irep, cur, filenames, filenames_len); - } - else { - result = write_section_lineno(mrb, irep, cur); - } - if (result != MRB_DUMP_OK) { - goto error_exit; - } - cur += section_lineno_size; - } - - if (lv_defined) { - result = write_section_lv(mrb, irep, cur, lv_syms, lv_syms_len); - if (result != MRB_DUMP_OK) { - goto error_exit; - } - cur += section_lv_size; - } - - write_footer(mrb, cur); - write_rite_binary_header(mrb, *bin_size, *bin, flags); - -error_exit: - if (result != MRB_DUMP_OK) { - mrb_free(mrb, *bin); - *bin = NULL; - } - mrb_free(mrb, lv_syms); - mrb_free(mrb, filenames); - return result; -} - -int -mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size) -{ - return dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), bin, bin_size); -} - -#ifndef MRB_DISABLE_STDIO - -int -mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp) -{ - uint8_t *bin = NULL; - size_t bin_size = 0; - int result; - - if (fp == NULL) { - return MRB_DUMP_INVALID_ARGUMENT; - } - - result = dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), &bin, &bin_size); - if (result == MRB_DUMP_OK) { - if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) { - result = MRB_DUMP_WRITE_FAULT; - } - } - - mrb_free(mrb, bin); - return result; -} - -static mrb_bool -dump_bigendian_p(uint8_t flags) -{ - switch (flags & DUMP_ENDIAN_NAT) { - case DUMP_ENDIAN_BIG: - return TRUE; - case DUMP_ENDIAN_LIL: - return FALSE; - default: - case DUMP_ENDIAN_NAT: - return bigendian_p(); - } -} - -int -mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname) -{ - uint8_t *bin = NULL; - size_t bin_size = 0, bin_idx = 0; - int result; - - if (fp == NULL || initname == NULL || initname[0] == '\0') { - return MRB_DUMP_INVALID_ARGUMENT; - } - flags = dump_flags(flags, FLAG_BYTEORDER_NATIVE); - result = dump_irep(mrb, irep, flags, &bin, &bin_size); - if (result == MRB_DUMP_OK) { - if (!dump_bigendian_p(flags)) { - if (fprintf(fp, "/* dumped in little endian order.\n" - " use `mrbc -E` option for big endian CPU. */\n") < 0) { - mrb_free(mrb, bin); - return MRB_DUMP_WRITE_FAULT; - } - } - else { - if (fprintf(fp, "/* dumped in big endian order.\n" - " use `mrbc -e` option for better performance on little endian CPU. */\n") < 0) { - mrb_free(mrb, bin); - return MRB_DUMP_WRITE_FAULT; - } - } - if (fprintf(fp, "#include \n") < 0) { /* for uint8_t under at least Darwin */ - mrb_free(mrb, bin); - return MRB_DUMP_WRITE_FAULT; - } - if (fprintf(fp, - "const uint8_t\n" - "#if defined __GNUC__\n" - "__attribute__((aligned(%u)))\n" - "#elif defined _MSC_VER\n" - "__declspec(align(%u))\n" - "#endif\n" - "%s[] = {", - (uint16_t)MRB_DUMP_ALIGNMENT, (uint16_t)MRB_DUMP_ALIGNMENT, initname) < 0) { - mrb_free(mrb, bin); - return MRB_DUMP_WRITE_FAULT; - } - while (bin_idx < bin_size) { - if (bin_idx % 16 == 0) { - if (fputs("\n", fp) == EOF) { - mrb_free(mrb, bin); - return MRB_DUMP_WRITE_FAULT; - } - } - if (fprintf(fp, "0x%02x,", bin[bin_idx++]) < 0) { - mrb_free(mrb, bin); - return MRB_DUMP_WRITE_FAULT; - } - } - if (fputs("\n};\n", fp) == EOF) { - mrb_free(mrb, bin); - return MRB_DUMP_WRITE_FAULT; - } - } - - mrb_free(mrb, bin); - return result; -} - -#endif /* MRB_DISABLE_STDIO */ diff -Nru nghttp2-1.13.0/third-party/mruby/src/enum.c nghttp2-0.6.7/third-party/mruby/src/enum.c --- nghttp2-1.13.0/third-party/mruby/src/enum.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/enum.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -/* -** enum.c - Enumerable module -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" - -void -mrb_init_enumerable(mrb_state *mrb) -{ - mrb_define_module(mrb, "Enumerable"); /* 15.3.2 */ -} - diff -Nru nghttp2-1.13.0/third-party/mruby/src/error.c nghttp2-0.6.7/third-party/mruby/src/error.c --- nghttp2-1.13.0/third-party/mruby/src/error.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/error.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,460 +0,0 @@ -/* -** error.c - Exception class -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/irep.h" -#include "mruby/proc.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/debug.h" -#include "mruby/error.h" -#include "mruby/class.h" -#include "mruby/throw.h" - -MRB_API mrb_value -mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, size_t len) -{ - mrb_value arg = mrb_str_new(mrb, ptr, len); - return mrb_obj_new(mrb, c, 1, &arg); -} - -MRB_API mrb_value -mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str) -{ - str = mrb_str_to_str(mrb, str); - return mrb_obj_new(mrb, c, 1, &str); -} - -/* - * call-seq: - * Exception.new(msg = nil) -> exception - * - * Construct a new Exception object, optionally passing in - * a message. - */ - -static mrb_value -exc_initialize(mrb_state *mrb, mrb_value exc) -{ - mrb_value mesg; - - if (mrb_get_args(mrb, "|o", &mesg) == 1) { - mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), mesg); - } - return exc; -} - -/* - * Document-method: exception - * - * call-seq: - * exc.exception(string) -> an_exception or exc - * - * With no argument, or if the argument is the same as the receiver, - * return the receiver. Otherwise, create a new - * exception object of the same class as the receiver, but with a - * message equal to string.to_str. - * - */ - -static mrb_value -exc_exception(mrb_state *mrb, mrb_value self) -{ - mrb_value exc; - mrb_value a; - int argc; - - argc = mrb_get_args(mrb, "|o", &a); - if (argc == 0) return self; - if (mrb_obj_equal(mrb, self, a)) return self; - exc = mrb_obj_clone(mrb, self); - mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), a); - - return exc; -} - -/* - * call-seq: - * exception.to_s -> string - * - * Returns exception's message (or the name of the exception if - * no message is set). - */ - -static mrb_value -exc_to_s(mrb_state *mrb, mrb_value exc) -{ - mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); - struct RObject *p; - - if (!mrb_string_p(mesg)) { - return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc)); - } - p = mrb_obj_ptr(mesg); - if (!p->c) { - p->c = mrb->string_class; - } - return mesg; -} - -/* - * call-seq: - * exception.message -> string - * - * Returns the result of invoking exception.to_s. - * Normally this returns the exception's message or name. By - * supplying a to_str method, exceptions are agreeing to - * be used where Strings are expected. - */ - -static mrb_value -exc_message(mrb_state *mrb, mrb_value exc) -{ - return mrb_funcall(mrb, exc, "to_s", 0); -} - -/* - * call-seq: - * exception.inspect -> string - * - * Returns this exception's file name, line number, - * message and class name. - * If file name or line number is not set, - * returns message and class name. - */ - -static mrb_value -exc_inspect(mrb_state *mrb, mrb_value exc) -{ - mrb_value str, mesg, file, line; - mrb_bool append_mesg; - - mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); - file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file")); - line = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "line")); - - append_mesg = !mrb_nil_p(mesg); - if (append_mesg) { - mesg = mrb_obj_as_string(mrb, mesg); - append_mesg = RSTRING_LEN(mesg) > 0; - } - - if (!mrb_nil_p(file) && !mrb_nil_p(line)) { - str = mrb_str_dup(mrb, file); - mrb_str_cat_lit(mrb, str, ":"); - mrb_str_append(mrb, str, line); - mrb_str_cat_lit(mrb, str, ": "); - if (append_mesg) { - mrb_str_cat_str(mrb, str, mesg); - mrb_str_cat_lit(mrb, str, " ("); - } - mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc)); - if (append_mesg) { - mrb_str_cat_lit(mrb, str, ")"); - } - } - else { - const char *cname = mrb_obj_classname(mrb, exc); - str = mrb_str_new_cstr(mrb, cname); - mrb_str_cat_lit(mrb, str, ": "); - if (append_mesg) { - mrb_str_cat_str(mrb, str, mesg); - } - else { - mrb_str_cat_cstr(mrb, str, cname); - } - } - return str; -} - - -static void -exc_debug_info(mrb_state *mrb, struct RObject *exc) -{ - mrb_callinfo *ci = mrb->c->ci; - mrb_code *pc = ci->pc; - - mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "ciidx"), mrb_fixnum_value((mrb_int)(ci - mrb->c->cibase))); - while (ci >= mrb->c->cibase) { - mrb_code *err = ci->err; - - if (!err && pc) err = pc - 1; - if (err && ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) { - mrb_irep *irep = ci->proc->body.irep; - - int32_t const line = mrb_debug_get_line(irep, (uint32_t)(err - irep->iseq)); - char const* file = mrb_debug_get_filename(irep, (uint32_t)(err - irep->iseq)); - if (line != -1 && file) { - mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "file"), mrb_str_new_cstr(mrb, file)); - mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "line"), mrb_fixnum_value(line)); - return; - } - } - pc = ci->pc; - ci--; - } -} - -MRB_API mrb_noreturn void -mrb_exc_raise(mrb_state *mrb, mrb_value exc) -{ - mrb->exc = mrb_obj_ptr(exc); - if (!mrb->gc.out_of_memory) { - exc_debug_info(mrb, mrb->exc); - } - if (!mrb->jmp) { - mrb_p(mrb, exc); - abort(); - } - MRB_THROW(mrb->jmp); -} - -MRB_API mrb_noreturn void -mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg) -{ - mrb_value mesg; - mesg = mrb_str_new_cstr(mrb, msg); - mrb_exc_raise(mrb, mrb_exc_new_str(mrb, c, mesg)); -} - -MRB_API mrb_value -mrb_vformat(mrb_state *mrb, const char *format, va_list ap) -{ - const char *p = format; - const char *b = p; - ptrdiff_t size; - mrb_value ary = mrb_ary_new_capa(mrb, 4); - - while (*p) { - const char c = *p++; - - if (c == '%') { - if (*p == 'S') { - size = p - b - 1; - mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size)); - mrb_ary_push(mrb, ary, va_arg(ap, mrb_value)); - b = p + 1; - } - } - else if (c == '\\') { - if (*p) { - size = p - b - 1; - mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size)); - mrb_ary_push(mrb, ary, mrb_str_new(mrb, p, 1)); - b = ++p; - } - else { - break; - } - } - } - if (b == format) { - return mrb_str_new_cstr(mrb, format); - } - else { - size = p - b; - mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size)); - return mrb_ary_join(mrb, ary, mrb_str_new(mrb, NULL, 0)); - } -} - -MRB_API mrb_value -mrb_format(mrb_state *mrb, const char *format, ...) -{ - va_list ap; - mrb_value str; - - va_start(ap, format); - str = mrb_vformat(mrb, format, ap); - va_end(ap); - - return str; -} - -MRB_API mrb_noreturn void -mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...) -{ - va_list args; - mrb_value mesg; - - va_start(args, fmt); - mesg = mrb_vformat(mrb, fmt, args); - va_end(args); - mrb_exc_raise(mrb, mrb_exc_new_str(mrb, c, mesg)); -} - -MRB_API mrb_noreturn void -mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...) -{ - mrb_value exc; - mrb_value argv[2]; - va_list args; - - va_start(args, fmt); - argv[0] = mrb_vformat(mrb, fmt, args); - va_end(args); - - argv[1] = mrb_symbol_value(id); - exc = mrb_obj_new(mrb, E_NAME_ERROR, 2, argv); - mrb_exc_raise(mrb, exc); -} - -MRB_API void -mrb_warn(mrb_state *mrb, const char *fmt, ...) -{ -#ifndef MRB_DISABLE_STDIO - va_list ap; - mrb_value str; - - va_start(ap, fmt); - str = mrb_vformat(mrb, fmt, ap); - fputs("warning: ", stderr); - fwrite(RSTRING_PTR(str), RSTRING_LEN(str), 1, stderr); - va_end(ap); -#endif -} - -MRB_API mrb_noreturn void -mrb_bug(mrb_state *mrb, const char *fmt, ...) -{ -#ifndef MRB_DISABLE_STDIO - va_list ap; - mrb_value str; - - va_start(ap, fmt); - str = mrb_vformat(mrb, fmt, ap); - fputs("bug: ", stderr); - fwrite(RSTRING_PTR(str), RSTRING_LEN(str), 1, stderr); - va_end(ap); -#endif - exit(EXIT_FAILURE); -} - -static void -set_backtrace(mrb_state *mrb, mrb_value info, mrb_value bt) -{ - mrb_funcall(mrb, info, "set_backtrace", 1, bt); -} - -static mrb_value -make_exception(mrb_state *mrb, int argc, const mrb_value *argv, mrb_bool isstr) -{ - mrb_value mesg; - int n; - - mesg = mrb_nil_value(); - switch (argc) { - case 0: - break; - case 1: - if (mrb_nil_p(argv[0])) - break; - if (isstr) { - mesg = mrb_check_string_type(mrb, argv[0]); - if (!mrb_nil_p(mesg)) { - mesg = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, mesg); - break; - } - } - n = 0; - goto exception_call; - - case 2: - case 3: - n = 1; -exception_call: - { - mrb_sym exc = mrb_intern_lit(mrb, "exception"); - if (mrb_respond_to(mrb, argv[0], exc)) { - mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1); - } - else { - /* undef */ - mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); - } - } - - break; - default: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 0..3)", mrb_fixnum_value(argc)); - break; - } - if (argc > 0) { - if (!mrb_obj_is_kind_of(mrb, mesg, mrb->eException_class)) - mrb_raise(mrb, E_TYPE_ERROR, "exception object expected"); - if (argc > 2) - set_backtrace(mrb, mesg, argv[2]); - } - - return mesg; -} - -MRB_API mrb_value -mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv) -{ - return make_exception(mrb, argc, argv, TRUE); -} - -MRB_API void -mrb_sys_fail(mrb_state *mrb, const char *mesg) -{ - struct RClass *sce; - mrb_int no; - - no = (mrb_int)errno; - if (mrb_class_defined(mrb, "SystemCallError")) { - sce = mrb_class_get(mrb, "SystemCallError"); - if (mesg != NULL) { - mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 2, mrb_fixnum_value(no), mrb_str_new_cstr(mrb, mesg)); - } - else { - mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 1, mrb_fixnum_value(no)); - } - } - else { - mrb_raise(mrb, E_RUNTIME_ERROR, mesg); - } -} - -MRB_API mrb_noreturn void -mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, ...) -{ - mrb_value exc; - va_list ap; - - va_start(ap, fmt); - exc = mrb_funcall(mrb, mrb_obj_value(E_NOMETHOD_ERROR), "new", 3, - mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id), args); - va_end(ap); - mrb_exc_raise(mrb, exc); -} - -void -mrb_init_exception(mrb_state *mrb) -{ - struct RClass *exception, *runtime_error, *script_error; - - mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */ - MRB_SET_INSTANCE_TT(exception, MRB_TT_EXCEPTION); - mrb_define_class_method(mrb, exception, "exception", mrb_instance_new, MRB_ARGS_ANY()); - mrb_define_method(mrb, exception, "exception", exc_exception, MRB_ARGS_ANY()); - mrb_define_method(mrb, exception, "initialize", exc_initialize, MRB_ARGS_ANY()); - mrb_define_method(mrb, exception, "to_s", exc_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, exception, "message", exc_message, MRB_ARGS_NONE()); - mrb_define_method(mrb, exception, "inspect", exc_inspect, MRB_ARGS_NONE()); - mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE()); - - mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */ - runtime_error = mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */ - mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, runtime_error, "Out of memory")); - script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */ - mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */ - mrb_define_class(mrb, "SystemStackError", exception); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/error.h nghttp2-0.6.7/third-party/mruby/src/error.h --- nghttp2-1.13.0/third-party/mruby/src/error.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/error.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -/* this header file is to be removed soon. - added for compatibility purpose (1.0.0) */ -#include "mruby/error.h" diff -Nru nghttp2-1.13.0/third-party/mruby/src/etc.c nghttp2-0.6.7/third-party/mruby/src/etc.c --- nghttp2-1.13.0/third-party/mruby/src/etc.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/etc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,220 +0,0 @@ -/* -** etc.c - -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/string.h" -#include "mruby/data.h" -#include "mruby/class.h" -#include "mruby/re.h" -#include "mruby/irep.h" - -MRB_API struct RData* -mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb_data_type *type) -{ - struct RData *data; - - data = (struct RData*)mrb_obj_alloc(mrb, MRB_TT_DATA, klass); - data->data = ptr; - data->type = type; - - return data; -} - -MRB_API void -mrb_data_check_type(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) -{ - if (mrb_type(obj) != MRB_TT_DATA) { - mrb_check_type(mrb, obj, MRB_TT_DATA); - } - if (DATA_TYPE(obj) != type) { - const mrb_data_type *t2 = DATA_TYPE(obj); - - if (t2) { - mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)", - mrb_str_new_cstr(mrb, t2->struct_name), mrb_str_new_cstr(mrb, type->struct_name)); - } - else { - struct RClass *c = mrb_class(mrb, obj); - - mrb_raisef(mrb, E_TYPE_ERROR, "uninitialized %S (expected %S)", - mrb_obj_value(c), mrb_str_new_cstr(mrb, type->struct_name)); - } - } -} - -MRB_API void* -mrb_data_check_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) -{ - if (mrb_type(obj) != MRB_TT_DATA) { - return NULL; - } - if (DATA_TYPE(obj) != type) { - return NULL; - } - return DATA_PTR(obj); -} - -MRB_API void* -mrb_data_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) -{ - mrb_data_check_type(mrb, obj, type); - return DATA_PTR(obj); -} - -MRB_API mrb_sym -mrb_obj_to_sym(mrb_state *mrb, mrb_value name) -{ - mrb_sym id; - - switch (mrb_type(name)) { - default: - name = mrb_check_string_type(mrb, name); - if (mrb_nil_p(name)) { - name = mrb_inspect(mrb, name); - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", name); - } - /* fall through */ - case MRB_TT_STRING: - name = mrb_str_intern(mrb, name); - /* fall through */ - case MRB_TT_SYMBOL: - id = mrb_symbol(name); - } - return id; -} - -MRB_API mrb_int -mrb_float_id(mrb_float f) -{ - const char *p = (const char*)&f; - int len = sizeof(f); - mrb_int id = 0; - - while (len--) { - id = id*65599 + *p; - p++; - } - id = id + (id>>5); - - return id; -} - -MRB_API mrb_int -mrb_obj_id(mrb_value obj) -{ - mrb_int tt = mrb_type(obj); - -#define MakeID2(p,t) (mrb_int)(((intptr_t)(p))^(t)) -#define MakeID(p) MakeID2(p,tt) - - switch (tt) { - case MRB_TT_FREE: - case MRB_TT_UNDEF: - return MakeID(0); /* not define */ - case MRB_TT_FALSE: - if (mrb_nil_p(obj)) - return MakeID(1); - return MakeID(0); - case MRB_TT_TRUE: - return MakeID(1); - case MRB_TT_SYMBOL: - return MakeID(mrb_symbol(obj)); - case MRB_TT_FIXNUM: - return MakeID2(mrb_float_id((mrb_float)mrb_fixnum(obj)), MRB_TT_FLOAT); - case MRB_TT_FLOAT: - return MakeID(mrb_float_id(mrb_float(obj))); - case MRB_TT_STRING: - case MRB_TT_OBJECT: - case MRB_TT_CLASS: - case MRB_TT_MODULE: - case MRB_TT_ICLASS: - case MRB_TT_SCLASS: - case MRB_TT_PROC: - case MRB_TT_ARRAY: - case MRB_TT_HASH: - case MRB_TT_RANGE: - case MRB_TT_EXCEPTION: - case MRB_TT_FILE: - case MRB_TT_DATA: - default: - return MakeID(mrb_ptr(obj)); - } -} - -#ifdef MRB_WORD_BOXING -MRB_API mrb_value -mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f) -{ - mrb_value v; - - v.value.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class); - v.value.fp->f = f; - return v; -} - -MRB_API mrb_value -mrb_word_boxing_float_pool(mrb_state *mrb, mrb_float f) -{ - struct RFloat *nf = (struct RFloat *)mrb_malloc(mrb, sizeof(struct RFloat)); - nf->tt = MRB_TT_FLOAT; - nf->c = mrb->float_class; - nf->f = f; - return mrb_obj_value(nf); -} - -MRB_API mrb_value -mrb_word_boxing_cptr_value(mrb_state *mrb, void *p) -{ - mrb_value v; - - v.value.p = mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class); - v.value.vp->p = p; - return v; -} -#endif /* MRB_WORD_BOXING */ - -MRB_API mrb_bool -mrb_regexp_p(mrb_state *mrb, mrb_value v) -{ - return mrb_class_defined(mrb, REGEXP_CLASS) && mrb_obj_is_kind_of(mrb, v, mrb_class_get(mrb, REGEXP_CLASS)); -} - -#if defined _MSC_VER && _MSC_VER < 1900 - -#ifndef va_copy -static void -mrb_msvc_va_copy(va_list *dest, va_list src) -{ - *dest = src; -} -#define va_copy(dest, src) mrb_msvc_va_copy(&(dest), src) -#endif - -MRB_API int -mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg) -{ - int cnt; - va_list argcp; - va_copy(argcp, arg); - if (n == 0 || (cnt = _vsnprintf_s(s, n, _TRUNCATE, format, argcp)) < 0) { - cnt = _vscprintf(format, arg); - } - va_end(argcp); - return cnt; -} - -MRB_API int -mrb_msvc_snprintf(char *s, size_t n, const char *format, ...) -{ - va_list arg; - int ret; - va_start(arg, format); - ret = mrb_msvc_vsnprintf(s, n, format, arg); - va_end(arg); - return ret; -} - -#endif /* defined _MSC_VER && _MSC_VER < 1900 */ diff -Nru nghttp2-1.13.0/third-party/mruby/src/fmt_fp.c nghttp2-0.6.7/third-party/mruby/src/fmt_fp.c --- nghttp2-1.13.0/third-party/mruby/src/fmt_fp.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/fmt_fp.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,371 +0,0 @@ -/* - -Most code in this file originates from musl (src/stdio/vfprintf.c) -which, just like mruby itself, is licensed under the MIT license. - -Copyright (c) 2005-2014 Rich Felker, et al. - -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. - -*/ - -#include -#include -#include -#include -#include -#include - -#include "mruby.h" -#include "mruby/string.h" - -struct fmt_args { - mrb_state *mrb; - mrb_value str; -}; - -#define MAX(a,b) ((a)>(b) ? (a) : (b)) -#define MIN(a,b) ((a)<(b) ? (a) : (b)) - -/* Convenient bit representation for modifier flags, which all fall - * within 31 codepoints of the space character. */ - -#define ALT_FORM (1U<<('#'-' ')) -#define ZERO_PAD (1U<<('0'-' ')) -#define LEFT_ADJ (1U<<('-'-' ')) -#define PAD_POS (1U<<(' '-' ')) -#define MARK_POS (1U<<('+'-' ')) - -static void -out(struct fmt_args *f, const char *s, size_t l) -{ - mrb_str_cat(f->mrb, f->str, s, l); -} - -#define PAD_SIZE 256 -static void -pad(struct fmt_args *f, char c, int w, int l, int fl) -{ - char pad[PAD_SIZE]; - if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return; - l = w - l; - memset(pad, c, l>PAD_SIZE ? PAD_SIZE : l); - for (; l >= PAD_SIZE; l -= PAD_SIZE) - out(f, pad, PAD_SIZE); - out(f, pad, l); -} - -static const char xdigits[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - -static char* -fmt_u(uint32_t x, char *s) -{ - for (; x; x /= 10) *--s = '0' + x % 10; - return s; -} - -/* Do not override this check. The floating point printing code below - * depends on the float.h constants being right. If they are wrong, it - * may overflow the stack. */ -#if LDBL_MANT_DIG == 53 -typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)]; -#endif - -static int -fmt_fp(struct fmt_args *f, long double y, int w, int p, int fl, int t) -{ - uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion - + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion - uint32_t *a, *d, *r, *z; - uint32_t i; - int e2=0, e, j, l; - char buf[9+LDBL_MANT_DIG/4], *s; - const char *prefix="-0X+0X 0X-0x+0x 0x"; - int pl; - char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr; - - pl=1; - if (signbit(y)) { - y=-y; - } else if (fl & MARK_POS) { - prefix+=3; - } else if (fl & PAD_POS) { - prefix+=6; - } else prefix++, pl=0; - - if (!isfinite(y)) { - const char *ss = (t&32)?"inf":"INF"; - if (y!=y) ss=(t&32)?"nan":"NAN"; - pad(f, ' ', w, 3+pl, fl&~ZERO_PAD); - out(f, prefix, pl); - out(f, ss, 3); - pad(f, ' ', w, 3+pl, fl^LEFT_ADJ); - return MAX(w, 3+pl); - } - - y = frexp((double)y, &e2) * 2; - if (y) e2--; - - if ((t|32)=='a') { - long double round = 8.0; - int re; - - if (t&32) prefix += 9; - pl += 2; - - if (p<0 || p>=LDBL_MANT_DIG/4-1) re=0; - else re=LDBL_MANT_DIG/4-1-p; - - if (re) { - while (re--) round*=16; - if (*prefix=='-') { - y=-y; - y-=round; - y+=round; - y=-y; - } - else { - y+=round; - y-=round; - } - } - - estr=fmt_u(e2<0 ? -e2 : e2, ebuf); - if (estr==ebuf) *--estr='0'; - *--estr = (e2<0 ? '-' : '+'); - *--estr = t+('p'-'a'); - - s=buf; - do { - int x=y; - *s++=xdigits[x]|(t&32); - y=16*(y-x); - if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.'; - } while (y); - - if (p && s-buf-2 < p) - l = (p+2) + (ebuf-estr); - else - l = (s-buf) + (ebuf-estr); - - pad(f, ' ', w, pl+l, fl); - out(f, prefix, pl); - pad(f, '0', w, pl+l, fl^ZERO_PAD); - out(f, buf, s-buf); - pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0); - out(f, estr, ebuf-estr); - pad(f, ' ', w, pl+l, fl^LEFT_ADJ); - return MAX(w, pl+l); - } - if (p<0) p=6; - - if (y) y *= 268435456.0, e2-=28; - - if (e2<0) a=r=z=big; - else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1; - - do { - *z = y; - y = 1000000000*(y-*z++); - } while (y); - - while (e2>0) { - uint32_t carry=0; - int sh=MIN(29,e2); - for (d=z-1; d>=a; d--) { - uint64_t x = ((uint64_t)*d<a && !z[-1]) z--; - e2-=sh; - } - while (e2<0) { - uint32_t carry=0, *b; - int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3+8)/9; - for (d=a; d>sh) + carry; - carry = (1000000000>>sh) * rm; - } - if (!*a) a++; - if (carry) *z++ = carry; - /* Avoid (slow!) computation past requested precision */ - b = (t|32)=='f' ? r : a; - if (z-b > need) z = b+need; - e2+=sh; - } - - if (a=i; i*=10, e++); - else e=0; - - /* Perform rounding: j is precision after the radix (possibly neg) */ - j = p - ((t|32)!='f')*e - ((t|32)=='g' && p); - if (j < 9*(z-r-1)) { - uint32_t x; - /* We avoid C's broken division of negative numbers */ - d = r + 1 + ((j+9*LDBL_MAX_EXP)/9 - LDBL_MAX_EXP); - j += 9*LDBL_MAX_EXP; - j %= 9; - for (i=10, j++; j<9; i*=10, j++); - x = *d % i; - /* Are there any significant digits past j? */ - if (x || d+1!=z) { - long double round = 2/LDBL_EPSILON; - long double small; - if (*d/i & 1) round += 2; - if (x 999999999) { - *d--=0; - if (d=i; i*=10, e++); - } - } - if (z>d+1) z=d+1; - } - for (; z>a && !z[-1]; z--); - - if ((t|32)=='g') { - if (!p) p++; - if (p>e && e>=-4) { - t--; - p-=e+1; - } - else { - t-=2; - p--; - } - if (!(fl&ALT_FORM)) { - /* Count trailing zeros in last place */ - if (z>a && z[-1]) for (i=10, j=0; z[-1]%i==0; i*=10, j++); - else j=9; - if ((t|32)=='f') - p = MIN(p,MAX(0,9*(z-r-1)-j)); - else - p = MIN(p,MAX(0,9*(z-r-1)+e-j)); - } - } - l = 1 + p + (p || (fl&ALT_FORM)); - if ((t|32)=='f') { - if (e>0) l+=e; - } - else { - estr=fmt_u(e<0 ? -e : e, ebuf); - while(ebuf-estr<2) *--estr='0'; - *--estr = (e<0 ? '-' : '+'); - *--estr = t; - l += ebuf-estr; - } - - pad(f, ' ', w, pl+l, fl); - out(f, prefix, pl); - pad(f, '0', w, pl+l, fl^ZERO_PAD); - - if ((t|32)=='f') { - if (a>r) a=r; - for (d=a; d<=r; d++) { - char *ss = fmt_u(*d, buf+9); - if (d!=a) while (ss>buf) *--ss='0'; - else if (ss==buf+9) *--ss='0'; - out(f, ss, buf+9-ss); - } - if (p || (fl&ALT_FORM)) out(f, ".", 1); - for (; d0; d++, p-=9) { - char *ss = fmt_u(*d, buf+9); - while (ss>buf) *--ss='0'; - out(f, ss, MIN(9,p)); - } - pad(f, '0', p+9, 9, 0); - } - else { - if (z<=a) z=a+1; - for (d=a; d=0; d++) { - char *ss = fmt_u(*d, buf+9); - if (ss==buf+9) *--ss='0'; - if (d!=a) while (ss>buf) *--ss='0'; - else { - out(f, ss++, 1); - if (p>0||(fl&ALT_FORM)) out(f, ".", 1); - } - out(f, ss, MIN(buf+9-ss, p)); - p -= buf+9-ss; - } - pad(f, '0', p+18, 18, 0); - out(f, estr, ebuf-estr); - } - - pad(f, ' ', w, pl+l, fl^LEFT_ADJ); - - return MAX(w, pl+l); -} - -static int -fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo) -{ - int p; - - if (*fmt != '%') { - return -1; - } - ++fmt; - - if (*fmt == '.') { - ++fmt; - for (p = 0; ISDIGIT(*fmt); ++fmt) { - p = 10 * p + (*fmt - '0'); - } - } - else { - p = -1; - } - - switch (*fmt) { - case 'e': case 'f': case 'g': case 'a': - case 'E': case 'F': case 'G': case 'A': - return fmt_fp(f, flo, 0, p, 0, *fmt); - default: - return -1; - } -} - -mrb_value -mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt) -{ - struct fmt_args f; - - f.mrb = mrb; - f.str = mrb_str_buf_new(mrb, 24); - if (fmt_core(&f, fmt, mrb_float(flo)) < 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string"); - } - return f.str; -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/gc.c nghttp2-0.6.7/third-party/mruby/src/gc.c --- nghttp2-1.13.0/third-party/mruby/src/gc.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/gc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1727 +0,0 @@ -/* -** gc.c - garbage collector for mruby -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/data.h" -#include "mruby/hash.h" -#include "mruby/proc.h" -#include "mruby/range.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/gc.h" -#include "mruby/error.h" - -/* - = Tri-color Incremental Garbage Collection - - mruby's GC is Tri-color Incremental GC with Mark & Sweep. - Algorithm details are omitted. - Instead, the implementation part is described below. - - == Object's Color - - Each object can be painted in three colors: - - * White - Unmarked. - * Gray - Marked, But the child objects are unmarked. - * Black - Marked, the child objects are also marked. - - == Two White Types - - There're two white color types in a flip-flop fashion: White-A and White-B, - which respectively represent the Current White color (the newly allocated - objects in the current GC cycle) and the Sweep Target White color (the - dead objects to be swept). - - A and B will be switched just at the beginning of the next GC cycle. At - that time, all the dead objects have been swept, while the newly created - objects in the current GC cycle which finally remains White are now - regarded as dead objects. Instead of traversing all the White-A objects and - painting them as White-B, just switch the meaning of White-A and White-B as - this will be much cheaper. - - As a result, the objects we sweep in the current GC cycle are always - left from the previous GC cycle. This allows us to sweep objects - incrementally, without the disturbance of the newly created objects. - - == Execution Timing - - GC Execution Time and Each step interval are decided by live objects count. - List of Adjustment API: - - * gc_interval_ratio_set - * gc_step_ratio_set - - For details, see the comments for each function. - - == Write Barrier - - mruby implementer and C extension library writer must insert a write - barrier when updating a reference from a field of an object. - When updating a reference from a field of object A to object B, - two different types of write barrier are available: - - * mrb_field_write_barrier - target B object for a mark. - * mrb_write_barrier - target A object for a mark. - - == Generational Mode - - mruby's GC offers an Generational Mode while re-using the tri-color GC - infrastructure. It will treat the Black objects as Old objects after each - sweep phase, instead of painting them White. The key ideas are still the same - as traditional generational GC: - - * Minor GC - just traverse the Young objects (Gray objects) in the mark - phase, then only sweep the newly created objects, and leave - the Old objects live. - - * Major GC - same as a full regular GC cycle. - - The difference from "traditional" generational GC is, that the major GC - in mruby is triggered incrementally in a tri-color manner. - - - For details, see the comments for each function. - -*/ - -struct free_obj { - MRB_OBJECT_HEADER; - struct RBasic *next; -}; - -typedef struct { - union { - struct free_obj free; - struct RBasic basic; - struct RObject object; - struct RClass klass; - struct RString string; - struct RArray array; - struct RHash hash; - struct RRange range; - struct RData data; - struct RProc proc; - struct RException exc; -#ifdef MRB_WORD_BOXING - struct RFloat floatv; - struct RCptr cptr; -#endif - } as; -} RVALUE; - -#ifdef GC_PROFILE -#include -#include - -static double program_invoke_time = 0; -static double gc_time = 0; -static double gc_total_time = 0; - -static double -gettimeofday_time(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec + tv.tv_usec * 1e-6; -} - -#define GC_INVOKE_TIME_REPORT(with) do {\ - fprintf(stderr, "%s\n", with);\ - fprintf(stderr, "gc_invoke: %19.3f\n", gettimeofday_time() - program_invoke_time);\ - fprintf(stderr, "is_generational: %d\n", is_generational(gc));\ - fprintf(stderr, "is_major_gc: %d\n", is_major_gc(mrb));\ -} while(0) - -#define GC_TIME_START do {\ - gc_time = gettimeofday_time();\ -} while(0) - -#define GC_TIME_STOP_AND_REPORT do {\ - gc_time = gettimeofday_time() - gc_time;\ - gc_total_time += gc_time;\ - fprintf(stderr, "gc_state: %d\n", gc->state);\ - fprintf(stderr, "live: %zu\n", gc->live);\ - fprintf(stderr, "majorgc_old_threshold: %zu\n", gc->majorgc_old_threshold);\ - fprintf(stderr, "gc_threshold: %zu\n", gc->threshold);\ - fprintf(stderr, "gc_time: %30.20f\n", gc_time);\ - fprintf(stderr, "gc_total_time: %30.20f\n\n", gc_total_time);\ -} while(0) -#else -#define GC_INVOKE_TIME_REPORT(s) -#define GC_TIME_START -#define GC_TIME_STOP_AND_REPORT -#endif - -#ifdef GC_DEBUG -#define DEBUG(x) (x) -#else -#define DEBUG(x) -#endif - -#ifndef MRB_HEAP_PAGE_SIZE -#define MRB_HEAP_PAGE_SIZE 1024 -#endif - -#define GC_STEP_SIZE 1024 - -/* white: 011, black: 100, gray: 000 */ -#define GC_GRAY 0 -#define GC_WHITE_A 1 -#define GC_WHITE_B (1 << 1) -#define GC_BLACK (1 << 2) -#define GC_WHITES (GC_WHITE_A | GC_WHITE_B) -#define GC_COLOR_MASK 7 - -#define paint_gray(o) ((o)->color = GC_GRAY) -#define paint_black(o) ((o)->color = GC_BLACK) -#define paint_white(o) ((o)->color = GC_WHITES) -#define paint_partial_white(s, o) ((o)->color = (s)->current_white_part) -#define is_gray(o) ((o)->color == GC_GRAY) -#define is_white(o) ((o)->color & GC_WHITES) -#define is_black(o) ((o)->color & GC_BLACK) -#define flip_white_part(s) ((s)->current_white_part = other_white_part(s)) -#define other_white_part(s) ((s)->current_white_part ^ GC_WHITES) -#define is_dead(s, o) (((o)->color & other_white_part(s) & GC_WHITES) || (o)->tt == MRB_TT_FREE) - -#define objects(p) ((RVALUE *)p->objects) - -MRB_API void* -mrb_realloc_simple(mrb_state *mrb, void *p, size_t len) -{ - void *p2; - - p2 = (mrb->allocf)(mrb, p, len, mrb->allocf_ud); - if (!p2 && len > 0 && mrb->gc.heaps) { - mrb_full_gc(mrb); - p2 = (mrb->allocf)(mrb, p, len, mrb->allocf_ud); - } - - return p2; -} - -MRB_API void* -mrb_realloc(mrb_state *mrb, void *p, size_t len) -{ - void *p2; - - p2 = mrb_realloc_simple(mrb, p, len); - if (!p2 && len) { - if (mrb->gc.out_of_memory) { - /* mrb_panic(mrb); */ - } - else { - mrb->gc.out_of_memory = TRUE; - mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err)); - } - } - else { - mrb->gc.out_of_memory = FALSE; - } - - return p2; -} - -MRB_API void* -mrb_malloc(mrb_state *mrb, size_t len) -{ - return mrb_realloc(mrb, 0, len); -} - -MRB_API void* -mrb_malloc_simple(mrb_state *mrb, size_t len) -{ - return mrb_realloc_simple(mrb, 0, len); -} - -MRB_API void* -mrb_calloc(mrb_state *mrb, size_t nelem, size_t len) -{ - void *p; - - if (nelem > 0 && len > 0 && - nelem <= SIZE_MAX / len) { - size_t size; - size = nelem * len; - p = mrb_malloc(mrb, size); - - memset(p, 0, size); - } - else { - p = NULL; - } - - return p; -} - -MRB_API void -mrb_free(mrb_state *mrb, void *p) -{ - (mrb->allocf)(mrb, p, 0, mrb->allocf_ud); -} - -MRB_API mrb_bool -mrb_object_dead_p(mrb_state *mrb, struct RBasic *object) { - return is_dead(&mrb->gc, object); -} - -static void -link_heap_page(mrb_gc *gc, mrb_heap_page *page) -{ - page->next = gc->heaps; - if (gc->heaps) - gc->heaps->prev = page; - gc->heaps = page; -} - -static void -unlink_heap_page(mrb_gc *gc, mrb_heap_page *page) -{ - if (page->prev) - page->prev->next = page->next; - if (page->next) - page->next->prev = page->prev; - if (gc->heaps == page) - gc->heaps = page->next; - page->prev = NULL; - page->next = NULL; -} - -static void -link_free_heap_page(mrb_gc *gc, mrb_heap_page *page) -{ - page->free_next = gc->free_heaps; - if (gc->free_heaps) { - gc->free_heaps->free_prev = page; - } - gc->free_heaps = page; -} - -static void -unlink_free_heap_page(mrb_gc *gc, mrb_heap_page *page) -{ - if (page->free_prev) - page->free_prev->free_next = page->free_next; - if (page->free_next) - page->free_next->free_prev = page->free_prev; - if (gc->free_heaps == page) - gc->free_heaps = page->free_next; - page->free_prev = NULL; - page->free_next = NULL; -} - -static void -add_heap(mrb_state *mrb, mrb_gc *gc) -{ - mrb_heap_page *page = (mrb_heap_page *)mrb_calloc(mrb, 1, sizeof(mrb_heap_page) + MRB_HEAP_PAGE_SIZE * sizeof(RVALUE)); - RVALUE *p, *e; - struct RBasic *prev = NULL; - - for (p = objects(page), e=p+MRB_HEAP_PAGE_SIZE; pas.free.tt = MRB_TT_FREE; - p->as.free.next = prev; - prev = &p->as.basic; - } - page->freelist = prev; - - link_heap_page(gc, page); - link_free_heap_page(gc, page); -} - -#define DEFAULT_GC_INTERVAL_RATIO 200 -#define DEFAULT_GC_STEP_RATIO 200 -#define DEFAULT_MAJOR_GC_INC_RATIO 200 -#define is_generational(gc) ((gc)->generational) -#define is_major_gc(gc) (is_generational(gc) && (gc)->full) -#define is_minor_gc(gc) (is_generational(gc) && !(gc)->full) - -void -mrb_gc_init(mrb_state *mrb, mrb_gc *gc) -{ -#ifndef MRB_GC_FIXED_ARENA - gc->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE); - gc->arena_capa = MRB_GC_ARENA_SIZE; -#endif - - gc->current_white_part = GC_WHITE_A; - gc->heaps = NULL; - gc->free_heaps = NULL; - add_heap(mrb, gc); - gc->interval_ratio = DEFAULT_GC_INTERVAL_RATIO; - gc->step_ratio = DEFAULT_GC_STEP_RATIO; -#ifndef MRB_GC_TURN_OFF_GENERATIONAL - gc->generational = TRUE; - gc->full = TRUE; -#endif - -#ifdef GC_PROFILE - program_invoke_time = gettimeofday_time(); -#endif -} - -static void obj_free(mrb_state *mrb, struct RBasic *obj); - -void -free_heap(mrb_state *mrb, mrb_gc *gc) -{ - mrb_heap_page *page = gc->heaps; - mrb_heap_page *tmp; - RVALUE *p, *e; - - while (page) { - tmp = page; - page = page->next; - for (p = objects(tmp), e=p+MRB_HEAP_PAGE_SIZE; pas.free.tt != MRB_TT_FREE) - obj_free(mrb, &p->as.basic); - } - mrb_free(mrb, tmp); - } -} - -void -mrb_gc_destroy(mrb_state *mrb, mrb_gc *gc) -{ - free_heap(mrb, gc); -#ifndef MRB_GC_FIXED_ARENA - mrb_free(mrb, gc->arena); -#endif -} - -static void -gc_protect(mrb_state *mrb, mrb_gc *gc, struct RBasic *p) -{ -#ifdef MRB_GC_FIXED_ARENA - if (gc->arena_idx >= MRB_GC_ARENA_SIZE) { - /* arena overflow error */ - gc->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */ - mrb_raise(mrb, E_RUNTIME_ERROR, "arena overflow error"); - } -#else - if (gc->arena_idx >= gc->arena_capa) { - /* extend arena */ - gc->arena_capa = (int)(gc->arena_capa * 1.5); - gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*gc->arena_capa); - } -#endif - gc->arena[gc->arena_idx++] = p; -} - -/* mrb_gc_protect() leaves the object in the arena */ -MRB_API void -mrb_gc_protect(mrb_state *mrb, mrb_value obj) -{ - if (mrb_immediate_p(obj)) return; - gc_protect(mrb, &mrb->gc, mrb_basic_ptr(obj)); -} - -#define GC_ROOT_NAME "_gc_root_" - -/* mrb_gc_register() keeps the object from GC. - - Register your object when it's exported to C world, - without reference from Ruby world, e.g. callback - arguments. Don't forget to remove the obejct using - mrb_gc_unregister, otherwise your object will leak. -*/ - -MRB_API void -mrb_gc_register(mrb_state *mrb, mrb_value obj) -{ - mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME); - mrb_value table = mrb_gv_get(mrb, root); - - if (mrb_nil_p(table) || mrb_type(table) != MRB_TT_ARRAY) { - table = mrb_ary_new(mrb); - mrb_gv_set(mrb, root, table); - } - mrb_ary_push(mrb, table, obj); -} - -/* mrb_gc_unregister() removes the object from GC root. */ -MRB_API void -mrb_gc_unregister(mrb_state *mrb, mrb_value obj) -{ - mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME); - mrb_value table = mrb_gv_get(mrb, root); - struct RArray *a; - mrb_int i, j; - - if (mrb_nil_p(table)) return; - if (mrb_type(table) != MRB_TT_ARRAY) { - mrb_gv_set(mrb, root, mrb_nil_value()); - return; - } - a = mrb_ary_ptr(table); - mrb_ary_modify(mrb, a); - for (i=j=0; ilen; i++) { - if (!mrb_obj_eq(mrb, a->ptr[i], obj)) { - a->ptr[j++] = a->ptr[i]; - } - } - a->len = j; -} - -MRB_API struct RBasic* -mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) -{ - struct RBasic *p; - static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } }; - mrb_gc *gc = &mrb->gc; - -#ifdef MRB_GC_STRESS - mrb_full_gc(mrb); -#endif - if (gc->threshold < gc->live) { - mrb_incremental_gc(mrb); - } - if (gc->free_heaps == NULL) { - add_heap(mrb, gc); - } - - p = gc->free_heaps->freelist; - gc->free_heaps->freelist = ((struct free_obj*)p)->next; - if (gc->free_heaps->freelist == NULL) { - unlink_free_heap_page(gc, gc->free_heaps); - } - - gc->live++; - gc_protect(mrb, gc, p); - *(RVALUE *)p = RVALUE_zero; - p->tt = ttype; - p->c = cls; - paint_partial_white(gc, p); - return p; -} - -static inline void -add_gray_list(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) -{ -#ifdef MRB_GC_STRESS - if (obj->tt > MRB_TT_MAXDEFINE) { - abort(); - } -#endif - paint_gray(obj); - obj->gcnext = gc->gray_list; - gc->gray_list = obj; -} - -static void -mark_context_stack(mrb_state *mrb, struct mrb_context *c) -{ - size_t i; - size_t e; - - e = c->stack - c->stbase; - if (c->ci) e += c->ci->nregs; - if (c->stbase + e > c->stend) e = c->stend - c->stbase; - for (i=0; istbase[i]; - - if (!mrb_immediate_p(v)) { - if (mrb_basic_ptr(v)->tt == MRB_TT_FREE) { - c->stbase[i] = mrb_nil_value(); - } - else { - mrb_gc_mark(mrb, mrb_basic_ptr(v)); - } - } - } -} - -static void -mark_context(mrb_state *mrb, struct mrb_context *c) -{ - int i, e = 0; - mrb_callinfo *ci; - - /* mark stack */ - mark_context_stack(mrb, c); - - /* mark VM stack */ - if (c->cibase) { - for (ci = c->cibase; ci <= c->ci; ci++) { - if (ci->eidx > e) { - e = ci->eidx; - } - mrb_gc_mark(mrb, (struct RBasic*)ci->env); - mrb_gc_mark(mrb, (struct RBasic*)ci->proc); - mrb_gc_mark(mrb, (struct RBasic*)ci->target_class); - } - } - /* mark ensure stack */ - for (i=0; iensure[i]); - } - /* mark fibers */ - if (c->prev && c->prev->fib) { - mrb_gc_mark(mrb, (struct RBasic*)c->prev->fib); - } -} - -static void -gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) -{ - mrb_assert(is_gray(obj)); - paint_black(obj); - gc->gray_list = obj->gcnext; - mrb_gc_mark(mrb, (struct RBasic*)obj->c); - switch (obj->tt) { - case MRB_TT_ICLASS: - { - struct RClass *c = (struct RClass*)obj; - if (MRB_FLAG_TEST(c, MRB_FLAG_IS_ORIGIN)) - mrb_gc_mark_mt(mrb, c); - mrb_gc_mark(mrb, (struct RBasic*)((struct RClass*)obj)->super); - } - break; - - case MRB_TT_CLASS: - case MRB_TT_MODULE: - case MRB_TT_SCLASS: - { - struct RClass *c = (struct RClass*)obj; - - mrb_gc_mark_mt(mrb, c); - mrb_gc_mark(mrb, (struct RBasic*)c->super); - } - /* fall through */ - - case MRB_TT_OBJECT: - case MRB_TT_DATA: - case MRB_TT_EXCEPTION: - mrb_gc_mark_iv(mrb, (struct RObject*)obj); - break; - - case MRB_TT_PROC: - { - struct RProc *p = (struct RProc*)obj; - - mrb_gc_mark(mrb, (struct RBasic*)p->env); - mrb_gc_mark(mrb, (struct RBasic*)p->target_class); - } - break; - - case MRB_TT_ENV: - { - struct REnv *e = (struct REnv*)obj; - - if (!MRB_ENV_STACK_SHARED_P(e)) { - mrb_int i, len; - - len = MRB_ENV_STACK_LEN(e); - for (i=0; istack[i]); - } - } - } - break; - - case MRB_TT_FIBER: - { - struct mrb_context *c = ((struct RFiber*)obj)->cxt; - - if (c) mark_context(mrb, c); - } - break; - - case MRB_TT_ARRAY: - { - struct RArray *a = (struct RArray*)obj; - size_t i, e; - - for (i=0,e=a->len; iptr[i]); - } - } - break; - - case MRB_TT_HASH: - mrb_gc_mark_iv(mrb, (struct RObject*)obj); - mrb_gc_mark_hash(mrb, (struct RHash*)obj); - break; - - case MRB_TT_STRING: - break; - - case MRB_TT_RANGE: - { - struct RRange *r = (struct RRange*)obj; - - if (r->edges) { - mrb_gc_mark_value(mrb, r->edges->beg); - mrb_gc_mark_value(mrb, r->edges->end); - } - } - break; - - default: - break; - } -} - -MRB_API void -mrb_gc_mark(mrb_state *mrb, struct RBasic *obj) -{ - if (obj == 0) return; - if (!is_white(obj)) return; - mrb_assert((obj)->tt != MRB_TT_FREE); - add_gray_list(mrb, &mrb->gc, obj); -} - -static void -obj_free(mrb_state *mrb, struct RBasic *obj) -{ - DEBUG(printf("obj_free(%p,tt=%d)\n",obj,obj->tt)); - switch (obj->tt) { - /* immediate - no mark */ - case MRB_TT_TRUE: - case MRB_TT_FIXNUM: - case MRB_TT_SYMBOL: - /* cannot happen */ - return; - - case MRB_TT_FLOAT: -#ifdef MRB_WORD_BOXING - break; -#else - return; -#endif - - case MRB_TT_OBJECT: - case MRB_TT_EXCEPTION: - mrb_gc_free_iv(mrb, (struct RObject*)obj); - break; - - case MRB_TT_CLASS: - case MRB_TT_MODULE: - case MRB_TT_SCLASS: - mrb_gc_free_mt(mrb, (struct RClass*)obj); - mrb_gc_free_iv(mrb, (struct RObject*)obj); - break; - case MRB_TT_ICLASS: - if (MRB_FLAG_TEST(obj, MRB_FLAG_IS_ORIGIN)) - mrb_gc_free_mt(mrb, (struct RClass*)obj); - break; - case MRB_TT_ENV: - { - struct REnv *e = (struct REnv*)obj; - - if (!MRB_ENV_STACK_SHARED_P(e)) { - mrb_free(mrb, e->stack); - e->stack = NULL; - } - } - break; - - case MRB_TT_FIBER: - { - struct mrb_context *c = ((struct RFiber*)obj)->cxt; - - if (c != mrb->root_c) - mrb_free_context(mrb, c); - } - break; - - case MRB_TT_ARRAY: - if (ARY_SHARED_P(obj)) - mrb_ary_decref(mrb, ((struct RArray*)obj)->aux.shared); - else - mrb_free(mrb, ((struct RArray*)obj)->ptr); - break; - - case MRB_TT_HASH: - mrb_gc_free_iv(mrb, (struct RObject*)obj); - mrb_gc_free_hash(mrb, (struct RHash*)obj); - break; - - case MRB_TT_STRING: - mrb_gc_free_str(mrb, (struct RString*)obj); - break; - - case MRB_TT_PROC: - { - struct RProc *p = (struct RProc*)obj; - - if (!MRB_PROC_CFUNC_P(p) && p->body.irep) { - mrb_irep_decref(mrb, p->body.irep); - } - } - break; - - case MRB_TT_RANGE: - mrb_free(mrb, ((struct RRange*)obj)->edges); - break; - - case MRB_TT_DATA: - { - struct RData *d = (struct RData*)obj; - if (d->type && d->type->dfree) { - d->type->dfree(mrb, d->data); - } - mrb_gc_free_iv(mrb, (struct RObject*)obj); - } - break; - - default: - break; - } - obj->tt = MRB_TT_FREE; -} - -static void -root_scan_phase(mrb_state *mrb, mrb_gc *gc) -{ - size_t i, e; - - if (!is_minor_gc(gc)) { - gc->gray_list = NULL; - gc->atomic_gray_list = NULL; - } - - mrb_gc_mark_gv(mrb); - /* mark arena */ - for (i=0,e=gc->arena_idx; iarena[i]); - } - /* mark class hierarchy */ - mrb_gc_mark(mrb, (struct RBasic*)mrb->object_class); - /* mark top_self */ - mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self); - /* mark exception */ - mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); - /* mark pre-allocated exception */ - mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); - - mark_context(mrb, mrb->root_c); - if (mrb->root_c->fib) { - mrb_gc_mark(mrb, (struct RBasic*)mrb->root_c->fib); - } - if (mrb->root_c != mrb->c) { - mark_context(mrb, mrb->c); - } -} - -static size_t -gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) -{ - size_t children = 0; - - gc_mark_children(mrb, gc, obj); - - switch (obj->tt) { - case MRB_TT_ICLASS: - children++; - break; - - case MRB_TT_CLASS: - case MRB_TT_SCLASS: - case MRB_TT_MODULE: - { - struct RClass *c = (struct RClass*)obj; - - children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj); - children += mrb_gc_mark_mt_size(mrb, c); - children++; - } - break; - - case MRB_TT_OBJECT: - case MRB_TT_DATA: - case MRB_TT_EXCEPTION: - children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj); - break; - - case MRB_TT_ENV: - children += (int)obj->flags; - break; - - case MRB_TT_FIBER: - { - struct mrb_context *c = ((struct RFiber*)obj)->cxt; - size_t i; - mrb_callinfo *ci; - - if (!c) break; - /* mark stack */ - i = c->stack - c->stbase; - if (c->ci) i += c->ci->nregs; - if (c->stbase + i > c->stend) i = c->stend - c->stbase; - children += i; - - /* mark ensure stack */ - children += (c->ci) ? c->ci->eidx : 0; - - /* mark closure */ - if (c->cibase) { - for (i=0, ci = c->cibase; ci <= c->ci; i++, ci++) - ; - } - children += i; - } - break; - - case MRB_TT_ARRAY: - { - struct RArray *a = (struct RArray*)obj; - children += a->len; - } - break; - - case MRB_TT_HASH: - children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj); - children += mrb_gc_mark_hash_size(mrb, (struct RHash*)obj); - break; - - case MRB_TT_PROC: - case MRB_TT_RANGE: - children+=2; - break; - - default: - break; - } - return children; -} - - -static void -gc_mark_gray_list(mrb_state *mrb, mrb_gc *gc) { - while (gc->gray_list) { - if (is_gray(gc->gray_list)) - gc_mark_children(mrb, gc, gc->gray_list); - else - gc->gray_list = gc->gray_list->gcnext; - } -} - - -static size_t -incremental_marking_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) -{ - size_t tried_marks = 0; - - while (gc->gray_list && tried_marks < limit) { - tried_marks += gc_gray_mark(mrb, gc, gc->gray_list); - } - - return tried_marks; -} - -static void -final_marking_phase(mrb_state *mrb, mrb_gc *gc) -{ - mark_context_stack(mrb, mrb->root_c); - gc_mark_gray_list(mrb, gc); - mrb_assert(gc->gray_list == NULL); - gc->gray_list = gc->atomic_gray_list; - gc->atomic_gray_list = NULL; - gc_mark_gray_list(mrb, gc); - mrb_assert(gc->gray_list == NULL); -} - -static void -prepare_incremental_sweep(mrb_state *mrb, mrb_gc *gc) -{ - gc->state = MRB_GC_STATE_SWEEP; - gc->sweeps = gc->heaps; - gc->live_after_mark = gc->live; -} - -static size_t -incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) -{ - mrb_heap_page *page = gc->sweeps; - size_t tried_sweep = 0; - - while (page && (tried_sweep < limit)) { - RVALUE *p = objects(page); - RVALUE *e = p + MRB_HEAP_PAGE_SIZE; - size_t freed = 0; - mrb_bool dead_slot = TRUE; - mrb_bool full = (page->freelist == NULL); - - if (is_minor_gc(gc) && page->old) { - /* skip a slot which doesn't contain any young object */ - p = e; - dead_slot = FALSE; - } - while (pas.basic)) { - if (p->as.basic.tt != MRB_TT_FREE) { - obj_free(mrb, &p->as.basic); - p->as.free.next = page->freelist; - page->freelist = (struct RBasic*)p; - freed++; - } - } - else { - if (!is_generational(gc)) - paint_partial_white(gc, &p->as.basic); /* next gc target */ - dead_slot = 0; - } - p++; - } - - /* free dead slot */ - if (dead_slot && freed < MRB_HEAP_PAGE_SIZE) { - mrb_heap_page *next = page->next; - - unlink_heap_page(gc, page); - unlink_free_heap_page(gc, page); - mrb_free(mrb, page); - page = next; - } - else { - if (full && freed > 0) { - link_free_heap_page(gc, page); - } - if (page->freelist == NULL && is_minor_gc(gc)) - page->old = TRUE; - else - page->old = FALSE; - page = page->next; - } - tried_sweep += MRB_HEAP_PAGE_SIZE; - gc->live -= freed; - gc->live_after_mark -= freed; - } - gc->sweeps = page; - return tried_sweep; -} - -static size_t -incremental_gc(mrb_state *mrb, mrb_gc *gc, size_t limit) -{ - switch (gc->state) { - case MRB_GC_STATE_ROOT: - root_scan_phase(mrb, gc); - gc->state = MRB_GC_STATE_MARK; - flip_white_part(gc); - return 0; - case MRB_GC_STATE_MARK: - if (gc->gray_list) { - return incremental_marking_phase(mrb, gc, limit); - } - else { - final_marking_phase(mrb, gc); - prepare_incremental_sweep(mrb, gc); - return 0; - } - case MRB_GC_STATE_SWEEP: { - size_t tried_sweep = 0; - tried_sweep = incremental_sweep_phase(mrb, gc, limit); - if (tried_sweep == 0) - gc->state = MRB_GC_STATE_ROOT; - return tried_sweep; - } - default: - /* unknown state */ - mrb_assert(0); - return 0; - } -} - -static void -incremental_gc_until(mrb_state *mrb, mrb_gc *gc, mrb_gc_state to_state) -{ - do { - incremental_gc(mrb, gc, SIZE_MAX); - } while (gc->state != to_state); -} - -static void -incremental_gc_step(mrb_state *mrb, mrb_gc *gc) -{ - size_t limit = 0, result = 0; - limit = (GC_STEP_SIZE/100) * gc->step_ratio; - while (result < limit) { - result += incremental_gc(mrb, gc, limit); - if (gc->state == MRB_GC_STATE_ROOT) - break; - } - - gc->threshold = gc->live + GC_STEP_SIZE; -} - -static void -clear_all_old(mrb_state *mrb, mrb_gc *gc) -{ - mrb_bool origin_mode = gc->generational; - - mrb_assert(is_generational(gc)); - if (is_major_gc(gc)) { - /* finish the half baked GC */ - incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); - } - - /* Sweep the dead objects, then reset all the live objects - * (including all the old objects, of course) to white. */ - gc->generational = FALSE; - prepare_incremental_sweep(mrb, gc); - incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); - gc->generational = origin_mode; - - /* The gray objects have already been painted as white */ - gc->atomic_gray_list = gc->gray_list = NULL; -} - -MRB_API void -mrb_incremental_gc(mrb_state *mrb) -{ - mrb_gc *gc = &mrb->gc; - - if (gc->disabled) return; - - GC_INVOKE_TIME_REPORT("mrb_incremental_gc()"); - GC_TIME_START; - - if (is_minor_gc(gc)) { - incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); - } - else { - incremental_gc_step(mrb, gc); - } - - if (gc->state == MRB_GC_STATE_ROOT) { - mrb_assert(gc->live >= gc->live_after_mark); - gc->threshold = (gc->live_after_mark/100) * gc->interval_ratio; - if (gc->threshold < GC_STEP_SIZE) { - gc->threshold = GC_STEP_SIZE; - } - - if (is_major_gc(gc)) { - gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; - gc->full = FALSE; - } - else if (is_minor_gc(gc)) { - if (gc->live > gc->majorgc_old_threshold) { - clear_all_old(mrb, gc); - gc->full = TRUE; - } - } - } - - GC_TIME_STOP_AND_REPORT; -} - -/* Perform a full gc cycle */ -MRB_API void -mrb_full_gc(mrb_state *mrb) -{ - mrb_gc *gc = &mrb->gc; - - if (gc->disabled) return; - - GC_INVOKE_TIME_REPORT("mrb_full_gc()"); - GC_TIME_START; - - if (is_generational(gc)) { - /* clear all the old objects back to young */ - clear_all_old(mrb, gc); - gc->full = TRUE; - } - else if (gc->state != MRB_GC_STATE_ROOT) { - /* finish half baked GC cycle */ - incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); - } - - incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); - gc->threshold = (gc->live_after_mark/100) * gc->interval_ratio; - - if (is_generational(gc)) { - gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; - gc->full = FALSE; - } - - GC_TIME_STOP_AND_REPORT; -} - -MRB_API void -mrb_garbage_collect(mrb_state *mrb) -{ - mrb_full_gc(mrb); -} - -MRB_API int -mrb_gc_arena_save(mrb_state *mrb) -{ - return mrb->gc.arena_idx; -} - -MRB_API void -mrb_gc_arena_restore(mrb_state *mrb, int idx) -{ - mrb_gc *gc = &mrb->gc; - -#ifndef MRB_GC_FIXED_ARENA - int capa = gc->arena_capa; - - if (idx < capa / 2) { - capa = (int)(capa * 0.66); - if (capa < MRB_GC_ARENA_SIZE) { - capa = MRB_GC_ARENA_SIZE; - } - if (capa != gc->arena_capa) { - gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa); - gc->arena_capa = capa; - } - } -#endif - gc->arena_idx = idx; -} - -/* - * Field write barrier - * Paint obj(Black) -> value(White) to obj(Black) -> value(Gray). - */ - -MRB_API void -mrb_field_write_barrier(mrb_state *mrb, struct RBasic *obj, struct RBasic *value) -{ - mrb_gc *gc = &mrb->gc; - - if (!is_black(obj)) return; - if (!is_white(value)) return; - - mrb_assert(gc->state == MRB_GC_STATE_MARK || (!is_dead(gc, value) && !is_dead(gc, obj))); - mrb_assert(is_generational(gc) || gc->state != MRB_GC_STATE_ROOT); - - if (is_generational(gc) || gc->state == MRB_GC_STATE_MARK) { - add_gray_list(mrb, gc, value); - } - else { - mrb_assert(gc->state == MRB_GC_STATE_SWEEP); - paint_partial_white(gc, obj); /* for never write barriers */ - } -} - -/* - * Write barrier - * Paint obj(Black) to obj(Gray). - * - * The object that is painted gray will be traversed atomically in final - * mark phase. So you use this write barrier if it's frequency written spot. - * e.g. Set element on Array. - */ - -MRB_API void -mrb_write_barrier(mrb_state *mrb, struct RBasic *obj) -{ - mrb_gc *gc = &mrb->gc; - - if (!is_black(obj)) return; - - mrb_assert(!is_dead(gc, obj)); - mrb_assert(is_generational(gc) || gc->state != MRB_GC_STATE_ROOT); - paint_gray(obj); - obj->gcnext = gc->atomic_gray_list; - gc->atomic_gray_list = obj; -} - -/* - * call-seq: - * GC.start -> nil - * - * Initiates full garbage collection. - * - */ - -static mrb_value -gc_start(mrb_state *mrb, mrb_value obj) -{ - mrb_full_gc(mrb); - return mrb_nil_value(); -} - -/* - * call-seq: - * GC.enable -> true or false - * - * Enables garbage collection, returning true if garbage - * collection was previously disabled. - * - * GC.disable #=> false - * GC.enable #=> true - * GC.enable #=> false - * - */ - -static mrb_value -gc_enable(mrb_state *mrb, mrb_value obj) -{ - mrb_bool old = mrb->gc.disabled; - - mrb->gc.disabled = FALSE; - - return mrb_bool_value(old); -} - -/* - * call-seq: - * GC.disable -> true or false - * - * Disables garbage collection, returning true if garbage - * collection was already disabled. - * - * GC.disable #=> false - * GC.disable #=> true - * - */ - -static mrb_value -gc_disable(mrb_state *mrb, mrb_value obj) -{ - mrb_bool old = mrb->gc.disabled; - - mrb->gc.disabled = TRUE; - - return mrb_bool_value(old); -} - -/* - * call-seq: - * GC.interval_ratio -> fixnum - * - * Returns ratio of GC interval. Default value is 200(%). - * - */ - -static mrb_value -gc_interval_ratio_get(mrb_state *mrb, mrb_value obj) -{ - return mrb_fixnum_value(mrb->gc.interval_ratio); -} - -/* - * call-seq: - * GC.interval_ratio = fixnum -> nil - * - * Updates ratio of GC interval. Default value is 200(%). - * GC start as soon as after end all step of GC if you set 100(%). - * - */ - -static mrb_value -gc_interval_ratio_set(mrb_state *mrb, mrb_value obj) -{ - mrb_int ratio; - - mrb_get_args(mrb, "i", &ratio); - mrb->gc.interval_ratio = ratio; - return mrb_nil_value(); -} - -/* - * call-seq: - * GC.step_ratio -> fixnum - * - * Returns step span ratio of Incremental GC. Default value is 200(%). - * - */ - -static mrb_value -gc_step_ratio_get(mrb_state *mrb, mrb_value obj) -{ - return mrb_fixnum_value(mrb->gc.step_ratio); -} - -/* - * call-seq: - * GC.step_ratio = fixnum -> nil - * - * Updates step span ratio of Incremental GC. Default value is 200(%). - * 1 step of incrementalGC becomes long if a rate is big. - * - */ - -static mrb_value -gc_step_ratio_set(mrb_state *mrb, mrb_value obj) -{ - mrb_int ratio; - - mrb_get_args(mrb, "i", &ratio); - mrb->gc.step_ratio = ratio; - return mrb_nil_value(); -} - -static void -change_gen_gc_mode(mrb_state *mrb, mrb_gc *gc, mrb_bool enable) -{ - if (is_generational(gc) && !enable) { - clear_all_old(mrb, gc); - mrb_assert(gc->state == MRB_GC_STATE_ROOT); - gc->full = FALSE; - } - else if (!is_generational(gc) && enable) { - incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); - gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; - gc->full = FALSE; - } - gc->generational = enable; -} - -/* - * call-seq: - * GC.generational_mode -> true or false - * - * Returns generational or normal gc mode. - * - */ - -static mrb_value -gc_generational_mode_get(mrb_state *mrb, mrb_value self) -{ - return mrb_bool_value(mrb->gc.generational); -} - -/* - * call-seq: - * GC.generational_mode = true or false -> true or false - * - * Changes to generational or normal gc mode. - * - */ - -static mrb_value -gc_generational_mode_set(mrb_state *mrb, mrb_value self) -{ - mrb_bool enable; - - mrb_get_args(mrb, "b", &enable); - if (mrb->gc.generational != enable) - change_gen_gc_mode(mrb, &mrb->gc, enable); - - return mrb_bool_value(enable); -} - - -static void -gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback, void *data) -{ - mrb_heap_page* page = gc->heaps; - - while (page != NULL) { - RVALUE *p, *pend; - - p = objects(page); - pend = p + MRB_HEAP_PAGE_SIZE; - for (;p < pend; p++) { - (*callback)(mrb, &p->as.basic, data); - } - - page = page->next; - } -} - -void -mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data) -{ - gc_each_objects(mrb, &mrb->gc, callback, data); -} - -#ifdef GC_TEST -#ifdef GC_DEBUG -static mrb_value gc_test(mrb_state *, mrb_value); -#endif -#endif - -void -mrb_init_gc(mrb_state *mrb) -{ - struct RClass *gc; - - gc = mrb_define_module(mrb, "GC"); - - mrb_define_class_method(mrb, gc, "start", gc_start, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, gc, "enable", gc_enable, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, gc, "disable", gc_disable, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, gc, "interval_ratio", gc_interval_ratio_get, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, gc, "interval_ratio=", gc_interval_ratio_set, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, gc, "step_ratio", gc_step_ratio_get, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, gc, "step_ratio=", gc_step_ratio_set, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, gc, "generational_mode=", gc_generational_mode_set, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, gc, "generational_mode", gc_generational_mode_get, MRB_ARGS_NONE()); -#ifdef GC_TEST -#ifdef GC_DEBUG - mrb_define_class_method(mrb, gc, "test", gc_test, MRB_ARGS_NONE()); -#endif -#endif -} - -#ifdef GC_TEST -#ifdef GC_DEBUG -void -test_mrb_field_write_barrier(void) -{ - mrb_state *mrb = mrb_open(); - struct RBasic *obj, *value; - mrb_gc *gc = &mrb->gc; - - puts("test_mrb_field_write_barrier"); - gc->generational = FALSE; - obj = mrb_basic_ptr(mrb_ary_new(mrb)); - value = mrb_basic_ptr(mrb_str_new_lit(mrb, "value")); - paint_black(obj); - paint_partial_white(gc, value); - - - puts(" in MRB_GC_STATE_MARK"); - gc->state = MRB_GC_STATE_MARK; - mrb_field_write_barrier(mrb, obj, value); - - mrb_assert(is_gray(value)); - - - puts(" in MRB_GC_STATE_SWEEP"); - paint_partial_white(gc, value); - gc->state = MRB_GC_STATE_SWEEP; - mrb_field_write_barrier(mrb, obj, value); - - mrb_assert(obj->color & gc->current_white_part); - mrb_assert(value->color & gc->current_white_part); - - - puts(" fail with black"); - gc->state = MRB_GC_STATE_MARK; - paint_white(obj); - paint_partial_white(gc, value); - mrb_field_write_barrier(mrb, obj, value); - - mrb_assert(obj->color & gc->current_white_part); - - - puts(" fail with gray"); - gc->state = MRB_GC_STATE_MARK; - paint_black(obj); - paint_gray(value); - mrb_field_write_barrier(mrb, obj, value); - - mrb_assert(is_gray(value)); - - - { - puts("test_mrb_field_write_barrier_value"); - obj = mrb_basic_ptr(mrb_ary_new(mrb)); - mrb_value value = mrb_str_new_lit(mrb, "value"); - paint_black(obj); - paint_partial_white(gc, mrb_basic_ptr(value)); - - gc->state = MRB_GC_STATE_MARK; - mrb_field_write_barrier_value(mrb, obj, value); - - mrb_assert(is_gray(mrb_basic_ptr(value))); - } - - mrb_close(mrb); -} - -void -test_mrb_write_barrier(void) -{ - mrb_state *mrb = mrb_open(); - struct RBasic *obj; - mrb_gc *gc = &mrb->gc; - - puts("test_mrb_write_barrier"); - obj = mrb_basic_ptr(mrb_ary_new(mrb)); - paint_black(obj); - - puts(" in MRB_GC_STATE_MARK"); - gc->state = MRB_GC_STATE_MARK; - mrb_write_barrier(mrb, obj); - - mrb_assert(is_gray(obj)); - mrb_assert(gc->atomic_gray_list == obj); - - - puts(" fail with gray"); - paint_gray(obj); - mrb_write_barrier(mrb, obj); - - mrb_assert(is_gray(obj)); - - mrb_close(mrb); -} - -void -test_add_gray_list(void) -{ - mrb_state *mrb = mrb_open(); - struct RBasic *obj1, *obj2; - mrb_gc *gc = &mrb->gc; - - puts("test_add_gray_list"); - change_gen_gc_mode(mrb, gc, FALSE); - mrb_assert(gc->gray_list == NULL); - obj1 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test")); - add_gray_list(mrb, gc, obj1); - mrb_assert(gc->gray_list == obj1); - mrb_assert(is_gray(obj1)); - - obj2 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test")); - add_gray_list(mrb, gc, obj2); - mrb_assert(gc->gray_list == obj2); - mrb_assert(gc->gray_list->gcnext == obj1); - mrb_assert(is_gray(obj2)); - - mrb_close(mrb); -} - -void -test_gc_gray_mark(void) -{ - mrb_state *mrb = mrb_open(); - mrb_value obj_v, value_v; - struct RBasic *obj; - size_t gray_num = 0; - mrb_gc *gc = &mrb->gc; - - puts("test_gc_gray_mark"); - - puts(" in MRB_TT_CLASS"); - obj = (struct RBasic*)mrb->object_class; - paint_gray(obj); - gray_num = gc_gray_mark(mrb, gc, obj); - mrb_assert(is_black(obj)); - mrb_assert(gray_num > 1); - - puts(" in MRB_TT_ARRAY"); - obj_v = mrb_ary_new(mrb); - value_v = mrb_str_new_lit(mrb, "test"); - paint_gray(mrb_basic_ptr(obj_v)); - paint_partial_white(gc, mrb_basic_ptr(value_v)); - mrb_ary_push(mrb, obj_v, value_v); - gray_num = gc_gray_mark(mrb, gc, mrb_basic_ptr(obj_v)); - mrb_assert(is_black(mrb_basic_ptr(obj_v))); - mrb_assert(is_gray(mrb_basic_ptr(value_v))); - mrb_assert(gray_num == 1); - - mrb_close(mrb); -} - -void -test_incremental_gc(void) -{ - mrb_state *mrb = mrb_open(); - size_t max = ~0, live = 0, total = 0, freed = 0; - RVALUE *free; - mrb_heap_page *page; - mrb_gc *gc = &mrb->gc; - - puts("test_incremental_gc"); - change_gen_gc_mode(mrb, gc, FALSE); - - puts(" in mrb_full_gc"); - mrb_full_gc(mrb); - - mrb_assert(gc->state == MRB_GC_STATE_ROOT); - puts(" in MRB_GC_STATE_ROOT"); - incremental_gc(mrb, gc, max); - mrb_assert(gc->state == MRB_GC_STATE_MARK); - puts(" in MRB_GC_STATE_MARK"); - incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP); - mrb_assert(gc->state == MRB_GC_STATE_SWEEP); - - puts(" in MRB_GC_STATE_SWEEP"); - page = gc->heaps; - while (page) { - RVALUE *p = objects(page); - RVALUE *e = p + MRB_HEAP_PAGE_SIZE; - while (pas.basic)) { - live++; - } - if (is_gray(&p->as.basic) && !is_dead(gc, &p->as.basic)) { - printf("%p\n", &p->as.basic); - } - p++; - } - page = page->next; - total += MRB_HEAP_PAGE_SIZE; - } - - mrb_assert(gc->gray_list == NULL); - - incremental_gc(mrb, gc, max); - mrb_assert(gc->state == MRB_GC_STATE_SWEEP); - - incremental_gc(mrb, gc, max); - mrb_assert(gc->state == MRB_GC_STATE_ROOT); - - free = (RVALUE*)gc->heaps->freelist; - while (free) { - freed++; - free = (RVALUE*)free->as.free.next; - } - - mrb_assert(gc->live == live); - mrb_assert(gc->live == total-freed); - - puts("test_incremental_gc(gen)"); - incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP); - change_gen_gc_mode(mrb, gc, TRUE); - - mrb_assert(gc->full == FALSE); - mrb_assert(gc->state == MRB_GC_STATE_ROOT); - - puts(" in minor"); - mrb_assert(is_minor_gc(gc)); - mrb_assert(gc->majorgc_old_threshold > 0); - gc->majorgc_old_threshold = 0; - mrb_incremental_gc(mrb); - mrb_assert(gc->full == TRUE); - mrb_assert(gc->state == MRB_GC_STATE_ROOT); - - puts(" in major"); - mrb_assert(is_major_gc(gc)); - do { - mrb_incremental_gc(mrb); - } while (gc->state != MRB_GC_STATE_ROOT); - mrb_assert(gc->full == FALSE); - - mrb_close(mrb); -} - -void -test_incremental_sweep_phase(void) -{ - mrb_state *mrb = mrb_open(); - mrb_gc *gc = &mrb->gc; - - puts("test_incremental_sweep_phase"); - - add_heap(mrb, gc); - gc->sweeps = gc->heaps; - - mrb_assert(gc->heaps->next->next == NULL); - mrb_assert(gc->free_heaps->next->next == NULL); - incremental_sweep_phase(mrb, gc, MRB_HEAP_PAGE_SIZE * 3); - - mrb_assert(gc->heaps->next == NULL); - mrb_assert(gc->heaps == gc->free_heaps); - - mrb_close(mrb); -} - -static mrb_value -gc_test(mrb_state *mrb, mrb_value self) -{ - test_mrb_field_write_barrier(); - test_mrb_write_barrier(); - test_add_gray_list(); - test_gc_gray_mark(); - test_incremental_gc(); - test_incremental_sweep_phase(); - return mrb_nil_value(); -} -#endif /* GC_DEBUG */ -#endif /* GC_TEST */ diff -Nru nghttp2-1.13.0/third-party/mruby/src/hash.c nghttp2-0.6.7/third-party/mruby/src/hash.c --- nghttp2-1.13.0/third-party/mruby/src/hash.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/hash.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,858 +0,0 @@ -/* -** hash.c - Hash class -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/hash.h" -#include "mruby/khash.h" -#include "mruby/string.h" -#include "mruby/variable.h" - -/* a function to get hash value of a float number */ -mrb_int mrb_float_id(mrb_float f); - -static inline khint_t -mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key) -{ - enum mrb_vtype t = mrb_type(key); - mrb_value hv; - const char *p; - mrb_int i, len; - khint_t h; - - switch (t) { - case MRB_TT_STRING: - p = RSTRING_PTR(key); - len = RSTRING_LEN(key); - h = 0; - for (i=0; iht; - - if (!h) return; - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)) { - mrb_value key = kh_key(h, k); - mrb_value val = kh_value(h, k).v; - - mrb_gc_mark_value(mrb, key); - mrb_gc_mark_value(mrb, val); - } - } -} - -size_t -mrb_gc_mark_hash_size(mrb_state *mrb, struct RHash *hash) -{ - if (!hash->ht) return 0; - return kh_size(hash->ht)*2; -} - -void -mrb_gc_free_hash(mrb_state *mrb, struct RHash *hash) -{ - if (hash->ht) kh_destroy(ht, mrb, hash->ht); -} - - -MRB_API mrb_value -mrb_hash_new_capa(mrb_state *mrb, int capa) -{ - struct RHash *h; - - h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); - h->ht = kh_init(ht, mrb); - if (capa > 0) { - kh_resize(ht, mrb, h->ht, capa); - } - h->iv = 0; - return mrb_obj_value(h); -} - -MRB_API mrb_value -mrb_hash_new(mrb_state *mrb) -{ - return mrb_hash_new_capa(mrb, 0); -} - -MRB_API mrb_value -mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) -{ - khash_t(ht) *h = RHASH_TBL(hash); - khiter_t k; - - if (h) { - k = kh_get(ht, mrb, h, key); - if (k != kh_end(h)) - return kh_value(h, k).v; - } - - /* not found */ - if (MRB_RHASH_PROCDEFAULT_P(hash)) { - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); - } - return RHASH_IFNONE(hash); -} - -MRB_API mrb_value -mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def) -{ - khash_t(ht) *h = RHASH_TBL(hash); - khiter_t k; - - if (h) { - k = kh_get(ht, mrb, h, key); - if (k != kh_end(h)) - return kh_value(h, k).v; - } - - /* not found */ - return def; -} - -MRB_API void -mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) -{ - khash_t(ht) *h; - khiter_t k; - int r; - - mrb_hash_modify(mrb, hash); - h = RHASH_TBL(hash); - - if (!h) h = RHASH_TBL(hash) = kh_init(ht, mrb); - k = kh_put2(ht, mrb, h, key, &r); - kh_value(h, k).v = val; - - if (r != 0) { - /* expand */ - int ai = mrb_gc_arena_save(mrb); - key = kh_key(h, k) = KEY(key); - mrb_gc_arena_restore(mrb, ai); - kh_value(h, k).n = kh_size(h)-1; - } - - mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), key); - mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), val); - return; -} - -static mrb_value -mrb_hash_dup(mrb_state *mrb, mrb_value hash) -{ - struct RHash* ret; - khash_t(ht) *h, *ret_h; - khiter_t k, ret_k; - - h = RHASH_TBL(hash); - ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); - ret->ht = kh_init(ht, mrb); - - if (kh_size(h) > 0) { - ret_h = ret->ht; - - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)) { - int ai = mrb_gc_arena_save(mrb); - ret_k = kh_put(ht, mrb, ret_h, KEY(kh_key(h, k))); - mrb_gc_arena_restore(mrb, ai); - kh_val(ret_h, ret_k) = kh_val(h, k); - } - } - } - - return mrb_obj_value(ret); -} - -MRB_API mrb_value -mrb_check_hash_type(mrb_state *mrb, mrb_value hash) -{ - return mrb_check_convert_type(mrb, hash, MRB_TT_HASH, "Hash", "to_hash"); -} - -MRB_API khash_t(ht)* -mrb_hash_tbl(mrb_state *mrb, mrb_value hash) -{ - khash_t(ht) *h = RHASH_TBL(hash); - - if (!h) { - return RHASH_TBL(hash) = kh_init(ht, mrb); - } - return h; -} - -static void -mrb_hash_modify(mrb_state *mrb, mrb_value hash) -{ - mrb_hash_tbl(mrb, hash); -} - -/* 15.2.13.4.16 */ -/* - * call-seq: - * Hash.new -> new_hash - * Hash.new(obj) -> new_hash - * Hash.new {|hash, key| block } -> new_hash - * - * Returns a new, empty hash. If this hash is subsequently accessed by - * a key that doesn't correspond to a hash entry, the value returned - * depends on the style of new used to create the hash. In - * the first form, the access returns nil. If - * obj is specified, this single object will be used for - * all default values. If a block is specified, it will be - * called with the hash object and the key, and should return the - * default value. It is the block's responsibility to store the value - * in the hash if required. - * - * h = Hash.new("Go Fish") - * h["a"] = 100 - * h["b"] = 200 - * h["a"] #=> 100 - * h["c"] #=> "Go Fish" - * # The following alters the single default object - * h["c"].upcase! #=> "GO FISH" - * h["d"] #=> "GO FISH" - * h.keys #=> ["a", "b"] - * - * # While this creates a new default object each time - * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" } - * h["c"] #=> "Go Fish: c" - * h["c"].upcase! #=> "GO FISH: C" - * h["d"] #=> "Go Fish: d" - * h.keys #=> ["c", "d"] - * - */ - -static mrb_value -mrb_hash_init(mrb_state *mrb, mrb_value hash) -{ - mrb_value block, ifnone; - mrb_bool ifnone_p; - - ifnone = mrb_nil_value(); - mrb_get_args(mrb, "&|o?", &block, &ifnone, &ifnone_p); - mrb_hash_modify(mrb, hash); - if (!mrb_nil_p(block)) { - if (ifnone_p) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); - } - RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; - ifnone = block; - } - mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); - return hash; -} - -/* 15.2.13.4.2 */ -/* - * call-seq: - * hsh[key] -> value - * - * Element Reference---Retrieves the value object corresponding - * to the key object. If not found, returns the default value (see - * Hash::new for details). - * - * h = { "a" => 100, "b" => 200 } - * h["a"] #=> 100 - * h["c"] #=> nil - * - */ -static mrb_value -mrb_hash_aget(mrb_state *mrb, mrb_value self) -{ - mrb_value key; - - mrb_get_args(mrb, "o", &key); - return mrb_hash_get(mrb, self, key); -} - -/* 15.2.13.4.5 */ -/* - * call-seq: - * hsh.default(key=nil) -> obj - * - * Returns the default value, the value that would be returned by - * hsh[key] if key did not exist in hsh. - * See also Hash::new and Hash#default=. - * - * h = Hash.new #=> {} - * h.default #=> nil - * h.default(2) #=> nil - * - * h = Hash.new("cat") #=> {} - * h.default #=> "cat" - * h.default(2) #=> "cat" - * - * h = Hash.new {|h,k| h[k] = k.to_i*10} #=> {} - * h.default #=> nil - * h.default(2) #=> 20 - */ - -static mrb_value -mrb_hash_default(mrb_state *mrb, mrb_value hash) -{ - mrb_value key; - mrb_bool given; - - mrb_get_args(mrb, "|o?", &key, &given); - if (MRB_RHASH_PROCDEFAULT_P(hash)) { - if (!given) return mrb_nil_value(); - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); - } - else { - return RHASH_IFNONE(hash); - } -} - -/* 15.2.13.4.6 */ -/* - * call-seq: - * hsh.default = obj -> obj - * - * Sets the default value, the value returned for a key that does not - * exist in the hash. It is not possible to set the default to a - * Proc that will be executed on each key lookup. - * - * h = { "a" => 100, "b" => 200 } - * h.default = "Go fish" - * h["a"] #=> 100 - * h["z"] #=> "Go fish" - * # This doesn't do what you might hope... - * h.default = proc do |hash, key| - * hash[key] = key + key - * end - * h[2] #=> # - * h["cat"] #=> # - */ - -static mrb_value -mrb_hash_set_default(mrb_state *mrb, mrb_value hash) -{ - mrb_value ifnone; - - mrb_get_args(mrb, "o", &ifnone); - mrb_hash_modify(mrb, hash); - mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); - RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT); - - return ifnone; -} - -/* 15.2.13.4.7 */ -/* - * call-seq: - * hsh.default_proc -> anObject - * - * If Hash::new was invoked with a block, return that - * block, otherwise return nil. - * - * h = Hash.new {|h,k| h[k] = k*k } #=> {} - * p = h.default_proc #=> # - * a = [] #=> [] - * p.call(a, 2) - * a #=> [nil, nil, 4] - */ - - -static mrb_value -mrb_hash_default_proc(mrb_state *mrb, mrb_value hash) -{ - if (MRB_RHASH_PROCDEFAULT_P(hash)) { - return RHASH_PROCDEFAULT(hash); - } - return mrb_nil_value(); -} - -/* - * call-seq: - * hsh.default_proc = proc_obj -> proc_obj - * - * Sets the default proc to be executed on each key lookup. - * - * h.default_proc = proc do |hash, key| - * hash[key] = key + key - * end - * h[2] #=> 4 - * h["cat"] #=> "catcat" - */ - -static mrb_value -mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash) -{ - mrb_value ifnone; - - mrb_get_args(mrb, "o", &ifnone); - mrb_hash_modify(mrb, hash); - mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); - RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; - - return ifnone; -} - -MRB_API mrb_value -mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key) -{ - khash_t(ht) *h = RHASH_TBL(hash); - khiter_t k; - mrb_value delVal; - mrb_int n; - - if (h) { - k = kh_get(ht, mrb, h, key); - if (k != kh_end(h)) { - delVal = kh_value(h, k).v; - n = kh_value(h, k).n; - kh_del(ht, mrb, h, k); - for (k = kh_begin(h); k != kh_end(h); k++) { - if (!kh_exist(h, k)) continue; - if (kh_value(h, k).n > n) kh_value(h, k).n--; - } - return delVal; - } - } - - /* not found */ - return mrb_nil_value(); -} - -/* 15.2.13.4.8 */ -/* - * call-seq: - * hsh.delete(key) -> value - * hsh.delete(key) {| key | block } -> value - * - * Deletes and returns a key-value pair from hsh whose key is - * equal to key. If the key is not found, returns the - * default value. If the optional code block is given and the - * key is not found, pass in the key and return the result of - * block. - * - * h = { "a" => 100, "b" => 200 } - * h.delete("a") #=> 100 - * h.delete("z") #=> nil - * h.delete("z") { |el| "#{el} not found" } #=> "z not found" - * - */ -static mrb_value -mrb_hash_delete(mrb_state *mrb, mrb_value self) -{ - mrb_value key; - - mrb_get_args(mrb, "o", &key); - return mrb_hash_delete_key(mrb, self, key); -} - -/* 15.2.13.4.24 */ -/* - * call-seq: - * hsh.shift -> anArray or obj - * - * Removes a key-value pair from hsh and returns it as the - * two-item array [ key, value ], or - * the hash's default value if the hash is empty. - * - * h = { 1 => "a", 2 => "b", 3 => "c" } - * h.shift #=> [1, "a"] - * h #=> {2=>"b", 3=>"c"} - */ - -static mrb_value -mrb_hash_shift(mrb_state *mrb, mrb_value hash) -{ - khash_t(ht) *h = RHASH_TBL(hash); - khiter_t k; - mrb_value delKey, delVal; - - mrb_hash_modify(mrb, hash); - if (h && kh_size(h) > 0) { - for (k = kh_begin(h); k != kh_end(h); k++) { - if (!kh_exist(h, k)) continue; - - delKey = kh_key(h, k); - mrb_gc_protect(mrb, delKey); - delVal = mrb_hash_delete_key(mrb, hash, delKey); - mrb_gc_protect(mrb, delVal); - - return mrb_assoc_new(mrb, delKey, delVal); - } - } - - if (MRB_RHASH_PROCDEFAULT_P(hash)) { - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, mrb_nil_value()); - } - else { - return RHASH_IFNONE(hash); - } -} - -/* 15.2.13.4.4 */ -/* - * call-seq: - * hsh.clear -> hsh - * - * Removes all key-value pairs from `hsh`. - * - * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200} - * h.clear #=> {} - * - */ - -MRB_API mrb_value -mrb_hash_clear(mrb_state *mrb, mrb_value hash) -{ - khash_t(ht) *h = RHASH_TBL(hash); - - if (h) kh_clear(ht, mrb, h); - return hash; -} - -/* 15.2.13.4.3 */ -/* 15.2.13.4.26 */ -/* - * call-seq: - * hsh[key] = value -> value - * hsh.store(key, value) -> value - * - * Element Assignment---Associates the value given by - * value with the key given by key. - * key should not have its value changed while it is in - * use as a key (a String passed as a key will be - * duplicated and frozen). - * - * h = { "a" => 100, "b" => 200 } - * h["a"] = 9 - * h["c"] = 4 - * h #=> {"a"=>9, "b"=>200, "c"=>4} - * - */ -static mrb_value -mrb_hash_aset(mrb_state *mrb, mrb_value self) -{ - mrb_value key, val; - - mrb_get_args(mrb, "oo", &key, &val); - mrb_hash_set(mrb, self, key, val); - return val; -} - -/* 15.2.13.4.20 */ -/* 15.2.13.4.25 */ -/* - * call-seq: - * hsh.length -> fixnum - * hsh.size -> fixnum - * - * Returns the number of key-value pairs in the hash. - * - * h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 } - * h.length #=> 4 - * h.delete("a") #=> 200 - * h.length #=> 3 - */ -static mrb_value -mrb_hash_size_m(mrb_state *mrb, mrb_value self) -{ - khash_t(ht) *h = RHASH_TBL(self); - - if (!h) return mrb_fixnum_value(0); - return mrb_fixnum_value(kh_size(h)); -} - -/* 15.2.13.4.12 */ -/* - * call-seq: - * hsh.empty? -> true or false - * - * Returns true if hsh contains no key-value pairs. - * - * {}.empty? #=> true - * - */ -MRB_API mrb_value -mrb_hash_empty_p(mrb_state *mrb, mrb_value self) -{ - khash_t(ht) *h = RHASH_TBL(self); - - if (h) return mrb_bool_value(kh_size(h) == 0); - return mrb_true_value(); -} - -/* 15.2.13.4.29 (x)*/ -/* - * call-seq: - * hsh.to_hash => hsh - * - * Returns +self+. - */ - -static mrb_value -mrb_hash_to_hash(mrb_state *mrb, mrb_value hash) -{ - return hash; -} - -/* 15.2.13.4.19 */ -/* - * call-seq: - * hsh.keys -> array - * - * Returns a new array populated with the keys from this hash. See also - * Hash#values. - * - * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 } - * h.keys #=> ["a", "b", "c", "d"] - * - */ - -MRB_API mrb_value -mrb_hash_keys(mrb_state *mrb, mrb_value hash) -{ - khash_t(ht) *h = RHASH_TBL(hash); - khiter_t k; - mrb_value ary; - mrb_value *p; - - if (!h || kh_size(h) == 0) return mrb_ary_new(mrb); - ary = mrb_ary_new_capa(mrb, kh_size(h)); - mrb_ary_set(mrb, ary, kh_size(h)-1, mrb_nil_value()); - p = mrb_ary_ptr(ary)->ptr; - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)) { - mrb_value kv = kh_key(h, k); - mrb_hash_value hv = kh_value(h, k); - - p[hv.n] = kv; - } - } - return ary; -} - -/* 15.2.13.4.28 */ -/* - * call-seq: - * hsh.values -> array - * - * Returns a new array populated with the values from hsh. See - * also Hash#keys. - * - * h = { "a" => 100, "b" => 200, "c" => 300 } - * h.values #=> [100, 200, 300] - * - */ - -static mrb_value -mrb_hash_values(mrb_state *mrb, mrb_value hash) -{ - khash_t(ht) *h = RHASH_TBL(hash); - khiter_t k; - mrb_value ary; - - if (!h) return mrb_ary_new(mrb); - ary = mrb_ary_new_capa(mrb, kh_size(h)); - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)) { - mrb_hash_value hv = kh_value(h, k); - - mrb_ary_set(mrb, ary, hv.n, hv.v); - } - } - return ary; -} - -/* 15.2.13.4.13 */ -/* 15.2.13.4.15 */ -/* 15.2.13.4.18 */ -/* 15.2.13.4.21 */ -/* - * call-seq: - * hsh.has_key?(key) -> true or false - * hsh.include?(key) -> true or false - * hsh.key?(key) -> true or false - * hsh.member?(key) -> true or false - * - * Returns true if the given key is present in hsh. - * - * h = { "a" => 100, "b" => 200 } - * h.has_key?("a") #=> true - * h.has_key?("z") #=> false - * - */ - -static mrb_value -mrb_hash_has_key(mrb_state *mrb, mrb_value hash) -{ - mrb_value key; - khash_t(ht) *h; - khiter_t k; - - mrb_get_args(mrb, "o", &key); - - h = RHASH_TBL(hash); - if (h) { - k = kh_get(ht, mrb, h, key); - return mrb_bool_value(k != kh_end(h)); - } - return mrb_false_value(); -} - -/* 15.2.13.4.14 */ -/* 15.2.13.4.27 */ -/* - * call-seq: - * hsh.has_value?(value) -> true or false - * hsh.value?(value) -> true or false - * - * Returns true if the given value is present for some key - * in hsh. - * - * h = { "a" => 100, "b" => 200 } - * h.has_value?(100) #=> true - * h.has_value?(999) #=> false - */ - -static mrb_value -mrb_hash_has_value(mrb_state *mrb, mrb_value hash) -{ - mrb_value val; - khash_t(ht) *h; - khiter_t k; - - mrb_get_args(mrb, "o", &val); - h = RHASH_TBL(hash); - - if (h) { - for (k = kh_begin(h); k != kh_end(h); k++) { - if (!kh_exist(h, k)) continue; - - if (mrb_equal(mrb, kh_value(h, k).v, val)) { - return mrb_true_value(); - } - } - } - return mrb_false_value(); -} - -void -mrb_init_hash(mrb_state *mrb) -{ - struct RClass *h; - - mrb->hash_class = h = mrb_define_class(mrb, "Hash", mrb->object_class); /* 15.2.13 */ - MRB_SET_INSTANCE_TT(h, MRB_TT_HASH); - - mrb_define_method(mrb, h, "[]", mrb_hash_aget, MRB_ARGS_REQ(1)); /* 15.2.13.4.2 */ - mrb_define_method(mrb, h, "[]=", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.3 */ - mrb_define_method(mrb, h, "clear", mrb_hash_clear, MRB_ARGS_NONE()); /* 15.2.13.4.4 */ - mrb_define_method(mrb, h, "default", mrb_hash_default, MRB_ARGS_ANY()); /* 15.2.13.4.5 */ - mrb_define_method(mrb, h, "default=", mrb_hash_set_default, MRB_ARGS_REQ(1)); /* 15.2.13.4.6 */ - mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,MRB_ARGS_NONE()); /* 15.2.13.4.7 */ - mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,MRB_ARGS_REQ(1)); /* 15.2.13.4.7 */ - mrb_define_method(mrb, h, "__delete", mrb_hash_delete, MRB_ARGS_REQ(1)); /* core of 15.2.13.4.8 */ - mrb_define_method(mrb, h, "empty?", mrb_hash_empty_p, MRB_ARGS_NONE()); /* 15.2.13.4.12 */ - mrb_define_method(mrb, h, "has_key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.13 */ - mrb_define_method(mrb, h, "has_value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.14 */ - mrb_define_method(mrb, h, "include?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.15 */ - mrb_define_method(mrb, h, "initialize", mrb_hash_init, MRB_ARGS_OPT(1)); /* 15.2.13.4.16 */ - mrb_define_method(mrb, h, "key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.18 */ - mrb_define_method(mrb, h, "keys", mrb_hash_keys, MRB_ARGS_NONE()); /* 15.2.13.4.19 */ - mrb_define_method(mrb, h, "length", mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.20 */ - mrb_define_method(mrb, h, "member?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.21 */ - mrb_define_method(mrb, h, "shift", mrb_hash_shift, MRB_ARGS_NONE()); /* 15.2.13.4.24 */ - mrb_define_method(mrb, h, "dup", mrb_hash_dup, MRB_ARGS_NONE()); - mrb_define_method(mrb, h, "size", mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.25 */ - mrb_define_method(mrb, h, "store", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.26 */ - mrb_define_method(mrb, h, "value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.27 */ - mrb_define_method(mrb, h, "values", mrb_hash_values, MRB_ARGS_NONE()); /* 15.2.13.4.28 */ - - mrb_define_method(mrb, h, "to_hash", mrb_hash_to_hash, MRB_ARGS_NONE()); /* 15.2.13.4.29 (x)*/ -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/init.c nghttp2-0.6.7/third-party/mruby/src/init.c --- nghttp2-1.13.0/third-party/mruby/src/init.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/init.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* -** init.c - initialize mruby core -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" - -void mrb_init_symtbl(mrb_state*); -void mrb_init_class(mrb_state*); -void mrb_init_object(mrb_state*); -void mrb_init_kernel(mrb_state*); -void mrb_init_comparable(mrb_state*); -void mrb_init_enumerable(mrb_state*); -void mrb_init_symbol(mrb_state*); -void mrb_init_exception(mrb_state*); -void mrb_init_proc(mrb_state*); -void mrb_init_string(mrb_state*); -void mrb_init_array(mrb_state*); -void mrb_init_hash(mrb_state*); -void mrb_init_numeric(mrb_state*); -void mrb_init_range(mrb_state*); -void mrb_init_gc(mrb_state*); -void mrb_init_math(mrb_state*); -void mrb_init_version(mrb_state*); -void mrb_init_mrblib(mrb_state*); - -#define DONE mrb_gc_arena_restore(mrb, 0); -void -mrb_init_core(mrb_state *mrb) -{ - mrb_init_symtbl(mrb); DONE; - - mrb_init_class(mrb); DONE; - mrb_init_object(mrb); DONE; - mrb_init_kernel(mrb); DONE; - mrb_init_comparable(mrb); DONE; - mrb_init_enumerable(mrb); DONE; - - mrb_init_symbol(mrb); DONE; - mrb_init_exception(mrb); DONE; - mrb_init_proc(mrb); DONE; - mrb_init_string(mrb); DONE; - mrb_init_array(mrb); DONE; - mrb_init_hash(mrb); DONE; - mrb_init_numeric(mrb); DONE; - mrb_init_range(mrb); DONE; - mrb_init_gc(mrb); DONE; - mrb_init_version(mrb); DONE; - mrb_init_mrblib(mrb); DONE; -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/kernel.c nghttp2-0.6.7/third-party/mruby/src/kernel.c --- nghttp2-1.13.0/third-party/mruby/src/kernel.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/kernel.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1153 +0,0 @@ -/* -** kernel.c - Kernel module -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/proc.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/error.h" - -typedef enum { - NOEX_PUBLIC = 0x00, - NOEX_NOSUPER = 0x01, - NOEX_PRIVATE = 0x02, - NOEX_PROTECTED = 0x04, - NOEX_MASK = 0x06, - NOEX_BASIC = 0x08, - NOEX_UNDEF = NOEX_NOSUPER, - NOEX_MODFUNC = 0x12, - NOEX_SUPER = 0x20, - NOEX_VCALL = 0x40, - NOEX_RESPONDS = 0x80 -} mrb_method_flag_t; - -static mrb_bool -mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) -{ - struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern_lit(mrb, "to_s")); - if (MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) - return TRUE; - return FALSE; -} - -/* 15.3.1.3.17 */ -/* - * call-seq: - * obj.inspect -> string - * - * Returns a string containing a human-readable representation of - * obj. If not overridden and no instance variables, uses the - * to_s method to generate the string. - * obj. If not overridden, uses the to_s method to - * generate the string. - * - * [ 1, 2, 3..4, 'five' ].inspect #=> "[1, 2, 3..4, \"five\"]" - * Time.new.inspect #=> "2008-03-08 19:43:39 +0900" - */ -MRB_API mrb_value -mrb_obj_inspect(mrb_state *mrb, mrb_value obj) -{ - if ((mrb_type(obj) == MRB_TT_OBJECT) && mrb_obj_basic_to_s_p(mrb, obj)) { - return mrb_obj_iv_inspect(mrb, mrb_obj_ptr(obj)); - } - return mrb_any_to_s(mrb, obj); -} - -/* 15.3.1.3.1 */ -/* 15.3.1.3.10 */ -/* 15.3.1.3.11 */ -/* - * call-seq: - * obj == other -> true or false - * obj.equal?(other) -> true or false - * obj.eql?(other) -> true or false - * - * Equality---At the Object level, == returns - * true only if obj and other are the - * same object. Typically, this method is overridden in descendant - * classes to provide class-specific meaning. - * - * Unlike ==, the equal? method should never be - * overridden by subclasses: it is used to determine object identity - * (that is, a.equal?(b) iff a is the same - * object as b). - * - * The eql? method returns true if - * obj and anObject have the same value. Used by - * Hash to test members for equality. For objects of - * class Object, eql? is synonymous with - * ==. Subclasses normally continue this tradition, but - * there are exceptions. Numeric types, for example, - * perform type conversion across ==, but not across - * eql?, so: - * - * 1 == 1.0 #=> true - * 1.eql? 1.0 #=> false - */ -static mrb_value -mrb_obj_equal_m(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "o", &arg); - return mrb_bool_value(mrb_obj_equal(mrb, self, arg)); -} - -static mrb_value -mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "o", &arg); - return mrb_bool_value(!mrb_equal(mrb, self, arg)); -} - -/* 15.3.1.3.2 */ -/* - * call-seq: - * obj === other -> true or false - * - * Case Equality---For class Object, effectively the same - * as calling #==, but typically overridden by descendants - * to provide meaningful semantics in case statements. - */ -static mrb_value -mrb_equal_m(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "o", &arg); - return mrb_bool_value(mrb_equal(mrb, self, arg)); -} - -/* 15.3.1.3.3 */ -/* 15.3.1.3.33 */ -/* - * Document-method: __id__ - * Document-method: object_id - * - * call-seq: - * obj.__id__ -> fixnum - * obj.object_id -> fixnum - * - * Returns an integer identifier for obj. The same number will - * be returned on all calls to id for a given object, and - * no two active objects will share an id. - * Object#object_id is a different concept from the - * :name notation, which returns the symbol id of - * name. Replaces the deprecated Object#id. - */ -static mrb_value -mrb_obj_id_m(mrb_state *mrb, mrb_value self) -{ - return mrb_fixnum_value(mrb_obj_id(self)); -} - -/* 15.3.1.2.2 */ -/* 15.3.1.2.5 */ -/* 15.3.1.3.6 */ -/* 15.3.1.3.25 */ -/* - * call-seq: - * block_given? -> true or false - * iterator? -> true or false - * - * Returns true if yield would execute a - * block in the current context. The iterator? form - * is mildly deprecated. - * - * def try - * if block_given? - * yield - * else - * "no block" - * end - * end - * try #=> "no block" - * try { "hello" } #=> "hello" - * try do "hello" end #=> "hello" - */ -static mrb_value -mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) -{ - mrb_callinfo *ci = mrb->c->ci; - mrb_value *bp; - mrb_bool given_p; - - bp = ci->stackent + 1; - ci--; - if (ci <= mrb->c->cibase) { - given_p = FALSE; - } - else { - /* block_given? called within block; check upper scope */ - if (ci->proc->env) { - struct REnv *e = ci->proc->env; - mrb_value *sp; - - while (e->c) { - e = (struct REnv*)e->c; - } - sp = e->stack; - if (sp) { - /* top-level does not have block slot (alway false) */ - if (sp == mrb->c->stbase) - return mrb_false_value(); - ci = mrb->c->cibase + e->cioff; - bp = ci[1].stackent + 1; - } - } - if (ci->argc > 0) { - bp += ci->argc; - } - given_p = !mrb_nil_p(*bp); - } - - return mrb_bool_value(given_p); -} - -/* 15.3.1.3.7 */ -/* - * call-seq: - * obj.class -> class - * - * Returns the class of obj. This method must always be - * called with an explicit receiver, as class is also a - * reserved word in Ruby. - * - * 1.class #=> Fixnum - * self.class #=> Object - */ -static mrb_value -mrb_obj_class_m(mrb_state *mrb, mrb_value self) -{ - return mrb_obj_value(mrb_obj_class(mrb, self)); -} - -static struct RClass* -mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) -{ - struct RClass *klass = mrb_basic_ptr(obj)->c; - - if (klass->tt != MRB_TT_SCLASS) - return klass; - else { - /* copy singleton(unnamed) class */ - struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class); - - if ((mrb_type(obj) == MRB_TT_CLASS) || (mrb_type(obj) == MRB_TT_SCLASS)) { - clone->c = clone; - } - else { - clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass)); - } - clone->super = klass->super; - if (klass->iv) { - mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass)); - mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern_lit(mrb, "__attached__"), obj); - } - if (klass->mt) { - clone->mt = kh_copy(mt, mrb, klass->mt); - } - else { - clone->mt = kh_init(mt, mrb); - } - clone->tt = MRB_TT_SCLASS; - return clone; - } -} - -static void -copy_class(mrb_state *mrb, mrb_value dst, mrb_value src) -{ - struct RClass *dc = mrb_class_ptr(dst); - struct RClass *sc = mrb_class_ptr(src); - /* if the origin is not the same as the class, then the origin and - the current class need to be copied */ - if (sc->flags & MRB_FLAG_IS_PREPENDED) { - struct RClass *c0 = sc->super; - struct RClass *c1 = dc; - - /* copy prepended iclasses */ - while (!(c0->flags & MRB_FLAG_IS_ORIGIN)) { - c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0))); - c1 = c1->super; - c0 = c0->super; - } - c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0))); - c1->super->flags |= MRB_FLAG_IS_ORIGIN; - } - dc->mt = kh_copy(mt, mrb, sc->mt); - dc->super = sc->super; -} - -static void -init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) -{ - switch (mrb_type(obj)) { - case MRB_TT_CLASS: - case MRB_TT_MODULE: - copy_class(mrb, dest, obj); - /* fall through */ - case MRB_TT_OBJECT: - case MRB_TT_SCLASS: - case MRB_TT_HASH: - case MRB_TT_DATA: - case MRB_TT_EXCEPTION: - mrb_iv_copy(mrb, dest, obj); - break; - - default: - break; - } - mrb_funcall(mrb, dest, "initialize_copy", 1, obj); -} - -/* 15.3.1.3.8 */ -/* - * call-seq: - * obj.clone -> an_object - * - * Produces a shallow copy of obj---the instance variables of - * obj are copied, but not the objects they reference. Copies - * the frozen state of obj. See also the discussion - * under Object#dup. - * - * class Klass - * attr_accessor :str - * end - * s1 = Klass.new #=> # - * s1.str = "Hello" #=> "Hello" - * s2 = s1.clone #=> # - * s2.str[1,4] = "i" #=> "i" - * s1.inspect #=> "#" - * s2.inspect #=> "#" - * - * This method may have class-specific behavior. If so, that - * behavior will be documented under the #+initialize_copy+ method of - * the class. - * - * Some Class(True False Nil Symbol Fixnum Float) Object cannot clone. - */ -MRB_API mrb_value -mrb_obj_clone(mrb_state *mrb, mrb_value self) -{ - struct RObject *p; - mrb_value clone; - - if (mrb_immediate_p(self)) { - mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self); - } - if (mrb_type(self) == MRB_TT_SCLASS) { - mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class"); - } - p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self)); - p->c = mrb_singleton_class_clone(mrb, self); - clone = mrb_obj_value(p); - init_copy(mrb, clone, self); - - return clone; -} - -/* 15.3.1.3.9 */ -/* - * call-seq: - * obj.dup -> an_object - * - * Produces a shallow copy of obj---the instance variables of - * obj are copied, but not the objects they reference. - * dup copies the frozen state of obj. See also - * the discussion under Object#clone. In general, - * clone and dup may have different semantics - * in descendant classes. While clone is used to duplicate - * an object, including its internal state, dup typically - * uses the class of the descendant object to create the new instance. - * - * This method may have class-specific behavior. If so, that - * behavior will be documented under the #+initialize_copy+ method of - * the class. - */ - -MRB_API mrb_value -mrb_obj_dup(mrb_state *mrb, mrb_value obj) -{ - struct RBasic *p; - mrb_value dup; - - if (mrb_immediate_p(obj)) { - mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %S", obj); - } - if (mrb_type(obj) == MRB_TT_SCLASS) { - mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class"); - } - p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj)); - dup = mrb_obj_value(p); - init_copy(mrb, dup, obj); - - return dup; -} - -static mrb_value -mrb_obj_extend(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb_value obj) -{ - mrb_int i; - - if (argc == 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (at least 1)"); - } - for (i = 0; i < argc; i++) { - mrb_check_type(mrb, argv[i], MRB_TT_MODULE); - } - while (argc--) { - mrb_funcall(mrb, argv[argc], "extend_object", 1, obj); - mrb_funcall(mrb, argv[argc], "extended", 1, obj); - } - return obj; -} - -/* 15.3.1.3.13 */ -/* - * call-seq: - * obj.extend(module, ...) -> obj - * - * Adds to _obj_ the instance methods from each module given as a - * parameter. - * - * module Mod - * def hello - * "Hello from Mod.\n" - * end - * end - * - * class Klass - * def hello - * "Hello from Klass.\n" - * end - * end - * - * k = Klass.new - * k.hello #=> "Hello from Klass.\n" - * k.extend(Mod) #=> # - * k.hello #=> "Hello from Mod.\n" - */ -static mrb_value -mrb_obj_extend_m(mrb_state *mrb, mrb_value self) -{ - mrb_value *argv; - mrb_int argc; - - mrb_get_args(mrb, "*", &argv, &argc); - return mrb_obj_extend(mrb, argc, argv, self); -} - -/* 15.3.1.3.15 */ -/* - * call-seq: - * obj.hash -> fixnum - * - * Generates a Fixnum hash value for this object. This - * function must have the property that a.eql?(b) implies - * a.hash == b.hash. The hash value is used by class - * Hash. Any hash value that exceeds the capacity of a - * Fixnum will be truncated before being used. - */ -MRB_API mrb_value -mrb_obj_hash(mrb_state *mrb, mrb_value self) -{ - return mrb_fixnum_value(mrb_obj_id(self)); -} - -/* 15.3.1.3.16 */ -static mrb_value -mrb_obj_init_copy(mrb_state *mrb, mrb_value self) -{ - mrb_value orig; - - mrb_get_args(mrb, "o", &orig); - if (mrb_obj_equal(mrb, self, orig)) return self; - if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) { - mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object"); - } - return self; -} - - -/* implementation of instance_eval */ -mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value); - -MRB_API mrb_bool -mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c) -{ - if (mrb_obj_class(mrb, obj) == c) return TRUE; - return FALSE; -} - -/* 15.3.1.3.19 */ -/* - * call-seq: - * obj.instance_of?(class) -> true or false - * - * Returns true if obj is an instance of the given - * class. See also Object#kind_of?. - */ -static mrb_value -obj_is_instance_of(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "C", &arg); - - return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg))); -} - -/* 15.3.1.3.20 */ -/* - * call-seq: - * obj.instance_variable_defined?(symbol) -> true or false - * - * Returns true if the given instance variable is - * defined in obj. - * - * class Fred - * def initialize(p1, p2) - * @a, @b = p1, p2 - * end - * end - * fred = Fred.new('cat', 99) - * fred.instance_variable_defined?(:@a) #=> true - * fred.instance_variable_defined?("@b") #=> true - * fred.instance_variable_defined?("@c") #=> false - */ -static mrb_value -mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self) -{ - mrb_sym sym; - - mrb_get_args(mrb, "n", &sym); - mrb_iv_check(mrb, sym); - return mrb_bool_value(mrb_iv_defined(mrb, self, sym)); -} - -/* 15.3.1.3.21 */ -/* - * call-seq: - * obj.instance_variable_get(symbol) -> obj - * - * Returns the value of the given instance variable, or nil if the - * instance variable is not set. The @ part of the - * variable name should be included for regular instance - * variables. Throws a NameError exception if the - * supplied symbol is not valid as an instance variable name. - * - * class Fred - * def initialize(p1, p2) - * @a, @b = p1, p2 - * end - * end - * fred = Fred.new('cat', 99) - * fred.instance_variable_get(:@a) #=> "cat" - * fred.instance_variable_get("@b") #=> 99 - */ -static mrb_value -mrb_obj_ivar_get(mrb_state *mrb, mrb_value self) -{ - mrb_sym iv_name; - - mrb_get_args(mrb, "n", &iv_name); - mrb_iv_check(mrb, iv_name); - return mrb_iv_get(mrb, self, iv_name); -} - -/* 15.3.1.3.22 */ -/* - * call-seq: - * obj.instance_variable_set(symbol, obj) -> obj - * - * Sets the instance variable names by symbol to - * object, thereby frustrating the efforts of the class's - * author to attempt to provide proper encapsulation. The variable - * did not have to exist prior to this call. - * - * class Fred - * def initialize(p1, p2) - * @a, @b = p1, p2 - * end - * end - * fred = Fred.new('cat', 99) - * fred.instance_variable_set(:@a, 'dog') #=> "dog" - * fred.instance_variable_set(:@c, 'cat') #=> "cat" - * fred.inspect #=> "#" - */ -static mrb_value -mrb_obj_ivar_set(mrb_state *mrb, mrb_value self) -{ - mrb_sym iv_name; - mrb_value val; - - mrb_get_args(mrb, "no", &iv_name, &val); - mrb_iv_check(mrb, iv_name); - mrb_iv_set(mrb, self, iv_name, val); - return val; -} - -/* 15.3.1.3.24 */ -/* 15.3.1.3.26 */ -/* - * call-seq: - * obj.is_a?(class) -> true or false - * obj.kind_of?(class) -> true or false - * - * Returns true if class is the class of - * obj, or if class is one of the superclasses of - * obj or modules included in obj. - * - * module M; end - * class A - * include M - * end - * class B < A; end - * class C < B; end - * b = B.new - * b.instance_of? A #=> false - * b.instance_of? B #=> true - * b.instance_of? C #=> false - * b.instance_of? M #=> false - * b.kind_of? A #=> true - * b.kind_of? B #=> true - * b.kind_of? C #=> false - * b.kind_of? M #=> true - */ -static mrb_value -mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "C", &arg); - - return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg))); -} - -KHASH_DECLARE(st, mrb_sym, char, FALSE) -KHASH_DEFINE(st, mrb_sym, char, FALSE, kh_int_hash_func, kh_int_hash_equal) - -static void -method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set) -{ - khint_t i; - - khash_t(mt) *h = klass->mt; - if (!h) return; - for (i=0;iflags & MRB_FLAG_IS_PREPENDED)) { - MRB_CLASS_ORIGIN(klass); - prepended = TRUE; - } - - oldklass = 0; - while (klass && (klass != oldklass)) { - method_entry_loop(mrb, klass, set); - if ((klass->tt == MRB_TT_ICLASS && !prepended) || - (klass->tt == MRB_TT_SCLASS)) { - } - else { - if (!recur) break; - } - oldklass = klass; - klass = klass->super; - } - - ary = mrb_ary_new(mrb); - for (i=0;itt == MRB_TT_SCLASS)) { - method_entry_loop(mrb, klass, set); - klass = klass->super; - } - if (recur) { - while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) { - method_entry_loop(mrb, klass, set); - klass = klass->super; - } - } - - ary = mrb_ary_new(mrb); - for (i=0;i array - * - * Returns a list of the names of methods publicly accessible in - * obj. This will include all the methods accessible in - * obj's ancestors. - * - * class Klass - * def kMethod() - * end - * end - * k = Klass.new - * k.methods[0..9] #=> [:kMethod, :respond_to?, :nil?, :is_a?, - * # :class, :instance_variable_set, - * # :methods, :extend, :__send__, :instance_eval] - * k.methods.length #=> 42 - */ -static mrb_value -mrb_obj_methods_m(mrb_state *mrb, mrb_value self) -{ - mrb_bool recur = TRUE; - mrb_get_args(mrb, "|b", &recur); - return mrb_obj_methods(mrb, recur, self, (mrb_method_flag_t)0); /* everything but private */ -} - -/* 15.3.1.3.32 */ -/* - * call_seq: - * nil.nil? -> true - * .nil? -> false - * - * Only the object nil responds true to nil?. - */ -static mrb_value -mrb_false(mrb_state *mrb, mrb_value self) -{ - return mrb_false_value(); -} - -/* 15.3.1.3.36 */ -/* - * call-seq: - * obj.private_methods(all=true) -> array - * - * Returns the list of private methods accessible to obj. If - * the all parameter is set to false, only those methods - * in the receiver will be listed. - */ -static mrb_value -mrb_obj_private_methods(mrb_state *mrb, mrb_value self) -{ - mrb_bool recur = TRUE; - mrb_get_args(mrb, "|b", &recur); - return mrb_obj_methods(mrb, recur, self, NOEX_PRIVATE); /* private attribute not define */ -} - -/* 15.3.1.3.37 */ -/* - * call-seq: - * obj.protected_methods(all=true) -> array - * - * Returns the list of protected methods accessible to obj. If - * the all parameter is set to false, only those methods - * in the receiver will be listed. - */ -static mrb_value -mrb_obj_protected_methods(mrb_state *mrb, mrb_value self) -{ - mrb_bool recur = TRUE; - mrb_get_args(mrb, "|b", &recur); - return mrb_obj_methods(mrb, recur, self, NOEX_PROTECTED); /* protected attribute not define */ -} - -/* 15.3.1.3.38 */ -/* - * call-seq: - * obj.public_methods(all=true) -> array - * - * Returns the list of public methods accessible to obj. If - * the all parameter is set to false, only those methods - * in the receiver will be listed. - */ -static mrb_value -mrb_obj_public_methods(mrb_state *mrb, mrb_value self) -{ - mrb_bool recur = TRUE; - mrb_get_args(mrb, "|b", &recur); - return mrb_obj_methods(mrb, recur, self, NOEX_PUBLIC); /* public attribute not define */ -} - -/* 15.3.1.2.12 */ -/* 15.3.1.3.40 */ -/* - * call-seq: - * raise - * raise(string) - * raise(exception [, string]) - * - * With no arguments, raises a RuntimeError - * With a single +String+ argument, raises a - * +RuntimeError+ with the string as a message. Otherwise, - * the first parameter should be the name of an +Exception+ - * class (or an object that returns an +Exception+ object when sent - * an +exception+ message). The optional second parameter sets the - * message associated with the exception, and the third parameter is an - * array of callback information. Exceptions are caught by the - * +rescue+ clause of begin...end blocks. - * - * raise "Failed to create socket" - * raise ArgumentError, "No parameters", caller - */ -MRB_API mrb_value -mrb_f_raise(mrb_state *mrb, mrb_value self) -{ - mrb_value a[2], exc; - int argc; - - - argc = mrb_get_args(mrb, "|oo", &a[0], &a[1]); - switch (argc) { - case 0: - mrb_raise(mrb, E_RUNTIME_ERROR, ""); - break; - case 1: - a[1] = mrb_check_string_type(mrb, a[0]); - if (!mrb_nil_p(a[1])) { - argc = 2; - a[0] = mrb_obj_value(E_RUNTIME_ERROR); - } - /* fall through */ - default: - exc = mrb_make_exception(mrb, argc, a); - mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, mrb->c->ci->pc)); - mrb_exc_raise(mrb, exc); - break; - } - return mrb_nil_value(); /* not reached */ -} - -/* 15.3.1.3.41 */ -/* - * call-seq: - * obj.remove_instance_variable(symbol) -> obj - * - * Removes the named instance variable from obj, returning that - * variable's value. - * - * class Dummy - * attr_reader :var - * def initialize - * @var = 99 - * end - * def remove - * remove_instance_variable(:@var) - * end - * end - * d = Dummy.new - * d.var #=> 99 - * d.remove #=> 99 - * d.var #=> nil - */ -static mrb_value -mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self) -{ - mrb_sym sym; - mrb_value val; - - mrb_get_args(mrb, "n", &sym); - mrb_iv_check(mrb, sym); - val = mrb_iv_remove(mrb, self, sym); - if (mrb_undef_p(val)) { - mrb_name_error(mrb, sym, "instance variable %S not defined", mrb_sym2str(mrb, sym)); - } - return val; -} - -static inline mrb_bool -basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub) -{ - return mrb_respond_to(mrb, obj, id); -} -/* 15.3.1.3.43 */ -/* - * call-seq: - * obj.respond_to?(symbol, include_private=false) -> true or false - * - * Returns +true+ if _obj_ responds to the given - * method. Private methods are included in the search only if the - * optional second parameter evaluates to +true+. - * - * If the method is not implemented, - * as Process.fork on Windows, File.lchmod on GNU/Linux, etc., - * false is returned. - * - * If the method is not defined, respond_to_missing? - * method is called and the result is returned. - */ -static mrb_value -obj_respond_to(mrb_state *mrb, mrb_value self) -{ - mrb_value mid; - mrb_sym id, rtm_id; - mrb_bool priv = FALSE, respond_to_p = TRUE; - - mrb_get_args(mrb, "o|b", &mid, &priv); - - if (mrb_symbol_p(mid)) { - id = mrb_symbol(mid); - } - else { - mrb_value tmp; - if (!mrb_string_p(mid)) { - tmp = mrb_check_string_type(mrb, mid); - if (mrb_nil_p(tmp)) { - tmp = mrb_inspect(mrb, mid); - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp); - } - } - tmp = mrb_check_intern_str(mrb, mid); - if (mrb_nil_p(tmp)) { - respond_to_p = FALSE; - } - else { - id = mrb_symbol(tmp); - } - } - - if (respond_to_p) { - respond_to_p = basic_obj_respond_to(mrb, self, id, !priv); - } - - if (!respond_to_p) { - rtm_id = mrb_intern_lit(mrb, "respond_to_missing?"); - if (basic_obj_respond_to(mrb, self, rtm_id, !priv)) { - mrb_value args[2]; - args[0] = mid; - args[1] = mrb_bool_value(priv); - return mrb_funcall_argv(mrb, self, rtm_id, 2, args); - } - } - return mrb_bool_value(respond_to_p); -} - -/* 15.3.1.3.45 */ -/* - * call-seq: - * obj.singleton_methods(all=true) -> array - * - * Returns an array of the names of singleton methods for obj. - * If the optional all parameter is true, the list will include - * methods in modules included in obj. - * Only public and protected singleton methods are returned. - * - * module Other - * def three() end - * end - * - * class Single - * def Single.four() end - * end - * - * a = Single.new - * - * def a.one() - * end - * - * class << a - * include Other - * def two() - * end - * end - * - * Single.singleton_methods #=> [:four] - * a.singleton_methods(false) #=> [:two, :one] - * a.singleton_methods #=> [:two, :one, :three] - */ -static mrb_value -mrb_obj_singleton_methods_m(mrb_state *mrb, mrb_value self) -{ - mrb_bool recur = TRUE; - mrb_get_args(mrb, "|b", &recur); - return mrb_obj_singleton_methods(mrb, recur, self); -} - -static mrb_value -mod_define_singleton_method(mrb_state *mrb, mrb_value self) -{ - struct RProc *p; - mrb_sym mid; - mrb_value blk = mrb_nil_value(); - - mrb_get_args(mrb, "n&", &mid, &blk); - if (mrb_nil_p(blk)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); - } - p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); - mrb_proc_copy(p, mrb_proc_ptr(blk)); - p->flags |= MRB_PROC_STRICT; - mrb_define_method_raw(mrb, mrb_class_ptr(mrb_singleton_class(mrb, self)), mid, p); - return mrb_symbol_value(mid); -} - -static mrb_value -mrb_obj_ceqq(mrb_state *mrb, mrb_value self) -{ - mrb_value v; - mrb_int i, len; - mrb_sym eqq = mrb_intern_lit(mrb, "==="); - mrb_value ary = mrb_ary_splat(mrb, self); - - mrb_get_args(mrb, "o", &v); - len = RARRAY_LEN(ary); - for (i=0; ic->ci[-1].proc; - - if (MRB_PROC_CFUNC_P(proc)) { - return mrb_ary_new(mrb); - } - - irep = proc->body.irep; - if (!irep->lv) { - return mrb_ary_new(mrb); - } - ret = mrb_ary_new_capa(mrb, irep->nlocals - 1); - for (i = 0; i + 1 < irep->nlocals; ++i) { - if (irep->lv[i].name) { - mrb_ary_push(mrb, ret, mrb_symbol_value(irep->lv[i].name)); - } - } - if (proc->env) { - struct REnv *e = proc->env; - - while (e) { - if (!MRB_PROC_CFUNC_P(mrb->c->cibase[e->cioff].proc)) { - irep = mrb->c->cibase[e->cioff].proc->body.irep; - if (irep->lv) { - for (i = 0; i + 1 < irep->nlocals; ++i) { - if (irep->lv[i].name) { - mrb_ary_push(mrb, ret, mrb_symbol_value(irep->lv[i].name)); - } - } - } - } - e = (struct REnv*)e->c; - } - } - - return ret; -} - -void -mrb_init_kernel(mrb_state *mrb) -{ - struct RClass *krn; - - mrb->kernel_module = krn = mrb_define_module(mrb, "Kernel"); /* 15.3.1 */ - mrb_define_class_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.2 */ - mrb_define_class_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.2.4 */ - mrb_define_class_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.5 */ - mrb_define_class_method(mrb, krn, "local_variables", mrb_local_variables, MRB_ARGS_NONE()); /* 15.3.1.2.7 */ -; /* 15.3.1.2.11 */ - mrb_define_class_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_OPT(2)); /* 15.3.1.2.12 */ - - mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, MRB_ARGS_NONE()); - - mrb_define_method(mrb, krn, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ - mrb_define_method(mrb, krn, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */ - mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */ - mrb_define_method(mrb, krn, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ - mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */ - mrb_define_method(mrb, krn, "class", mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */ - mrb_define_method(mrb, krn, "clone", mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */ - mrb_define_method(mrb, krn, "dup", mrb_obj_dup, MRB_ARGS_NONE()); /* 15.3.1.3.9 */ - mrb_define_method(mrb, krn, "eql?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.10 */ - mrb_define_method(mrb, krn, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */ - mrb_define_method(mrb, krn, "extend", mrb_obj_extend_m, MRB_ARGS_ANY()); /* 15.3.1.3.13 */ - mrb_define_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.3.14 */ - mrb_define_method(mrb, krn, "hash", mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */ - mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */ - mrb_define_method(mrb, krn, "inspect", mrb_obj_inspect, MRB_ARGS_NONE()); /* 15.3.1.3.17 */ - mrb_define_method(mrb, krn, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */ - mrb_define_method(mrb, krn, "instance_of?", obj_is_instance_of, MRB_ARGS_REQ(1)); /* 15.3.1.3.19 */ - mrb_define_method(mrb, krn, "instance_variable_defined?", mrb_obj_ivar_defined, MRB_ARGS_REQ(1)); /* 15.3.1.3.20 */ - mrb_define_method(mrb, krn, "instance_variable_get", mrb_obj_ivar_get, MRB_ARGS_REQ(1)); /* 15.3.1.3.21 */ - mrb_define_method(mrb, krn, "instance_variable_set", mrb_obj_ivar_set, MRB_ARGS_REQ(2)); /* 15.3.1.3.22 */ - mrb_define_method(mrb, krn, "instance_variables", mrb_obj_instance_variables, MRB_ARGS_NONE()); /* 15.3.1.3.23 */ - mrb_define_method(mrb, krn, "is_a?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.24 */ - mrb_define_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.25 */ - mrb_define_method(mrb, krn, "kind_of?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.26 */ - mrb_define_method(mrb, krn, "local_variables", mrb_local_variables, MRB_ARGS_NONE()); /* 15.3.1.3.28 */ - mrb_define_method(mrb, krn, "methods", mrb_obj_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.31 */ - mrb_define_method(mrb, krn, "nil?", mrb_false, MRB_ARGS_NONE()); /* 15.3.1.3.32 */ - mrb_define_method(mrb, krn, "object_id", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.33 */ - mrb_define_method(mrb, krn, "private_methods", mrb_obj_private_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.36 */ - mrb_define_method(mrb, krn, "protected_methods", mrb_obj_protected_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.37 */ - mrb_define_method(mrb, krn, "public_methods", mrb_obj_public_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.38 */ - mrb_define_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_ANY()); /* 15.3.1.3.40 */ - mrb_define_method(mrb, krn, "remove_instance_variable", mrb_obj_remove_instance_variable,MRB_ARGS_REQ(1)); /* 15.3.1.3.41 */ - mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ANY()); /* 15.3.1.3.43 */ - mrb_define_method(mrb, krn, "send", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.44 */ - mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.45 */ - mrb_define_method(mrb, krn, "define_singleton_method", mod_define_singleton_method, MRB_ARGS_ANY()); - mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */ - mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */ - - mrb_include_module(mrb, mrb->object_class, mrb->kernel_module); - mrb_alias_method(mrb, mrb->module_class, mrb_intern_lit(mrb, "dup"), mrb_intern_lit(mrb, "clone")); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/load.c nghttp2-0.6.7/third-party/mruby/src/load.c --- nghttp2-1.13.0/third-party/mruby/src/load.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/load.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,707 +0,0 @@ -/* -** load.c - mruby binary loader -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include -#include "mruby/dump.h" -#include "mruby/irep.h" -#include "mruby/proc.h" -#include "mruby/string.h" -#include "mruby/debug.h" -#include "mruby/error.h" - -#if SIZE_MAX < UINT32_MAX -# error size_t must be at least 32 bits wide -#endif - -#define FLAG_BYTEORDER_BIG 2 -#define FLAG_BYTEORDER_LIL 4 -#define FLAG_BYTEORDER_NATIVE 8 -#define FLAG_SRC_MALLOC 1 -#define FLAG_SRC_STATIC 0 - -#define SIZE_ERROR_MUL(nmemb, size) ((nmemb) > SIZE_MAX / (size)) - -static size_t -skip_padding(const uint8_t *buf) -{ - const size_t align = MRB_DUMP_ALIGNMENT; - return -(intptr_t)buf & (align-1); -} - -static size_t -offset_crc_body(void) -{ - struct rite_binary_header header; - return ((uint8_t *)header.binary_crc - (uint8_t *)&header) + sizeof(header.binary_crc); -} - -static mrb_irep* -read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags) -{ - size_t i; - const uint8_t *src = bin; - ptrdiff_t diff; - uint16_t tt, pool_data_len, snl; - size_t plen; - int ai = mrb_gc_arena_save(mrb); - mrb_irep *irep = mrb_add_irep(mrb); - - /* skip record size */ - src += sizeof(uint32_t); - - /* number of local variable */ - irep->nlocals = bin_to_uint16(src); - src += sizeof(uint16_t); - - /* number of register variable */ - irep->nregs = bin_to_uint16(src); - src += sizeof(uint16_t); - - /* number of child irep */ - irep->rlen = (size_t)bin_to_uint16(src); - src += sizeof(uint16_t); - - /* Binary Data Section */ - /* ISEQ BLOCK */ - irep->ilen = (size_t)bin_to_uint32(src); - src += sizeof(uint32_t); - src += skip_padding(src); - - if (irep->ilen > 0) { - if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) { - return NULL; - } - if ((flags & FLAG_SRC_MALLOC) == 0 && - (flags & FLAG_BYTEORDER_NATIVE)) { - irep->iseq = (mrb_code*)src; - src += sizeof(uint32_t) * irep->ilen; - irep->flags |= MRB_ISEQ_NO_FREE; - } - else { - irep->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen); - if (flags & FLAG_BYTEORDER_NATIVE) { - memcpy(irep->iseq, src, sizeof(uint32_t) * irep->ilen); - src += sizeof(uint32_t) * irep->ilen; - } - else if (flags & FLAG_BYTEORDER_BIG) { - for (i = 0; i < irep->ilen; i++) { - irep->iseq[i] = (mrb_code)bin_to_uint32(src); /* iseq */ - src += sizeof(uint32_t); - } - } - else { - for (i = 0; i < irep->ilen; i++) { - irep->iseq[i] = (mrb_code)bin_to_uint32l(src); /* iseq */ - src += sizeof(uint32_t); - } - } - } - } - - /* POOL BLOCK */ - plen = (size_t)bin_to_uint32(src); /* number of pool */ - src += sizeof(uint32_t); - if (plen > 0) { - if (SIZE_ERROR_MUL(plen, sizeof(mrb_value))) { - return NULL; - } - irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * plen); - - for (i = 0; i < plen; i++) { - mrb_value s; - - tt = *src++; /* pool TT */ - pool_data_len = bin_to_uint16(src); /* pool data length */ - src += sizeof(uint16_t); - if (flags & FLAG_SRC_MALLOC) { - s = mrb_str_new(mrb, (char *)src, pool_data_len); - } - else { - s = mrb_str_new_static(mrb, (char *)src, pool_data_len); - } - src += pool_data_len; - switch (tt) { /* pool data */ - case IREP_TT_FIXNUM: - irep->pool[i] = mrb_str_to_inum(mrb, s, 10, FALSE); - break; - - case IREP_TT_FLOAT: - irep->pool[i] = mrb_float_pool(mrb, mrb_str_to_dbl(mrb, s, FALSE)); - break; - - case IREP_TT_STRING: - irep->pool[i] = mrb_str_pool(mrb, s); - break; - - default: - /* should not happen */ - irep->pool[i] = mrb_nil_value(); - break; - } - irep->plen++; - mrb_gc_arena_restore(mrb, ai); - } - } - - /* SYMS BLOCK */ - irep->slen = (size_t)bin_to_uint32(src); /* syms length */ - src += sizeof(uint32_t); - if (irep->slen > 0) { - if (SIZE_ERROR_MUL(irep->slen, sizeof(mrb_sym))) { - return NULL; - } - irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen); - - for (i = 0; i < irep->slen; i++) { - snl = bin_to_uint16(src); /* symbol name length */ - src += sizeof(uint16_t); - - if (snl == MRB_DUMP_NULL_SYM_LEN) { - irep->syms[i] = 0; - continue; - } - - if (flags & FLAG_SRC_MALLOC) { - irep->syms[i] = mrb_intern(mrb, (char *)src, snl); - } - else { - irep->syms[i] = mrb_intern_static(mrb, (char *)src, snl); - } - src += snl + 1; - - mrb_gc_arena_restore(mrb, ai); - } - } - - irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*irep->rlen); - - diff = src - bin; - mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); - *len = (size_t)diff; - - return irep; -} - -static mrb_irep* -read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags) -{ - mrb_irep *irep = read_irep_record_1(mrb, bin, len, flags); - size_t i; - - if (irep == NULL) { - return NULL; - } - - bin += *len; - for (i=0; irlen; i++) { - size_t rlen; - - irep->reps[i] = read_irep_record(mrb, bin, &rlen, flags); - if (irep->reps[i] == NULL) { - return NULL; - } - bin += rlen; - *len += rlen; - } - return irep; -} - -static mrb_irep* -read_section_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags) -{ - size_t len; - - bin += sizeof(struct rite_section_irep_header); - return read_irep_record(mrb, bin, &len, flags); -} - -static int -read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *len) -{ - size_t i, fname_len, niseq; - char *fname; - uint16_t *lines; - - *len = 0; - bin += sizeof(uint32_t); /* record size */ - *len += sizeof(uint32_t); - fname_len = bin_to_uint16(bin); - bin += sizeof(uint16_t); - *len += sizeof(uint16_t); - fname = (char *)mrb_malloc(mrb, fname_len + 1); - memcpy(fname, bin, fname_len); - fname[fname_len] = '\0'; - bin += fname_len; - *len += fname_len; - - niseq = (size_t)bin_to_uint32(bin); - bin += sizeof(uint32_t); /* niseq */ - *len += sizeof(uint32_t); - - if (SIZE_ERROR_MUL(niseq, sizeof(uint16_t))) { - return MRB_DUMP_GENERAL_FAILURE; - } - lines = (uint16_t *)mrb_malloc(mrb, niseq * sizeof(uint16_t)); - for (i = 0; i < niseq; i++) { - lines[i] = bin_to_uint16(bin); - bin += sizeof(uint16_t); /* niseq */ - *len += sizeof(uint16_t); - } - - irep->filename = fname; - irep->lines = lines; - return MRB_DUMP_OK; -} - -static int -read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *lenp) -{ - int result = read_lineno_record_1(mrb, bin, irep, lenp); - size_t i; - - if (result != MRB_DUMP_OK) return result; - for (i = 0; i < irep->rlen; i++) { - size_t len; - - result = read_lineno_record(mrb, bin, irep->reps[i], &len); - if (result != MRB_DUMP_OK) break; - bin += len; - *lenp += len; - } - return result; -} - -static int -read_section_lineno(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep) -{ - size_t len; - - len = 0; - bin += sizeof(struct rite_section_lineno_header); - - /* Read Binary Data Section */ - return read_lineno_record(mrb, bin, irep, &len); -} - -static int -read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *record_len, const mrb_sym *filenames, size_t filenames_len) -{ - const uint8_t *bin = start; - ptrdiff_t diff; - size_t record_size, i; - uint16_t f_idx; - - if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; } - - irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info)); - irep->debug_info->pc_count = irep->ilen; - - record_size = (size_t)bin_to_uint32(bin); - bin += sizeof(uint32_t); - - irep->debug_info->flen = bin_to_uint16(bin); - irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_malloc(mrb, sizeof(mrb_irep_debug_info*) * irep->debug_info->flen); - bin += sizeof(uint16_t); - - for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { - mrb_irep_debug_info_file *file; - uint16_t filename_idx; - mrb_int len; - - file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file)); - irep->debug_info->files[f_idx] = file; - - file->start_pos = bin_to_uint32(bin); - bin += sizeof(uint32_t); - - /* filename */ - filename_idx = bin_to_uint16(bin); - bin += sizeof(uint16_t); - mrb_assert(filename_idx < filenames_len); - file->filename_sym = filenames[filename_idx]; - len = 0; - file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len); - - file->line_entry_count = bin_to_uint32(bin); - bin += sizeof(uint32_t); - file->line_type = (mrb_debug_line_type)bin_to_uint8(bin); - bin += sizeof(uint8_t); - switch (file->line_type) { - case mrb_debug_line_ary: { - uint32_t l; - - file->lines.ary = (uint16_t *)mrb_malloc(mrb, sizeof(uint16_t) * (size_t)(file->line_entry_count)); - for (l = 0; l < file->line_entry_count; ++l) { - file->lines.ary[l] = bin_to_uint16(bin); - bin += sizeof(uint16_t); - } - } break; - - case mrb_debug_line_flat_map: { - uint32_t l; - - file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc( - mrb, sizeof(mrb_irep_debug_info_line) * (size_t)(file->line_entry_count)); - for (l = 0; l < file->line_entry_count; ++l) { - file->lines.flat_map[l].start_pos = bin_to_uint32(bin); - bin += sizeof(uint32_t); - file->lines.flat_map[l].line = bin_to_uint16(bin); - bin += sizeof(uint16_t); - } - } break; - - default: return MRB_DUMP_GENERAL_FAILURE; - } - } - - diff = bin - start; - mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); - - if (record_size != (size_t)diff) { - return MRB_DUMP_GENERAL_FAILURE; - } - - for (i = 0; i < irep->rlen; i++) { - size_t len; - int ret; - - ret = read_debug_record(mrb, bin, irep->reps[i], &len, filenames, filenames_len); - if (ret != MRB_DUMP_OK) return ret; - bin += len; - } - - diff = bin - start; - mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); - *record_len = (size_t)diff; - - return MRB_DUMP_OK; -} - -static int -read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t flags) -{ - const uint8_t *bin; - ptrdiff_t diff; - struct rite_section_debug_header *header; - uint16_t i; - size_t len = 0; - int result; - uint16_t filenames_len; - mrb_sym *filenames; - - bin = start; - header = (struct rite_section_debug_header *)bin; - bin += sizeof(struct rite_section_debug_header); - - filenames_len = bin_to_uint16(bin); - bin += sizeof(uint16_t); - filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)filenames_len); - for (i = 0; i < filenames_len; ++i) { - uint16_t f_len = bin_to_uint16(bin); - bin += sizeof(uint16_t); - if (flags & FLAG_SRC_MALLOC) { - filenames[i] = mrb_intern(mrb, (const char *)bin, (size_t)f_len); - } - else { - filenames[i] = mrb_intern_static(mrb, (const char *)bin, (size_t)f_len); - } - bin += f_len; - } - - result = read_debug_record(mrb, bin, irep, &len, filenames, filenames_len); - if (result != MRB_DUMP_OK) goto debug_exit; - - bin += len; - diff = bin - start; - mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); - if ((uint32_t)diff != bin_to_uint32(header->section_size)) { - result = MRB_DUMP_GENERAL_FAILURE; - } - -debug_exit: - mrb_free(mrb, filenames); - return result; -} - -static int -read_lv_record(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, size_t *record_len, mrb_sym const *syms, uint32_t syms_len) -{ - const uint8_t *bin = start; - size_t i; - ptrdiff_t diff; - - irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (irep->nlocals - 1)); - - for (i = 0; i + 1< irep->nlocals; ++i) { - uint16_t const sym_idx = bin_to_uint16(bin); - bin += sizeof(uint16_t); - if (sym_idx == RITE_LV_NULL_MARK) { - irep->lv[i].name = 0; - irep->lv[i].r = 0; - } - else { - if (sym_idx >= syms_len) { - return MRB_DUMP_GENERAL_FAILURE; - } - irep->lv[i].name = syms[sym_idx]; - - irep->lv[i].r = bin_to_uint16(bin); - } - bin += sizeof(uint16_t); - } - - for (i = 0; i < irep->rlen; ++i) { - size_t len; - int ret; - - ret = read_lv_record(mrb, bin, irep->reps[i], &len, syms, syms_len); - if (ret != MRB_DUMP_OK) return ret; - bin += len; - } - - diff = bin - start; - mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); - *record_len = (size_t)diff; - - return MRB_DUMP_OK; -} - -static int -read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t flags) -{ - const uint8_t *bin; - ptrdiff_t diff; - struct rite_section_lv_header const *header; - uint32_t i; - size_t len = 0; - int result; - uint32_t syms_len; - mrb_sym *syms; - mrb_sym (*intern_func)(mrb_state*, const char*, size_t) = - (flags & FLAG_SRC_MALLOC)? mrb_intern : mrb_intern_static; - - bin = start; - header = (struct rite_section_lv_header const*)bin; - bin += sizeof(struct rite_section_lv_header); - - syms_len = bin_to_uint32(bin); - bin += sizeof(uint32_t); - syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)syms_len); - for (i = 0; i < syms_len; ++i) { - uint16_t const str_len = bin_to_uint16(bin); - bin += sizeof(uint16_t); - - syms[i] = intern_func(mrb, (const char*)bin, str_len); - bin += str_len; - } - - result = read_lv_record(mrb, bin, irep, &len, syms, syms_len); - if (result != MRB_DUMP_OK) goto lv_exit; - - bin += len; - diff = bin - start; - mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); - if ((uint32_t)diff != bin_to_uint32(header->section_size)) { - result = MRB_DUMP_GENERAL_FAILURE; - } - -lv_exit: - mrb_free(mrb, syms); - return result; -} - -static int -read_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc, uint8_t *flags) -{ - const struct rite_binary_header *header = (const struct rite_binary_header *)bin; - - if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) == 0) { - if (bigendian_p()) - *flags |= FLAG_BYTEORDER_NATIVE; - else - *flags |= FLAG_BYTEORDER_BIG; - } - else if (memcmp(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)) == 0) { - if (bigendian_p()) - *flags |= FLAG_BYTEORDER_LIL; - else - *flags |= FLAG_BYTEORDER_NATIVE; - } - else { - return MRB_DUMP_INVALID_FILE_HEADER; - } - - if (crc) { - *crc = bin_to_uint16(header->binary_crc); - } - *bin_size = (size_t)bin_to_uint32(header->binary_size); - - return MRB_DUMP_OK; -} - -MRB_API mrb_irep* -read_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags) -{ - int result; - mrb_irep *irep = NULL; - const struct rite_section_header *section_header; - uint16_t crc; - size_t bin_size = 0; - size_t n; - - if ((mrb == NULL) || (bin == NULL)) { - return NULL; - } - - result = read_binary_header(bin, &bin_size, &crc, &flags); - if (result != MRB_DUMP_OK) { - return NULL; - } - - n = offset_crc_body(); - if (crc != calc_crc_16_ccitt(bin + n, bin_size - n, 0)) { - return NULL; - } - - bin += sizeof(struct rite_binary_header); - do { - section_header = (const struct rite_section_header *)bin; - if (memcmp(section_header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(section_header->section_ident)) == 0) { - irep = read_section_irep(mrb, bin, flags); - if (!irep) return NULL; - } - else if (memcmp(section_header->section_ident, RITE_SECTION_LINENO_IDENT, sizeof(section_header->section_ident)) == 0) { - if (!irep) return NULL; /* corrupted data */ - result = read_section_lineno(mrb, bin, irep); - if (result < MRB_DUMP_OK) { - return NULL; - } - } - else if (memcmp(section_header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(section_header->section_ident)) == 0) { - if (!irep) return NULL; /* corrupted data */ - result = read_section_debug(mrb, bin, irep, flags); - if (result < MRB_DUMP_OK) { - return NULL; - } - } - else if (memcmp(section_header->section_ident, RITE_SECTION_LV_IDENT, sizeof(section_header->section_ident)) == 0) { - if (!irep) return NULL; - result = read_section_lv(mrb, bin, irep, flags); - if (result < MRB_DUMP_OK) { - return NULL; - } - } - bin += bin_to_uint32(section_header->section_size); - } while (memcmp(section_header->section_ident, RITE_BINARY_EOF, sizeof(section_header->section_ident)) != 0); - - return irep; -} - -MRB_API mrb_irep* -mrb_read_irep(mrb_state *mrb, const uint8_t *bin) -{ -#ifdef MRB_USE_ETEXT_EDATA - uint8_t flags = mrb_ro_data_p((char*)bin) ? FLAG_SRC_STATIC : FLAG_SRC_MALLOC; -#else - uint8_t flags = FLAG_SRC_STATIC; -#endif - - return read_irep(mrb, bin, flags); -} - -static void -irep_error(mrb_state *mrb) -{ - mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "irep load error")); -} - -MRB_API mrb_value -mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c) -{ - mrb_irep *irep = mrb_read_irep(mrb, bin); - struct RProc *proc; - - if (!irep) { - irep_error(mrb); - return mrb_nil_value(); - } - proc = mrb_proc_new(mrb, irep); - mrb_irep_decref(mrb, irep); - if (c && c->no_exec) return mrb_obj_value(proc); - return mrb_toplevel_run(mrb, proc); -} - -MRB_API mrb_value -mrb_load_irep(mrb_state *mrb, const uint8_t *bin) -{ - return mrb_load_irep_cxt(mrb, bin, NULL); -} - -#ifndef MRB_DISABLE_STDIO - -MRB_API mrb_irep* -mrb_read_irep_file(mrb_state *mrb, FILE* fp) -{ - mrb_irep *irep = NULL; - uint8_t *buf; - const size_t header_size = sizeof(struct rite_binary_header); - size_t buf_size = 0; - uint8_t flags = 0; - int result; - - if ((mrb == NULL) || (fp == NULL)) { - return NULL; - } - - buf = (uint8_t*)mrb_malloc(mrb, header_size); - if (fread(buf, header_size, 1, fp) == 0) { - goto irep_exit; - } - result = read_binary_header(buf, &buf_size, NULL, &flags); - if (result != MRB_DUMP_OK || buf_size <= header_size) { - goto irep_exit; - } - - buf = (uint8_t*)mrb_realloc(mrb, buf, buf_size); - if (fread(buf+header_size, buf_size-header_size, 1, fp) == 0) { - goto irep_exit; - } - irep = read_irep(mrb, buf, FLAG_SRC_MALLOC); - -irep_exit: - mrb_free(mrb, buf); - return irep; -} - -void mrb_codedump_all(mrb_state*, struct RProc*); - -MRB_API mrb_value -mrb_load_irep_file_cxt(mrb_state *mrb, FILE* fp, mrbc_context *c) -{ - mrb_irep *irep = mrb_read_irep_file(mrb, fp); - mrb_value val; - struct RProc *proc; - - if (!irep) { - irep_error(mrb); - return mrb_nil_value(); - } - proc = mrb_proc_new(mrb, irep); - mrb_irep_decref(mrb, irep); - if (c && c->dump_result) mrb_codedump_all(mrb, proc); - if (c && c->no_exec) return mrb_obj_value(proc); - val = mrb_toplevel_run(mrb, proc); - return val; -} - -MRB_API mrb_value -mrb_load_irep_file(mrb_state *mrb, FILE* fp) -{ - return mrb_load_irep_file_cxt(mrb, fp, NULL); -} -#endif /* MRB_DISABLE_STDIO */ diff -Nru nghttp2-1.13.0/third-party/mruby/src/mruby_core.rake nghttp2-0.6.7/third-party/mruby/src/mruby_core.rake --- nghttp2-1.13.0/third-party/mruby/src/mruby_core.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/mruby_core.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -MRuby.each_target do - current_dir = File.dirname(__FILE__).relative_path_from(Dir.pwd) - relative_from_root = File.dirname(__FILE__).relative_path_from(MRUBY_ROOT) - current_build_dir = "#{build_dir}/#{relative_from_root}" - - objs = Dir.glob("#{current_dir}/*.c").map { |f| - next nil if cxx_abi_enabled? and f =~ /(error|vm).c$/ - objfile(f.pathmap("#{current_build_dir}/%n")) - }.compact - - if cxx_abi_enabled? - objs += %w(vm error).map { |v| compile_as_cxx "#{current_dir}/#{v}.c", "#{current_build_dir}/#{v}.cxx" } - end - self.libmruby << objs - - file libfile("#{build_dir}/lib/libmruby_core") => objs do |t| - archiver.run t.name, t.prerequisites - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/src/numeric.c nghttp2-0.6.7/third-party/mruby/src/numeric.c --- nghttp2-1.13.0/third-party/mruby/src/numeric.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/numeric.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1213 +0,0 @@ -/* -** numeric.c - Numeric, Integer, Float, Fixnum class -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include -#include - -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/numeric.h" -#include "mruby/string.h" - -#ifdef MRB_USE_FLOAT -#define floor(f) floorf(f) -#define ceil(f) ceilf(f) -#define fmod(x,y) fmodf(x,y) -#define MRB_FLO_TO_STR_FMT "%.7g" -#else -#define MRB_FLO_TO_STR_FMT "%.14g" -#endif - -MRB_API mrb_float -mrb_to_flo(mrb_state *mrb, mrb_value val) -{ - switch (mrb_type(val)) { - case MRB_TT_FIXNUM: - return (mrb_float)mrb_fixnum(val); - case MRB_TT_FLOAT: - break; - default: - mrb_raise(mrb, E_TYPE_ERROR, "non float value"); - } - return mrb_float(val); -} - -/* - * call-seq: - * - * num ** other -> num - * - * Raises num the other power. - * - * 2.0**3 #=> 8.0 - */ -static mrb_value -num_pow(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - mrb_float d, yv; - - mrb_get_args(mrb, "o", &y); - yv = mrb_to_flo(mrb, y); - d = pow(mrb_to_flo(mrb, x), yv); - if (mrb_fixnum_p(x) && mrb_fixnum_p(y) && FIXABLE(d) && yv > 0 && - (d < 0 || (d > 0 && (mrb_int)d > 0))) - return mrb_fixnum_value((mrb_int)d); - return mrb_float_value(mrb, d); -} - -/* 15.2.8.3.4 */ -/* 15.2.9.3.4 */ -/* - * call-seq: - * num / other -> num - * - * Performs division: the class of the resulting object depends on - * the class of num and on the magnitude of the - * result. - */ - -mrb_value -mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y) -{ - return mrb_float_value(mrb, mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y)); -} - -/* 15.2.9.3.19(x) */ -/* - * call-seq: - * num.quo(numeric) -> real - * - * Returns most exact division. - */ - -static mrb_value -num_div(mrb_state *mrb, mrb_value x) -{ - mrb_float y; - - mrb_get_args(mrb, "f", &y); - return mrb_float_value(mrb, mrb_to_flo(mrb, x) / y); -} - -/******************************************************************** - * - * Document-class: Float - * - * Float objects represent inexact real numbers using - * the native architecture's double-precision floating point - * representation. - */ - -/* 15.2.9.3.16(x) */ -/* - * call-seq: - * flt.to_s -> string - * - * Returns a string containing a representation of self. As well as a - * fixed or exponential form of the number, the call may return - * "NaN", "Infinity", and - * "-Infinity". - */ - -static mrb_value -flo_to_s(mrb_state *mrb, mrb_value flt) -{ - if (isnan(mrb_float(flt))) { - return mrb_str_new_lit(mrb, "NaN"); - } - return mrb_float_to_str(mrb, flt, MRB_FLO_TO_STR_FMT); -} - -/* 15.2.9.3.2 */ -/* - * call-seq: - * float - other -> float - * - * Returns a new float which is the difference of float - * and other. - */ - -static mrb_value -flo_minus(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y)); -} - -/* 15.2.9.3.3 */ -/* - * call-seq: - * float * other -> float - * - * Returns a new float which is the product of float - * and other. - */ - -static mrb_value -flo_mul(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y)); -} - -static void -flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float *modp) -{ - mrb_float div; - mrb_float mod; - - if (y == 0.0) { - div = INFINITY; - mod = NAN; - } - else { - mod = fmod(x, y); - if (isinf(x) && isfinite(y)) - div = x; - else - div = (x - mod) / y; - if (y*mod < 0) { - mod += y; - div -= 1.0; - } - } - - if (modp) *modp = mod; - if (divp) *divp = div; -} - -/* 15.2.9.3.5 */ -/* - * call-seq: - * flt % other -> float - * flt.modulo(other) -> float - * - * Return the modulo after division of flt by other. - * - * 6543.21.modulo(137) #=> 104.21 - * 6543.21.modulo(137.24) #=> 92.9299999999996 - */ - -static mrb_value -flo_mod(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - mrb_float mod; - - mrb_get_args(mrb, "o", &y); - - flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), 0, &mod); - return mrb_float_value(mrb, mod); -} - -/* 15.2.8.3.16 */ -/* - * call-seq: - * num.eql?(numeric) -> true or false - * - * Returns true if num and numeric are the - * same type and have equal values. - * - * 1 == 1.0 #=> true - * 1.eql?(1.0) #=> false - * (1.0).eql?(1.0) #=> true - */ -static mrb_value -fix_eql(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - if (!mrb_fixnum_p(y)) return mrb_false_value(); - return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y)); -} - -static mrb_value -flo_eql(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - if (!mrb_float_p(y)) return mrb_false_value(); - return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y)); -} - -/* 15.2.9.3.7 */ -/* - * call-seq: - * flt == obj -> true or false - * - * Returns true only if obj has the same value - * as flt. Contrast this with Float#eql?, which - * requires obj to be a Float. - * - * 1.0 == 1 #=> true - * - */ - -static mrb_value -flo_eq(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - mrb_get_args(mrb, "o", &y); - - switch (mrb_type(y)) { - case MRB_TT_FIXNUM: - return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y)); - case MRB_TT_FLOAT: - return mrb_bool_value(mrb_float(x) == mrb_float(y)); - default: - return mrb_false_value(); - } -} - -/* 15.2.8.3.18 */ -/* - * call-seq: - * flt.hash -> integer - * - * Returns a hash code for this float. - */ -static mrb_value -flo_hash(mrb_state *mrb, mrb_value num) -{ - mrb_float d; - char *c; - size_t i; - int hash; - - d = (mrb_float)mrb_fixnum(num); - /* normalize -0.0 to 0.0 */ - if (d == 0) d = 0.0; - c = (char*)&d; - for (hash=0, i=0; i self - * - * As flt is already a float, returns +self+. - */ - -static mrb_value -flo_to_f(mrb_state *mrb, mrb_value num) -{ - return num; -} - -/* 15.2.9.3.11 */ -/* - * call-seq: - * flt.infinite? -> nil, -1, +1 - * - * Returns nil, -1, or +1 depending on whether flt - * is finite, -infinity, or +infinity. - * - * (0.0).infinite? #=> nil - * (-1.0/0.0).infinite? #=> -1 - * (+1.0/0.0).infinite? #=> 1 - */ - -static mrb_value -flo_infinite_p(mrb_state *mrb, mrb_value num) -{ - mrb_float value = mrb_float(num); - - if (isinf(value)) { - return mrb_fixnum_value(value < 0 ? -1 : 1); - } - return mrb_nil_value(); -} - -/* 15.2.9.3.9 */ -/* - * call-seq: - * flt.finite? -> true or false - * - * Returns true if flt is a valid IEEE floating - * point number (it is not infinite, and nan? is - * false). - * - */ - -static mrb_value -flo_finite_p(mrb_state *mrb, mrb_value num) -{ - return mrb_bool_value(isfinite(mrb_float(num))); -} - -/* 15.2.9.3.10 */ -/* - * call-seq: - * flt.floor -> integer - * - * Returns the largest integer less than or equal to flt. - * - * 1.2.floor #=> 1 - * 2.0.floor #=> 2 - * (-1.2).floor #=> -2 - * (-2.0).floor #=> -2 - */ - -static mrb_value -flo_floor(mrb_state *mrb, mrb_value num) -{ - mrb_float f = floor(mrb_float(num)); - - if (!FIXABLE(f)) { - return mrb_float_value(mrb, f); - } - return mrb_fixnum_value((mrb_int)f); -} - -/* 15.2.9.3.8 */ -/* - * call-seq: - * flt.ceil -> integer - * - * Returns the smallest Integer greater than or equal to - * flt. - * - * 1.2.ceil #=> 2 - * 2.0.ceil #=> 2 - * (-1.2).ceil #=> -1 - * (-2.0).ceil #=> -2 - */ - -static mrb_value -flo_ceil(mrb_state *mrb, mrb_value num) -{ - mrb_float f = ceil(mrb_float(num)); - - if (!FIXABLE(f)) { - return mrb_float_value(mrb, f); - } - return mrb_fixnum_value((mrb_int)f); -} - -/* 15.2.9.3.12 */ -/* - * call-seq: - * flt.round([ndigits]) -> integer or float - * - * Rounds flt to a given precision in decimal digits (default 0 digits). - * Precision may be negative. Returns a floating point number when ndigits - * is more than zero. - * - * 1.4.round #=> 1 - * 1.5.round #=> 2 - * 1.6.round #=> 2 - * (-1.5).round #=> -2 - * - * 1.234567.round(2) #=> 1.23 - * 1.234567.round(3) #=> 1.235 - * 1.234567.round(4) #=> 1.2346 - * 1.234567.round(5) #=> 1.23457 - * - * 34567.89.round(-5) #=> 0 - * 34567.89.round(-4) #=> 30000 - * 34567.89.round(-3) #=> 35000 - * 34567.89.round(-2) #=> 34600 - * 34567.89.round(-1) #=> 34570 - * 34567.89.round(0) #=> 34568 - * 34567.89.round(1) #=> 34567.9 - * 34567.89.round(2) #=> 34567.89 - * 34567.89.round(3) #=> 34567.89 - * - */ - -static mrb_value -flo_round(mrb_state *mrb, mrb_value num) -{ - double number, f; - mrb_int ndigits = 0; - mrb_int i; - - mrb_get_args(mrb, "|i", &ndigits); - number = mrb_float(num); - - if (isinf(number)) { - if (0 < ndigits) return num; - else mrb_raise(mrb, E_FLOATDOMAIN_ERROR, number < 0 ? "-Infinity" : "Infinity"); - } - if (isnan(number)) { - if (0 < ndigits) return num; - else mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN"); - } - - f = 1.0; - i = ndigits >= 0 ? ndigits : -ndigits; - while (--i >= 0) - f = f*10.0; - - if (isinf(f)) { - if (ndigits < 0) number = 0; - } - else { - double d; - - if (ndigits < 0) number /= f; - else number *= f; - - /* home-made inline implementation of round(3) */ - if (number > 0.0) { - d = floor(number); - number = d + (number - d >= 0.5); - } - else if (number < 0.0) { - d = ceil(number); - number = d - (d - number >= 0.5); - } - - if (ndigits < 0) number *= f; - else number /= f; - } - - if (ndigits > 0) { - if (!isfinite(number)) return num; - return mrb_float_value(mrb, number); - } - return mrb_fixnum_value((mrb_int)number); -} - -/* 15.2.9.3.14 */ -/* 15.2.9.3.15 */ -/* - * call-seq: - * flt.to_i -> integer - * flt.to_int -> integer - * flt.truncate -> integer - * - * Returns flt truncated to an Integer. - */ - -static mrb_value -flo_truncate(mrb_state *mrb, mrb_value num) -{ - mrb_float f = mrb_float(num); - - if (f > 0.0) f = floor(f); - if (f < 0.0) f = ceil(f); - - if (!FIXABLE(f)) { - return mrb_float_value(mrb, f); - } - return mrb_fixnum_value((mrb_int)f); -} - -static mrb_value -flo_nan_p(mrb_state *mrb, mrb_value num) -{ - return mrb_bool_value(isnan(mrb_float(num))); -} - -/* - * Document-class: Integer - * - * Integer is the basis for the two concrete classes that - * hold whole numbers, Bignum and Fixnum. - * - */ - - -/* - * call-seq: - * int.to_i -> integer - * int.to_int -> integer - * - * As int is already an Integer, all these - * methods simply return the receiver. - */ - -static mrb_value -int_to_i(mrb_state *mrb, mrb_value num) -{ - return num; -} - -/*tests if N*N would overflow*/ -#define SQRT_INT_MAX ((mrb_int)1<<((MRB_INT_BIT-1-MRB_FIXNUM_SHIFT)/2)) -#define FIT_SQRT_INT(n) (((n)=-SQRT_INT_MAX)) - -mrb_value -mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y) -{ - mrb_int a; - - a = mrb_fixnum(x); - if (mrb_fixnum_p(y)) { - mrb_float c; - mrb_int b; - - if (a == 0) return x; - b = mrb_fixnum(y); - if (FIT_SQRT_INT(a) && FIT_SQRT_INT(b)) - return mrb_fixnum_value(a*b); - c = a * b; - if ((a != 0 && c/a != b) || !FIXABLE(c)) { - return mrb_float_value(mrb, (mrb_float)a*(mrb_float)b); - } - return mrb_fixnum_value((mrb_int)c); - } - return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y)); -} - -/* 15.2.8.3.3 */ -/* - * call-seq: - * fix * numeric -> numeric_result - * - * Performs multiplication: the class of the resulting object depends on - * the class of numeric and on the magnitude of the - * result. - */ - -static mrb_value -fix_mul(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - return mrb_fixnum_mul(mrb, x, y); -} - -static void -fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp) -{ - mrb_int div, mod; - - /* TODO: add mrb_assert(y != 0) to make sure */ - - if (y < 0) { - if (x < 0) - div = -x / -y; - else - div = - (x / -y); - } - else { - if (x < 0) - div = - (-x / y); - else - div = x / y; - } - mod = x - div*y; - if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) { - mod += y; - div -= 1; - } - if (divp) *divp = div; - if (modp) *modp = mod; -} - -/* 15.2.8.3.5 */ -/* - * call-seq: - * fix % other -> real - * fix.modulo(other) -> real - * - * Returns fix modulo other. - * See numeric.divmod for more information. - */ - -static mrb_value -fix_mod(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - mrb_int a; - - mrb_get_args(mrb, "o", &y); - a = mrb_fixnum(x); - if (mrb_fixnum_p(y)) { - mrb_int b, mod; - - if ((b=mrb_fixnum(y)) == 0) { - return mrb_float_value(mrb, NAN); - } - fixdivmod(mrb, a, b, 0, &mod); - return mrb_fixnum_value(mod); - } - else { - mrb_float mod; - - flodivmod(mrb, (mrb_float)a, mrb_to_flo(mrb, y), 0, &mod); - return mrb_float_value(mrb, mod); - } -} - -/* - * call-seq: - * fix.divmod(numeric) -> array - * - * See Numeric#divmod. - */ -static mrb_value -fix_divmod(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - - if (mrb_fixnum_p(y)) { - mrb_int div, mod; - - if (mrb_fixnum(y) == 0) { - return mrb_assoc_new(mrb, mrb_float_value(mrb, INFINITY), - mrb_float_value(mrb, NAN)); - } - fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod); - return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod)); - } - else { - mrb_float div, mod; - mrb_value a, b; - - flodivmod(mrb, (mrb_float)mrb_fixnum(x), mrb_to_flo(mrb, y), &div, &mod); - a = mrb_float_value(mrb, (mrb_int)div); - b = mrb_float_value(mrb, mod); - return mrb_assoc_new(mrb, a, b); - } -} - -static mrb_value -flo_divmod(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - mrb_float div, mod; - mrb_value a, b; - - mrb_get_args(mrb, "o", &y); - - flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod); - a = mrb_float_value(mrb, (mrb_int)div); - b = mrb_float_value(mrb, mod); - return mrb_assoc_new(mrb, a, b); -} - -/* 15.2.8.3.7 */ -/* - * call-seq: - * fix == other -> true or false - * - * Return true if fix equals other - * numerically. - * - * 1 == 2 #=> false - * 1 == 1.0 #=> true - */ - -static mrb_value -fix_equal(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - switch (mrb_type(y)) { - case MRB_TT_FIXNUM: - return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y)); - case MRB_TT_FLOAT: - return mrb_bool_value((mrb_float)mrb_fixnum(x) == mrb_float(y)); - default: - return mrb_false_value(); - } -} - -/* 15.2.8.3.8 */ -/* - * call-seq: - * ~fix -> integer - * - * One's complement: returns a number where each bit is flipped. - * ex.0---00001 (1)-> 1---11110 (-2) - * ex.0---00010 (2)-> 1---11101 (-3) - * ex.0---00100 (4)-> 1---11011 (-5) - */ - -static mrb_value -fix_rev(mrb_state *mrb, mrb_value num) -{ - mrb_int val = mrb_fixnum(num); - - return mrb_fixnum_value(~val); -} - -static mrb_value -bit_coerce(mrb_state *mrb, mrb_value x) -{ - while (!mrb_fixnum_p(x)) { - if (mrb_float_p(x)) { - mrb_raise(mrb, E_TYPE_ERROR, "can't convert Float into Integer"); - } - x = mrb_to_int(mrb, x); - } - return x; -} - -/* 15.2.8.3.9 */ -/* - * call-seq: - * fix & integer -> integer_result - * - * Bitwise AND. - */ - -static mrb_value -fix_and(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - - y = bit_coerce(mrb, y); - return mrb_fixnum_value(mrb_fixnum(x) & mrb_fixnum(y)); -} - -/* 15.2.8.3.10 */ -/* - * call-seq: - * fix | integer -> integer_result - * - * Bitwise OR. - */ - -static mrb_value -fix_or(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - - y = bit_coerce(mrb, y); - return mrb_fixnum_value(mrb_fixnum(x) | mrb_fixnum(y)); -} - -/* 15.2.8.3.11 */ -/* - * call-seq: - * fix ^ integer -> integer_result - * - * Bitwise EXCLUSIVE OR. - */ - -static mrb_value -fix_xor(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - - y = bit_coerce(mrb, y); - return mrb_fixnum_value(mrb_fixnum(x) ^ mrb_fixnum(y)); -} - -#define NUMERIC_SHIFT_WIDTH_MAX (MRB_INT_BIT-1) - -static mrb_value -lshift(mrb_state *mrb, mrb_int val, mrb_int width) -{ - mrb_assert(width > 0); - if (width > NUMERIC_SHIFT_WIDTH_MAX) { - mrb_float f = (mrb_float)val; - while (width--) { - f *= 2; - } - return mrb_float_value(mrb, f); - } - return mrb_fixnum_value(val << width); -} - -static mrb_value -rshift(mrb_int val, mrb_int width) -{ - mrb_assert(width > 0); - if (width >= NUMERIC_SHIFT_WIDTH_MAX) { - if (val < 0) { - return mrb_fixnum_value(-1); - } - return mrb_fixnum_value(0); - } - return mrb_fixnum_value(val >> width); -} - -static inline void -fix_shift_get_width(mrb_state *mrb, mrb_int *width) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - *width = mrb_fixnum(bit_coerce(mrb, y)); -} - -/* 15.2.8.3.12 */ -/* - * call-seq: - * fix << count -> integer or float - * - * Shifts _fix_ left _count_ positions (right if _count_ is negative). - */ - -static mrb_value -fix_lshift(mrb_state *mrb, mrb_value x) -{ - mrb_int width, val; - - fix_shift_get_width(mrb, &width); - - if (width == 0) { - return x; - } - val = mrb_fixnum(x); - if (width < 0) { - return rshift(val, -width); - } - return lshift(mrb, val, width); -} - -/* 15.2.8.3.13 */ -/* - * call-seq: - * fix >> count -> integer or float - * - * Shifts _fix_ right _count_ positions (left if _count_ is negative). - */ - -static mrb_value -fix_rshift(mrb_state *mrb, mrb_value x) -{ - mrb_int width, val; - - fix_shift_get_width(mrb, &width); - - if (width == 0) { - return x; - } - val = mrb_fixnum(x); - if (width < 0) { - return lshift(mrb, val, -width); - } - return rshift(val, width); -} - -/* 15.2.8.3.23 */ -/* - * call-seq: - * fix.to_f -> float - * - * Converts fix to a Float. - * - */ - -static mrb_value -fix_to_f(mrb_state *mrb, mrb_value num) -{ - return mrb_float_value(mrb, (mrb_float)mrb_fixnum(num)); -} - -/* - * Document-class: FloatDomainError - * - * Raised when attempting to convert special float values - * (in particular infinite or NaN) - * to numerical classes which don't support them. - * - * Float::INFINITY.to_r - * - * raises the exception: - * - * FloatDomainError: Infinity - */ -/* ------------------------------------------------------------------------*/ -MRB_API mrb_value -mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x) -{ - mrb_int z; - - if (!mrb_float_p(x)) { - mrb_raise(mrb, E_TYPE_ERROR, "non float value"); - z = 0; /* not reached. just suppress warnings. */ - } - else { - mrb_float d = mrb_float(x); - - if (isinf(d)) { - mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity"); - } - if (isnan(d)) { - mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN"); - } - z = (mrb_int)d; - } - return mrb_fixnum_value(z); -} - -mrb_value -mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y) -{ - mrb_int a; - - a = mrb_fixnum(x); - if (mrb_fixnum_p(y)) { - mrb_int b, c; - - if (a == 0) return y; - b = mrb_fixnum(y); - if (mrb_int_add_overflow(a, b, &c)) { - return mrb_float_value(mrb, (mrb_float)a + (mrb_float)b); - } - return mrb_fixnum_value(c); - } - return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y)); -} - -/* 15.2.8.3.1 */ -/* - * call-seq: - * fix + numeric -> numeric_result - * - * Performs addition: the class of the resulting object depends on - * the class of numeric and on the magnitude of the - * result. - */ -static mrb_value -fix_plus(mrb_state *mrb, mrb_value self) -{ - mrb_value other; - - mrb_get_args(mrb, "o", &other); - return mrb_fixnum_plus(mrb, self, other); -} - -mrb_value -mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y) -{ - mrb_int a; - - a = mrb_fixnum(x); - if (mrb_fixnum_p(y)) { - mrb_int b, c; - - b = mrb_fixnum(y); - if (mrb_int_sub_overflow(a, b, &c)) { - return mrb_float_value(mrb, (mrb_float)a - (mrb_float)b); - } - return mrb_fixnum_value(c); - } - return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y)); -} - -/* 15.2.8.3.2 */ -/* 15.2.8.3.16 */ -/* - * call-seq: - * fix - numeric -> numeric_result - * - * Performs subtraction: the class of the resulting object depends on - * the class of numeric and on the magnitude of the - * result. - */ -static mrb_value -fix_minus(mrb_state *mrb, mrb_value self) -{ - mrb_value other; - - mrb_get_args(mrb, "o", &other); - return mrb_fixnum_minus(mrb, self, other); -} - - -MRB_API mrb_value -mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base) -{ - char buf[MRB_INT_BIT+1]; - char *b = buf + sizeof buf; - mrb_int val = mrb_fixnum(x); - - if (base < 2 || 36 < base) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base)); - } - - if (val == 0) { - *--b = '0'; - } - else if (val < 0) { - do { - *--b = mrb_digitmap[-(val % base)]; - } while (val /= base); - *--b = '-'; - } - else { - do { - *--b = mrb_digitmap[(int)(val % base)]; - } while (val /= base); - } - - return mrb_str_new(mrb, b, buf + sizeof(buf) - b); -} - -/* 15.2.8.3.25 */ -/* - * call-seq: - * fix.to_s(base=10) -> string - * - * Returns a string containing the representation of fix radix - * base (between 2 and 36). - * - * 12345.to_s #=> "12345" - * 12345.to_s(2) #=> "11000000111001" - * 12345.to_s(8) #=> "30071" - * 12345.to_s(10) #=> "12345" - * 12345.to_s(16) #=> "3039" - * 12345.to_s(36) #=> "9ix" - * - */ -static mrb_value -fix_to_s(mrb_state *mrb, mrb_value self) -{ - mrb_int base = 10; - - mrb_get_args(mrb, "|i", &base); - return mrb_fixnum_to_str(mrb, self, base); -} - -/* 15.2.9.3.6 */ -/* - * call-seq: - * self.f <=> other.f => -1, 0, +1 - * < => -1 - * = => 0 - * > => +1 - * Comparison---Returns -1, 0, or +1 depending on whether fix is - * less than, equal to, or greater than numeric. This is the - * basis for the tests in Comparable. - */ -static mrb_value -num_cmp(mrb_state *mrb, mrb_value self) -{ - mrb_value other; - mrb_float x, y; - - mrb_get_args(mrb, "o", &other); - - x = mrb_to_flo(mrb, self); - switch (mrb_type(other)) { - case MRB_TT_FIXNUM: - y = (mrb_float)mrb_fixnum(other); - break; - case MRB_TT_FLOAT: - y = mrb_float(other); - break; - default: - return mrb_nil_value(); - } - if (x > y) - return mrb_fixnum_value(1); - else { - if (x < y) - return mrb_fixnum_value(-1); - return mrb_fixnum_value(0); - } -} - -/* 15.2.9.3.1 */ -/* - * call-seq: - * float + other -> float - * - * Returns a new float which is the sum of float - * and other. - */ -static mrb_value -flo_plus(mrb_state *mrb, mrb_value x) -{ - mrb_value y; - - mrb_get_args(mrb, "o", &y); - return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y)); -} - -/* ------------------------------------------------------------------------*/ -void -mrb_init_numeric(mrb_state *mrb) -{ - struct RClass *numeric, *integer, *fixnum, *fl; - - /* Numeric Class */ - numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); /* 15.2.7 */ - - mrb_define_method(mrb, numeric, "**", num_pow, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, numeric, "/", num_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.4 */ - mrb_define_method(mrb, numeric, "quo", num_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */ - mrb_define_method(mrb, numeric, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */ - - /* Integer Class */ - integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */ - mrb_undef_class_method(mrb, integer, "new"); - mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */ - mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE()); - - /* Fixnum Class */ - mrb->fixnum_class = fixnum = mrb_define_class(mrb, "Fixnum", integer); - mrb_define_method(mrb, fixnum, "+", fix_plus, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */ - mrb_define_method(mrb, fixnum, "-", fix_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */ - mrb_define_method(mrb, fixnum, "*", fix_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */ - mrb_define_method(mrb, fixnum, "%", fix_mod, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */ - mrb_define_method(mrb, fixnum, "==", fix_equal, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */ - mrb_define_method(mrb, fixnum, "~", fix_rev, MRB_ARGS_NONE()); /* 15.2.8.3.8 */ - mrb_define_method(mrb, fixnum, "&", fix_and, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */ - mrb_define_method(mrb, fixnum, "|", fix_or, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 */ - mrb_define_method(mrb, fixnum, "^", fix_xor, MRB_ARGS_REQ(1)); /* 15.2.8.3.11 */ - mrb_define_method(mrb, fixnum, "<<", fix_lshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 */ - mrb_define_method(mrb, fixnum, ">>", fix_rshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */ - mrb_define_method(mrb, fixnum, "eql?", fix_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ - mrb_define_method(mrb, fixnum, "hash", flo_hash, MRB_ARGS_NONE()); /* 15.2.8.3.18 */ - mrb_define_method(mrb, fixnum, "to_f", fix_to_f, MRB_ARGS_NONE()); /* 15.2.8.3.23 */ - mrb_define_method(mrb, fixnum, "to_s", fix_to_s, MRB_ARGS_NONE()); /* 15.2.8.3.25 */ - mrb_define_method(mrb, fixnum, "inspect", fix_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, fixnum, "divmod", fix_divmod, MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */ - - /* Float Class */ - mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */ - mrb_undef_class_method(mrb, fl, "new"); - mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */ - mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */ - mrb_define_method(mrb, fl, "*", flo_mul, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */ - mrb_define_method(mrb, fl, "%", flo_mod, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */ - mrb_define_method(mrb, fl, "==", flo_eq, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */ - mrb_define_method(mrb, fl, "ceil", flo_ceil, MRB_ARGS_NONE()); /* 15.2.9.3.8 */ - mrb_define_method(mrb, fl, "finite?", flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */ - mrb_define_method(mrb, fl, "floor", flo_floor, MRB_ARGS_NONE()); /* 15.2.9.3.10 */ - mrb_define_method(mrb, fl, "infinite?", flo_infinite_p, MRB_ARGS_NONE()); /* 15.2.9.3.11 */ - mrb_define_method(mrb, fl, "round", flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */ - mrb_define_method(mrb, fl, "to_f", flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */ - mrb_define_method(mrb, fl, "to_i", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.14 */ - mrb_define_method(mrb, fl, "to_int", flo_truncate, MRB_ARGS_NONE()); - mrb_define_method(mrb, fl, "truncate", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.15 */ - mrb_define_method(mrb, fl, "divmod", flo_divmod, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, "eql?", flo_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ - - mrb_define_method(mrb, fl, "to_s", flo_to_s, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */ - mrb_define_method(mrb, fl, "inspect", flo_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, fl, "nan?", flo_nan_p, MRB_ARGS_NONE()); - -#ifdef INFINITY - mrb_define_const(mrb, fl, "INFINITY", mrb_float_value(mrb, INFINITY)); -#endif -#ifdef NAN - mrb_define_const(mrb, fl, "NAN", mrb_float_value(mrb, NAN)); -#endif -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/object.c nghttp2-0.6.7/third-party/mruby/src/object.c --- nghttp2-1.13.0/third-party/mruby/src/object.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/object.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,601 +0,0 @@ -/* -** object.c - Object, NilClass, TrueClass, FalseClass class -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/numeric.h" -#include "mruby/string.h" - -MRB_API mrb_bool -mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) -{ - if (mrb_type(v1) != mrb_type(v2)) return FALSE; - switch (mrb_type(v1)) { - case MRB_TT_TRUE: - return TRUE; - - case MRB_TT_FALSE: - case MRB_TT_FIXNUM: - return (mrb_fixnum(v1) == mrb_fixnum(v2)); - case MRB_TT_SYMBOL: - return (mrb_symbol(v1) == mrb_symbol(v2)); - - case MRB_TT_FLOAT: - return (mrb_float(v1) == mrb_float(v2)); - - default: - return (mrb_ptr(v1) == mrb_ptr(v2)); - } -} - -MRB_API mrb_bool -mrb_obj_equal(mrb_state *mrb, mrb_value v1, mrb_value v2) -{ - /* temporary definition */ - return mrb_obj_eq(mrb, v1, v2); -} - -MRB_API mrb_bool -mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2) -{ - mrb_value result; - - if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE; - result = mrb_funcall(mrb, obj1, "==", 1, obj2); - if (mrb_test(result)) return TRUE; - return FALSE; -} - -/* - * Document-class: NilClass - * - * The class of the singleton object nil. - */ - -/* 15.2.4.3.4 */ -/* - * call_seq: - * nil.nil? -> true - * - * Only the object nil responds true to nil?. - */ - -static mrb_value -mrb_true(mrb_state *mrb, mrb_value obj) -{ - return mrb_true_value(); -} - -/* 15.2.4.3.5 */ -/* - * call-seq: - * nil.to_s -> "" - * - * Always returns the empty string. - */ - -static mrb_value -nil_to_s(mrb_state *mrb, mrb_value obj) -{ - return mrb_str_new(mrb, 0, 0); -} - -static mrb_value -nil_inspect(mrb_state *mrb, mrb_value obj) -{ - return mrb_str_new_lit(mrb, "nil"); -} - -/*********************************************************************** - * Document-class: TrueClass - * - * The global value true is the only instance of class - * TrueClass and represents a logically true value in - * boolean expressions. The class provides operators allowing - * true to be used in logical expressions. - */ - -/* 15.2.5.3.1 */ -/* - * call-seq: - * true & obj -> true or false - * - * And---Returns false if obj is - * nil or false, true otherwise. - */ - -static mrb_value -true_and(mrb_state *mrb, mrb_value obj) -{ - mrb_bool obj2; - - mrb_get_args(mrb, "b", &obj2); - - return mrb_bool_value(obj2); -} - -/* 15.2.5.3.2 */ -/* - * call-seq: - * true ^ obj -> !obj - * - * Exclusive Or---Returns true if obj is - * nil or false, false - * otherwise. - */ - -static mrb_value -true_xor(mrb_state *mrb, mrb_value obj) -{ - mrb_bool obj2; - - mrb_get_args(mrb, "b", &obj2); - return mrb_bool_value(!obj2); -} - -/* 15.2.5.3.3 */ -/* - * call-seq: - * true.to_s -> "true" - * - * The string representation of true is "true". - */ - -static mrb_value -true_to_s(mrb_state *mrb, mrb_value obj) -{ - return mrb_str_new_lit(mrb, "true"); -} - -/* 15.2.5.3.4 */ -/* - * call-seq: - * true | obj -> true - * - * Or---Returns true. As anObject is an argument to - * a method call, it is always evaluated; there is no short-circuit - * evaluation in this case. - * - * true | puts("or") - * true || puts("logical or") - * - * produces: - * - * or - */ - -static mrb_value -true_or(mrb_state *mrb, mrb_value obj) -{ - return mrb_true_value(); -} - -/* - * Document-class: FalseClass - * - * The global value false is the only instance of class - * FalseClass and represents a logically false value in - * boolean expressions. The class provides operators allowing - * false to participate correctly in logical expressions. - * - */ - -/* 15.2.4.3.1 */ -/* 15.2.6.3.1 */ -/* - * call-seq: - * false & obj -> false - * nil & obj -> false - * - * And---Returns false. obj is always - * evaluated as it is the argument to a method call---there is no - * short-circuit evaluation in this case. - */ - -static mrb_value -false_and(mrb_state *mrb, mrb_value obj) -{ - return mrb_false_value(); -} - -/* 15.2.4.3.2 */ -/* 15.2.6.3.2 */ -/* - * call-seq: - * false ^ obj -> true or false - * nil ^ obj -> true or false - * - * Exclusive Or---If obj is nil or - * false, returns false; otherwise, returns - * true. - * - */ - -static mrb_value -false_xor(mrb_state *mrb, mrb_value obj) -{ - mrb_bool obj2; - - mrb_get_args(mrb, "b", &obj2); - return mrb_bool_value(obj2); -} - -/* 15.2.4.3.3 */ -/* 15.2.6.3.4 */ -/* - * call-seq: - * false | obj -> true or false - * nil | obj -> true or false - * - * Or---Returns false if obj is - * nil or false; true otherwise. - */ - -static mrb_value -false_or(mrb_state *mrb, mrb_value obj) -{ - mrb_bool obj2; - - mrb_get_args(mrb, "b", &obj2); - return mrb_bool_value(obj2); -} - -/* 15.2.6.3.3 */ -/* - * call-seq: - * false.to_s -> "false" - * - * 'nuf said... - */ - -static mrb_value -false_to_s(mrb_state *mrb, mrb_value obj) -{ - return mrb_str_new_lit(mrb, "false"); -} - -void -mrb_init_object(mrb_state *mrb) -{ - struct RClass *n; - struct RClass *t; - struct RClass *f; - - mrb->nil_class = n = mrb_define_class(mrb, "NilClass", mrb->object_class); - mrb_undef_class_method(mrb, n, "new"); - mrb_define_method(mrb, n, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.4.3.1 */ - mrb_define_method(mrb, n, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.4.3.2 */ - mrb_define_method(mrb, n, "|", false_or, MRB_ARGS_REQ(1)); /* 15.2.4.3.3 */ - mrb_define_method(mrb, n, "nil?", mrb_true, MRB_ARGS_NONE()); /* 15.2.4.3.4 */ - mrb_define_method(mrb, n, "to_s", nil_to_s, MRB_ARGS_NONE()); /* 15.2.4.3.5 */ - mrb_define_method(mrb, n, "inspect", nil_inspect, MRB_ARGS_NONE()); - - mrb->true_class = t = mrb_define_class(mrb, "TrueClass", mrb->object_class); - mrb_undef_class_method(mrb, t, "new"); - mrb_define_method(mrb, t, "&", true_and, MRB_ARGS_REQ(1)); /* 15.2.5.3.1 */ - mrb_define_method(mrb, t, "^", true_xor, MRB_ARGS_REQ(1)); /* 15.2.5.3.2 */ - mrb_define_method(mrb, t, "to_s", true_to_s, MRB_ARGS_NONE()); /* 15.2.5.3.3 */ - mrb_define_method(mrb, t, "|", true_or, MRB_ARGS_REQ(1)); /* 15.2.5.3.4 */ - mrb_define_method(mrb, t, "inspect", true_to_s, MRB_ARGS_NONE()); - - mrb->false_class = f = mrb_define_class(mrb, "FalseClass", mrb->object_class); - mrb_undef_class_method(mrb, f, "new"); - mrb_define_method(mrb, f, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.6.3.1 */ - mrb_define_method(mrb, f, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.6.3.2 */ - mrb_define_method(mrb, f, "to_s", false_to_s, MRB_ARGS_NONE()); /* 15.2.6.3.3 */ - mrb_define_method(mrb, f, "|", false_or, MRB_ARGS_REQ(1)); /* 15.2.6.3.4 */ - mrb_define_method(mrb, f, "inspect", false_to_s, MRB_ARGS_NONE()); -} - -static mrb_value -inspect_type(mrb_state *mrb, mrb_value val) -{ - if (mrb_type(val) == MRB_TT_FALSE || mrb_type(val) == MRB_TT_TRUE) { - return mrb_inspect(mrb, val); - } - else { - return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, val)); - } -} - -static mrb_value -convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, mrb_bool raise) -{ - mrb_sym m = 0; - - m = mrb_intern_cstr(mrb, method); - if (!mrb_respond_to(mrb, val, m)) { - if (raise) { - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", inspect_type(mrb, val), mrb_str_new_cstr(mrb, tname)); - } - return mrb_nil_value(); - } - return mrb_funcall_argv(mrb, val, m, 0, 0); -} - -MRB_API mrb_value -mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method) -{ - mrb_value v; - - if (mrb_fixnum_p(val)) return val; - v = convert_type(mrb, val, "Integer", method, FALSE); - if (mrb_nil_p(v) || !mrb_fixnum_p(v)) { - return mrb_nil_value(); - } - return v; -} - -MRB_API mrb_value -mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method) -{ - mrb_value v; - - if (mrb_type(val) == type) return val; - v = convert_type(mrb, val, tname, method, TRUE); - if (mrb_type(v) != type) { - mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to %S by #%S", val, - mrb_str_new_cstr(mrb, tname), mrb_str_new_cstr(mrb, method)); - } - return v; -} - -MRB_API mrb_value -mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method) -{ - mrb_value v; - - if (mrb_type(val) == type && type != MRB_TT_DATA) return val; - v = convert_type(mrb, val, tname, method, FALSE); - if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value(); - return v; -} - -static const struct types { - unsigned char type; - const char *name; -} builtin_types[] = { -/* {MRB_TT_NIL, "nil"}, */ - {MRB_TT_FALSE, "false"}, - {MRB_TT_TRUE, "true"}, - {MRB_TT_FIXNUM, "Fixnum"}, - {MRB_TT_SYMBOL, "Symbol"}, /* :symbol */ - {MRB_TT_MODULE, "Module"}, - {MRB_TT_OBJECT, "Object"}, - {MRB_TT_CLASS, "Class"}, - {MRB_TT_ICLASS, "iClass"}, /* internal use: mixed-in module holder */ - {MRB_TT_SCLASS, "SClass"}, - {MRB_TT_PROC, "Proc"}, - {MRB_TT_FLOAT, "Float"}, - {MRB_TT_ARRAY, "Array"}, - {MRB_TT_HASH, "Hash"}, - {MRB_TT_STRING, "String"}, - {MRB_TT_RANGE, "Range"}, -/* {MRB_TT_BIGNUM, "Bignum"}, */ - {MRB_TT_FILE, "File"}, - {MRB_TT_DATA, "Data"}, /* internal use: wrapped C pointers */ -/* {MRB_TT_VARMAP, "Varmap"}, */ /* internal use: dynamic variables */ -/* {MRB_TT_NODE, "Node"}, */ /* internal use: syntax tree node */ -/* {MRB_TT_UNDEF, "undef"}, */ /* internal use: #undef; should not happen */ - {-1, 0} -}; - -MRB_API void -mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) -{ - const struct types *type = builtin_types; - enum mrb_vtype xt; - - xt = mrb_type(x); - if ((xt != t) || (xt == MRB_TT_DATA)) { - while (type->type < MRB_TT_MAXDEFINE) { - if (type->type == t) { - const char *etype; - - if (mrb_nil_p(x)) { - etype = "nil"; - } - else if (mrb_fixnum_p(x)) { - etype = "Fixnum"; - } - else if (mrb_type(x) == MRB_TT_SYMBOL) { - etype = "Symbol"; - } - else if (mrb_immediate_p(x)) { - etype = RSTRING_PTR(mrb_obj_as_string(mrb, x)); - } - else { - etype = mrb_obj_classname(mrb, x); - } - mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)", - mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->name)); - } - type++; - } - mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %S (%S given)", - mrb_fixnum_value(t), mrb_fixnum_value(mrb_type(x))); - } -} - -/* 15.3.1.3.46 */ -/* - * call-seq: - * obj.to_s => string - * - * Returns a string representing obj. The default - * to_s prints the object's class and an encoding of the - * object id. As a special case, the top-level object that is the - * initial execution context of Ruby programs returns "main." - */ - -MRB_API mrb_value -mrb_any_to_s(mrb_state *mrb, mrb_value obj) -{ - mrb_value str = mrb_str_buf_new(mrb, 20); - const char *cname = mrb_obj_classname(mrb, obj); - - mrb_str_cat_lit(mrb, str, "#<"); - mrb_str_cat_cstr(mrb, str, cname); - mrb_str_cat_lit(mrb, str, ":"); - mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(obj))); - mrb_str_cat_lit(mrb, str, ">"); - - return str; -} - -/* - * call-seq: - * obj.is_a?(class) => true or false - * obj.kind_of?(class) => true or false - * - * Returns true if class is the class of - * obj, or if class is one of the superclasses of - * obj or modules included in obj. - * - * module M; end - * class A - * include M - * end - * class B < A; end - * class C < B; end - * b = B.new - * b.instance_of? A #=> false - * b.instance_of? B #=> true - * b.instance_of? C #=> false - * b.instance_of? M #=> false - * b.kind_of? A #=> true - * b.kind_of? B #=> true - * b.kind_of? C #=> false - * b.kind_of? M #=> true - */ - -MRB_API mrb_bool -mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c) -{ - struct RClass *cl = mrb_class(mrb, obj); - - switch (c->tt) { - case MRB_TT_MODULE: - case MRB_TT_CLASS: - case MRB_TT_ICLASS: - break; - - default: - mrb_raise(mrb, E_TYPE_ERROR, "class or module required"); - } - - MRB_CLASS_ORIGIN(c); - while (cl) { - if (cl == c || cl->mt == c->mt) - return TRUE; - cl = cl->super; - } - return FALSE; -} - -static mrb_value -mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method) -{ - mrb_value v; - - if (mrb_fixnum_p(val)) return val; - v = convert_type(mrb, val, "Integer", method, TRUE); - if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) { - mrb_value type = inspect_type(mrb, val); - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)", - type, type, mrb_str_new_cstr(mrb, method), inspect_type(mrb, v)); - } - return v; -} - -MRB_API mrb_value -mrb_to_int(mrb_state *mrb, mrb_value val) -{ - return mrb_to_integer(mrb, val, "to_int"); -} - -MRB_API mrb_value -mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base) -{ - mrb_value tmp; - - if (mrb_nil_p(val)) { - if (base != 0) goto arg_error; - mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer"); - } - switch (mrb_type(val)) { - case MRB_TT_FLOAT: - if (base != 0) goto arg_error; - if (FIXABLE(mrb_float(val))) { - break; - } - return mrb_flo_to_fixnum(mrb, val); - - case MRB_TT_FIXNUM: - if (base != 0) goto arg_error; - return val; - - case MRB_TT_STRING: - string_conv: - return mrb_str_to_inum(mrb, val, base, TRUE); - - default: - break; - } - if (base != 0) { - tmp = mrb_check_string_type(mrb, val); - if (!mrb_nil_p(tmp)) { - goto string_conv; - } -arg_error: - mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value"); - } - tmp = convert_type(mrb, val, "Integer", "to_int", FALSE); - if (mrb_nil_p(tmp)) { - return mrb_to_integer(mrb, val, "to_i"); - } - return tmp; -} - -MRB_API mrb_value -mrb_Integer(mrb_state *mrb, mrb_value val) -{ - return mrb_convert_to_integer(mrb, val, 0); -} - -MRB_API mrb_value -mrb_Float(mrb_state *mrb, mrb_value val) -{ - if (mrb_nil_p(val)) { - mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Float"); - } - switch (mrb_type(val)) { - case MRB_TT_FIXNUM: - return mrb_float_value(mrb, (mrb_float)mrb_fixnum(val)); - - case MRB_TT_FLOAT: - return val; - - case MRB_TT_STRING: - return mrb_float_value(mrb, mrb_str_to_dbl(mrb, val, TRUE)); - - default: - return mrb_convert_type(mrb, val, MRB_TT_FLOAT, "Float", "to_f"); - } -} - -MRB_API mrb_value -mrb_inspect(mrb_state *mrb, mrb_value obj) -{ - return mrb_obj_as_string(mrb, mrb_funcall(mrb, obj, "inspect", 0)); -} - -MRB_API mrb_bool -mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2) -{ - if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE; - return mrb_test(mrb_funcall(mrb, obj1, "eql?", 1, obj2)); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/opcode.h nghttp2-0.6.7/third-party/mruby/src/opcode.h --- nghttp2-1.13.0/third-party/mruby/src/opcode.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/opcode.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -/* this header file is to be removed soon. */ -#include "mruby/opcode.h" diff -Nru nghttp2-1.13.0/third-party/mruby/src/pool.c nghttp2-0.6.7/third-party/mruby/src/pool.c --- nghttp2-1.13.0/third-party/mruby/src/pool.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/pool.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,194 +0,0 @@ -/* -** pool.c - memory pool -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include -#include "mruby.h" - -/* configuration section */ -/* allocated memory address should be multiple of POOL_ALIGNMENT */ -/* or undef it if alignment does not matter */ -#ifndef POOL_ALIGNMENT -#define POOL_ALIGNMENT 4 -#endif -/* page size of memory pool */ -#ifndef POOL_PAGE_SIZE -#define POOL_PAGE_SIZE 16000 -#endif -/* end of configuration section */ - -struct mrb_pool_page { - struct mrb_pool_page *next; - size_t offset; - size_t len; - void *last; - char page[]; -}; - -struct mrb_pool { - mrb_state *mrb; - struct mrb_pool_page *pages; -}; - -#undef TEST_POOL -#ifdef TEST_POOL - -#define mrb_malloc_simple(m,s) malloc(s) -#define mrb_free(m,p) free(p) -#endif - -#ifdef POOL_ALIGNMENT -# define ALIGN_PADDING(x) ((SIZE_MAX - (x) + 1) & (POOL_ALIGNMENT - 1)) -#else -# define ALIGN_PADDING(x) (0) -#endif - -MRB_API mrb_pool* -mrb_pool_open(mrb_state *mrb) -{ - mrb_pool *pool = (mrb_pool *)mrb_malloc_simple(mrb, sizeof(mrb_pool)); - - if (pool) { - pool->mrb = mrb; - pool->pages = NULL; - } - - return pool; -} - -MRB_API void -mrb_pool_close(mrb_pool *pool) -{ - struct mrb_pool_page *page, *tmp; - - if (!pool) return; - page = pool->pages; - while (page) { - tmp = page; - page = page->next; - mrb_free(pool->mrb, tmp); - } - mrb_free(pool->mrb, pool); -} - -static struct mrb_pool_page* -page_alloc(mrb_pool *pool, size_t len) -{ - struct mrb_pool_page *page; - - if (len < POOL_PAGE_SIZE) - len = POOL_PAGE_SIZE; - page = (struct mrb_pool_page *)mrb_malloc_simple(pool->mrb, sizeof(struct mrb_pool_page)+len); - if (page) { - page->offset = 0; - page->len = len; - } - - return page; -} - -MRB_API void* -mrb_pool_alloc(mrb_pool *pool, size_t len) -{ - struct mrb_pool_page *page; - size_t n; - - if (!pool) return NULL; - len += ALIGN_PADDING(len); - page = pool->pages; - while (page) { - if (page->offset + len <= page->len) { - n = page->offset; - page->offset += len; - page->last = (char*)page->page+n; - return page->last; - } - page = page->next; - } - page = page_alloc(pool, len); - if (!page) return NULL; - page->offset = len; - page->next = pool->pages; - pool->pages = page; - - page->last = (void*)page->page; - return page->last; -} - -MRB_API mrb_bool -mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len) -{ - struct mrb_pool_page *page; - - if (!pool) return FALSE; - len += ALIGN_PADDING(len); - page = pool->pages; - while (page) { - if (page->last == p) { - size_t beg; - - beg = (char*)p - page->page; - if (beg + len > page->len) return FALSE; - return TRUE; - } - page = page->next; - } - return FALSE; -} - -MRB_API void* -mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen) -{ - struct mrb_pool_page *page; - void *np; - - if (!pool) return NULL; - oldlen += ALIGN_PADDING(oldlen); - newlen += ALIGN_PADDING(newlen); - page = pool->pages; - while (page) { - if (page->last == p) { - size_t beg; - - beg = (char*)p - page->page; - if (beg + oldlen != page->offset) break; - if (beg + newlen > page->len) { - page->offset = beg; - break; - } - page->offset = beg + newlen; - return p; - } - page = page->next; - } - np = mrb_pool_alloc(pool, newlen); - if (np == NULL) { - return NULL; - } - memcpy(np, p, oldlen); - return np; -} - -#ifdef TEST_POOL -int -main(void) -{ - int i, len = 250; - mrb_pool *pool; - void *p; - - pool = mrb_pool_open(NULL); - p = mrb_pool_alloc(pool, len); - for (i=1; i<20; i++) { - printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2)); - p = mrb_pool_realloc(pool, p, len, len*2); - len *= 2; - } - mrb_pool_close(pool); - return 0; -} -#endif diff -Nru nghttp2-1.13.0/third-party/mruby/src/print.c nghttp2-0.6.7/third-party/mruby/src/print.c --- nghttp2-1.13.0/third-party/mruby/src/print.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/print.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -/* -** print.c - Kernel.#p -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/string.h" -#include "mruby/variable.h" - -#ifndef MRB_DISABLE_STDIO -static void -printstr(mrb_value obj, FILE *stream) -{ - if (mrb_string_p(obj)) { - fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stream); - putc('\n', stream); - } -} -#else -# define printstr(obj, stream) (void)0 -#endif - -MRB_API void -mrb_p(mrb_state *mrb, mrb_value obj) -{ - printstr(mrb_inspect(mrb, obj), stdout); -} - -MRB_API void -mrb_print_error(mrb_state *mrb) -{ - mrb_print_backtrace(mrb); - printstr(mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0), stderr); -} - -MRB_API void -mrb_show_version(mrb_state *mrb) -{ - printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_DESCRIPTION")), stdout); -} - -MRB_API void -mrb_show_copyright(mrb_state *mrb) -{ - printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_COPYRIGHT")), stdout); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/proc.c nghttp2-0.6.7/third-party/mruby/src/proc.c --- nghttp2-1.13.0/third-party/mruby/src/proc.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/proc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,280 +0,0 @@ -/* -** proc.c - Proc class -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/proc.h" -#include "mruby/opcode.h" - -static mrb_code call_iseq[] = { - MKOP_A(OP_CALL, 0), -}; - -struct RProc * -mrb_proc_new(mrb_state *mrb, mrb_irep *irep) -{ - struct RProc *p; - mrb_callinfo *ci = mrb->c->ci; - - p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); - p->target_class = 0; - if (ci) { - if (ci->proc) - p->target_class = ci->proc->target_class; - if (!p->target_class) - p->target_class = ci->target_class; - } - p->body.irep = irep; - p->env = 0; - mrb_irep_incref(mrb, irep); - - return p; -} - -static struct REnv* -env_new(mrb_state *mrb, int nlocals) -{ - struct REnv *e; - - e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env); - MRB_SET_ENV_STACK_LEN(e, nlocals); - e->mid = mrb->c->ci->mid; - e->cioff = mrb->c->ci - mrb->c->cibase; - e->stack = mrb->c->stack; - - return e; -} - -static void -closure_setup(mrb_state *mrb, struct RProc *p, int nlocals) -{ - struct REnv *e; - - if (!mrb->c->ci->env) { - e = env_new(mrb, nlocals); - mrb->c->ci->env = e; - } - else { - e = mrb->c->ci->env; - } - p->env = e; -} - -struct RProc * -mrb_closure_new(mrb_state *mrb, mrb_irep *irep) -{ - struct RProc *p = mrb_proc_new(mrb, irep); - - closure_setup(mrb, p, mrb->c->ci->proc->body.irep->nlocals); - return p; -} - -MRB_API struct RProc * -mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func) -{ - struct RProc *p; - - p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); - p->body.func = func; - p->flags |= MRB_PROC_CFUNC; - p->env = 0; - - return p; -} - -MRB_API struct RProc * -mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv) -{ - struct RProc *p = mrb_proc_new_cfunc(mrb, func); - struct REnv *e; - int i; - - p->env = e = env_new(mrb, argc); - mrb_field_write_barrier(mrb, (struct RBasic *)p, (struct RBasic *)p->env); - MRB_ENV_UNSHARE_STACK(e); - e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc); - if (argv) { - for (i = 0; i < argc; ++i) { - e->stack[i] = argv[i]; - } - } - else { - for (i = 0; i < argc; ++i) { - SET_NIL_VALUE(e->stack[i]); - } - } - return p; -} - -MRB_API struct RProc * -mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals) -{ - return mrb_proc_new_cfunc_with_env(mrb, func, nlocals, NULL); -} - -MRB_API mrb_value -mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx) -{ - struct RProc *p = mrb->c->ci->proc; - struct REnv *e = p->env; - - if (!MRB_PROC_CFUNC_P(p)) { - mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from non-cfunc proc."); - } - if (!e) { - mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv."); - } - if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) { - mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %S (expected: 0 <= index < %S)", - mrb_fixnum_value(idx), mrb_fixnum_value(MRB_ENV_STACK_LEN(e))); - } - - return e->stack[idx]; -} - -MRB_API void -mrb_proc_copy(struct RProc *a, struct RProc *b) -{ - a->flags = b->flags; - a->body = b->body; - if (!MRB_PROC_CFUNC_P(a)) { - a->body.irep->refcnt++; - } - a->target_class = b->target_class; - a->env = b->env; -} - -static mrb_value -mrb_proc_initialize(mrb_state *mrb, mrb_value self) -{ - mrb_value blk; - - mrb_get_args(mrb, "&", &blk); - if (mrb_nil_p(blk)) { - /* Calling Proc.new without a block is not implemented yet */ - mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); - } - else { - mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(blk)); - } - return self; -} - -static mrb_value -mrb_proc_init_copy(mrb_state *mrb, mrb_value self) -{ - mrb_value proc; - - mrb_get_args(mrb, "o", &proc); - if (mrb_type(proc) != MRB_TT_PROC) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc"); - } - mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(proc)); - return self; -} - -int -mrb_proc_cfunc_p(struct RProc *p) -{ - return MRB_PROC_CFUNC_P(p); -} - -mrb_value -mrb_proc_call_cfunc(mrb_state *mrb, struct RProc *p, mrb_value self) -{ - return (p->body.func)(mrb, self); -} - -mrb_code* -mrb_proc_iseq(mrb_state *mrb, struct RProc *p) -{ - return p->body.irep->iseq; -} - -/* 15.2.17.4.2 */ -static mrb_value -mrb_proc_arity(mrb_state *mrb, mrb_value self) -{ - struct RProc *p = mrb_proc_ptr(self); - mrb_code *iseq = mrb_proc_iseq(mrb, p); - mrb_aspec aspec; - int ma, op, ra, pa, arity; - - if (MRB_PROC_CFUNC_P(p)) { - /* TODO cfunc aspec not implemented yet */ - return mrb_fixnum_value(-1); - } - - /* arity is depend on OP_ENTER */ - if (GET_OPCODE(*iseq) != OP_ENTER) { - return mrb_fixnum_value(0); - } - - aspec = GETARG_Ax(*iseq); - ma = MRB_ASPEC_REQ(aspec); - op = MRB_ASPEC_OPT(aspec); - ra = MRB_ASPEC_REST(aspec); - pa = MRB_ASPEC_POST(aspec); - arity = ra || (MRB_PROC_STRICT_P(p) && op) ? -(ma + pa + 1) : ma + pa; - - return mrb_fixnum_value(arity); -} - -/* 15.3.1.2.6 */ -/* 15.3.1.3.27 */ -/* - * call-seq: - * lambda { |...| block } -> a_proc - * - * Equivalent to Proc.new, except the resulting Proc objects - * check the number of parameters passed when called. - */ -static mrb_value -proc_lambda(mrb_state *mrb, mrb_value self) -{ - mrb_value blk; - struct RProc *p; - - mrb_get_args(mrb, "&", &blk); - if (mrb_nil_p(blk)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block"); - } - if (mrb_type(blk) != MRB_TT_PROC) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc"); - } - p = mrb_proc_ptr(blk); - if (!MRB_PROC_STRICT_P(p)) { - struct RProc *p2 = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, p->c); - mrb_proc_copy(p2, p); - p2->flags |= MRB_PROC_STRICT; - return mrb_obj_value(p2); - } - return blk; -} - -void -mrb_init_proc(mrb_state *mrb) -{ - struct RProc *m; - mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); - static const mrb_irep mrb_irep_zero = { 0 }; - - *call_irep = mrb_irep_zero; - call_irep->flags = MRB_ISEQ_NO_FREE; - call_irep->iseq = call_iseq; - call_irep->ilen = 1; - - mrb_define_method(mrb, mrb->proc_class, "initialize", mrb_proc_initialize, MRB_ARGS_NONE()); - mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE()); - - m = mrb_proc_new(mrb, call_irep); - mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m); - mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m); - - mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.2.6 */ - mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.3.27 */ -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/range.c nghttp2-0.6.7/third-party/mruby/src/range.c --- nghttp2-1.13.0/third-party/mruby/src/range.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/range.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,434 +0,0 @@ -/* -** range.c - Range class -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/range.h" -#include "mruby/string.h" -#include "mruby/array.h" - -#define RANGE_CLASS (mrb_class_get(mrb, "Range")) - -static void -range_check(mrb_state *mrb, mrb_value a, mrb_value b) -{ - mrb_value ans; - enum mrb_vtype ta; - enum mrb_vtype tb; - - ta = mrb_type(a); - tb = mrb_type(b); - if ((ta == MRB_TT_FIXNUM || ta == MRB_TT_FLOAT) && - (tb == MRB_TT_FIXNUM || tb == MRB_TT_FLOAT)) { - return; - } - - ans = mrb_funcall(mrb, a, "<=>", 1, b); - if (mrb_nil_p(ans)) { - /* can not be compared */ - mrb_raise(mrb, E_ARGUMENT_ERROR, "bad value for range"); - } -} - -MRB_API mrb_value -mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl) -{ - struct RRange *r; - - range_check(mrb, beg, end); - r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, RANGE_CLASS); - r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges)); - r->edges->beg = beg; - r->edges->end = end; - r->excl = excl; - return mrb_range_value(r); -} - -/* - * call-seq: - * rng.first => obj - * rng.begin => obj - * - * Returns the first object in rng. - */ -mrb_value -mrb_range_beg(mrb_state *mrb, mrb_value range) -{ - struct RRange *r = mrb_range_ptr(range); - - return r->edges->beg; -} - -/* - * call-seq: - * rng.end => obj - * rng.last => obj - * - * Returns the object that defines the end of rng. - * - * (1..10).end #=> 10 - * (1...10).end #=> 10 - */ - -mrb_value -mrb_range_end(mrb_state *mrb, mrb_value range) -{ - struct RRange *r = mrb_range_ptr(range); - - return r->edges->end; -} - -/* - * call-seq: - * range.exclude_end? => true or false - * - * Returns true if range excludes its end value. - */ -mrb_value -mrb_range_excl(mrb_state *mrb, mrb_value range) -{ - struct RRange *r = mrb_range_ptr(range); - - return mrb_bool_value(r->excl); -} - -static void -range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_bool exclude_end) -{ - struct RRange *r = mrb_range_ptr(range); - - range_check(mrb, beg, end); - r->excl = exclude_end; - if (!r->edges) { - r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges)); - } - r->edges->beg = beg; - r->edges->end = end; -} -/* - * call-seq: - * Range.new(start, end, exclusive=false) => range - * - * Constructs a range using the given start and end. If the third - * parameter is omitted or is false, the range will include - * the end object; otherwise, it will be excluded. - */ - -mrb_value -mrb_range_initialize(mrb_state *mrb, mrb_value range) -{ - mrb_value beg, end; - mrb_bool exclusive; - int n; - - n = mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive); - if (n != 3) { - exclusive = FALSE; - } - /* Ranges are immutable, so that they should be initialized only once. */ - range_init(mrb, range, beg, end, exclusive); - return range; -} -/* - * call-seq: - * range == obj => true or false - * - * Returns true only if - * 1) obj is a Range, - * 2) obj has equivalent beginning and end items (by comparing them with ==), - * 3) obj has the same #exclude_end? setting as rng. - * - * (0..2) == (0..2) #=> true - * (0..2) == Range.new(0,2) #=> true - * (0..2) == (0...2) #=> false - * - */ - -mrb_value -mrb_range_eq(mrb_state *mrb, mrb_value range) -{ - struct RRange *rr; - struct RRange *ro; - mrb_value obj; - - mrb_get_args(mrb, "o", &obj); - - if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); - if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */ - return mrb_false_value(); - } - - rr = mrb_range_ptr(range); - ro = mrb_range_ptr(obj); - if (!mrb_bool(mrb_funcall(mrb, rr->edges->beg, "==", 1, ro->edges->beg)) || - !mrb_bool(mrb_funcall(mrb, rr->edges->end, "==", 1, ro->edges->end)) || - rr->excl != ro->excl) { - return mrb_false_value(); - } - return mrb_true_value(); -} - -static mrb_bool -r_le(mrb_state *mrb, mrb_value a, mrb_value b) -{ - mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ - /* output :a < b => -1, a = b => 0, a > b => +1 */ - - if (mrb_fixnum_p(r)) { - mrb_int c = mrb_fixnum(r); - if (c == 0 || c == -1) return TRUE; - } - - return FALSE; -} - -static mrb_bool -r_gt(mrb_state *mrb, mrb_value a, mrb_value b) -{ - mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); - /* output :a < b => -1, a = b => 0, a > b => +1 */ - - return mrb_fixnum_p(r) && mrb_fixnum(r) == 1; -} - -static mrb_bool -r_ge(mrb_state *mrb, mrb_value a, mrb_value b) -{ - mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ - /* output :a < b => -1, a = b => 0, a > b => +1 */ - - if (mrb_fixnum_p(r)) { - mrb_int c = mrb_fixnum(r); - if (c == 0 || c == 1) return TRUE; - } - - return FALSE; -} - -/* - * call-seq: - * range === obj => true or false - * range.member?(val) => true or false - * range.include?(val) => true or false - * - */ -mrb_value -mrb_range_include(mrb_state *mrb, mrb_value range) -{ - mrb_value val; - struct RRange *r = mrb_range_ptr(range); - mrb_value beg, end; - mrb_bool include_p; - - mrb_get_args(mrb, "o", &val); - - beg = r->edges->beg; - end = r->edges->end; - include_p = r_le(mrb, beg, val) && /* beg <= val */ - ((r->excl && r_gt(mrb, end, val)) || /* end > val */ - (r_ge(mrb, end, val))); /* end >= val */ - - return mrb_bool_value(include_p); -} - -static mrb_bool -range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc) -{ - mrb_int beg, end; - struct RRange *r = mrb_range_ptr(range); - - if (mrb_type(range) != MRB_TT_RANGE) return FALSE; - - beg = mrb_int(mrb, r->edges->beg); - end = mrb_int(mrb, r->edges->end); - - if (beg < 0) { - beg += len; - if (beg < 0) return FALSE; - } - - if (trunc) { - if (beg > len) return FALSE; - if (end > len) end = len; - } - - if (end < 0) end += len; - if (!r->excl && (!trunc || end < len)) - end++; /* include end point */ - len = end - beg; - if (len < 0) len = 0; - - *begp = beg; - *lenp = len; - return TRUE; -} - -MRB_API mrb_bool -mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len) -{ - return range_beg_len(mrb, range, begp, lenp, len, TRUE); -} - -/* 15.2.14.4.12(x) */ -/* - * call-seq: - * rng.to_s -> string - * - * Convert this range object to a printable form. - */ - -static mrb_value -range_to_s(mrb_state *mrb, mrb_value range) -{ - mrb_value str, str2; - struct RRange *r = mrb_range_ptr(range); - - str = mrb_obj_as_string(mrb, r->edges->beg); - str2 = mrb_obj_as_string(mrb, r->edges->end); - str = mrb_str_dup(mrb, str); - mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2); - mrb_str_cat_str(mrb, str, str2); - - return str; -} - -/* 15.2.14.4.13(x) */ -/* - * call-seq: - * rng.inspect -> string - * - * Convert this range object to a printable form (using - * inspect to convert the start and end - * objects). - */ - -static mrb_value -range_inspect(mrb_state *mrb, mrb_value range) -{ - mrb_value str, str2; - struct RRange *r = mrb_range_ptr(range); - - str = mrb_inspect(mrb, r->edges->beg); - str2 = mrb_inspect(mrb, r->edges->end); - str = mrb_str_dup(mrb, str); - mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2); - mrb_str_cat_str(mrb, str, str2); - - return str; -} - -/* 15.2.14.4.14(x) */ -/* - * call-seq: - * rng.eql?(obj) -> true or false - * - * Returns true only if obj is a Range, has equivalent - * beginning and end items (by comparing them with #eql?), and has the same - * #exclude_end? setting as rng. - * - * (0..2).eql?(0..2) #=> true - * (0..2).eql?(Range.new(0,2)) #=> true - * (0..2).eql?(0...2) #=> false - * - */ - -static mrb_value -range_eql(mrb_state *mrb, mrb_value range) -{ - mrb_value obj; - struct RRange *r, *o; - - mrb_get_args(mrb, "o", &obj); - - if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); - if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) { - return mrb_false_value(); - } - if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value(); - - r = mrb_range_ptr(range); - o = mrb_range_ptr(obj); - if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) || - !mrb_eql(mrb, r->edges->end, o->edges->end) || - (r->excl != o->excl)) { - return mrb_false_value(); - } - return mrb_true_value(); -} - -/* 15.2.14.4.15(x) */ -static mrb_value -range_initialize_copy(mrb_state *mrb, mrb_value copy) -{ - mrb_value src; - struct RRange *r; - - mrb_get_args(mrb, "o", &src); - - if (mrb_obj_equal(mrb, copy, src)) return copy; - if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) { - mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class"); - } - - r = mrb_range_ptr(src); - range_init(mrb, copy, r->edges->beg, r->edges->end, r->excl); - - return copy; -} - -mrb_value -mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int)) -{ - mrb_int i, j, beg, len; - mrb_value result; - result = mrb_ary_new(mrb); - - for (i = 0; i < argc; ++i) { - if (mrb_fixnum_p(argv[i])) { - mrb_ary_push(mrb, result, func(mrb, obj, mrb_fixnum(argv[i]))); - } - else if (range_beg_len(mrb, argv[i], &beg, &len, olen, FALSE)) { - mrb_int const end = olen < beg + len ? olen : beg + len; - for (j = beg; j < end; ++j) { - mrb_ary_push(mrb, result, func(mrb, obj, j)); - } - - for (; j < beg + len; ++j) { - mrb_ary_push(mrb, result, mrb_nil_value()); - } - } - else { - mrb_raisef(mrb, E_TYPE_ERROR, "invalid values selector: %S", argv[i]); - } - } - - return result; -} - -void -mrb_init_range(mrb_state *mrb) -{ - struct RClass *r; - - r = mrb_define_class(mrb, "Range", mrb->object_class); /* 15.2.14 */ - MRB_SET_INSTANCE_TT(r, MRB_TT_RANGE); - - mrb_define_method(mrb, r, "begin", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */ - mrb_define_method(mrb, r, "end", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */ - mrb_define_method(mrb, r, "==", mrb_range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */ - mrb_define_method(mrb, r, "===", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */ - mrb_define_method(mrb, r, "exclude_end?", mrb_range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */ - mrb_define_method(mrb, r, "first", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.7 */ - mrb_define_method(mrb, r, "include?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */ - mrb_define_method(mrb, r, "initialize", mrb_range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */ - mrb_define_method(mrb, r, "last", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.10 */ - mrb_define_method(mrb, r, "member?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */ - - mrb_define_method(mrb, r, "to_s", range_to_s, MRB_ARGS_NONE()); /* 15.2.14.4.12(x) */ - mrb_define_method(mrb, r, "inspect", range_inspect, MRB_ARGS_NONE()); /* 15.2.14.4.13(x) */ - mrb_define_method(mrb, r, "eql?", range_eql, MRB_ARGS_REQ(1)); /* 15.2.14.4.14(x) */ - mrb_define_method(mrb, r, "initialize_copy", range_initialize_copy, MRB_ARGS_REQ(1)); /* 15.2.14.4.15(x) */ -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/state.c nghttp2-0.6.7/third-party/mruby/src/state.c --- nghttp2-1.13.0/third-party/mruby/src/state.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/state.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,295 +0,0 @@ -/* -** state.c - mrb_state open/close functions -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/variable.h" -#include "mruby/debug.h" -#include "mruby/string.h" - -void mrb_init_core(mrb_state*); -void mrb_init_mrbgems(mrb_state*); - -void mrb_gc_init(mrb_state*, mrb_gc *gc); -void mrb_gc_destroy(mrb_state*, mrb_gc *gc); - -static mrb_value -inspect_main(mrb_state *mrb, mrb_value mod) -{ - return mrb_str_new_lit(mrb, "main"); -} - -MRB_API mrb_state* -mrb_open_core(mrb_allocf f, void *ud) -{ - static const mrb_state mrb_state_zero = { 0 }; - static const struct mrb_context mrb_context_zero = { 0 }; - mrb_state *mrb; - - mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud); - if (mrb == NULL) return NULL; - - *mrb = mrb_state_zero; - mrb->allocf_ud = ud; - mrb->allocf = f; - mrb->atexit_stack_len = 0; - - mrb_gc_init(mrb, &mrb->gc); - mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); - *mrb->c = mrb_context_zero; - mrb->root_c = mrb->c; - - mrb_init_core(mrb); - - return mrb; -} - -void* -mrb_default_allocf(mrb_state *mrb, void *p, size_t size, void *ud) -{ - if (size == 0) { - free(p); - return NULL; - } - else { - return realloc(p, size); - } -} - -struct alloca_header { - struct alloca_header *next; - char buf[]; -}; - -MRB_API void* -mrb_alloca(mrb_state *mrb, size_t size) -{ - struct alloca_header *p; - - p = (struct alloca_header*) mrb_malloc(mrb, sizeof(struct alloca_header)+size); - p->next = mrb->mems; - mrb->mems = p; - return (void*)p->buf; -} - -static void -mrb_alloca_free(mrb_state *mrb) -{ - struct alloca_header *p; - struct alloca_header *tmp; - - if (mrb == NULL) return; - p = mrb->mems; - - while (p) { - tmp = p; - p = p->next; - mrb_free(mrb, tmp); - } -} - -MRB_API mrb_state* -mrb_open(void) -{ - mrb_state *mrb = mrb_open_allocf(mrb_default_allocf, NULL); - - return mrb; -} - -MRB_API mrb_state* -mrb_open_allocf(mrb_allocf f, void *ud) -{ - mrb_state *mrb = mrb_open_core(f, ud); - - if (mrb == NULL) { - return NULL; - } - -#ifndef DISABLE_GEMS - mrb_init_mrbgems(mrb); - mrb_gc_arena_restore(mrb, 0); -#endif - return mrb; -} - -void mrb_free_symtbl(mrb_state *mrb); - -void -mrb_irep_incref(mrb_state *mrb, mrb_irep *irep) -{ - irep->refcnt++; -} - -void -mrb_irep_decref(mrb_state *mrb, mrb_irep *irep) -{ - irep->refcnt--; - if (irep->refcnt == 0) { - mrb_irep_free(mrb, irep); - } -} - -void -mrb_irep_free(mrb_state *mrb, mrb_irep *irep) -{ - size_t i; - - if (!(irep->flags & MRB_ISEQ_NO_FREE)) - mrb_free(mrb, irep->iseq); - for (i=0; iplen; i++) { - if (mrb_type(irep->pool[i]) == MRB_TT_STRING) { - mrb_gc_free_str(mrb, RSTRING(irep->pool[i])); - mrb_free(mrb, mrb_obj_ptr(irep->pool[i])); - } -#ifdef MRB_WORD_BOXING - else if (mrb_type(irep->pool[i]) == MRB_TT_FLOAT) { - mrb_free(mrb, mrb_obj_ptr(irep->pool[i])); - } -#endif - } - mrb_free(mrb, irep->pool); - mrb_free(mrb, irep->syms); - for (i=0; irlen; i++) { - mrb_irep_decref(mrb, irep->reps[i]); - } - mrb_free(mrb, irep->reps); - mrb_free(mrb, irep->lv); - mrb_free(mrb, (void *)irep->filename); - mrb_free(mrb, irep->lines); - mrb_debug_info_free(mrb, irep->debug_info); - mrb_free(mrb, irep); -} - -mrb_value -mrb_str_pool(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - struct RString *ns; - char *ptr; - mrb_int len; - - ns = (struct RString *)mrb_malloc(mrb, sizeof(struct RString)); - ns->tt = MRB_TT_STRING; - ns->c = mrb->string_class; - - if (RSTR_NOFREE_P(s)) { - ns->flags = MRB_STR_NOFREE; - ns->as.heap.ptr = s->as.heap.ptr; - ns->as.heap.len = s->as.heap.len; - ns->as.heap.aux.capa = 0; - } - else { - ns->flags = 0; - if (RSTR_EMBED_P(s)) { - ptr = s->as.ary; - len = RSTR_EMBED_LEN(s); - } - else { - ptr = s->as.heap.ptr; - len = s->as.heap.len; - } - - if (len < RSTRING_EMBED_LEN_MAX) { - RSTR_SET_EMBED_FLAG(ns); - RSTR_SET_EMBED_LEN(ns, len); - if (ptr) { - memcpy(ns->as.ary, ptr, len); - } - ns->as.ary[len] = '\0'; - } - else { - ns->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1); - ns->as.heap.len = len; - ns->as.heap.aux.capa = len; - if (ptr) { - memcpy(ns->as.heap.ptr, ptr, len); - } - ns->as.heap.ptr[len] = '\0'; - } - } - return mrb_obj_value(ns); -} - -MRB_API void -mrb_free_context(mrb_state *mrb, struct mrb_context *c) -{ - if (!c) return; - mrb_free(mrb, c->stbase); - mrb_free(mrb, c->cibase); - mrb_free(mrb, c->rescue); - mrb_free(mrb, c->ensure); - mrb_free(mrb, c); -} - -MRB_API void -mrb_close(mrb_state *mrb) -{ - if (!mrb) return; - if (mrb->atexit_stack_len > 0) { - mrb_int i; - for (i = mrb->atexit_stack_len; i > 0; --i) { - mrb->atexit_stack[i - 1](mrb); - } -#ifndef MRB_FIXED_STATE_ATEXIT_STACK - mrb_free(mrb, mrb->atexit_stack); -#endif - } - - /* free */ - mrb_gc_free_gv(mrb); - mrb_free_context(mrb, mrb->root_c); - mrb_free_symtbl(mrb); - mrb_alloca_free(mrb); - mrb_gc_destroy(mrb, &mrb->gc); - mrb_free(mrb, mrb); -} - -MRB_API mrb_irep* -mrb_add_irep(mrb_state *mrb) -{ - static const mrb_irep mrb_irep_zero = { 0 }; - mrb_irep *irep; - - irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); - *irep = mrb_irep_zero; - irep->refcnt = 1; - - return irep; -} - -MRB_API mrb_value -mrb_top_self(mrb_state *mrb) -{ - if (!mrb->top_self) { - mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class); - mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, MRB_ARGS_NONE()); - mrb_define_singleton_method(mrb, mrb->top_self, "to_s", inspect_main, MRB_ARGS_NONE()); - } - return mrb_obj_value(mrb->top_self); -} - -MRB_API void -mrb_state_atexit(mrb_state *mrb, mrb_atexit_func f) -{ -#ifdef MRB_FIXED_STATE_ATEXIT_STACK - if (mrb->atexit_stack_len + 1 > MRB_FIXED_STATE_ATEXIT_STACK_SIZE) { - mrb_raise(mrb, E_RUNTIME_ERROR, "exceeded fixed state atexit stack limit"); - } -#else - size_t stack_size; - - stack_size = sizeof(mrb_atexit_func) * (mrb->atexit_stack_len + 1); - if (mrb->atexit_stack_len == 0) { - mrb->atexit_stack = (mrb_atexit_func*)mrb_malloc(mrb, stack_size); - } else { - mrb->atexit_stack = (mrb_atexit_func*)mrb_realloc(mrb, mrb->atexit_stack, stack_size); - } -#endif - - mrb->atexit_stack[mrb->atexit_stack_len++] = f; -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/string.c nghttp2-0.6.7/third-party/mruby/src/string.c --- nghttp2-1.13.0/third-party/mruby/src/string.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/string.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,2724 +0,0 @@ -/* -** string.c - String class -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include -#include -#include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/range.h" -#include "mruby/string.h" -#include "mruby/re.h" - -typedef struct mrb_shared_string { - mrb_bool nofree : 1; - int refcnt; - char *ptr; - mrb_int len; -} mrb_shared_string; - -const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - -#define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class)) - -static struct RString* -str_new_static(mrb_state *mrb, const char *p, size_t len) -{ - struct RString *s; - - if (len >= MRB_INT_MAX) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big"); - } - s = mrb_obj_alloc_string(mrb); - s->as.heap.len = len; - s->as.heap.aux.capa = 0; /* nofree */ - s->as.heap.ptr = (char *)p; - s->flags = MRB_STR_NOFREE; - - return s; -} - -static struct RString* -str_new(mrb_state *mrb, const char *p, size_t len) -{ - struct RString *s; - - if (p && mrb_ro_data_p(p)) { - return str_new_static(mrb, p, len); - } - s = mrb_obj_alloc_string(mrb); - if (len < RSTRING_EMBED_LEN_MAX) { - RSTR_SET_EMBED_FLAG(s); - RSTR_SET_EMBED_LEN(s, len); - if (p) { - memcpy(s->as.ary, p, len); - } - } else { - if (len >= MRB_INT_MAX) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big"); - } - s->as.heap.len = len; - s->as.heap.aux.capa = len; - s->as.heap.ptr = (char *)mrb_malloc(mrb, len+1); - if (p) { - memcpy(s->as.heap.ptr, p, len); - } - } - RSTR_PTR(s)[len] = '\0'; - return s; -} - -static inline void -str_with_class(mrb_state *mrb, struct RString *s, mrb_value obj) -{ - s->c = mrb_str_ptr(obj)->c; -} - -static mrb_value -mrb_str_new_empty(mrb_state *mrb, mrb_value str) -{ - struct RString *s = str_new(mrb, 0, 0); - - str_with_class(mrb, s, str); - return mrb_obj_value(s); -} - -#ifndef MRB_STR_BUF_MIN_SIZE -# define MRB_STR_BUF_MIN_SIZE 128 -#endif - -MRB_API mrb_value -mrb_str_buf_new(mrb_state *mrb, size_t capa) -{ - struct RString *s; - - s = mrb_obj_alloc_string(mrb); - - if (capa >= MRB_INT_MAX) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string capacity size too big"); - } - if (capa < MRB_STR_BUF_MIN_SIZE) { - capa = MRB_STR_BUF_MIN_SIZE; - } - s->as.heap.len = 0; - s->as.heap.aux.capa = capa; - s->as.heap.ptr = (char *)mrb_malloc(mrb, capa+1); - RSTR_PTR(s)[0] = '\0'; - - return mrb_obj_value(s); -} - -static inline void -resize_capa(mrb_state *mrb, struct RString *s, mrb_int capacity) -{ - if (RSTR_EMBED_P(s)) { - if (RSTRING_EMBED_LEN_MAX < capacity) { - char *const tmp = (char *)mrb_malloc(mrb, capacity+1); - const mrb_int len = RSTR_EMBED_LEN(s); - memcpy(tmp, s->as.ary, len); - RSTR_UNSET_EMBED_FLAG(s); - s->as.heap.ptr = tmp; - s->as.heap.len = len; - s->as.heap.aux.capa = capacity; - } - } - else { - s->as.heap.ptr = (char *)mrb_realloc(mrb, RSTR_PTR(s), capacity+1); - s->as.heap.aux.capa = capacity; - } -} - -static void -str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) -{ - size_t capa; - size_t total; - ptrdiff_t off = -1; - - if (len == 0) return; - mrb_str_modify(mrb, s); - if (ptr >= RSTR_PTR(s) && ptr <= RSTR_PTR(s) + (size_t)RSTR_LEN(s)) { - off = ptr - RSTR_PTR(s); - } - - if (RSTR_EMBED_P(s)) - capa = RSTRING_EMBED_LEN_MAX; - else - capa = s->as.heap.aux.capa; - - if (RSTR_LEN(s) >= MRB_INT_MAX - (mrb_int)len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big"); - } - total = RSTR_LEN(s)+len; - if (capa <= total) { - while (total > capa) { - if (capa + 1 >= MRB_INT_MAX / 2) { - capa = (total + 4095) / 4096; - break; - } - capa = (capa + 1) * 2; - } - resize_capa(mrb, s, capa); - } - if (off != -1) { - ptr = RSTR_PTR(s) + off; - } - memcpy(RSTR_PTR(s) + RSTR_LEN(s), ptr, len); - mrb_assert_int_fit(size_t, total, mrb_int, MRB_INT_MAX); - RSTR_SET_LEN(s, total); - RSTR_PTR(s)[total] = '\0'; /* sentinel */ -} - -MRB_API mrb_value -mrb_str_new(mrb_state *mrb, const char *p, size_t len) -{ - return mrb_obj_value(str_new(mrb, p, len)); -} - -/* - * call-seq: (Caution! NULL string) - * String.new(str="") => new_str - * - * Returns a new string object containing a copy of str. - */ - -MRB_API mrb_value -mrb_str_new_cstr(mrb_state *mrb, const char *p) -{ - struct RString *s; - size_t len; - - if (p) { - len = strlen(p); - } - else { - len = 0; - } - - s = str_new(mrb, p, len); - - return mrb_obj_value(s); -} - -MRB_API mrb_value -mrb_str_new_static(mrb_state *mrb, const char *p, size_t len) -{ - struct RString *s = str_new_static(mrb, p, len); - return mrb_obj_value(s); -} - -static void -str_decref(mrb_state *mrb, mrb_shared_string *shared) -{ - shared->refcnt--; - if (shared->refcnt == 0) { - if (!shared->nofree) { - mrb_free(mrb, shared->ptr); - } - mrb_free(mrb, shared); - } -} - -void -mrb_gc_free_str(mrb_state *mrb, struct RString *str) -{ - if (RSTR_EMBED_P(str)) - /* no code */; - else if (RSTR_SHARED_P(str)) - str_decref(mrb, str->as.heap.aux.shared); - else if (!RSTR_NOFREE_P(str)) - mrb_free(mrb, str->as.heap.ptr); -} - -#ifdef MRB_UTF8_STRING -static const char utf8len_codepage[256] = -{ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1, -}; - -static mrb_int -utf8len(const char* p, const char* e) -{ - mrb_int len; - mrb_int i; - - len = utf8len_codepage[(unsigned char)*p]; - if (p + len > e) return 1; - for (i = 1; i < len; ++i) - if ((p[i] & 0xc0) != 0x80) - return 1; - return len; -} - -static mrb_int -utf8_strlen(mrb_value str, mrb_int len) -{ - mrb_int total = 0; - char* p = RSTRING_PTR(str); - char* e = p; - e += len < 0 ? RSTRING_LEN(str) : len; - while (p n) return -1; - else if (m == n) { - return memcmp(x0, y0, m) == 0 ? 0 : -1; - } - else if (m < 1) { - return 0; - } - else if (m == 1) { - const unsigned char *ys = y, *ye = ys + n; - for (; y < ye; ++y) { - if (*x == *y) - return y - ys; - } - return -1; - } - return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n); -} - -static void -str_make_shared(mrb_state *mrb, struct RString *s) -{ - if (!RSTR_SHARED_P(s)) { - mrb_shared_string *shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string)); - - shared->refcnt = 1; - if (RSTR_EMBED_P(s)) { - const mrb_int len = RSTR_EMBED_LEN(s); - char *const tmp = (char *)mrb_malloc(mrb, len+1); - memcpy(tmp, s->as.ary, len); - tmp[len] = '\0'; - RSTR_UNSET_EMBED_FLAG(s); - s->as.heap.ptr = tmp; - s->as.heap.len = len; - shared->nofree = FALSE; - shared->ptr = s->as.heap.ptr; - } - else if (RSTR_NOFREE_P(s)) { - shared->nofree = TRUE; - shared->ptr = s->as.heap.ptr; - RSTR_UNSET_NOFREE_FLAG(s); - } - else { - shared->nofree = FALSE; - if (s->as.heap.aux.capa > s->as.heap.len) { - s->as.heap.ptr = shared->ptr = (char *)mrb_realloc(mrb, s->as.heap.ptr, s->as.heap.len+1); - } - else { - shared->ptr = s->as.heap.ptr; - } - } - shared->len = s->as.heap.len; - s->as.heap.aux.shared = shared; - RSTR_SET_SHARED_FLAG(s); - } -} - -static mrb_value -byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) -{ - struct RString *orig, *s; - mrb_shared_string *shared; - - orig = mrb_str_ptr(str); - if (RSTR_EMBED_P(orig)) { - s = str_new(mrb, orig->as.ary+beg, len); - } - else { - str_make_shared(mrb, orig); - shared = orig->as.heap.aux.shared; - s = mrb_obj_alloc_string(mrb); - s->as.heap.ptr = orig->as.heap.ptr + beg; - s->as.heap.len = len; - s->as.heap.aux.shared = shared; - RSTR_SET_SHARED_FLAG(s); - shared->refcnt++; - } - - return mrb_obj_value(s); -} -#ifdef MRB_UTF8_STRING -static inline mrb_value -str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) -{ - beg = chars2bytes(str, 0, beg); - len = chars2bytes(str, beg, len); - - return byte_subseq(mrb, str, beg, len); -} -#else -#define str_subseq(mrb, str, beg, len) byte_subseq(mrb, str, beg, len) -#endif - -static mrb_value -str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) -{ - mrb_int clen = RSTRING_CHAR_LEN(str); - - if (len < 0) return mrb_nil_value(); - if (clen == 0) { - len = 0; - } - else if (beg < 0) { - beg = clen + beg; - } - if (beg > clen) return mrb_nil_value(); - if (beg < 0) { - beg += clen; - if (beg < 0) return mrb_nil_value(); - } - if (beg + len > clen) - len = clen - beg; - if (len <= 0) { - len = 0; - } - return str_subseq(mrb, str, beg, len); -} - -static mrb_int -str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) -{ - mrb_int pos; - char *s, *sptr; - mrb_int len, slen; - - len = RSTRING_LEN(str); - slen = RSTRING_LEN(sub); - if (offset < 0) { - offset += len; - if (offset < 0) return -1; - } - if (len - offset < slen) return -1; - s = RSTRING_PTR(str); - if (offset) { - s += offset; - } - if (slen == 0) return offset; - /* need proceed one character at a time */ - sptr = RSTRING_PTR(sub); - slen = RSTRING_LEN(sub); - len = RSTRING_LEN(str) - offset; - pos = mrb_memsearch(sptr, slen, s, len); - if (pos < 0) return pos; - return pos + offset; -} - -static void -check_frozen(mrb_state *mrb, struct RString *s) -{ - if (RSTR_FROZEN_P(s)) { - mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string"); - } -} - -static mrb_value -str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) -{ - long len; - - check_frozen(mrb, s1); - len = RSTR_LEN(s2); - if (RSTR_SHARED_P(s1)) { - str_decref(mrb, s1->as.heap.aux.shared); - } - else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1)) { - mrb_free(mrb, s1->as.heap.ptr); - } - - RSTR_UNSET_NOFREE_FLAG(s1); - - if (RSTR_SHARED_P(s2)) { -L_SHARE: - RSTR_UNSET_EMBED_FLAG(s1); - s1->as.heap.ptr = s2->as.heap.ptr; - s1->as.heap.len = len; - s1->as.heap.aux.shared = s2->as.heap.aux.shared; - RSTR_SET_SHARED_FLAG(s1); - s1->as.heap.aux.shared->refcnt++; - } - else { - if (len <= RSTRING_EMBED_LEN_MAX) { - RSTR_UNSET_SHARED_FLAG(s1); - RSTR_SET_EMBED_FLAG(s1); - memcpy(s1->as.ary, RSTR_PTR(s2), len); - RSTR_SET_EMBED_LEN(s1, len); - } - else { - str_make_shared(mrb, s2); - goto L_SHARE; - } - } - - return mrb_obj_value(s1); -} - -static mrb_int -str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) -{ - char *s, *sbeg, *t; - struct RString *ps = mrb_str_ptr(str); - mrb_int len = RSTRING_LEN(sub); - - /* substring longer than string */ - if (RSTR_LEN(ps) < len) return -1; - if (RSTR_LEN(ps) - pos < len) { - pos = RSTR_LEN(ps) - len; - } - sbeg = RSTR_PTR(ps); - s = RSTR_PTR(ps) + pos; - t = RSTRING_PTR(sub); - if (len) { - while (sbeg <= s) { - if (memcmp(s, t, len) == 0) { - return s - RSTR_PTR(ps); - } - s--; - } - return -1; - } - else { - return pos; - } -} - -MRB_API mrb_int -mrb_str_strlen(mrb_state *mrb, struct RString *s) -{ - mrb_int i, max = RSTR_LEN(s); - char *p = RSTR_PTR(s); - - if (!p) return 0; - for (i=0; i - -char* -mrb_utf8_from_locale(const char *str, size_t len) -{ - wchar_t* wcsp; - char* mbsp; - size_t mbssize, wcssize; - - if (len == 0) - return strdup(""); - if (len == -1) - len = strlen(str); - wcssize = MultiByteToWideChar(GetACP(), 0, str, len, NULL, 0); - wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t)); - if (!wcsp) - return NULL; - wcssize = MultiByteToWideChar(GetACP(), 0, str, len, wcsp, wcssize + 1); - wcsp[wcssize] = 0; - - mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL); - mbsp = (char*) malloc((mbssize + 1)); - if (!mbsp) { - free(wcsp); - return NULL; - } - mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL); - mbsp[mbssize] = 0; - free(wcsp); - return mbsp; -} - -char* -mrb_locale_from_utf8(const char *utf8, size_t len) -{ - wchar_t* wcsp; - char* mbsp; - size_t mbssize, wcssize; - - if (len == 0) - return strdup(""); - if (len == -1) - len = strlen(utf8); - wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0); - wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t)); - if (!wcsp) - return NULL; - wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, wcsp, wcssize + 1); - wcsp[wcssize] = 0; - mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL); - mbsp = (char*) malloc((mbssize + 1)); - if (!mbsp) { - free(wcsp); - return NULL; - } - mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL); - mbsp[mbssize] = 0; - free(wcsp); - return mbsp; -} -#endif - -MRB_API void -mrb_str_modify(mrb_state *mrb, struct RString *s) -{ - check_frozen(mrb, s); - if (RSTR_SHARED_P(s)) { - mrb_shared_string *shared = s->as.heap.aux.shared; - - if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) { - s->as.heap.ptr = shared->ptr; - s->as.heap.aux.capa = shared->len; - RSTR_PTR(s)[s->as.heap.len] = '\0'; - mrb_free(mrb, shared); - } - else { - char *ptr, *p; - mrb_int len; - - p = RSTR_PTR(s); - len = s->as.heap.len; - ptr = (char *)mrb_malloc(mrb, (size_t)len + 1); - if (p) { - memcpy(ptr, p, len); - } - ptr[len] = '\0'; - s->as.heap.ptr = ptr; - s->as.heap.aux.capa = len; - str_decref(mrb, shared); - } - RSTR_UNSET_SHARED_FLAG(s); - return; - } - if (RSTR_NOFREE_P(s)) { - char *p = s->as.heap.ptr; - - s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)s->as.heap.len+1); - if (p) { - memcpy(RSTR_PTR(s), p, s->as.heap.len); - } - RSTR_PTR(s)[s->as.heap.len] = '\0'; - s->as.heap.aux.capa = s->as.heap.len; - RSTR_UNSET_NOFREE_FLAG(s); - return; - } -} - -static mrb_value -mrb_str_freeze(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - - RSTR_SET_FROZEN_FLAG(s); - return str; -} - -MRB_API mrb_value -mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) -{ - mrb_int slen; - struct RString *s = mrb_str_ptr(str); - - mrb_str_modify(mrb, s); - slen = RSTR_LEN(s); - if (len != slen) { - if (slen < len || slen - len > 256) { - resize_capa(mrb, s, len); - } - RSTR_SET_LEN(s, len); - RSTR_PTR(s)[len] = '\0'; /* sentinel */ - } - return str; -} - -MRB_API char* -mrb_str_to_cstr(mrb_state *mrb, mrb_value str0) -{ - struct RString *s; - - if (!mrb_string_p(str0)) { - mrb_raise(mrb, E_TYPE_ERROR, "expected String"); - } - - s = str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0)); - if ((strlen(RSTR_PTR(s)) ^ RSTR_LEN(s)) != 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); - } - return RSTR_PTR(s); -} - -/* - * call-seq: (Caution! String("abcd") change) - * String("abcdefg") = String("abcd") + String("efg") - * - * Returns a new string object containing a copy of str. - */ -MRB_API void -mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other) -{ - struct RString *s1 = mrb_str_ptr(self), *s2; - mrb_int len; - - mrb_str_modify(mrb, s1); - if (!mrb_string_p(other)) { - other = mrb_str_to_str(mrb, other); - } - s2 = mrb_str_ptr(other); - len = RSTR_LEN(s1) + RSTR_LEN(s2); - - if (RSTRING_CAPA(self) < len) { - resize_capa(mrb, s1, len); - } - memcpy(RSTR_PTR(s1)+RSTR_LEN(s1), RSTR_PTR(s2), RSTR_LEN(s2)); - RSTR_SET_LEN(s1, len); - RSTR_PTR(s1)[len] = '\0'; -} - -/* - * call-seq: (Caution! String("abcd") remain) - * String("abcdefg") = String("abcd") + String("efg") - * - * Returns a new string object containing a copy of str. - */ -MRB_API mrb_value -mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b) -{ - struct RString *s = mrb_str_ptr(a); - struct RString *s2 = mrb_str_ptr(b); - struct RString *t; - - t = str_new(mrb, 0, RSTR_LEN(s) + RSTR_LEN(s2)); - memcpy(RSTR_PTR(t), RSTR_PTR(s), RSTR_LEN(s)); - memcpy(RSTR_PTR(t) + RSTR_LEN(s), RSTR_PTR(s2), RSTR_LEN(s2)); - - return mrb_obj_value(t); -} - -/* 15.2.10.5.2 */ - -/* - * call-seq: (Caution! String("abcd") remain) for stack_argument - * String("abcdefg") = String("abcd") + String("efg") - * - * Returns a new string object containing a copy of str. - */ -static mrb_value -mrb_str_plus_m(mrb_state *mrb, mrb_value self) -{ - mrb_value str; - - mrb_get_args(mrb, "S", &str); - return mrb_str_plus(mrb, self, str); -} - -/* 15.2.10.5.26 */ -/* 15.2.10.5.33 */ -/* - * call-seq: - * "abcd".size => int - * - * Returns the length of string. - */ -static mrb_value -mrb_str_size(mrb_state *mrb, mrb_value self) -{ - mrb_int len = RSTRING_CHAR_LEN(self); - return mrb_fixnum_value(len); -} - -static mrb_value -mrb_str_bytesize(mrb_state *mrb, mrb_value self) -{ - mrb_int len = RSTRING_LEN(self); - return mrb_fixnum_value(len); -} - -/* 15.2.10.5.1 */ -/* - * call-seq: - * str * integer => new_str - * - * Copy---Returns a new String containing integer copies of - * the receiver. - * - * "Ho! " * 3 #=> "Ho! Ho! Ho! " - */ -static mrb_value -mrb_str_times(mrb_state *mrb, mrb_value self) -{ - mrb_int n,len,times; - struct RString *str2; - char *p; - - mrb_get_args(mrb, "i", ×); - if (times < 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument"); - } - if (times && MRB_INT_MAX / times < RSTRING_LEN(self)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big"); - } - - len = RSTRING_LEN(self)*times; - str2 = str_new(mrb, 0, len); - str_with_class(mrb, str2, self); - p = RSTR_PTR(str2); - if (len > 0) { - n = RSTRING_LEN(self); - memcpy(p, RSTRING_PTR(self), n); - while (n <= len/2) { - memcpy(p + n, p, n); - n *= 2; - } - memcpy(p + n, p, len-n); - } - p[RSTR_LEN(str2)] = '\0'; - - return mrb_obj_value(str2); -} -/* -------------------------------------------------------------- */ - -#define lesser(a,b) (((a)>(b))?(b):(a)) - -/* ---------------------------*/ -/* - * call-seq: - * mrb_value str1 <=> mrb_value str2 => int - * > 1 - * = 0 - * < -1 - */ -MRB_API int -mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2) -{ - mrb_int len; - mrb_int retval; - struct RString *s1 = mrb_str_ptr(str1); - struct RString *s2 = mrb_str_ptr(str2); - - len = lesser(RSTR_LEN(s1), RSTR_LEN(s2)); - retval = memcmp(RSTR_PTR(s1), RSTR_PTR(s2), len); - if (retval == 0) { - if (RSTR_LEN(s1) == RSTR_LEN(s2)) return 0; - if (RSTR_LEN(s1) > RSTR_LEN(s2)) return 1; - return -1; - } - if (retval > 0) return 1; - return -1; -} - -/* 15.2.10.5.3 */ - -/* - * call-seq: - * str <=> other_str => -1, 0, +1 - * - * Comparison---Returns -1 if other_str is less than, 0 if - * other_str is equal to, and +1 if other_str is greater than - * str. If the strings are of different lengths, and the strings are - * equal when compared up to the shortest length, then the longer string is - * considered greater than the shorter one. If the variable $= is - * false, the comparison is based on comparing the binary values - * of each character in the string. In older versions of Ruby, setting - * $= allowed case-insensitive comparisons; this is now deprecated - * in favor of using String#casecmp. - * - * <=> is the basis for the methods <, - * <=, >, >=, and between?, - * included from module Comparable. The method - * String#== does not use Comparable#==. - * - * "abcdef" <=> "abcde" #=> 1 - * "abcdef" <=> "abcdef" #=> 0 - * "abcdef" <=> "abcdefg" #=> -1 - * "abcdef" <=> "ABCDEF" #=> 1 - */ -static mrb_value -mrb_str_cmp_m(mrb_state *mrb, mrb_value str1) -{ - mrb_value str2; - mrb_int result; - - mrb_get_args(mrb, "o", &str2); - if (!mrb_string_p(str2)) { - if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_s"))) { - return mrb_nil_value(); - } - else if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "<=>"))) { - return mrb_nil_value(); - } - else { - mrb_value tmp = mrb_funcall(mrb, str2, "<=>", 1, str1); - - if (mrb_nil_p(tmp)) return mrb_nil_value(); - if (!mrb_fixnum(tmp)) { - return mrb_funcall(mrb, mrb_fixnum_value(0), "-", 1, tmp); - } - result = -mrb_fixnum(tmp); - } - } - else { - result = mrb_str_cmp(mrb, str1, str2); - } - return mrb_fixnum_value(result); -} - -static mrb_bool -str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2) -{ - const mrb_int len = RSTRING_LEN(str1); - - if (len != RSTRING_LEN(str2)) return FALSE; - if (memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), (size_t)len) == 0) - return TRUE; - return FALSE; -} - -MRB_API mrb_bool -mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2) -{ - if (mrb_immediate_p(str2)) return FALSE; - if (!mrb_string_p(str2)) { - if (mrb_nil_p(str2)) return FALSE; - if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_str"))) { - return FALSE; - } - str2 = mrb_funcall(mrb, str2, "to_str", 0); - return mrb_equal(mrb, str2, str1); - } - return str_eql(mrb, str1, str2); -} - -/* 15.2.10.5.4 */ -/* - * call-seq: - * str == obj => true or false - * - * Equality--- - * If obj is not a String, returns false. - * Otherwise, returns false or true - * - * caution:if str <=> obj returns zero. - */ -static mrb_value -mrb_str_equal_m(mrb_state *mrb, mrb_value str1) -{ - mrb_value str2; - - mrb_get_args(mrb, "o", &str2); - - return mrb_bool_value(mrb_str_equal(mrb, str1, str2)); -} -/* ---------------------------------- */ -MRB_API mrb_value -mrb_str_to_str(mrb_state *mrb, mrb_value str) -{ - mrb_value s; - - if (!mrb_string_p(str)) { - s = mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); - if (mrb_nil_p(s)) { - s = mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s"); - } - return s; - } - return str; -} - -MRB_API const char* -mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr) -{ - mrb_value str = mrb_str_to_str(mrb, ptr); - return RSTRING_PTR(str); -} - -void -mrb_noregexp(mrb_state *mrb, mrb_value self) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp class not implemented"); -} - -void -mrb_regexp_check(mrb_state *mrb, mrb_value obj) -{ - if (mrb_regexp_p(mrb, obj)) { - mrb_noregexp(mrb, obj); - } -} - -MRB_API mrb_value -mrb_str_dup(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - struct RString *dup = str_new(mrb, 0, 0); - - str_with_class(mrb, dup, str); - return str_replace(mrb, dup, s); -} - -static mrb_value -mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx) -{ - mrb_int idx; - - mrb_regexp_check(mrb, indx); - switch (mrb_type(indx)) { - case MRB_TT_FIXNUM: - idx = mrb_fixnum(indx); - -num_index: - str = str_substr(mrb, str, idx, 1); - if (!mrb_nil_p(str) && RSTRING_LEN(str) == 0) return mrb_nil_value(); - return str; - - case MRB_TT_STRING: - if (str_index(mrb, str, indx, 0) != -1) - return mrb_str_dup(mrb, indx); - return mrb_nil_value(); - - case MRB_TT_RANGE: - /* check if indx is Range */ - { - mrb_int beg, len; - - len = RSTRING_CHAR_LEN(str); - if (mrb_range_beg_len(mrb, indx, &beg, &len, len)) { - return str_subseq(mrb, str, beg, len); - } - else { - return mrb_nil_value(); - } - } - case MRB_TT_FLOAT: - default: - indx = mrb_Integer(mrb, indx); - if (mrb_nil_p(indx)) { - mrb_raise(mrb, E_TYPE_ERROR, "can't convert to Fixnum"); - } - idx = mrb_fixnum(indx); - goto num_index; - } - return mrb_nil_value(); /* not reached */ -} - -/* 15.2.10.5.6 */ -/* 15.2.10.5.34 */ -/* - * call-seq: - * str[fixnum] => fixnum or nil - * str[fixnum, fixnum] => new_str or nil - * str[range] => new_str or nil - * str[regexp] => new_str or nil - * str[regexp, fixnum] => new_str or nil - * str[other_str] => new_str or nil - * str.slice(fixnum) => fixnum or nil - * str.slice(fixnum, fixnum) => new_str or nil - * str.slice(range) => new_str or nil - * str.slice(other_str) => new_str or nil - * - * Element Reference---If passed a single Fixnum, returns the code - * of the character at that position. If passed two Fixnum - * objects, returns a substring starting at the offset given by the first, and - * a length given by the second. If given a range, a substring containing - * characters at offsets given by the range is returned. In all three cases, if - * an offset is negative, it is counted from the end of str. Returns - * nil if the initial offset falls outside the string, the length - * is negative, or the beginning of the range is greater than the end. - * - * If a String is given, that string is returned if it occurs in - * str. In both cases, nil is returned if there is no - * match. - * - * a = "hello there" - * a[1] #=> 101(1.8.7) "e"(1.9.2) - * a[1.1] #=> "e"(1.9.2) - * a[1,3] #=> "ell" - * a[1..3] #=> "ell" - * a[-3,2] #=> "er" - * a[-4..-2] #=> "her" - * a[12..-1] #=> nil - * a[-2..-4] #=> "" - * a["lo"] #=> "lo" - * a["bye"] #=> nil - */ -static mrb_value -mrb_str_aref_m(mrb_state *mrb, mrb_value str) -{ - mrb_value a1, a2; - int argc; - - argc = mrb_get_args(mrb, "o|o", &a1, &a2); - if (argc == 2) { - mrb_regexp_check(mrb, a1); - return str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2)); - } - if (argc != 1) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(argc)); - } - return mrb_str_aref(mrb, str, a1); -} - -/* 15.2.10.5.8 */ -/* - * call-seq: - * str.capitalize! => str or nil - * - * Modifies str by converting the first character to uppercase and the - * remainder to lowercase. Returns nil if no changes are made. - * - * a = "hello" - * a.capitalize! #=> "Hello" - * a #=> "Hello" - * a.capitalize! #=> nil - */ -static mrb_value -mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str) -{ - char *p, *pend; - mrb_bool modify = FALSE; - struct RString *s = mrb_str_ptr(str); - - mrb_str_modify(mrb, s); - if (RSTR_LEN(s) == 0 || !RSTR_PTR(s)) return mrb_nil_value(); - p = RSTR_PTR(s); pend = RSTR_PTR(s) + RSTR_LEN(s); - if (ISLOWER(*p)) { - *p = TOUPPER(*p); - modify = TRUE; - } - while (++p < pend) { - if (ISUPPER(*p)) { - *p = TOLOWER(*p); - modify = TRUE; - } - } - if (modify) return str; - return mrb_nil_value(); -} - -/* 15.2.10.5.7 */ -/* - * call-seq: - * str.capitalize => new_str - * - * Returns a copy of str with the first character converted to uppercase - * and the remainder to lowercase. - * - * "hello".capitalize #=> "Hello" - * "HELLO".capitalize #=> "Hello" - * "123ABC".capitalize #=> "123abc" - */ -static mrb_value -mrb_str_capitalize(mrb_state *mrb, mrb_value self) -{ - mrb_value str; - - str = mrb_str_dup(mrb, self); - mrb_str_capitalize_bang(mrb, str); - return str; -} - -/* 15.2.10.5.10 */ -/* - * call-seq: - * str.chomp!(separator="\n") => str or nil - * - * Modifies str in place as described for String#chomp, - * returning str, or nil if no modifications were made. - */ -static mrb_value -mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) -{ - mrb_value rs; - mrb_int newline; - char *p, *pp; - mrb_int rslen; - mrb_int len; - struct RString *s = mrb_str_ptr(str); - - mrb_str_modify(mrb, s); - len = RSTR_LEN(s); - if (mrb_get_args(mrb, "|S", &rs) == 0) { - if (len == 0) return mrb_nil_value(); - smart_chomp: - if (RSTR_PTR(s)[len-1] == '\n') { - RSTR_SET_LEN(s, RSTR_LEN(s) - 1); - if (RSTR_LEN(s) > 0 && - RSTR_PTR(s)[RSTR_LEN(s)-1] == '\r') { - RSTR_SET_LEN(s, RSTR_LEN(s) - 1); - } - } - else if (RSTR_PTR(s)[len-1] == '\r') { - RSTR_SET_LEN(s, RSTR_LEN(s) - 1); - } - else { - return mrb_nil_value(); - } - RSTR_PTR(s)[RSTR_LEN(s)] = '\0'; - return str; - } - - if (len == 0 || mrb_nil_p(rs)) return mrb_nil_value(); - p = RSTR_PTR(s); - rslen = RSTRING_LEN(rs); - if (rslen == 0) { - while (len>0 && p[len-1] == '\n') { - len--; - if (len>0 && p[len-1] == '\r') - len--; - } - if (len < RSTR_LEN(s)) { - RSTR_SET_LEN(s, len); - p[len] = '\0'; - return str; - } - return mrb_nil_value(); - } - if (rslen > len) return mrb_nil_value(); - newline = RSTRING_PTR(rs)[rslen-1]; - if (rslen == 1 && newline == '\n') - newline = RSTRING_PTR(rs)[rslen-1]; - if (rslen == 1 && newline == '\n') - goto smart_chomp; - - pp = p + len - rslen; - if (p[len-1] == newline && - (rslen <= 1 || - memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) { - RSTR_SET_LEN(s, len - rslen); - p[RSTR_LEN(s)] = '\0'; - return str; - } - return mrb_nil_value(); -} - -/* 15.2.10.5.9 */ -/* - * call-seq: - * str.chomp(separator="\n") => new_str - * - * Returns a new String with the given record separator removed - * from the end of str (if present). If $/ has not been - * changed from the default Ruby record separator, then chomp also - * removes carriage return characters (that is it will remove \n, - * \r, and \r\n). - * - * "hello".chomp #=> "hello" - * "hello\n".chomp #=> "hello" - * "hello\r\n".chomp #=> "hello" - * "hello\n\r".chomp #=> "hello\n" - * "hello\r".chomp #=> "hello" - * "hello \n there".chomp #=> "hello \n there" - * "hello".chomp("llo") #=> "he" - */ -static mrb_value -mrb_str_chomp(mrb_state *mrb, mrb_value self) -{ - mrb_value str; - - str = mrb_str_dup(mrb, self); - mrb_str_chomp_bang(mrb, str); - return str; -} - -/* 15.2.10.5.12 */ -/* - * call-seq: - * str.chop! => str or nil - * - * Processes str as for String#chop, returning str, - * or nil if str is the empty string. See also - * String#chomp!. - */ -static mrb_value -mrb_str_chop_bang(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - - mrb_str_modify(mrb, s); - if (RSTR_LEN(s) > 0) { - mrb_int len; -#ifdef MRB_UTF8_STRING - const char* t = RSTR_PTR(s), *p = t; - const char* e = p + RSTR_LEN(s); - while (p=e) break; - p += clen; - } - len = p - t; -#else - len = RSTR_LEN(s) - 1; -#endif - if (RSTR_PTR(s)[len] == '\n') { - if (len > 0 && - RSTR_PTR(s)[len-1] == '\r') { - len--; - } - } - RSTR_SET_LEN(s, len); - RSTR_PTR(s)[len] = '\0'; - return str; - } - return mrb_nil_value(); -} - -/* 15.2.10.5.11 */ -/* - * call-seq: - * str.chop => new_str - * - * Returns a new String with the last character removed. If the - * string ends with \r\n, both characters are removed. Applying - * chop to an empty string returns an empty - * string. String#chomp is often a safer alternative, as it leaves - * the string unchanged if it doesn't end in a record separator. - * - * "string\r\n".chop #=> "string" - * "string\n\r".chop #=> "string\n" - * "string\n".chop #=> "string" - * "string".chop #=> "strin" - * "x".chop #=> "" - */ -static mrb_value -mrb_str_chop(mrb_state *mrb, mrb_value self) -{ - mrb_value str; - str = mrb_str_dup(mrb, self); - mrb_str_chop_bang(mrb, str); - return str; -} - -/* 15.2.10.5.14 */ -/* - * call-seq: - * str.downcase! => str or nil - * - * Downcases the contents of str, returning nil if no - * changes were made. - */ -static mrb_value -mrb_str_downcase_bang(mrb_state *mrb, mrb_value str) -{ - char *p, *pend; - mrb_bool modify = FALSE; - struct RString *s = mrb_str_ptr(str); - - mrb_str_modify(mrb, s); - p = RSTR_PTR(s); - pend = RSTR_PTR(s) + RSTR_LEN(s); - while (p < pend) { - if (ISUPPER(*p)) { - *p = TOLOWER(*p); - modify = TRUE; - } - p++; - } - - if (modify) return str; - return mrb_nil_value(); -} - -/* 15.2.10.5.13 */ -/* - * call-seq: - * str.downcase => new_str - * - * Returns a copy of str with all uppercase letters replaced with their - * lowercase counterparts. The operation is locale insensitive---only - * characters 'A' to 'Z' are affected. - * - * "hEllO".downcase #=> "hello" - */ -static mrb_value -mrb_str_downcase(mrb_state *mrb, mrb_value self) -{ - mrb_value str; - - str = mrb_str_dup(mrb, self); - mrb_str_downcase_bang(mrb, str); - return str; -} - -/* 15.2.10.5.16 */ -/* - * call-seq: - * str.empty? => true or false - * - * Returns true if str has a length of zero. - * - * "hello".empty? #=> false - * "".empty? #=> true - */ -static mrb_value -mrb_str_empty_p(mrb_state *mrb, mrb_value self) -{ - struct RString *s = mrb_str_ptr(self); - - return mrb_bool_value(RSTR_LEN(s) == 0); -} - -/* 15.2.10.5.17 */ -/* - * call-seq: - * str.eql?(other) => true or false - * - * Two strings are equal if the have the same length and content. - */ -static mrb_value -mrb_str_eql(mrb_state *mrb, mrb_value self) -{ - mrb_value str2; - mrb_bool eql_p; - - mrb_get_args(mrb, "o", &str2); - eql_p = (mrb_type(str2) == MRB_TT_STRING) && str_eql(mrb, self, str2); - - return mrb_bool_value(eql_p); -} - -MRB_API mrb_value -mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) -{ - return str_substr(mrb, str, beg, len); -} - -mrb_int -mrb_str_hash(mrb_state *mrb, mrb_value str) -{ - /* 1-8-7 */ - struct RString *s = mrb_str_ptr(str); - mrb_int len = RSTR_LEN(s); - char *p = RSTR_PTR(s); - mrb_int key = 0; - - while (len--) { - key = key*65599 + *p; - p++; - } - return key + (key>>5); -} - -/* 15.2.10.5.20 */ -/* - * call-seq: - * str.hash => fixnum - * - * Return a hash based on the string's length and content. - */ -static mrb_value -mrb_str_hash_m(mrb_state *mrb, mrb_value self) -{ - mrb_int key = mrb_str_hash(mrb, self); - return mrb_fixnum_value(key); -} - -/* 15.2.10.5.21 */ -/* - * call-seq: - * str.include? other_str => true or false - * str.include? fixnum => true or false - * - * Returns true if str contains the given string or - * character. - * - * "hello".include? "lo" #=> true - * "hello".include? "ol" #=> false - * "hello".include? ?h #=> true - */ -static mrb_value -mrb_str_include(mrb_state *mrb, mrb_value self) -{ - mrb_int i; - mrb_value str2; - mrb_bool include_p; - - mrb_get_args(mrb, "o", &str2); - if (mrb_fixnum_p(str2)) { - include_p = (memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self)) != NULL); - } - else { - str2 = mrb_str_to_str(mrb, str2); - i = str_index(mrb, self, str2, 0); - - include_p = (i != -1); - } - - return mrb_bool_value(include_p); -} - -/* 15.2.10.5.22 */ -/* - * call-seq: - * str.index(substring [, offset]) => fixnum or nil - * str.index(fixnum [, offset]) => fixnum or nil - * str.index(regexp [, offset]) => fixnum or nil - * - * Returns the index of the first occurrence of the given - * substring, - * character (fixnum), or pattern (regexp) in str. - * Returns - * nil if not found. - * If the second parameter is present, it - * specifies the position in the string to begin the search. - * - * "hello".index('e') #=> 1 - * "hello".index('lo') #=> 3 - * "hello".index('a') #=> nil - * "hello".index(101) #=> 1(101=0x65='e') - * "hello".index(/[aeiou]/, -3) #=> 4 - */ -static mrb_value -mrb_str_index(mrb_state *mrb, mrb_value str) -{ - mrb_value *argv; - mrb_int argc; - mrb_value sub; - mrb_int pos, clen; - - mrb_get_args(mrb, "*", &argv, &argc); - if (argc == 2) { - pos = mrb_fixnum(argv[1]); - sub = argv[0]; - } - else { - pos = 0; - if (argc > 0) - sub = argv[0]; - else - sub = mrb_nil_value(); - } - mrb_regexp_check(mrb, sub); - clen = RSTRING_CHAR_LEN(str); - if (pos < 0) { - pos += clen; - if (pos < 0) { - return mrb_nil_value(); - } - } - if (pos >= clen) return mrb_nil_value(); - pos = chars2bytes(str, 0, pos); - - switch (mrb_type(sub)) { - default: { - mrb_value tmp; - - tmp = mrb_check_string_type(mrb, sub); - if (mrb_nil_p(tmp)) { - mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub); - } - sub = tmp; - } - /* fall through */ - case MRB_TT_STRING: - pos = str_index(mrb, str, sub, pos); - break; - } - - if (pos == -1) return mrb_nil_value(); - pos = bytes2chars(RSTRING_PTR(str), pos); - return mrb_fixnum_value(pos); -} - -#define STR_REPLACE_SHARED_MIN 10 - -/* 15.2.10.5.24 */ -/* 15.2.10.5.28 */ -/* - * call-seq: - * str.replace(other_str) => str - * - * s = "hello" #=> "hello" - * s.replace "world" #=> "world" - */ -static mrb_value -mrb_str_replace(mrb_state *mrb, mrb_value str) -{ - mrb_value str2; - - mrb_get_args(mrb, "S", &str2); - return str_replace(mrb, mrb_str_ptr(str), mrb_str_ptr(str2)); -} - -/* 15.2.10.5.23 */ -/* - * call-seq: - * String.new(str="") => new_str - * - * Returns a new string object containing a copy of str. - */ -static mrb_value -mrb_str_init(mrb_state *mrb, mrb_value self) -{ - mrb_value str2; - - if (mrb_get_args(mrb, "|S", &str2) == 1) { - str_replace(mrb, mrb_str_ptr(self), mrb_str_ptr(str2)); - } - return self; -} - -/* 15.2.10.5.25 */ -/* 15.2.10.5.41 */ -/* - * call-seq: - * str.intern => symbol - * str.to_sym => symbol - * - * Returns the Symbol corresponding to str, creating the - * symbol if it did not previously exist. See Symbol#id2name. - * - * "Koala".intern #=> :Koala - * s = 'cat'.to_sym #=> :cat - * s == :cat #=> true - * s = '@cat'.to_sym #=> :@cat - * s == :@cat #=> true - * - * This can also be used to create symbols that cannot be represented using the - * :xxx notation. - * - * 'cat and dog'.to_sym #=> :"cat and dog" - */ -MRB_API mrb_value -mrb_str_intern(mrb_state *mrb, mrb_value self) -{ - return mrb_symbol_value(mrb_intern_str(mrb, self)); -} -/* ---------------------------------- */ -MRB_API mrb_value -mrb_obj_as_string(mrb_state *mrb, mrb_value obj) -{ - mrb_value str; - - if (mrb_string_p(obj)) { - return obj; - } - str = mrb_funcall(mrb, obj, "to_s", 0); - if (!mrb_string_p(str)) - return mrb_any_to_s(mrb, obj); - return str; -} - -MRB_API mrb_value -mrb_ptr_to_str(mrb_state *mrb, void *p) -{ - struct RString *p_str; - char *p1; - char *p2; - uintptr_t n = (uintptr_t)p; - - p_str = str_new(mrb, NULL, 2 + sizeof(uintptr_t) * CHAR_BIT / 4); - p1 = RSTR_PTR(p_str); - *p1++ = '0'; - *p1++ = 'x'; - p2 = p1; - - do { - *p2++ = mrb_digitmap[n % 16]; - n /= 16; - } while (n > 0); - *p2 = '\0'; - RSTR_SET_LEN(p_str, (mrb_int)(p2 - RSTR_PTR(p_str))); - - while (p1 < p2) { - const char c = *p1; - *p1++ = *--p2; - *p2 = c; - } - - return mrb_obj_value(p_str); -} - -MRB_API mrb_value -mrb_string_type(mrb_state *mrb, mrb_value str) -{ - return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); -} - -MRB_API mrb_value -mrb_check_string_type(mrb_state *mrb, mrb_value str) -{ - return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); -} - -/* 15.2.10.5.30 */ -/* - * call-seq: - * str.reverse! => str - * - * Reverses str in place. - */ -static mrb_value -mrb_str_reverse_bang(mrb_state *mrb, mrb_value str) -{ -#ifdef MRB_UTF8_STRING - mrb_int utf8_len = RSTRING_CHAR_LEN(str); - mrb_int len = RSTRING_LEN(str); - - if (utf8_len == len) goto bytes; - if (utf8_len > 1) { - char *buf; - char *p, *e, *r; - - mrb_str_modify(mrb, mrb_str_ptr(str)); - len = RSTRING_LEN(str); - buf = mrb_malloc(mrb, (size_t)len); - p = buf; - e = buf + len; - - memcpy(buf, RSTRING_PTR(str), len); - r = RSTRING_PTR(str) + len; - - while (p 1) { - p = RSTR_PTR(s); - e = p + RSTR_LEN(s) - 1; - while (p < e) { - c = *p; - *p++ = *e; - *e-- = c; - } - } - return str; - } -} - -/* ---------------------------------- */ -/* 15.2.10.5.29 */ -/* - * call-seq: - * str.reverse => new_str - * - * Returns a new string with the characters from str in reverse order. - * - * "stressed".reverse #=> "desserts" - */ -static mrb_value -mrb_str_reverse(mrb_state *mrb, mrb_value str) -{ - mrb_value str2 = mrb_str_dup(mrb, str); - mrb_str_reverse_bang(mrb, str2); - return str2; -} - -/* 15.2.10.5.31 */ -/* - * call-seq: - * str.rindex(substring [, fixnum]) => fixnum or nil - * str.rindex(fixnum [, fixnum]) => fixnum or nil - * str.rindex(regexp [, fixnum]) => fixnum or nil - * - * Returns the index of the last occurrence of the given substring, - * character (fixnum), or pattern (regexp) in str. Returns - * nil if not found. If the second parameter is present, it - * specifies the position in the string to end the search---characters beyond - * this point will not be considered. - * - * "hello".rindex('e') #=> 1 - * "hello".rindex('l') #=> 3 - * "hello".rindex('a') #=> nil - * "hello".rindex(101) #=> 1 - * "hello".rindex(/[aeiou]/, -2) #=> 1 - */ -static mrb_value -mrb_str_rindex(mrb_state *mrb, mrb_value str) -{ - mrb_value *argv; - mrb_int argc; - mrb_value sub; - mrb_value vpos; - mrb_int pos, len = RSTRING_CHAR_LEN(str); - - mrb_get_args(mrb, "*", &argv, &argc); - if (argc == 2) { - sub = argv[0]; - vpos = argv[1]; - pos = mrb_fixnum(vpos); - if (pos < 0) { - pos += len; - if (pos < 0) { - mrb_regexp_check(mrb, sub); - return mrb_nil_value(); - } - } - if (pos > len) pos = len; - } - else { - pos = len; - if (argc > 0) - sub = argv[0]; - else - sub = mrb_nil_value(); - } - pos = chars2bytes(str, 0, pos); - len = chars2bytes(str, pos, len); - mrb_regexp_check(mrb, sub); - - switch (mrb_type(sub)) { - default: { - mrb_value tmp; - - tmp = mrb_check_string_type(mrb, sub); - if (mrb_nil_p(tmp)) { - mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub); - } - sub = tmp; - } - /* fall through */ - case MRB_TT_STRING: - pos = str_rindex(mrb, str, sub, pos); - if (pos >= 0) { - pos = bytes2chars(RSTRING_PTR(str), pos); - return mrb_fixnum_value(pos); - } - break; - - } /* end of switch (TYPE(sub)) */ - return mrb_nil_value(); -} - -/* 15.2.10.5.35 */ - -/* - * call-seq: - * str.split(pattern="\n", [limit]) => anArray - * - * Divides str into substrings based on a delimiter, returning an array - * of these substrings. - * - * If pattern is a String, then its contents are used as - * the delimiter when splitting str. If pattern is a single - * space, str is split on whitespace, with leading whitespace and runs - * of contiguous whitespace characters ignored. - * - * If pattern is a Regexp, str is divided where the - * pattern matches. Whenever the pattern matches a zero-length string, - * str is split into individual characters. - * - * If pattern is omitted, the value of $; is used. If - * $; is nil (which is the default), str is - * split on whitespace as if ' ' were specified. - * - * If the limit parameter is omitted, trailing null fields are - * suppressed. If limit is a positive number, at most that number of - * fields will be returned (if limit is 1, the entire - * string is returned as the only entry in an array). If negative, there is no - * limit to the number of fields returned, and trailing null fields are not - * suppressed. - * - * " now's the time".split #=> ["now's", "the", "time"] - * " now's the time".split(' ') #=> ["now's", "the", "time"] - * " now's the time".split(/ /) #=> ["", "now's", "", "the", "time"] - * "hello".split(//) #=> ["h", "e", "l", "l", "o"] - * "hello".split(//, 3) #=> ["h", "e", "llo"] - * - * "mellow yellow".split("ello") #=> ["m", "w y", "w"] - * "1,2,,3,4,,".split(',') #=> ["1", "2", "", "3", "4"] - * "1,2,,3,4,,".split(',', 4) #=> ["1", "2", "", "3,4,,"] - * "1,2,,3,4,,".split(',', -4) #=> ["1", "2", "", "3", "4", "", ""] - */ - -static mrb_value -mrb_str_split_m(mrb_state *mrb, mrb_value str) -{ - int argc; - mrb_value spat = mrb_nil_value(); - enum {awk, string, regexp} split_type = string; - long i = 0, lim_p; - mrb_int beg; - mrb_int end; - mrb_int lim = 0; - mrb_value result, tmp; - - argc = mrb_get_args(mrb, "|oi", &spat, &lim); - lim_p = (lim > 0 && argc == 2); - if (argc == 2) { - if (lim == 1) { - if (RSTRING_LEN(str) == 0) - return mrb_ary_new_capa(mrb, 0); - return mrb_ary_new_from_values(mrb, 1, &str); - } - i = 1; - } - - if (argc == 0 || mrb_nil_p(spat)) { - split_type = awk; - } - else { - if (mrb_string_p(spat)) { - split_type = string; - if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') { - split_type = awk; - } - } - else { - mrb_noregexp(mrb, str); - } - } - - result = mrb_ary_new(mrb); - beg = 0; - if (split_type == awk) { - mrb_bool skip = TRUE; - mrb_int idx = 0; - mrb_int str_len = RSTRING_LEN(str); - unsigned int c; - int ai = mrb_gc_arena_save(mrb); - - idx = end = beg; - while (idx < str_len) { - c = (unsigned char)RSTRING_PTR(str)[idx++]; - if (skip) { - if (ISSPACE(c)) { - beg = idx; - } - else { - end = idx; - skip = FALSE; - if (lim_p && lim <= i) break; - } - } - else if (ISSPACE(c)) { - mrb_ary_push(mrb, result, byte_subseq(mrb, str, beg, end-beg)); - mrb_gc_arena_restore(mrb, ai); - skip = TRUE; - beg = idx; - if (lim_p) ++i; - } - else { - end = idx; - } - } - } - else if (split_type == string) { - mrb_int str_len = RSTRING_LEN(str); - mrb_int pat_len = RSTRING_LEN(spat); - mrb_int idx = 0; - int ai = mrb_gc_arena_save(mrb); - - while (idx < str_len) { - if (pat_len > 0) { - end = mrb_memsearch(RSTRING_PTR(spat), pat_len, RSTRING_PTR(str)+idx, str_len - idx); - if (end < 0) break; - } else { - end = chars2bytes(str, idx, 1); - } - mrb_ary_push(mrb, result, byte_subseq(mrb, str, idx, end)); - mrb_gc_arena_restore(mrb, ai); - idx += end + pat_len; - if (lim_p && lim <= ++i) break; - } - beg = idx; - } - else { - mrb_noregexp(mrb, str); - } - if (RSTRING_LEN(str) > 0 && (lim_p || RSTRING_LEN(str) > beg || lim < 0)) { - if (RSTRING_LEN(str) == beg) { - tmp = mrb_str_new_empty(mrb, str); - } - else { - tmp = byte_subseq(mrb, str, beg, RSTRING_LEN(str)-beg); - } - mrb_ary_push(mrb, result, tmp); - } - if (!lim_p && lim == 0) { - mrb_int len; - while ((len = RARRAY_LEN(result)) > 0 && - (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0)) - mrb_ary_pop(mrb, result); - } - - return result; -} - -MRB_API mrb_value -mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) -{ - const char *p; - char sign = 1; - int c, uscore; - uint64_t n = 0; - mrb_int val; - -#define conv_digit(c) \ - (ISDIGIT(c) ? ((c) - '0') : \ - ISLOWER(c) ? ((c) - 'a' + 10) : \ - ISUPPER(c) ? ((c) - 'A' + 10) : \ - -1) - - if (!str) { - if (badcheck) goto bad; - return mrb_fixnum_value(0); - } - while (ISSPACE(*str)) str++; - - if (str[0] == '+') { - str++; - } - else if (str[0] == '-') { - str++; - sign = 0; - } - if (str[0] == '+' || str[0] == '-') { - if (badcheck) goto bad; - return mrb_fixnum_value(0); - } - if (base <= 0) { - if (str[0] == '0') { - switch (str[1]) { - case 'x': case 'X': - base = 16; - break; - case 'b': case 'B': - base = 2; - break; - case 'o': case 'O': - base = 8; - break; - case 'd': case 'D': - base = 10; - break; - default: - base = 8; - } - } - else if (base < -1) { - base = -base; - } - else { - base = 10; - } - } - switch (base) { - case 2: - if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) { - str += 2; - } - break; - case 3: - break; - case 8: - if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) { - str += 2; - } - case 4: case 5: case 6: case 7: - break; - case 10: - if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) { - str += 2; - } - case 9: case 11: case 12: case 13: case 14: case 15: - break; - case 16: - if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) { - str += 2; - } - break; - default: - if (base < 2 || 36 < base) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %S", mrb_fixnum_value(base)); - } - break; - } /* end of switch (base) { */ - if (*str == '0') { /* squeeze preceding 0s */ - uscore = 0; - while ((c = *++str) == '0' || c == '_') { - if (c == '_') { - if (++uscore >= 2) - break; - } - else - uscore = 0; - } - if (!(c = *str) || ISSPACE(c)) --str; - } - c = *str; - c = conv_digit(c); - if (c < 0 || c >= base) { - if (badcheck) goto bad; - return mrb_fixnum_value(0); - } - - uscore = 0; - for (p=str;*p;p++) { - if (*p == '_') { - if (uscore == 0) { - uscore++; - continue; - } - if (badcheck) goto bad; - break; - } - uscore = 0; - c = conv_digit(*p); - if (c < 0 || c >= base) { - if (badcheck) goto bad; - break; - } - n *= base; - n += c; - if (n > MRB_INT_MAX) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str)); - } - } - val = n; - if (badcheck) { - if (p == str) goto bad; /* no number */ - while (*p && ISSPACE(*p)) p++; - if (*p) goto bad; /* trailing garbage */ - } - - return mrb_fixnum_value(sign ? val : -val); -bad: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%S)", mrb_str_new_cstr(mrb, str)); - /* not reached */ - return mrb_fixnum_value(0); -} - -MRB_API const char* -mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) -{ - mrb_value str = mrb_str_to_str(mrb, *ptr); - struct RString *ps = mrb_str_ptr(str); - mrb_int len = mrb_str_strlen(mrb, ps); - char *p = RSTR_PTR(ps); - - if (!p || p[len] != '\0') { - mrb_str_modify(mrb, ps); - return RSTR_PTR(ps); - } - return p; -} - -MRB_API mrb_value -mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck) -{ - const char *s; - mrb_int len; - - if (badcheck) { - /* Raises if the string contains a null character (the badcheck) */ - s = mrb_string_value_cstr(mrb, &str); - } - else { - s = mrb_string_value_ptr(mrb, str); - } - if (s) { - len = RSTRING_LEN(str); - if (s[len]) { /* no sentinel somehow */ - struct RString *temp_str = str_new(mrb, s, len); - s = RSTR_PTR(temp_str); - } - } - return mrb_cstr_to_inum(mrb, s, base, badcheck); -} - -/* 15.2.10.5.38 */ -/* - * call-seq: - * str.to_i(base=10) => integer - * - * Returns the result of interpreting leading characters in str as an - * integer base base (between 2 and 36). Extraneous characters past the - * end of a valid number are ignored. If there is not a valid number at the - * start of str, 0 is returned. This method never raises an - * exception. - * - * "12345".to_i #=> 12345 - * "99 red balloons".to_i #=> 99 - * "0a".to_i #=> 0 - * "0a".to_i(16) #=> 10 - * "hello".to_i #=> 0 - * "1100101".to_i(2) #=> 101 - * "1100101".to_i(8) #=> 294977 - * "1100101".to_i(10) #=> 1100101 - * "1100101".to_i(16) #=> 17826049 - */ -static mrb_value -mrb_str_to_i(mrb_state *mrb, mrb_value self) -{ - mrb_int base = 10; - - mrb_get_args(mrb, "|i", &base); - if (base < 0) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %S", mrb_fixnum_value(base)); - } - return mrb_str_to_inum(mrb, self, base, FALSE); -} - -MRB_API double -mrb_cstr_to_dbl(mrb_state *mrb, const char * p, mrb_bool badcheck) -{ - char *end; - char buf[DBL_DIG * 4 + 10]; - double d; - - enum {max_width = 20}; - - if (!p) return 0.0; - while (ISSPACE(*p)) p++; - - if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { - return 0.0; - } - d = strtod(p, &end); - if (p == end) { - if (badcheck) { -bad: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%S)", mrb_str_new_cstr(mrb, p)); - /* not reached */ - } - return d; - } - if (*end) { - char *n = buf; - char *e = buf + sizeof(buf) - 1; - char prev = 0; - - while (p < end && n < e) prev = *n++ = *p++; - while (*p) { - if (*p == '_') { - /* remove underscores between digits */ - if (badcheck) { - if (n == buf || !ISDIGIT(prev)) goto bad; - ++p; - if (!ISDIGIT(*p)) goto bad; - } - else { - while (*++p == '_'); - continue; - } - } - prev = *p++; - if (n < e) *n++ = prev; - } - *n = '\0'; - p = buf; - - if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { - return 0.0; - } - - d = strtod(p, &end); - if (badcheck) { - if (!end || p == end) goto bad; - while (*end && ISSPACE(*end)) end++; - if (*end) goto bad; - } - } - return d; -} - -MRB_API double -mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck) -{ - char *s; - mrb_int len; - - str = mrb_str_to_str(mrb, str); - s = RSTRING_PTR(str); - len = RSTRING_LEN(str); - if (s) { - if (badcheck && memchr(s, '\0', len)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte"); - } - if (s[len]) { /* no sentinel somehow */ - struct RString *temp_str = str_new(mrb, s, len); - s = RSTR_PTR(temp_str); - } - } - return mrb_cstr_to_dbl(mrb, s, badcheck); -} - -/* 15.2.10.5.39 */ -/* - * call-seq: - * str.to_f => float - * - * Returns the result of interpreting leading characters in str as a - * floating point number. Extraneous characters past the end of a valid number - * are ignored. If there is not a valid number at the start of str, - * 0.0 is returned. This method never raises an exception. - * - * "123.45e1".to_f #=> 1234.5 - * "45.67 degrees".to_f #=> 45.67 - * "thx1138".to_f #=> 0.0 - */ -static mrb_value -mrb_str_to_f(mrb_state *mrb, mrb_value self) -{ - return mrb_float_value(mrb, mrb_str_to_dbl(mrb, self, FALSE)); -} - -/* 15.2.10.5.40 */ -/* - * call-seq: - * str.to_s => str - * str.to_str => str - * - * Returns the receiver. - */ -static mrb_value -mrb_str_to_s(mrb_state *mrb, mrb_value self) -{ - if (mrb_obj_class(mrb, self) != mrb->string_class) { - return mrb_str_dup(mrb, self); - } - return self; -} - -/* 15.2.10.5.43 */ -/* - * call-seq: - * str.upcase! => str or nil - * - * Upcases the contents of str, returning nil if no changes - * were made. - */ -static mrb_value -mrb_str_upcase_bang(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - char *p, *pend; - mrb_bool modify = FALSE; - - mrb_str_modify(mrb, s); - p = RSTRING_PTR(str); - pend = RSTRING_END(str); - while (p < pend) { - if (ISLOWER(*p)) { - *p = TOUPPER(*p); - modify = TRUE; - } - p++; - } - - if (modify) return str; - return mrb_nil_value(); -} - -/* 15.2.10.5.42 */ -/* - * call-seq: - * str.upcase => new_str - * - * Returns a copy of str with all lowercase letters replaced with their - * uppercase counterparts. The operation is locale insensitive---only - * characters 'a' to 'z' are affected. - * - * "hEllO".upcase #=> "HELLO" - */ -static mrb_value -mrb_str_upcase(mrb_state *mrb, mrb_value self) -{ - mrb_value str; - - str = mrb_str_dup(mrb, self); - mrb_str_upcase_bang(mrb, str); - return str; -} - -#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{')) - -/* - * call-seq: - * str.dump -> new_str - * - * Produces a version of str with all nonprinting characters replaced by - * \nnn notation and all special characters escaped. - */ -mrb_value -mrb_str_dump(mrb_state *mrb, mrb_value str) -{ - mrb_int len; - const char *p, *pend; - char *q; - struct RString *result; - - len = 2; /* "" */ - p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str); - while (p < pend) { - unsigned char c = *p++; - switch (c) { - case '"': case '\\': - case '\n': case '\r': - case '\t': case '\f': - case '\013': case '\010': case '\007': case '\033': - len += 2; - break; - - case '#': - len += IS_EVSTR(p, pend) ? 2 : 1; - break; - - default: - if (ISPRINT(c)) { - len++; - } - else { - len += 4; /* \NNN */ - } - break; - } - } - - result = str_new(mrb, 0, len); - str_with_class(mrb, result, str); - p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str); - q = RSTR_PTR(result); - *q++ = '"'; - while (p < pend) { - unsigned char c = *p++; - - switch (c) { - case '"': - case '\\': - *q++ = '\\'; - *q++ = c; - break; - - case '\n': - *q++ = '\\'; - *q++ = 'n'; - break; - - case '\r': - *q++ = '\\'; - *q++ = 'r'; - break; - - case '\t': - *q++ = '\\'; - *q++ = 't'; - break; - - case '\f': - *q++ = '\\'; - *q++ = 'f'; - break; - - case '\013': - *q++ = '\\'; - *q++ = 'v'; - break; - - case '\010': - *q++ = '\\'; - *q++ = 'b'; - break; - - case '\007': - *q++ = '\\'; - *q++ = 'a'; - break; - - case '\033': - *q++ = '\\'; - *q++ = 'e'; - break; - - case '#': - if (IS_EVSTR(p, pend)) *q++ = '\\'; - *q++ = '#'; - break; - - default: - if (ISPRINT(c)) { - *q++ = c; - } - else { - *q++ = '\\'; - q[2] = '0' + c % 8; c /= 8; - q[1] = '0' + c % 8; c /= 8; - q[0] = '0' + c % 8; - q += 3; - } - } - } - *q = '"'; - return mrb_obj_value(result); -} - -MRB_API mrb_value -mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len) -{ - str_buf_cat(mrb, mrb_str_ptr(str), ptr, len); - return str; -} - -MRB_API mrb_value -mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr) -{ - return mrb_str_cat(mrb, str, ptr, strlen(ptr)); -} - -MRB_API mrb_value -mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2) -{ - return mrb_str_cat(mrb, str, RSTRING_PTR(str2), RSTRING_LEN(str2)); -} - -MRB_API mrb_value -mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2) -{ - str2 = mrb_str_to_str(mrb, str2); - return mrb_str_cat_str(mrb, str1, str2); -} - -#define CHAR_ESC_LEN 13 /* sizeof(\x{ hex of 32bit unsigned int } \0) */ - -/* - * call-seq: - * str.inspect -> string - * - * Returns a printable version of _str_, surrounded by quote marks, - * with special characters escaped. - * - * str = "hello" - * str[3] = "\b" - * str.inspect #=> "\"hel\\bo\"" - */ -mrb_value -mrb_str_inspect(mrb_state *mrb, mrb_value str) -{ - const char *p, *pend; - char buf[CHAR_ESC_LEN + 1]; - mrb_value result = mrb_str_new_lit(mrb, "\""); - - p = RSTRING_PTR(str); pend = RSTRING_END(str); - for (;p < pend; p++) { - unsigned char c, cc; -#ifdef MRB_UTF8_STRING - mrb_int clen; - - clen = utf8len(p, pend); - if (clen > 1) { - mrb_int i; - - for (i=0; i array of fixnums - * - * Returns an array of bytes in _str_. - * - * str = "hello" - * str.bytes #=> [104, 101, 108, 108, 111] - */ -static mrb_value -mrb_str_bytes(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - mrb_value a = mrb_ary_new_capa(mrb, RSTR_LEN(s)); - unsigned char *p = (unsigned char *)(RSTR_PTR(s)), *pend = p + RSTR_LEN(s); - - while (p < pend) { - mrb_ary_push(mrb, a, mrb_fixnum_value(p[0])); - p++; - } - return a; -} - -/* ---------------------------*/ -void -mrb_init_string(mrb_state *mrb) -{ - struct RClass *s; - - mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << 5), "pointer size too big for embedded string"); - - mrb->string_class = s = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */ - MRB_SET_INSTANCE_TT(s, MRB_TT_STRING); - - mrb_define_method(mrb, s, "bytesize", mrb_str_bytesize, MRB_ARGS_NONE()); - - mrb_define_method(mrb, s, "<=>", mrb_str_cmp_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.1 */ - mrb_define_method(mrb, s, "==", mrb_str_equal_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.2 */ - mrb_define_method(mrb, s, "+", mrb_str_plus_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.4 */ - mrb_define_method(mrb, s, "*", mrb_str_times, MRB_ARGS_REQ(1)); /* 15.2.10.5.5 */ - mrb_define_method(mrb, s, "[]", mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.6 */ - mrb_define_method(mrb, s, "capitalize", mrb_str_capitalize, MRB_ARGS_NONE()); /* 15.2.10.5.7 */ - mrb_define_method(mrb, s, "capitalize!", mrb_str_capitalize_bang, MRB_ARGS_NONE()); /* 15.2.10.5.8 */ - mrb_define_method(mrb, s, "chomp", mrb_str_chomp, MRB_ARGS_ANY()); /* 15.2.10.5.9 */ - mrb_define_method(mrb, s, "chomp!", mrb_str_chomp_bang, MRB_ARGS_ANY()); /* 15.2.10.5.10 */ - mrb_define_method(mrb, s, "chop", mrb_str_chop, MRB_ARGS_REQ(1)); /* 15.2.10.5.11 */ - mrb_define_method(mrb, s, "chop!", mrb_str_chop_bang, MRB_ARGS_REQ(1)); /* 15.2.10.5.12 */ - mrb_define_method(mrb, s, "downcase", mrb_str_downcase, MRB_ARGS_NONE()); /* 15.2.10.5.13 */ - mrb_define_method(mrb, s, "downcase!", mrb_str_downcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.14 */ - mrb_define_method(mrb, s, "empty?", mrb_str_empty_p, MRB_ARGS_NONE()); /* 15.2.10.5.16 */ - mrb_define_method(mrb, s, "eql?", mrb_str_eql, MRB_ARGS_REQ(1)); /* 15.2.10.5.17 */ - - mrb_define_method(mrb, s, "hash", mrb_str_hash_m, MRB_ARGS_NONE()); /* 15.2.10.5.20 */ - mrb_define_method(mrb, s, "include?", mrb_str_include, MRB_ARGS_REQ(1)); /* 15.2.10.5.21 */ - mrb_define_method(mrb, s, "index", mrb_str_index, MRB_ARGS_ANY()); /* 15.2.10.5.22 */ - mrb_define_method(mrb, s, "initialize", mrb_str_init, MRB_ARGS_REQ(1)); /* 15.2.10.5.23 */ - mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.24 */ - mrb_define_method(mrb, s, "intern", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.25 */ - mrb_define_method(mrb, s, "length", mrb_str_size, MRB_ARGS_NONE()); /* 15.2.10.5.26 */ - mrb_define_method(mrb, s, "replace", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.28 */ - mrb_define_method(mrb, s, "reverse", mrb_str_reverse, MRB_ARGS_NONE()); /* 15.2.10.5.29 */ - mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, MRB_ARGS_NONE()); /* 15.2.10.5.30 */ - mrb_define_method(mrb, s, "rindex", mrb_str_rindex, MRB_ARGS_ANY()); /* 15.2.10.5.31 */ - mrb_define_method(mrb, s, "size", mrb_str_size, MRB_ARGS_NONE()); /* 15.2.10.5.33 */ - mrb_define_method(mrb, s, "slice", mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.34 */ - mrb_define_method(mrb, s, "split", mrb_str_split_m, MRB_ARGS_ANY()); /* 15.2.10.5.35 */ - - mrb_define_method(mrb, s, "to_f", mrb_str_to_f, MRB_ARGS_NONE()); /* 15.2.10.5.38 */ - mrb_define_method(mrb, s, "to_i", mrb_str_to_i, MRB_ARGS_ANY()); /* 15.2.10.5.39 */ - mrb_define_method(mrb, s, "to_s", mrb_str_to_s, MRB_ARGS_NONE()); /* 15.2.10.5.40 */ - mrb_define_method(mrb, s, "to_str", mrb_str_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "to_sym", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.41 */ - mrb_define_method(mrb, s, "upcase", mrb_str_upcase, MRB_ARGS_NONE()); /* 15.2.10.5.42 */ - mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */ - mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */ - mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE()); - - mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/symbol.c nghttp2-0.6.7/third-party/mruby/src/symbol.c --- nghttp2-1.13.0/third-party/mruby/src/symbol.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/symbol.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,489 +0,0 @@ -/* -** symbol.c - Symbol class -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include "mruby.h" -#include "mruby/khash.h" -#include "mruby/string.h" -#include "mruby/dump.h" - -/* ------------------------------------------------------ */ -typedef struct symbol_name { - mrb_bool lit : 1; - uint16_t len; - const char *name; -} symbol_name; - -static inline khint_t -sym_hash_func(mrb_state *mrb, mrb_sym s) -{ - khint_t h = 0; - size_t i, len = mrb->symtbl[s].len; - const char *p = mrb->symtbl[s].name; - - for (i=0; isymtbl[a].len == mrb->symtbl[b].len && memcmp(mrb->symtbl[a].name, mrb->symtbl[b].name, mrb->symtbl[a].len) == 0) - -KHASH_DECLARE(n2s, mrb_sym, mrb_sym, FALSE) -KHASH_DEFINE (n2s, mrb_sym, mrb_sym, FALSE, sym_hash_func, sym_hash_equal) -/* ------------------------------------------------------ */ - -static void -sym_validate_len(mrb_state *mrb, size_t len) -{ - if (len >= RITE_LV_NULL_MARK) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long"); - } -} - -static mrb_sym -sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit) -{ - khash_t(n2s) *h = mrb->name2sym; - symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */ - khiter_t k; - mrb_sym sym; - char *p; - - sym_validate_len(mrb, len); - if (sname) { - sname->lit = lit; - sname->len = (uint16_t)len; - sname->name = name; - k = kh_get(n2s, mrb, h, 0); - if (k != kh_end(h)) - return kh_key(h, k); - } - - /* registering a new symbol */ - sym = ++mrb->symidx; - if (mrb->symcapa < sym) { - if (mrb->symcapa == 0) mrb->symcapa = 100; - else mrb->symcapa = (size_t)(mrb->symcapa * 1.2); - mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1)); - } - sname = &mrb->symtbl[sym]; - sname->len = (uint16_t)len; - if (lit || mrb_ro_data_p(name)) { - sname->name = name; - sname->lit = TRUE; - } - else { - p = (char *)mrb_malloc(mrb, len+1); - memcpy(p, name, len); - p[len] = 0; - sname->name = (const char*)p; - sname->lit = FALSE; - } - kh_put(n2s, mrb, h, sym); - - return sym; -} - -MRB_API mrb_sym -mrb_intern(mrb_state *mrb, const char *name, size_t len) -{ - return sym_intern(mrb, name, len, FALSE); -} - -MRB_API mrb_sym -mrb_intern_static(mrb_state *mrb, const char *name, size_t len) -{ - return sym_intern(mrb, name, len, TRUE); -} - -MRB_API mrb_sym -mrb_intern_cstr(mrb_state *mrb, const char *name) -{ - return mrb_intern(mrb, name, strlen(name)); -} - -MRB_API mrb_sym -mrb_intern_str(mrb_state *mrb, mrb_value str) -{ - return mrb_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); -} - -MRB_API mrb_value -mrb_check_intern(mrb_state *mrb, const char *name, size_t len) -{ - khash_t(n2s) *h = mrb->name2sym; - symbol_name *sname = mrb->symtbl; - khiter_t k; - - sym_validate_len(mrb, len); - sname->len = (uint16_t)len; - sname->name = name; - - k = kh_get(n2s, mrb, h, 0); - if (k != kh_end(h)) { - return mrb_symbol_value(kh_key(h, k)); - } - return mrb_nil_value(); -} - -MRB_API mrb_value -mrb_check_intern_cstr(mrb_state *mrb, const char *name) -{ - return mrb_check_intern(mrb, name, (mrb_int)strlen(name)); -} - -MRB_API mrb_value -mrb_check_intern_str(mrb_state *mrb, mrb_value str) -{ - return mrb_check_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); -} - -/* lenp must be a pointer to a size_t variable */ -MRB_API const char* -mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp) -{ - if (sym == 0 || mrb->symidx < sym) { - if (lenp) *lenp = 0; - return NULL; - } - - if (lenp) *lenp = mrb->symtbl[sym].len; - return mrb->symtbl[sym].name; -} - -void -mrb_free_symtbl(mrb_state *mrb) -{ - mrb_sym i, lim; - - for (i=1, lim=mrb->symidx+1; isymtbl[i].lit) { - mrb_free(mrb, (char*)mrb->symtbl[i].name); - } - } - mrb_free(mrb, mrb->symtbl); - kh_destroy(n2s, mrb, mrb->name2sym); -} - -void -mrb_init_symtbl(mrb_state *mrb) -{ - mrb->name2sym = kh_init(n2s, mrb); -} - -/********************************************************************** - * Document-class: Symbol - * - * Symbol objects represent names and some strings - * inside the Ruby - * interpreter. They are generated using the :name and - * :"string" literals - * syntax, and by the various to_sym methods. The same - * Symbol object will be created for a given name or string - * for the duration of a program's execution, regardless of the context - * or meaning of that name. Thus if Fred is a constant in - * one context, a method in another, and a class in a third, the - * Symbol :Fred will be the same object in - * all three contexts. - * - * module One - * class Fred - * end - * $f1 = :Fred - * end - * module Two - * Fred = 1 - * $f2 = :Fred - * end - * def Fred() - * end - * $f3 = :Fred - * $f1.object_id #=> 2514190 - * $f2.object_id #=> 2514190 - * $f3.object_id #=> 2514190 - * - */ - - -/* 15.2.11.3.1 */ -/* - * call-seq: - * sym == obj -> true or false - * - * Equality---If sym and obj are exactly the same - * symbol, returns true. - */ - -static mrb_value -sym_equal(mrb_state *mrb, mrb_value sym1) -{ - mrb_value sym2; - - mrb_get_args(mrb, "o", &sym2); - - return mrb_bool_value(mrb_obj_equal(mrb, sym1, sym2)); -} - -/* 15.2.11.3.2 */ -/* 15.2.11.3.3 */ -/* - * call-seq: - * sym.id2name -> string - * sym.to_s -> string - * - * Returns the name or string corresponding to sym. - * - * :fred.id2name #=> "fred" - */ -static mrb_value -mrb_sym_to_s(mrb_state *mrb, mrb_value sym) -{ - mrb_sym id = mrb_symbol(sym); - const char *p; - mrb_int len; - - p = mrb_sym2name_len(mrb, id, &len); - return mrb_str_new_static(mrb, p, len); -} - -/* 15.2.11.3.4 */ -/* - * call-seq: - * sym.to_sym -> sym - * sym.intern -> sym - * - * In general, to_sym returns the Symbol corresponding - * to an object. As sym is already a symbol, self is returned - * in this case. - */ - -static mrb_value -sym_to_sym(mrb_state *mrb, mrb_value sym) -{ - return sym; -} - -/* 15.2.11.3.5(x) */ -/* - * call-seq: - * sym.inspect -> string - * - * Returns the representation of sym as a symbol literal. - * - * :fred.inspect #=> ":fred" - */ - -#if __STDC__ -# define SIGN_EXTEND_CHAR(c) ((signed char)(c)) -#else /* not __STDC__ */ -/* As in Harbison and Steele. */ -# define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128) -#endif -#define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '_')) - -static mrb_bool -is_special_global_name(const char* m) -{ - switch (*m) { - case '~': case '*': case '$': case '?': case '!': case '@': - case '/': case '\\': case ';': case ',': case '.': case '=': - case ':': case '<': case '>': case '\"': - case '&': case '`': case '\'': case '+': - case '0': - ++m; - break; - case '-': - ++m; - if (is_identchar(*m)) m += 1; - break; - default: - if (!ISDIGIT(*m)) return FALSE; - do ++m; while (ISDIGIT(*m)); - break; - } - return !*m; -} - -static mrb_bool -symname_p(const char *name) -{ - const char *m = name; - mrb_bool localid = FALSE; - - if (!m) return FALSE; - switch (*m) { - case '\0': - return FALSE; - - case '$': - if (is_special_global_name(++m)) return TRUE; - goto id; - - case '@': - if (*++m == '@') ++m; - goto id; - - case '<': - switch (*++m) { - case '<': ++m; break; - case '=': if (*++m == '>') ++m; break; - default: break; - } - break; - - case '>': - switch (*++m) { - case '>': case '=': ++m; break; - default: break; - } - break; - - case '=': - switch (*++m) { - case '~': ++m; break; - case '=': if (*++m == '=') ++m; break; - default: return FALSE; - } - break; - - case '*': - if (*++m == '*') ++m; - break; - case '!': - if (*++m == '=') ++m; - break; - case '+': case '-': - if (*++m == '@') ++m; - break; - case '|': - if (*++m == '|') ++m; - break; - case '&': - if (*++m == '&') ++m; - break; - - case '^': case '/': case '%': case '~': case '`': - ++m; - break; - - case '[': - if (*++m != ']') return FALSE; - if (*++m == '=') ++m; - break; - - default: - localid = !ISUPPER(*m); -id: - if (*m != '_' && !ISALPHA(*m)) return FALSE; - while (is_identchar(*m)) m += 1; - if (localid) { - switch (*m) { - case '!': case '?': case '=': ++m; - default: break; - } - } - break; - } - return *m ? FALSE : TRUE; -} - -static mrb_value -sym_inspect(mrb_state *mrb, mrb_value sym) -{ - mrb_value str; - const char *name; - mrb_int len; - mrb_sym id = mrb_symbol(sym); - char *sp; - - name = mrb_sym2name_len(mrb, id, &len); - str = mrb_str_new(mrb, 0, len+1); - sp = RSTRING_PTR(str); - RSTRING_PTR(str)[0] = ':'; - memcpy(sp+1, name, len); - mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - if (!symname_p(name) || strlen(name) != (size_t)len) { - str = mrb_str_dump(mrb, str); - sp = RSTRING_PTR(str); - sp[0] = ':'; - sp[1] = '"'; - } - return str; -} - -MRB_API mrb_value -mrb_sym2str(mrb_state *mrb, mrb_sym sym) -{ - mrb_int len; - const char *name = mrb_sym2name_len(mrb, sym, &len); - - if (!name) return mrb_undef_value(); /* can't happen */ - return mrb_str_new_static(mrb, name, len); -} - -MRB_API const char* -mrb_sym2name(mrb_state *mrb, mrb_sym sym) -{ - mrb_int len; - const char *name = mrb_sym2name_len(mrb, sym, &len); - - if (!name) return NULL; - if (symname_p(name) && strlen(name) == (size_t)len) { - return name; - } - else { - mrb_value str = mrb_str_dump(mrb, mrb_str_new_static(mrb, name, len)); - return RSTRING_PTR(str); - } -} - -#define lesser(a,b) (((a)>(b))?(b):(a)) - -static mrb_value -sym_cmp(mrb_state *mrb, mrb_value s1) -{ - mrb_value s2; - mrb_sym sym1, sym2; - - mrb_get_args(mrb, "o", &s2); - if (mrb_type(s2) != MRB_TT_SYMBOL) return mrb_nil_value(); - sym1 = mrb_symbol(s1); - sym2 = mrb_symbol(s2); - if (sym1 == sym2) return mrb_fixnum_value(0); - else { - const char *p1, *p2; - int retval; - mrb_int len, len1, len2; - - p1 = mrb_sym2name_len(mrb, sym1, &len1); - p2 = mrb_sym2name_len(mrb, sym2, &len2); - len = lesser(len1, len2); - retval = memcmp(p1, p2, len); - if (retval == 0) { - if (len1 == len2) return mrb_fixnum_value(0); - if (len1 > len2) return mrb_fixnum_value(1); - return mrb_fixnum_value(-1); - } - if (retval > 0) return mrb_fixnum_value(1); - return mrb_fixnum_value(-1); - } -} - -void -mrb_init_symbol(mrb_state *mrb) -{ - struct RClass *sym; - - mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */ - - mrb_define_method(mrb, sym, "===", sym_equal, MRB_ARGS_REQ(1)); /* 15.2.11.3.1 */ - mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */ - mrb_define_method(mrb, sym, "to_s", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */ - mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */ - mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */ - mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1)); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/value_array.h nghttp2-0.6.7/third-party/mruby/src/value_array.h --- nghttp2-1.13.0/third-party/mruby/src/value_array.h 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/value_array.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -#ifndef MRB_VALUE_ARRAY_H__ -#define MRB_VALUE_ARRAY_H__ - -#include "mruby.h" - -static inline void -value_move(mrb_value *s1, const mrb_value *s2, size_t n) -{ - if (s1 > s2 && s1 < s2 + n) - { - s1 += n; - s2 += n; - while (n-- > 0) { - *--s1 = *--s2; - } - } - else if (s1 != s2) { - while (n-- > 0) { - *s1++ = *s2++; - } - } - else { - /* nothing to do. */ - } -} - -#endif /* MRB_VALUE_ARRAY_H__ */ diff -Nru nghttp2-1.13.0/third-party/mruby/src/variable.c nghttp2-0.6.7/third-party/mruby/src/variable.c --- nghttp2-1.13.0/third-party/mruby/src/variable.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/variable.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1181 +0,0 @@ -/* -** variable.c - mruby variables -** -** See Copyright Notice in mruby.h -*/ - -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/proc.h" -#include "mruby/string.h" - -typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*); - -#ifdef MRB_USE_IV_SEGLIST - -#ifndef MRB_SEGMENT_SIZE -#define MRB_SEGMENT_SIZE 4 -#endif - -typedef struct segment { - mrb_sym key[MRB_SEGMENT_SIZE]; - mrb_value val[MRB_SEGMENT_SIZE]; - struct segment *next; -} segment; - -/* Instance variable table structure */ -typedef struct iv_tbl { - segment *rootseg; - size_t size; - size_t last_len; -} iv_tbl; - -/* - * Creates the instance variable table. - * - * Parameters - * mrb - * Returns - * the instance variable table. - */ -static iv_tbl* -iv_new(mrb_state *mrb) -{ - iv_tbl *t; - - t = mrb_malloc(mrb, sizeof(iv_tbl)); - t->size = 0; - t->rootseg = NULL; - t->last_len = 0; - - return t; -} - -/* - * Set the value for the symbol in the instance variable table. - * - * Parameters - * mrb - * t the instance variable table to be set in. - * sym the symbol to be used as the key. - * val the value to be set. - */ -static void -iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) -{ - segment *seg = t->rootseg; - segment *prev = NULL; - segment *matched_seg = NULL; - size_t matched_idx = 0; - size_t i; - - while (seg) { - for (i=0; ikey[i]; - /* Found room in last segment after last_len */ - if (!seg->next && i >= t->last_len) { - seg->key[i] = sym; - seg->val[i] = val; - t->last_len = i+1; - t->size++; - return; - } - if (!matched_seg && key == 0) { - matched_seg = seg; - matched_idx = i; - } - else if (key == sym) { - seg->val[i] = val; - return; - } - } - prev = seg; - seg = seg->next; - } - - /* Not found */ - t->size++; - if (matched_seg) { - matched_seg->key[matched_idx] = sym; - matched_seg->val[matched_idx] = val; - return; - } - - seg = mrb_malloc(mrb, sizeof(segment)); - if (!seg) return; - seg->next = NULL; - seg->key[0] = sym; - seg->val[0] = val; - t->last_len = 1; - if (prev) { - prev->next = seg; - } - else { - t->rootseg = seg; - } -} - -/* - * Get a value for a symbol from the instance variable table. - * - * Parameters - * mrb - * t the variable table to be searched. - * sym the symbol to be used as the key. - * vp the value pointer. Receives the value if the specified symbol is - * contained in the instance variable table. - * Returns - * true if the specified symbol is contained in the instance variable table. - */ -static mrb_bool -iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) -{ - segment *seg; - size_t i; - - seg = t->rootseg; - while (seg) { - for (i=0; ikey[i]; - - if (!seg->next && i >= t->last_len) { - return FALSE; - } - if (key == sym) { - if (vp) *vp = seg->val[i]; - return TRUE; - } - } - seg = seg->next; - } - return FALSE; -} - -/* - * Deletes the value for the symbol from the instance variable table. - * - * Parameters - * t the variable table to be searched. - * sym the symbol to be used as the key. - * vp the value pointer. Receive the deleted value if the symbol is - * contained in the instance variable table. - * Returns - * true if the specified symbol is contained in the instance variable table. - */ -static mrb_bool -iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) -{ - segment *seg; - size_t i; - - seg = t->rootseg; - while (seg) { - for (i=0; ikey[i]; - - if (!seg->next && i >= t->last_len) { - return FALSE; - } - if (key == sym) { - t->size--; - seg->key[i] = 0; - if (vp) *vp = seg->val[i]; - return TRUE; - } - } - seg = seg->next; - } - return FALSE; -} - -static mrb_bool -iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) -{ - segment *seg; - size_t i; - int n; - - seg = t->rootseg; - while (seg) { - for (i=0; ikey[i]; - - /* no value in last segment after last_len */ - if (!seg->next && i >= t->last_len) { - return FALSE; - } - if (key != 0) { - n =(*func)(mrb, key, seg->val[i], p); - if (n > 0) return FALSE; - if (n < 0) { - t->size--; - seg->key[i] = 0; - } - } - } - seg = seg->next; - } - return TRUE; -} - -static size_t -iv_size(mrb_state *mrb, iv_tbl *t) -{ - segment *seg; - size_t size = 0; - - if (!t) return 0; - if (t->size > 0) return t->size; - seg = t->rootseg; - while (seg) { - if (seg->next == NULL) { - size += t->last_len; - return size; - } - seg = seg->next; - size += MRB_SEGMENT_SIZE; - } - /* empty iv_tbl */ - return 0; -} - -static iv_tbl* -iv_copy(mrb_state *mrb, iv_tbl *t) -{ - segment *seg; - iv_tbl *t2; - - size_t i; - - seg = t->rootseg; - t2 = iv_new(mrb); - - while (seg != NULL) { - for (i=0; ikey[i]; - mrb_value val = seg->val[i]; - - if ((seg->next == NULL) && (i >= t->last_len)) { - return t2; - } - iv_put(mrb, t2, key, val); - } - seg = seg->next; - } - return t2; -} - -static void -iv_free(mrb_state *mrb, iv_tbl *t) -{ - segment *seg; - - seg = t->rootseg; - while (seg) { - segment *p = seg; - seg = seg->next; - mrb_free(mrb, p); - } - mrb_free(mrb, t); -} - -#else - -#include "mruby/khash.h" - -#ifndef MRB_IVHASH_INIT_SIZE -#define MRB_IVHASH_INIT_SIZE 8 -#endif - -KHASH_DECLARE(iv, mrb_sym, mrb_value, TRUE) -KHASH_DEFINE(iv, mrb_sym, mrb_value, TRUE, kh_int_hash_func, kh_int_hash_equal) - -typedef struct iv_tbl { - khash_t(iv) h; -} iv_tbl; - -static iv_tbl* -iv_new(mrb_state *mrb) -{ - return (iv_tbl*)kh_init_size(iv, mrb, MRB_IVHASH_INIT_SIZE); -} - -static void -iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) -{ - khash_t(iv) *h = &t->h; - khiter_t k; - - k = kh_put(iv, mrb, h, sym); - kh_value(h, k) = val; -} - -static mrb_bool -iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) -{ - khash_t(iv) *h = &t->h; - khiter_t k; - - k = kh_get(iv, mrb, h, sym); - if (k != kh_end(h)) { - if (vp) *vp = kh_value(h, k); - return TRUE; - } - return FALSE; -} - -static mrb_bool -iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) -{ - khash_t(iv) *h = &t->h; - khiter_t k; - - if (h) { - k = kh_get(iv, mrb, h, sym); - if (k != kh_end(h)) { - mrb_value val = kh_value(h, k); - kh_del(iv, mrb, h, k); - if (vp) *vp = val; - return TRUE; - } - } - return FALSE; -} - -static mrb_bool -iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) -{ - khash_t(iv) *h = &t->h; - khiter_t k; - int n; - - if (h) { - for (k = kh_begin(h); k != kh_end(h); k++) { - if (kh_exist(h, k)) { - n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p); - if (n > 0) return FALSE; - if (n < 0) { - kh_del(iv, mrb, h, k); - } - } - } - } - return TRUE; -} - -static size_t -iv_size(mrb_state *mrb, iv_tbl *t) -{ - khash_t(iv) *h; - - if (t && (h = &t->h)) { - return kh_size(h); - } - return 0; -} - -static iv_tbl* -iv_copy(mrb_state *mrb, iv_tbl *t) -{ - return (iv_tbl*)kh_copy(iv, mrb, &t->h); -} - -static void -iv_free(mrb_state *mrb, iv_tbl *t) -{ - kh_destroy(iv, mrb, &t->h); -} - -#endif - -static int -iv_mark_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) -{ - mrb_gc_mark_value(mrb, v); - return 0; -} - -static void -mark_tbl(mrb_state *mrb, iv_tbl *t) -{ - if (t) { - iv_foreach(mrb, t, iv_mark_i, 0); - } -} - -void -mrb_gc_mark_gv(mrb_state *mrb) -{ - mark_tbl(mrb, mrb->globals); -} - -void -mrb_gc_free_gv(mrb_state *mrb) -{ - if (mrb->globals) - iv_free(mrb, mrb->globals); -} - -void -mrb_gc_mark_iv(mrb_state *mrb, struct RObject *obj) -{ - mark_tbl(mrb, obj->iv); -} - -size_t -mrb_gc_mark_iv_size(mrb_state *mrb, struct RObject *obj) -{ - return iv_size(mrb, obj->iv); -} - -void -mrb_gc_free_iv(mrb_state *mrb, struct RObject *obj) -{ - if (obj->iv) { - iv_free(mrb, obj->iv); - } -} - -mrb_value -mrb_vm_special_get(mrb_state *mrb, mrb_sym i) -{ - return mrb_fixnum_value(0); -} - -void -mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v) -{ -} - -static mrb_bool -obj_iv_p(mrb_value obj) -{ - switch (mrb_type(obj)) { - case MRB_TT_OBJECT: - case MRB_TT_CLASS: - case MRB_TT_MODULE: - case MRB_TT_SCLASS: - case MRB_TT_HASH: - case MRB_TT_DATA: - case MRB_TT_EXCEPTION: - return TRUE; - default: - return FALSE; - } -} - -MRB_API mrb_value -mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym) -{ - mrb_value v; - - if (obj->iv && iv_get(mrb, obj->iv, sym, &v)) - return v; - return mrb_nil_value(); -} - -MRB_API mrb_value -mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym) -{ - if (obj_iv_p(obj)) { - return mrb_obj_iv_get(mrb, mrb_obj_ptr(obj), sym); - } - return mrb_nil_value(); -} - -MRB_API void -mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) -{ - iv_tbl *t = obj->iv; - - if (!t) { - t = obj->iv = iv_new(mrb); - } - mrb_write_barrier(mrb, (struct RBasic*)obj); - iv_put(mrb, t, sym, v); -} - -MRB_API void -mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) -{ - iv_tbl *t = obj->iv; - - if (!t) { - t = obj->iv = iv_new(mrb); - } - else if (iv_get(mrb, t, sym, &v)) { - return; - } - mrb_write_barrier(mrb, (struct RBasic*)obj); - iv_put(mrb, t, sym, v); -} - -MRB_API void -mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v) -{ - if (obj_iv_p(obj)) { - mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v); - } - else { - mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot set instance variable"); - } -} - -MRB_API mrb_bool -mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym) -{ - iv_tbl *t; - - t = obj->iv; - if (t) { - return iv_get(mrb, t, sym, NULL); - } - return FALSE; -} - -MRB_API mrb_bool -mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym) -{ - if (!obj_iv_p(obj)) return FALSE; - return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym); -} - -#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) - -MRB_API mrb_bool -mrb_iv_p(mrb_state *mrb, mrb_sym iv_name) -{ - const char *s; - mrb_int i, len; - - s = mrb_sym2name_len(mrb, iv_name, &len); - if (len < 2) return FALSE; - if (s[0] != '@') return FALSE; - if (s[1] == '@') return FALSE; - for (i=1; iiv) { - iv_free(mrb, d->iv); - d->iv = 0; - } - if (s->iv) { - mrb_write_barrier(mrb, (struct RBasic*)d); - d->iv = iv_copy(mrb, s->iv); - } -} - -static int -inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) -{ - mrb_value str = *(mrb_value*)p; - const char *s; - mrb_int len; - mrb_value ins; - char *sp = RSTRING_PTR(str); - - /* need not to show internal data */ - if (sp[0] == '-') { /* first element */ - sp[0] = '#'; - mrb_str_cat_lit(mrb, str, " "); - } - else { - mrb_str_cat_lit(mrb, str, ", "); - } - s = mrb_sym2name_len(mrb, sym, &len); - mrb_str_cat(mrb, str, s, len); - mrb_str_cat_lit(mrb, str, "="); - if (mrb_type(v) == MRB_TT_OBJECT) { - ins = mrb_any_to_s(mrb, v); - } - else { - ins = mrb_inspect(mrb, v); - } - mrb_str_cat_str(mrb, str, ins); - return 0; -} - -mrb_value -mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj) -{ - iv_tbl *t = obj->iv; - size_t len = iv_size(mrb, t); - - if (len > 0) { - const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj)); - mrb_value str = mrb_str_buf_new(mrb, 30); - - mrb_str_cat_lit(mrb, str, "-<"); - mrb_str_cat_cstr(mrb, str, cn); - mrb_str_cat_lit(mrb, str, ":"); - mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj)); - - iv_foreach(mrb, t, inspect_i, &str); - mrb_str_cat_lit(mrb, str, ">"); - return str; - } - return mrb_any_to_s(mrb, mrb_obj_value(obj)); -} - -MRB_API mrb_value -mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym) -{ - if (obj_iv_p(obj)) { - iv_tbl *t = mrb_obj_ptr(obj)->iv; - mrb_value val; - - if (t && iv_del(mrb, t, sym, &val)) { - return val; - } - } - return mrb_undef_value(); -} - -mrb_value -mrb_vm_iv_get(mrb_state *mrb, mrb_sym sym) -{ - /* get self */ - return mrb_iv_get(mrb, mrb->c->stack[0], sym); -} - -void -mrb_vm_iv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) -{ - /* get self */ - mrb_iv_set(mrb, mrb->c->stack[0], sym, v); -} - -static int -iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) -{ - mrb_value ary; - const char* s; - mrb_int len; - - ary = *(mrb_value*)p; - s = mrb_sym2name_len(mrb, sym, &len); - if (len > 1 && s[0] == '@' && s[1] != '@') { - mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); - } - return 0; -} - -/* 15.3.1.3.23 */ -/* - * call-seq: - * obj.instance_variables -> array - * - * Returns an array of instance variable names for the receiver. Note - * that simply defining an accessor does not create the corresponding - * instance variable. - * - * class Fred - * attr_accessor :a1 - * def initialize - * @iv = 3 - * end - * end - * Fred.new.instance_variables #=> [:@iv] - */ -mrb_value -mrb_obj_instance_variables(mrb_state *mrb, mrb_value self) -{ - mrb_value ary; - - ary = mrb_ary_new(mrb); - if (obj_iv_p(self) && mrb_obj_ptr(self)->iv) { - iv_foreach(mrb, mrb_obj_ptr(self)->iv, iv_i, &ary); - } - return ary; -} - -static int -cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) -{ - mrb_value ary; - const char* s; - mrb_int len; - - ary = *(mrb_value*)p; - s = mrb_sym2name_len(mrb, sym, &len); - if (len > 2 && s[0] == '@' && s[1] == '@') { - mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); - } - return 0; -} - -/* 15.2.2.4.19 */ -/* - * call-seq: - * mod.class_variables -> array - * - * Returns an array of the names of class variables in mod. - * - * class One - * @@var1 = 1 - * end - * class Two < One - * @@var2 = 2 - * end - * One.class_variables #=> [:@@var1] - * Two.class_variables #=> [:@@var2] - */ -mrb_value -mrb_mod_class_variables(mrb_state *mrb, mrb_value mod) -{ - mrb_value ary; - struct RClass *c; - - ary = mrb_ary_new(mrb); - c = mrb_class_ptr(mod); - while (c) { - if (c->iv) { - iv_foreach(mrb, c->iv, cv_i, &ary); - } - c = c->super; - } - return ary; -} - -MRB_API mrb_value -mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym) -{ - struct RClass * cls = c; - mrb_value v; - - while (c) { - if (c->iv && iv_get(mrb, c->iv, sym, &v)) { - return v; - } - c = c->super; - } - if (cls && cls->tt == MRB_TT_SCLASS) { - mrb_value klass; - - klass = mrb_obj_iv_get(mrb, (struct RObject *)cls, - mrb_intern_lit(mrb, "__attached__")); - c = mrb_class_ptr(klass); - if (c->tt == MRB_TT_CLASS) { - while (c) { - if (c->iv && iv_get(mrb, c->iv, sym, &v)) { - return v; - } - c = c->super; - } - } - } - mrb_name_error(mrb, sym, "uninitialized class variable %S in %S", - mrb_sym2str(mrb, sym), mrb_obj_value(cls)); - /* not reached */ - return mrb_nil_value(); -} - -MRB_API mrb_value -mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym) -{ - return mrb_mod_cv_get(mrb, mrb_class_ptr(mod), sym); -} - -MRB_API void -mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v) -{ - struct RClass * cls = c; - - while (c) { - if (c->iv) { - iv_tbl *t = c->iv; - - if (iv_get(mrb, t, sym, NULL)) { - mrb_write_barrier(mrb, (struct RBasic*)c); - iv_put(mrb, t, sym, v); - return; - } - } - c = c->super; - } - - if (!cls->iv) { - cls->iv = iv_new(mrb); - } - - mrb_write_barrier(mrb, (struct RBasic*)cls); - iv_put(mrb, cls->iv, sym, v); -} - -MRB_API void -mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v) -{ - mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v); -} - -MRB_API mrb_bool -mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym) -{ - while (c) { - if (c->iv) { - iv_tbl *t = c->iv; - if (iv_get(mrb, t, sym, NULL)) return TRUE; - } - c = c->super; - } - - return FALSE; -} - -MRB_API mrb_bool -mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym) -{ - return mrb_mod_cv_defined(mrb, mrb_class_ptr(mod), sym); -} - -mrb_value -mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym) -{ - struct RClass *c = mrb->c->ci->proc->target_class; - - if (!c) c = mrb->c->ci->target_class; - - return mrb_mod_cv_get(mrb, c, sym); -} - -void -mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) -{ - struct RClass *c = mrb->c->ci->proc->target_class; - - if (!c) c = mrb->c->ci->target_class; - mrb_mod_cv_set(mrb, c, sym, v); -} - -static void -mod_const_check(mrb_state *mrb, mrb_value mod) -{ - switch (mrb_type(mod)) { - case MRB_TT_CLASS: - case MRB_TT_MODULE: - case MRB_TT_SCLASS: - break; - default: - mrb_raise(mrb, E_TYPE_ERROR, "constant look-up for non class/module"); - break; - } -} - -static mrb_value -const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym) -{ - struct RClass *c = base; - mrb_value v; - iv_tbl *t; - mrb_bool retry = FALSE; - mrb_value name; - -L_RETRY: - while (c) { - if (c->iv) { - t = c->iv; - if (iv_get(mrb, t, sym, &v)) - return v; - } - c = c->super; - } - if (!retry && base && base->tt == MRB_TT_MODULE) { - c = mrb->object_class; - retry = TRUE; - goto L_RETRY; - } - name = mrb_symbol_value(sym); - return mrb_funcall_argv(mrb, mrb_obj_value(base), mrb_intern_lit(mrb, "const_missing"), 1, &name); -} - -MRB_API mrb_value -mrb_const_get(mrb_state *mrb, mrb_value mod, mrb_sym sym) -{ - mod_const_check(mrb, mod); - return const_get(mrb, mrb_class_ptr(mod), sym); -} - -mrb_value -mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) -{ - struct RClass *c = mrb->c->ci->proc->target_class; - - if (!c) c = mrb->c->ci->target_class; - if (c) { - struct RClass *c2; - mrb_value v; - - if (c->iv && iv_get(mrb, c->iv, sym, &v)) { - return v; - } - if (c->tt == MRB_TT_SCLASS) { - mrb_value klass; - klass = mrb_obj_iv_get(mrb, (struct RObject *)c, - mrb_intern_lit(mrb, "__attached__")); - c2 = mrb_class_ptr(klass); - if (c2->tt == MRB_TT_CLASS) - c = c2; - } - c2 = c; - for (;;) { - c2 = mrb_class_outer_module(mrb, c2); - if (!c2) break; - if (c2->iv && iv_get(mrb, c2->iv, sym, &v)) { - return v; - } - } - } - return const_get(mrb, c, sym); -} - -MRB_API void -mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v) -{ - mod_const_check(mrb, mod); - mrb_iv_set(mrb, mod, sym, v); -} - -void -mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v) -{ - struct RClass *c = mrb->c->ci->proc->target_class; - - if (!c) c = mrb->c->ci->target_class; - mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v); -} - -MRB_API void -mrb_const_remove(mrb_state *mrb, mrb_value mod, mrb_sym sym) -{ - mod_const_check(mrb, mod); - mrb_iv_remove(mrb, mod, sym); -} - -MRB_API void -mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v) -{ - mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern_cstr(mrb, name), v); -} - -MRB_API void -mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val) -{ - mrb_define_const(mrb, mrb->object_class, name, val); -} - -static int -const_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) -{ - mrb_value ary; - const char* s; - mrb_int len; - - ary = *(mrb_value*)p; - s = mrb_sym2name_len(mrb, sym, &len); - if (len >= 1 && ISUPPER(s[0])) { - mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); - } - return 0; -} - -/* 15.2.2.4.24 */ -/* - * call-seq: - * mod.constants -> array - * - * Returns an array of all names of contants defined in the receiver. - */ -mrb_value -mrb_mod_constants(mrb_state *mrb, mrb_value mod) -{ - mrb_value ary; - mrb_bool inherit = TRUE; - struct RClass *c = mrb_class_ptr(mod); - - mrb_get_args(mrb, "|b", &inherit); - ary = mrb_ary_new(mrb); - while (c) { - if (c->iv) { - iv_foreach(mrb, c->iv, const_i, &ary); - } - if (!inherit) break; - c = c->super; - if (c == mrb->object_class) break; - } - return ary; -} - -MRB_API mrb_value -mrb_gv_get(mrb_state *mrb, mrb_sym sym) -{ - mrb_value v; - - if (!mrb->globals) { - return mrb_nil_value(); - } - if (iv_get(mrb, mrb->globals, sym, &v)) - return v; - return mrb_nil_value(); -} - -MRB_API void -mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) -{ - iv_tbl *t; - - if (!mrb->globals) { - t = mrb->globals = iv_new(mrb); - } - else { - t = mrb->globals; - } - iv_put(mrb, t, sym, v); -} - -MRB_API void -mrb_gv_remove(mrb_state *mrb, mrb_sym sym) -{ - if (!mrb->globals) { - return; - } - iv_del(mrb, mrb->globals, sym, NULL); -} - -static int -gv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) -{ - mrb_value ary; - - ary = *(mrb_value*)p; - mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); - return 0; -} - -/* 15.3.1.2.4 */ -/* 15.3.1.3.14 */ -/* - * call-seq: - * global_variables -> array - * - * Returns an array of the names of global variables. - * - * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr] - */ -mrb_value -mrb_f_global_variables(mrb_state *mrb, mrb_value self) -{ - iv_tbl *t = mrb->globals; - mrb_value ary = mrb_ary_new(mrb); - size_t i; - char buf[3]; - - if (t) { - iv_foreach(mrb, t, gv_i, &ary); - } - buf[0] = '$'; - buf[2] = 0; - for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); - mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern(mrb, buf, 2))); - } - return ary; -} - -static mrb_bool -mrb_const_defined_0(mrb_state *mrb, mrb_value mod, mrb_sym id, mrb_bool exclude, mrb_bool recurse) -{ - struct RClass *klass = mrb_class_ptr(mod); - struct RClass *tmp; - mrb_bool mod_retry = 0; - - tmp = klass; -retry: - while (tmp) { - if (tmp->iv && iv_get(mrb, tmp->iv, id, NULL)) { - return TRUE; - } - if (!recurse && (klass != mrb->object_class)) break; - tmp = tmp->super; - } - if (!exclude && !mod_retry && (klass->tt == MRB_TT_MODULE)) { - mod_retry = 1; - tmp = mrb->object_class; - goto retry; - } - return FALSE; -} - -MRB_API mrb_bool -mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym id) -{ - return mrb_const_defined_0(mrb, mod, id, TRUE, TRUE); -} - -MRB_API mrb_bool -mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id) -{ - return mrb_const_defined_0(mrb, mod, id, TRUE, FALSE); -} - -MRB_API mrb_value -mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id) -{ - return mrb_iv_get(mrb, obj, id); -} - -struct csym_arg { - struct RClass *c; - mrb_sym sym; -}; - -static int -csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) -{ - struct csym_arg *a = (struct csym_arg*)p; - struct RClass *c = a->c; - - if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) { - a->sym = sym; - return 1; /* stop iteration */ - } - return 0; -} - -mrb_sym -mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer) -{ - mrb_value name; - - name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__classid__")); - if (mrb_nil_p(name)) { - - if (!outer) return 0; - else { - struct csym_arg arg; - - arg.c = c; - arg.sym = 0; - iv_foreach(mrb, outer->iv, csym_i, &arg); - return arg.sym; - } - } - return mrb_symbol(name); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/version.c nghttp2-0.6.7/third-party/mruby/src/version.c --- nghttp2-1.13.0/third-party/mruby/src/version.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/version.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -#include "mruby.h" -#include "mruby/variable.h" - -void -mrb_init_version(mrb_state* mrb) -{ - mrb_value mruby_version = mrb_str_new_lit(mrb, MRUBY_VERSION); - - mrb_define_global_const(mrb, "RUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_RUBY_VERSION)); - mrb_define_global_const(mrb, "RUBY_ENGINE", mrb_str_new_lit(mrb, MRUBY_RUBY_ENGINE)); - mrb_define_global_const(mrb, "RUBY_ENGINE_VERSION", mruby_version); - mrb_define_global_const(mrb, "MRUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_VERSION)); - mrb_define_global_const(mrb, "MRUBY_RELEASE_NO", mrb_fixnum_value(MRUBY_RELEASE_NO)); - mrb_define_global_const(mrb, "MRUBY_RELEASE_DATE", mrb_str_new_lit(mrb, MRUBY_RELEASE_DATE)); - mrb_define_global_const(mrb, "MRUBY_DESCRIPTION", mrb_str_new_lit(mrb, MRUBY_DESCRIPTION)); - mrb_define_global_const(mrb, "MRUBY_COPYRIGHT", mrb_str_new_lit(mrb, MRUBY_COPYRIGHT)); -} diff -Nru nghttp2-1.13.0/third-party/mruby/src/vm.c nghttp2-0.6.7/third-party/mruby/src/vm.c --- nghttp2-1.13.0/third-party/mruby/src/vm.c 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/src/vm.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,2427 +0,0 @@ -/* -** vm.c - virtual machine for mruby -** -** See Copyright Notice in mruby.h -*/ - -#include -#include -#include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/hash.h" -#include "mruby/irep.h" -#include "mruby/numeric.h" -#include "mruby/proc.h" -#include "mruby/range.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/error.h" -#include "mruby/opcode.h" -#include "value_array.h" -#include "mruby/throw.h" - -#ifndef MRB_DISABLE_STDIO -#if defined(__cplusplus) -extern "C" { -#endif -void abort(void); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif -#endif - -#define STACK_INIT_SIZE 128 -#define CALLINFO_INIT_SIZE 32 - -/* Define amount of linear stack growth. */ -#ifndef MRB_STACK_GROWTH -#define MRB_STACK_GROWTH 128 -#endif - -/* Maximum stack depth. Should be set lower on memory constrained systems. -The value below allows about 60000 recursive calls in the simplest case. */ -#ifndef MRB_STACK_MAX -#define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH) -#endif - -#ifdef VM_DEBUG -# define DEBUG(x) (x) -#else -# define DEBUG(x) -#endif - -#define ARENA_RESTORE(mrb,ai) (mrb)->gc.arena_idx = (ai) - -static inline void -stack_clear(mrb_value *from, size_t count) -{ -#ifndef MRB_NAN_BOXING - const mrb_value mrb_value_zero = { { 0 } }; - - while (count-- > 0) { - *from++ = mrb_value_zero; - } -#else - while (count-- > 0) { - SET_NIL_VALUE(*from); - from++; - } -#endif -} - -static inline void -stack_copy(mrb_value *dst, const mrb_value *src, size_t size) -{ - while (size-- > 0) { - *dst++ = *src++; - } -} - -static void -stack_init(mrb_state *mrb) -{ - struct mrb_context *c = mrb->c; - - /* mrb_assert(mrb->stack == NULL); */ - c->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value)); - c->stend = c->stbase + STACK_INIT_SIZE; - c->stack = c->stbase; - - /* mrb_assert(ci == NULL); */ - c->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo)); - c->ciend = c->cibase + CALLINFO_INIT_SIZE; - c->ci = c->cibase; - c->ci->target_class = mrb->object_class; - c->ci->stackent = c->stack; -} - -static inline void -envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) -{ - mrb_callinfo *ci = mrb->c->cibase; - - if (newbase == oldbase) return; - while (ci <= mrb->c->ci) { - struct REnv *e = ci->env; - if (e && MRB_ENV_STACK_SHARED_P(e)) { - ptrdiff_t off = e->stack - oldbase; - - e->stack = newbase + off; - } - ci->stackent = newbase + (ci->stackent - oldbase); - ci++; - } -} - -static inline void -init_new_stack_space(mrb_state *mrb, int room, int keep) -{ - if (room > keep) { - /* do not leave uninitialized malloc region */ - stack_clear(&(mrb->c->stack[keep]), room - keep); - } -} - -/** def rec ; $deep =+ 1 ; if $deep > 1000 ; return 0 ; end ; rec ; end */ - -static void -stack_extend_alloc(mrb_state *mrb, int room, int keep) -{ - mrb_value *oldbase = mrb->c->stbase; - int size = mrb->c->stend - mrb->c->stbase; - int off = mrb->c->stack - mrb->c->stbase; - -#ifdef MRB_STACK_EXTEND_DOUBLING - if (room <= size) - size *= 2; - else - size += room; -#else - /* Use linear stack growth. - It is slightly slower than doubling the stack space, - but it saves memory on small devices. */ - if (room <= MRB_STACK_GROWTH) - size += MRB_STACK_GROWTH; - else - size += room; -#endif - - mrb->c->stbase = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size); - mrb->c->stack = mrb->c->stbase + off; - mrb->c->stend = mrb->c->stbase + size; - envadjust(mrb, oldbase, mrb->c->stbase); - - /* Raise an exception if the new stack size will be too large, - to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */ - if (size > MRB_STACK_MAX) { - init_new_stack_space(mrb, room, keep); - mrb_raise(mrb, E_SYSSTACK_ERROR, "stack level too deep. (limit=" MRB_STRINGIZE(MRB_STACK_MAX) ")"); - } -} - -static inline void -stack_extend(mrb_state *mrb, int room, int keep) -{ - if (mrb->c->stack + room >= mrb->c->stend) { - stack_extend_alloc(mrb, room, keep); - } - init_new_stack_space(mrb, room, keep); -} - -static inline struct REnv* -uvenv(mrb_state *mrb, int up) -{ - struct REnv *e = mrb->c->ci->proc->env; - - while (up--) { - if (!e) return NULL; - e = (struct REnv*)e->c; - } - return e; -} - -static inline mrb_bool -is_strict(mrb_state *mrb, struct REnv *e) -{ - int cioff = e->cioff; - - if (MRB_ENV_STACK_SHARED_P(e) && mrb->c->cibase[cioff].proc && - MRB_PROC_STRICT_P(mrb->c->cibase[cioff].proc)) { - return TRUE; - } - return FALSE; -} - -static inline struct REnv* -top_env(mrb_state *mrb, struct RProc *proc) -{ - struct REnv *e = proc->env; - - if (is_strict(mrb, e)) return e; - while (e->c) { - e = (struct REnv*)e->c; - if (is_strict(mrb, e)) return e; - } - return e; -} - -#define CI_ACC_SKIP -1 -#define CI_ACC_DIRECT -2 - -static mrb_callinfo* -cipush(mrb_state *mrb) -{ - struct mrb_context *c = mrb->c; - mrb_callinfo *ci = c->ci; - - int eidx = ci->eidx; - int ridx = ci->ridx; - - if (ci + 1 == c->ciend) { - ptrdiff_t size = ci - c->cibase; - - c->cibase = (mrb_callinfo *)mrb_realloc(mrb, c->cibase, sizeof(mrb_callinfo)*size*2); - c->ci = c->cibase + size; - c->ciend = c->cibase + size * 2; - } - ci = ++c->ci; - ci->eidx = eidx; - ci->ridx = ridx; - ci->env = 0; - ci->pc = 0; - ci->err = 0; - ci->proc = 0; - - return ci; -} - -static void -cipop(mrb_state *mrb) -{ - struct mrb_context *c = mrb->c; - - if (c->ci->env) { - struct REnv *e = c->ci->env; - size_t len = (size_t)MRB_ENV_STACK_LEN(e); - mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len); - - MRB_ENV_UNSHARE_STACK(e); - if (len > 0) { - stack_copy(p, e->stack, len); - } - e->stack = p; - mrb_write_barrier(mrb, (struct RBasic *)e); - } - - c->ci--; -} - -static void -ecall(mrb_state *mrb, int i) -{ - struct RProc *p; - mrb_callinfo *ci; - mrb_value *self = mrb->c->stack; - struct RObject *exc; - - if (i<0) return; - p = mrb->c->ensure[i]; - if (!p) return; - if (mrb->c->ci->eidx > i) - mrb->c->ci->eidx = i; - ci = cipush(mrb); - ci->stackent = mrb->c->stack; - ci->mid = ci[-1].mid; - ci->acc = CI_ACC_SKIP; - ci->argc = 0; - ci->proc = p; - ci->nregs = p->body.irep->nregs; - ci->target_class = p->target_class; - mrb->c->stack = mrb->c->stack + ci[-1].nregs; - exc = mrb->exc; mrb->exc = 0; - mrb_run(mrb, p, *self); - mrb->c->ensure[i] = NULL; - if (!mrb->exc) mrb->exc = exc; -} - -#ifndef MRB_FUNCALL_ARGC_MAX -#define MRB_FUNCALL_ARGC_MAX 16 -#endif - -MRB_API mrb_value -mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...) -{ - mrb_value argv[MRB_FUNCALL_ARGC_MAX]; - va_list ap; - mrb_int i; - mrb_sym mid = mrb_intern_cstr(mrb, name); - - if (argc > MRB_FUNCALL_ARGC_MAX) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")"); - } - - va_start(ap, argc); - for (i = 0; i < argc; i++) { - argv[i] = va_arg(ap, mrb_value); - } - va_end(ap); - return mrb_funcall_argv(mrb, self, mid, argc, argv); -} - -MRB_API mrb_value -mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk) -{ - mrb_value val; - - if (!mrb->jmp) { - struct mrb_jmpbuf c_jmp; - ptrdiff_t nth_ci = mrb->c->ci - mrb->c->cibase; - - MRB_TRY(&c_jmp) { - mrb->jmp = &c_jmp; - /* recursive call */ - val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk); - mrb->jmp = 0; - } - MRB_CATCH(&c_jmp) { /* error */ - while (nth_ci < (mrb->c->ci - mrb->c->cibase)) { - mrb->c->stack = mrb->c->ci->stackent; - cipop(mrb); - } - mrb->jmp = 0; - val = mrb_obj_value(mrb->exc); - } - MRB_END_EXC(&c_jmp); - } - else { - struct RProc *p; - struct RClass *c; - mrb_sym undef = 0; - mrb_callinfo *ci; - int n; - ptrdiff_t voff = -1; - - if (!mrb->c->stack) { - stack_init(mrb); - } - n = mrb->c->ci->nregs; - if (argc < 0) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc)); - } - c = mrb_class(mrb, self); - p = mrb_method_search_vm(mrb, &c, mid); - if (!p) { - undef = mid; - mid = mrb_intern_lit(mrb, "method_missing"); - p = mrb_method_search_vm(mrb, &c, mid); - n++; argc++; - } - ci = cipush(mrb); - ci->mid = mid; - ci->proc = p; - ci->stackent = mrb->c->stack; - ci->argc = argc; - ci->target_class = c; - mrb->c->stack = mrb->c->stack + n; - if (mrb->c->stbase <= argv && argv < mrb->c->stend) { - voff = argv - mrb->c->stbase; - } - if (MRB_PROC_CFUNC_P(p)) { - ci->nregs = argc + 2; - stack_extend(mrb, ci->nregs, 0); - } - else { - ci->nregs = p->body.irep->nregs + n; - stack_extend(mrb, ci->nregs, argc+2); - } - if (voff >= 0) { - argv = mrb->c->stbase + voff; - } - mrb->c->stack[0] = self; - if (undef) { - mrb->c->stack[1] = mrb_symbol_value(undef); - if (argc > 1) { - stack_copy(mrb->c->stack+2, argv, argc-1); - } - } - else if (argc > 0) { - stack_copy(mrb->c->stack+1, argv, argc); - } - mrb->c->stack[argc+1] = blk; - - if (MRB_PROC_CFUNC_P(p)) { - int ai = mrb_gc_arena_save(mrb); - - ci->acc = CI_ACC_DIRECT; - val = p->body.func(mrb, self); - mrb->c->stack = mrb->c->ci->stackent; - cipop(mrb); - mrb_gc_arena_restore(mrb, ai); - } - else { - ci->acc = CI_ACC_SKIP; - val = mrb_run(mrb, p, self); - } - } - mrb_gc_protect(mrb, val); - return val; -} - -MRB_API mrb_value -mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv) -{ - return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value()); -} - -/* 15.3.1.3.4 */ -/* 15.3.1.3.44 */ -/* - * call-seq: - * obj.send(symbol [, args...]) -> obj - * obj.__send__(symbol [, args...]) -> obj - * - * Invokes the method identified by _symbol_, passing it any - * arguments specified. You can use __send__ if the name - * +send+ clashes with an existing method in _obj_. - * - * class Klass - * def hello(*args) - * "Hello " + args.join(' ') - * end - * end - * k = Klass.new - * k.send :hello, "gentle", "readers" #=> "Hello gentle readers" - */ -MRB_API mrb_value -mrb_f_send(mrb_state *mrb, mrb_value self) -{ - mrb_sym name; - mrb_value block, *argv, *regs; - mrb_int argc, i, len; - struct RProc *p; - struct RClass *c; - mrb_callinfo *ci; - - mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block); - - c = mrb_class(mrb, self); - p = mrb_method_search_vm(mrb, &c, name); - - if (!p) { /* call method_mising */ - return mrb_funcall_with_block(mrb, self, name, argc, argv, block); - } - - ci = mrb->c->ci; - ci->mid = name; - ci->target_class = c; - ci->proc = p; - regs = mrb->c->stack+1; - /* remove first symbol from arguments */ - if (ci->argc >= 0) { - for (i=0,len=ci->argc; iargc--; - } - else { /* variable length arguments */ - mrb_ary_shift(mrb, regs[0]); - } - - if (MRB_PROC_CFUNC_P(p)) { - return p->body.func(mrb, self); - } - - if (ci->argc < 0) { - stack_extend(mrb, (p->body.irep->nregs < 3) ? 3 : p->body.irep->nregs, 3); - } - else { - stack_extend(mrb, p->body.irep->nregs, ci->argc+2); - } - - ci->nregs = p->body.irep->nregs; - ci = cipush(mrb); - ci->nregs = 0; - ci->target_class = 0; - ci->pc = p->body.irep->iseq; - ci->stackent = mrb->c->stack; - ci->acc = 0; - - return self; -} - -static mrb_value -eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c) -{ - struct RProc *p; - mrb_callinfo *ci; - - if (mrb_nil_p(blk)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); - } - ci = mrb->c->ci; - if (ci->acc == CI_ACC_DIRECT) { - return mrb_yield_with_class(mrb, blk, 0, 0, self, c); - } - ci->target_class = c; - p = mrb_proc_ptr(blk); - ci->proc = p; - if (MRB_PROC_CFUNC_P(p)) { - return p->body.func(mrb, self); - } - ci->nregs = p->body.irep->nregs; - ci = cipush(mrb); - ci->nregs = 0; - ci->target_class = 0; - ci->pc = p->body.irep->iseq; - ci->stackent = mrb->c->stack; - ci->acc = 0; - - return self; -} - -/* 15.2.2.4.35 */ -/* - * call-seq: - * mod.class_eval {| | block } -> obj - * mod.module_eval {| | block } -> obj - * - * Evaluates block in the context of _mod_. This can - * be used to add methods to a class. module_eval returns - * the result of evaluating its argument. - */ -mrb_value -mrb_mod_module_eval(mrb_state *mrb, mrb_value mod) -{ - mrb_value a, b; - - if (mrb_get_args(mrb, "|S&", &a, &b) == 1) { - mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented"); - } - return eval_under(mrb, mod, b, mrb_class_ptr(mod)); -} - -/* 15.3.1.3.18 */ -/* - * call-seq: - * obj.instance_eval {| | block } -> obj - * - * Evaluates the given block,within the context of the receiver (_obj_). - * In order to set the context, the variable +self+ is set to _obj_ while - * the code is executing, giving the code access to _obj_'s - * instance variables. In the version of instance_eval - * that takes a +String+, the optional second and third - * parameters supply a filename and starting line number that are used - * when reporting compilation errors. - * - * class KlassWithSecret - * def initialize - * @secret = 99 - * end - * end - * k = KlassWithSecret.new - * k.instance_eval { @secret } #=> 99 - */ -mrb_value -mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) -{ - mrb_value a, b; - mrb_value cv; - struct RClass *c; - - if (mrb_get_args(mrb, "|S&", &a, &b) == 1) { - mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented"); - } - switch (mrb_type(self)) { - case MRB_TT_SYMBOL: - case MRB_TT_FIXNUM: - case MRB_TT_FLOAT: - c = 0; - break; - default: - cv = mrb_singleton_class(mrb, self); - c = mrb_class_ptr(cv); - break; - } - return eval_under(mrb, self, b, c); -} - -MRB_API mrb_value -mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c) -{ - struct RProc *p; - mrb_sym mid = mrb->c->ci->mid; - mrb_callinfo *ci; - int n = mrb->c->ci->nregs; - mrb_value val; - - if (mrb_nil_p(b)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); - } - p = mrb_proc_ptr(b); - ci = cipush(mrb); - ci->mid = mid; - ci->proc = p; - ci->stackent = mrb->c->stack; - ci->argc = argc; - ci->target_class = c; - ci->acc = CI_ACC_SKIP; - mrb->c->stack = mrb->c->stack + n; - if (MRB_PROC_CFUNC_P(p)) { - ci->nregs = argc + 2; - stack_extend(mrb, ci->nregs, 0); - } - else { - ci->nregs = p->body.irep->nregs; - stack_extend(mrb, ci->nregs, argc+2); - } - - mrb->c->stack[0] = self; - if (argc > 0) { - stack_copy(mrb->c->stack+1, argv, argc); - } - mrb->c->stack[argc+1] = mrb_nil_value(); - - if (MRB_PROC_CFUNC_P(p)) { - val = p->body.func(mrb, self); - mrb->c->stack = mrb->c->ci->stackent; - cipop(mrb); - } - else { - val = mrb_run(mrb, p, self); - } - return val; -} - -MRB_API mrb_value -mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv) -{ - struct RProc *p = mrb_proc_ptr(b); - - return mrb_yield_with_class(mrb, b, argc, argv, p->env->stack[0], p->target_class); -} - -MRB_API mrb_value -mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg) -{ - struct RProc *p = mrb_proc_ptr(b); - - return mrb_yield_with_class(mrb, b, 1, &arg, p->env->stack[0], p->target_class); -} - -typedef enum { - LOCALJUMP_ERROR_RETURN = 0, - LOCALJUMP_ERROR_BREAK = 1, - LOCALJUMP_ERROR_YIELD = 2 -} localjump_error_kind; - -static void -localjump_error(mrb_state *mrb, localjump_error_kind kind) -{ - char kind_str[3][7] = { "return", "break", "yield" }; - char kind_str_len[] = { 6, 5, 5 }; - static const char lead[] = "unexpected "; - mrb_value msg; - mrb_value exc; - - msg = mrb_str_buf_new(mrb, sizeof(lead) + 7); - mrb_str_cat(mrb, msg, lead, sizeof(lead) - 1); - mrb_str_cat(mrb, msg, kind_str[kind], kind_str_len[kind]); - exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); - mrb->exc = mrb_obj_ptr(exc); -} - -static void -argnum_error(mrb_state *mrb, mrb_int num) -{ - mrb_value exc; - mrb_value str; - - if (mrb->c->ci->mid) { - str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)", - mrb_sym2str(mrb, mrb->c->ci->mid), - mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num)); - } - else { - str = mrb_format(mrb, "wrong number of arguments (%S for %S)", - mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num)); - } - exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str); - mrb->exc = mrb_obj_ptr(exc); -} - -#define ERR_PC_SET(mrb, pc) mrb->c->ci->err = pc; -#define ERR_PC_CLR(mrb) mrb->c->ci->err = 0; -#ifdef MRB_ENABLE_DEBUG_HOOK -#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs)); -#else -#define CODE_FETCH_HOOK(mrb, irep, pc, regs) -#endif - -#if defined __GNUC__ || defined __clang__ || defined __INTEL_COMPILER -#define DIRECT_THREADED -#endif - -#ifndef DIRECT_THREADED - -#define INIT_DISPATCH for (;;) { i = *pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (GET_OPCODE(i)) { -#define CASE(op) case op: -#define NEXT pc++; break -#define JUMP break -#define END_DISPATCH }} - -#else - -#define INIT_DISPATCH JUMP; return mrb_nil_value(); -#define CASE(op) L_ ## op: -#define NEXT i=*++pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)] -#define JUMP i=*pc; CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)] - -#define END_DISPATCH - -#endif - -#define CALL_MAXARGS 127 - -void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); - -MRB_API mrb_value -mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) -{ - /* mrb_assert(mrb_proc_cfunc_p(proc)) */ - mrb_irep *irep = proc->body.irep; - mrb_code *pc = irep->iseq; - mrb_value *pool = irep->pool; - mrb_sym *syms = irep->syms; - mrb_value *regs = NULL; - mrb_code i; - int ai = mrb_gc_arena_save(mrb); - struct mrb_jmpbuf *prev_jmp = mrb->jmp; - struct mrb_jmpbuf c_jmp; - -#ifdef DIRECT_THREADED - static void *optable[] = { - &&L_OP_NOP, &&L_OP_MOVE, - &&L_OP_LOADL, &&L_OP_LOADI, &&L_OP_LOADSYM, &&L_OP_LOADNIL, - &&L_OP_LOADSELF, &&L_OP_LOADT, &&L_OP_LOADF, - &&L_OP_GETGLOBAL, &&L_OP_SETGLOBAL, &&L_OP_GETSPECIAL, &&L_OP_SETSPECIAL, - &&L_OP_GETIV, &&L_OP_SETIV, &&L_OP_GETCV, &&L_OP_SETCV, - &&L_OP_GETCONST, &&L_OP_SETCONST, &&L_OP_GETMCNST, &&L_OP_SETMCNST, - &&L_OP_GETUPVAR, &&L_OP_SETUPVAR, - &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_JMPNOT, - &&L_OP_ONERR, &&L_OP_RESCUE, &&L_OP_POPERR, &&L_OP_RAISE, &&L_OP_EPUSH, &&L_OP_EPOP, - &&L_OP_SEND, &&L_OP_SENDB, &&L_OP_FSEND, - &&L_OP_CALL, &&L_OP_SUPER, &&L_OP_ARGARY, &&L_OP_ENTER, - &&L_OP_KARG, &&L_OP_KDICT, &&L_OP_RETURN, &&L_OP_TAILCALL, &&L_OP_BLKPUSH, - &&L_OP_ADD, &&L_OP_ADDI, &&L_OP_SUB, &&L_OP_SUBI, &&L_OP_MUL, &&L_OP_DIV, - &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_GT, &&L_OP_GE, - &&L_OP_ARRAY, &&L_OP_ARYCAT, &&L_OP_ARYPUSH, &&L_OP_AREF, &&L_OP_ASET, &&L_OP_APOST, - &&L_OP_STRING, &&L_OP_STRCAT, &&L_OP_HASH, - &&L_OP_LAMBDA, &&L_OP_RANGE, &&L_OP_OCLASS, - &&L_OP_CLASS, &&L_OP_MODULE, &&L_OP_EXEC, - &&L_OP_METHOD, &&L_OP_SCLASS, &&L_OP_TCLASS, - &&L_OP_DEBUG, &&L_OP_STOP, &&L_OP_ERR, - }; -#endif - - mrb_bool exc_catched = FALSE; -RETRY_TRY_BLOCK: - - MRB_TRY(&c_jmp) { - - if (exc_catched) { - exc_catched = FALSE; - goto L_RAISE; - } - mrb->jmp = &c_jmp; - if (!mrb->c->stack) { - stack_init(mrb); - } - stack_extend(mrb, irep->nregs, stack_keep); - mrb->c->ci->proc = proc; - mrb->c->ci->nregs = irep->nregs; - regs = mrb->c->stack; - regs[0] = self; - - INIT_DISPATCH { - CASE(OP_NOP) { - /* do nothing */ - NEXT; - } - - CASE(OP_MOVE) { - /* A B R(A) := R(B) */ - regs[GETARG_A(i)] = regs[GETARG_B(i)]; - NEXT; - } - - CASE(OP_LOADL) { - /* A Bx R(A) := Pool(Bx) */ - regs[GETARG_A(i)] = pool[GETARG_Bx(i)]; - NEXT; - } - - CASE(OP_LOADI) { - /* A sBx R(A) := sBx */ - SET_INT_VALUE(regs[GETARG_A(i)], GETARG_sBx(i)); - NEXT; - } - - CASE(OP_LOADSYM) { - /* A Bx R(A) := Syms(Bx) */ - SET_SYM_VALUE(regs[GETARG_A(i)], syms[GETARG_Bx(i)]); - NEXT; - } - - CASE(OP_LOADSELF) { - /* A R(A) := self */ - regs[GETARG_A(i)] = regs[0]; - NEXT; - } - - CASE(OP_LOADT) { - /* A R(A) := true */ - SET_TRUE_VALUE(regs[GETARG_A(i)]); - NEXT; - } - - CASE(OP_LOADF) { - /* A R(A) := false */ - SET_FALSE_VALUE(regs[GETARG_A(i)]); - NEXT; - } - - CASE(OP_GETGLOBAL) { - /* A Bx R(A) := getglobal(Syms(Bx)) */ - regs[GETARG_A(i)] = mrb_gv_get(mrb, syms[GETARG_Bx(i)]); - NEXT; - } - - CASE(OP_SETGLOBAL) { - /* setglobal(Syms(Bx), R(A)) */ - mrb_gv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); - NEXT; - } - - CASE(OP_GETSPECIAL) { - /* A Bx R(A) := Special[Bx] */ - regs[GETARG_A(i)] = mrb_vm_special_get(mrb, GETARG_Bx(i)); - NEXT; - } - - CASE(OP_SETSPECIAL) { - /* A Bx Special[Bx] := R(A) */ - mrb_vm_special_set(mrb, GETARG_Bx(i), regs[GETARG_A(i)]); - NEXT; - } - - CASE(OP_GETIV) { - /* A Bx R(A) := ivget(Bx) */ - regs[GETARG_A(i)] = mrb_vm_iv_get(mrb, syms[GETARG_Bx(i)]); - NEXT; - } - - CASE(OP_SETIV) { - /* ivset(Syms(Bx),R(A)) */ - mrb_vm_iv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); - NEXT; - } - - CASE(OP_GETCV) { - /* A Bx R(A) := cvget(Syms(Bx)) */ - ERR_PC_SET(mrb, pc); - regs[GETARG_A(i)] = mrb_vm_cv_get(mrb, syms[GETARG_Bx(i)]); - ERR_PC_CLR(mrb); - NEXT; - } - - CASE(OP_SETCV) { - /* cvset(Syms(Bx),R(A)) */ - mrb_vm_cv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); - NEXT; - } - - CASE(OP_GETCONST) { - /* A Bx R(A) := constget(Syms(Bx)) */ - mrb_value val; - - ERR_PC_SET(mrb, pc); - val = mrb_vm_const_get(mrb, syms[GETARG_Bx(i)]); - ERR_PC_CLR(mrb); - regs = mrb->c->stack; - regs[GETARG_A(i)] = val; - NEXT; - } - - CASE(OP_SETCONST) { - /* A Bx constset(Syms(Bx),R(A)) */ - mrb_vm_const_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); - NEXT; - } - - CASE(OP_GETMCNST) { - /* A Bx R(A) := R(A)::Syms(Bx) */ - mrb_value val; - int a = GETARG_A(i); - - ERR_PC_SET(mrb, pc); - val = mrb_const_get(mrb, regs[a], syms[GETARG_Bx(i)]); - ERR_PC_CLR(mrb); - regs = mrb->c->stack; - regs[a] = val; - NEXT; - } - - CASE(OP_SETMCNST) { - /* A Bx R(A+1)::Syms(Bx) := R(A) */ - int a = GETARG_A(i); - - mrb_const_set(mrb, regs[a+1], syms[GETARG_Bx(i)], regs[a]); - NEXT; - } - - CASE(OP_GETUPVAR) { - /* A B C R(A) := uvget(B,C) */ - mrb_value *regs_a = regs + GETARG_A(i); - int up = GETARG_C(i); - - struct REnv *e = uvenv(mrb, up); - - if (!e) { - *regs_a = mrb_nil_value(); - } - else { - int idx = GETARG_B(i); - *regs_a = e->stack[idx]; - } - NEXT; - } - - CASE(OP_SETUPVAR) { - /* A B C uvset(B,C,R(A)) */ - int up = GETARG_C(i); - - struct REnv *e = uvenv(mrb, up); - - if (e) { - mrb_value *regs_a = regs + GETARG_A(i); - int idx = GETARG_B(i); - e->stack[idx] = *regs_a; - mrb_write_barrier(mrb, (struct RBasic*)e); - } - NEXT; - } - - CASE(OP_JMP) { - /* sBx pc+=sBx */ - pc += GETARG_sBx(i); - JUMP; - } - - CASE(OP_JMPIF) { - /* A sBx if R(A) pc+=sBx */ - if (mrb_test(regs[GETARG_A(i)])) { - pc += GETARG_sBx(i); - JUMP; - } - NEXT; - } - - CASE(OP_JMPNOT) { - /* A sBx if !R(A) pc+=sBx */ - if (!mrb_test(regs[GETARG_A(i)])) { - pc += GETARG_sBx(i); - JUMP; - } - NEXT; - } - - CASE(OP_ONERR) { - /* sBx pc+=sBx on exception */ - if (mrb->c->rsize <= mrb->c->ci->ridx) { - if (mrb->c->rsize == 0) mrb->c->rsize = 16; - else mrb->c->rsize *= 2; - mrb->c->rescue = (mrb_code **)mrb_realloc(mrb, mrb->c->rescue, sizeof(mrb_code*) * mrb->c->rsize); - } - mrb->c->rescue[mrb->c->ci->ridx++] = pc + GETARG_sBx(i); - NEXT; - } - - CASE(OP_RESCUE) { - /* A R(A) := exc; clear(exc) */ - SET_OBJ_VALUE(regs[GETARG_A(i)], mrb->exc); - mrb->exc = 0; - NEXT; - } - - CASE(OP_POPERR) { - /* A A.times{rescue_pop()} */ - int a = GETARG_A(i); - - while (a--) { - mrb->c->ci->ridx--; - } - NEXT; - } - - CASE(OP_RAISE) { - /* A raise(R(A)) */ - mrb->exc = mrb_obj_ptr(regs[GETARG_A(i)]); - goto L_RAISE; - } - - CASE(OP_EPUSH) { - /* Bx ensure_push(SEQ[Bx]) */ - struct RProc *p; - - p = mrb_closure_new(mrb, irep->reps[GETARG_Bx(i)]); - /* push ensure_stack */ - if (mrb->c->esize <= mrb->c->ci->eidx) { - if (mrb->c->esize == 0) mrb->c->esize = 16; - else mrb->c->esize *= 2; - mrb->c->ensure = (struct RProc **)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*) * mrb->c->esize); - } - mrb->c->ensure[mrb->c->ci->eidx++] = p; - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_EPOP) { - /* A A.times{ensure_pop().call} */ - int a = GETARG_A(i); - mrb_callinfo *ci = mrb->c->ci; - int n, eidx = ci->eidx; - - for (n=0; nc->cibase || eidx > ci[-1].eidx); n++) { - ecall(mrb, --eidx); - ARENA_RESTORE(mrb, ai); - } - NEXT; - } - - CASE(OP_LOADNIL) { - /* A R(A) := nil */ - int a = GETARG_A(i); - - SET_NIL_VALUE(regs[a]); - NEXT; - } - - CASE(OP_SENDB) { - /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/ - /* fall through */ - }; - - L_SEND: - CASE(OP_SEND) { - /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */ - int a = GETARG_A(i); - int n = GETARG_C(i); - struct RProc *m; - struct RClass *c; - mrb_callinfo *ci; - mrb_value recv, result; - mrb_sym mid = syms[GETARG_B(i)]; - - recv = regs[a]; - if (GET_OPCODE(i) != OP_SENDB) { - if (n == CALL_MAXARGS) { - SET_NIL_VALUE(regs[a+2]); - } - else { - SET_NIL_VALUE(regs[a+n+1]); - } - } - c = mrb_class(mrb, recv); - m = mrb_method_search_vm(mrb, &c, mid); - if (!m) { - mrb_value sym = mrb_symbol_value(mid); - mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); - - m = mrb_method_search_vm(mrb, &c, missing); - if (!m) { - mrb_value args; - - if (n == CALL_MAXARGS) { - args = regs[a+1]; - } - else { - args = mrb_ary_new_from_values(mrb, n, regs+a+1); - } - mrb_method_missing(mrb, mid, recv, args); - } - mid = missing; - if (n == CALL_MAXARGS) { - mrb_ary_unshift(mrb, regs[a+1], sym); - } - else { - value_move(regs+a+2, regs+a+1, ++n); - regs[a+1] = sym; - } - } - - /* push callinfo */ - ci = cipush(mrb); - ci->mid = mid; - ci->proc = m; - ci->stackent = mrb->c->stack; - ci->target_class = c; - - ci->pc = pc + 1; - ci->acc = a; - - /* prepare stack */ - mrb->c->stack += a; - - if (MRB_PROC_CFUNC_P(m)) { - if (n == CALL_MAXARGS) { - ci->argc = -1; - ci->nregs = 3; - } - else { - ci->argc = n; - ci->nregs = n + 2; - } - result = m->body.func(mrb, recv); - mrb->c->stack[0] = result; - mrb_gc_arena_restore(mrb, ai); - if (mrb->exc) goto L_RAISE; - /* pop stackpos */ - ci = mrb->c->ci; - if (!ci->target_class) { /* return from context modifying method (resume/yield) */ - if (!MRB_PROC_CFUNC_P(ci[-1].proc)) { - proc = ci[-1].proc; - irep = proc->body.irep; - pool = irep->pool; - syms = irep->syms; - } - } - regs = mrb->c->stack = ci->stackent; - pc = ci->pc; - cipop(mrb); - JUMP; - } - else { - /* setup environment for calling method */ - proc = mrb->c->ci->proc = m; - irep = m->body.irep; - pool = irep->pool; - syms = irep->syms; - ci->nregs = irep->nregs; - if (n == CALL_MAXARGS) { - ci->argc = -1; - stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); - } - else { - ci->argc = n; - stack_extend(mrb, irep->nregs, n+2); - } - regs = mrb->c->stack; - pc = irep->iseq; - JUMP; - } - } - - CASE(OP_FSEND) { - /* A B C R(A) := fcall(R(A),Syms(B),R(A+1),... ,R(A+C-1)) */ - NEXT; - } - - CASE(OP_CALL) { - /* A R(A) := self.call(frame.argc, frame.argv) */ - mrb_callinfo *ci; - mrb_value recv = mrb->c->stack[0]; - struct RProc *m = mrb_proc_ptr(recv); - - /* replace callinfo */ - ci = mrb->c->ci; - ci->target_class = m->target_class; - ci->proc = m; - if (m->env) { - if (m->env->mid) { - ci->mid = m->env->mid; - } - if (!m->env->stack) { - m->env->stack = mrb->c->stack; - } - } - - /* prepare stack */ - if (MRB_PROC_CFUNC_P(m)) { - recv = m->body.func(mrb, recv); - mrb_gc_arena_restore(mrb, ai); - if (mrb->exc) goto L_RAISE; - /* pop stackpos */ - ci = mrb->c->ci; - regs = mrb->c->stack = ci->stackent; - regs[ci->acc] = recv; - pc = ci->pc; - cipop(mrb); - irep = mrb->c->ci->proc->body.irep; - pool = irep->pool; - syms = irep->syms; - JUMP; - } - else { - /* setup environment for calling method */ - proc = m; - irep = m->body.irep; - if (!irep) { - mrb->c->stack[0] = mrb_nil_value(); - goto L_RETURN; - } - pool = irep->pool; - syms = irep->syms; - ci->nregs = irep->nregs; - if (ci->argc < 0) { - stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); - } - else { - stack_extend(mrb, irep->nregs, ci->argc+2); - } - regs = mrb->c->stack; - regs[0] = m->env->stack[0]; - pc = irep->iseq; - JUMP; - } - } - - CASE(OP_SUPER) { - /* A C R(A) := super(R(A+1),... ,R(A+C+1)) */ - mrb_value recv; - mrb_callinfo *ci = mrb->c->ci; - struct RProc *m; - struct RClass *c; - mrb_sym mid = ci->mid; - int a = GETARG_A(i); - int n = GETARG_C(i); - - if (mid == 0) { - mrb_value exc; - - exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); - mrb->exc = mrb_obj_ptr(exc); - goto L_RAISE; - } - recv = regs[0]; - c = mrb->c->ci->target_class->super; - m = mrb_method_search_vm(mrb, &c, mid); - if (!m) { - mid = mrb_intern_lit(mrb, "method_missing"); - m = mrb_method_search_vm(mrb, &c, mid); - if (n == CALL_MAXARGS) { - mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); - } - else { - value_move(regs+a+2, regs+a+1, ++n); - SET_SYM_VALUE(regs[a+1], ci->mid); - } - } - - /* push callinfo */ - ci = cipush(mrb); - ci->mid = mid; - ci->proc = m; - ci->stackent = mrb->c->stack; - if (n == CALL_MAXARGS) { - ci->argc = -1; - } - else { - ci->argc = n; - } - ci->target_class = c; - ci->pc = pc + 1; - - /* prepare stack */ - mrb->c->stack += a; - mrb->c->stack[0] = recv; - - if (MRB_PROC_CFUNC_P(m)) { - if (n == CALL_MAXARGS) { - ci->nregs = 3; - } - else { - ci->nregs = n + 2; - } - mrb->c->stack[0] = m->body.func(mrb, recv); - mrb_gc_arena_restore(mrb, ai); - if (mrb->exc) goto L_RAISE; - /* pop stackpos */ - regs = mrb->c->stack = mrb->c->ci->stackent; - cipop(mrb); - NEXT; - } - else { - /* fill callinfo */ - ci->acc = a; - - /* setup environment for calling method */ - ci->proc = m; - irep = m->body.irep; - pool = irep->pool; - syms = irep->syms; - ci->nregs = irep->nregs; - if (n == CALL_MAXARGS) { - stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); - } - else { - stack_extend(mrb, irep->nregs, ci->argc+2); - } - regs = mrb->c->stack; - pc = irep->iseq; - JUMP; - } - } - - CASE(OP_ARGARY) { - /* A Bx R(A) := argument array (16=6:1:5:4) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - int m1 = (bx>>10)&0x3f; - int r = (bx>>9)&0x1; - int m2 = (bx>>4)&0x1f; - int lv = (bx>>0)&0xf; - mrb_value *stack; - - if (lv == 0) stack = regs + 1; - else { - struct REnv *e = uvenv(mrb, lv-1); - if (!e) { - mrb_value exc; - - exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); - mrb->exc = mrb_obj_ptr(exc); - goto L_RAISE; - } - stack = e->stack + 1; - } - if (r == 0) { - regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack); - } - else { - mrb_value *pp = NULL; - struct RArray *rest; - int len = 0; - - if (mrb_array_p(stack[m1])) { - struct RArray *ary = mrb_ary_ptr(stack[m1]); - - pp = ary->ptr; - len = ary->len; - } - regs[a] = mrb_ary_new_capa(mrb, m1+len+m2); - rest = mrb_ary_ptr(regs[a]); - if (m1 > 0) { - stack_copy(rest->ptr, stack, m1); - } - if (len > 0) { - stack_copy(rest->ptr+m1, pp, len); - } - if (m2 > 0) { - stack_copy(rest->ptr+m1+len, stack+m1+1, m2); - } - rest->len = m1+len+m2; - } - regs[a+1] = stack[m1+r+m2]; - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_ENTER) { - /* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */ - /* number of optional arguments times OP_JMP should follow */ - mrb_aspec ax = GETARG_Ax(i); - int m1 = MRB_ASPEC_REQ(ax); - int o = MRB_ASPEC_OPT(ax); - int r = MRB_ASPEC_REST(ax); - int m2 = MRB_ASPEC_POST(ax); - /* unused - int k = MRB_ASPEC_KEY(ax); - int kd = MRB_ASPEC_KDICT(ax); - int b = MRB_ASPEC_BLOCK(ax); - */ - int argc = mrb->c->ci->argc; - mrb_value *argv = regs+1; - mrb_value *argv0 = argv; - int len = m1 + o + r + m2; - mrb_value *blk = &argv[argc < 0 ? 1 : argc]; - - if (!mrb_nil_p(*blk) && mrb_type(*blk) != MRB_TT_PROC) { - *blk = mrb_convert_type(mrb, *blk, MRB_TT_PROC, "Proc", "to_proc"); - } - if (argc < 0) { - struct RArray *ary = mrb_ary_ptr(regs[1]); - argv = ary->ptr; - argc = ary->len; - mrb_gc_protect(mrb, regs[1]); - } - if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) { - if (argc >= 0) { - if (argc < m1 + m2 || (r == 0 && argc > len)) { - argnum_error(mrb, m1+m2); - goto L_RAISE; - } - } - } - else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) { - mrb_gc_protect(mrb, argv[0]); - argc = mrb_ary_ptr(argv[0])->len; - argv = mrb_ary_ptr(argv[0])->ptr; - } - mrb->c->ci->argc = len; - if (argc < len) { - int mlen = m2; - if (argc < m1+m2) { - if (m1 < argc) - mlen = argc - m1; - else - mlen = 0; - } - regs[len+1] = *blk; /* move block */ - SET_NIL_VALUE(regs[argc+1]); - if (argv0 != argv) { - value_move(®s[1], argv, argc-mlen); /* m1 + o */ - } - if (mlen) { - value_move(®s[len-m2+1], &argv[argc-mlen], mlen); - } - if (r) { - regs[m1+o+1] = mrb_ary_new_capa(mrb, 0); - } - if (o == 0 || argc < m1+m2) pc++; - else - pc += argc - m1 - m2 + 1; - } - else { - int rnum = 0; - if (argv0 != argv) { - regs[len+1] = *blk; /* move block */ - value_move(®s[1], argv, m1+o); - } - if (r) { - rnum = argc-m1-o-m2; - regs[m1+o+1] = mrb_ary_new_from_values(mrb, rnum, argv+m1+o); - } - if (m2) { - if (argc-m2 > m1) { - value_move(®s[m1+o+r+1], &argv[m1+o+rnum], m2); - } - } - if (argv0 == argv) { - regs[len+1] = *blk; /* move block */ - } - pc += o + 1; - } - JUMP; - } - - CASE(OP_KARG) { - /* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */ - /* if C == 2; raise unless kdict.empty? */ - /* OP_JMP should follow to skip init code */ - NEXT; - } - - CASE(OP_KDICT) { - /* A C R(A) := kdict */ - NEXT; - } - - L_RETURN: - i = MKOP_AB(OP_RETURN, GETARG_A(i), OP_R_NORMAL); - /* fall through */ - CASE(OP_RETURN) { - /* A B return R(A) (B=normal,in-block return/break) */ - if (mrb->exc) { - mrb_callinfo *ci; - int eidx; - - L_RAISE: - ci = mrb->c->ci; - mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, pc)); - mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->c->cibase)); - eidx = ci->eidx; - if (ci == mrb->c->cibase) { - if (ci->ridx == 0) goto L_STOP; - goto L_RESCUE; - } - while (ci[0].ridx == ci[-1].ridx) { - cipop(mrb); - ci = mrb->c->ci; - mrb->c->stack = ci[1].stackent; - if (ci[1].acc == CI_ACC_SKIP && prev_jmp) { - mrb->jmp = prev_jmp; - MRB_THROW(prev_jmp); - } - if (ci == mrb->c->cibase) { - while (eidx > 0) { - ecall(mrb, --eidx); - } - if (ci->ridx == 0) { - if (mrb->c == mrb->root_c) { - regs = mrb->c->stack = mrb->c->stbase; - goto L_STOP; - } - else { - struct mrb_context *c = mrb->c; - - mrb->c = c->prev; - c->prev = NULL; - goto L_RAISE; - } - } - break; - } - /* call ensure only when we skip this callinfo */ - if (ci[0].ridx == ci[-1].ridx) { - while (eidx > ci[-1].eidx) { - ecall(mrb, --eidx); - } - } - } - L_RESCUE: - if (ci->ridx == 0) goto L_STOP; - proc = ci->proc; - irep = proc->body.irep; - pool = irep->pool; - syms = irep->syms; - regs = mrb->c->stack = ci[1].stackent; - pc = mrb->c->rescue[--ci->ridx]; - } - else { - mrb_callinfo *ci = mrb->c->ci; - int acc, eidx = mrb->c->ci->eidx; - mrb_value v = regs[GETARG_A(i)]; - - switch (GETARG_B(i)) { - case OP_R_RETURN: - /* Fall through to OP_R_NORMAL otherwise */ - if (proc->env && !MRB_PROC_STRICT_P(proc)) { - struct REnv *e = top_env(mrb, proc); - - if (!MRB_ENV_STACK_SHARED_P(e)) { - localjump_error(mrb, LOCALJUMP_ERROR_RETURN); - goto L_RAISE; - } - ci = mrb->c->cibase + e->cioff; - if (ci == mrb->c->cibase) { - localjump_error(mrb, LOCALJUMP_ERROR_RETURN); - goto L_RAISE; - } - mrb->c->stack = mrb->c->ci->stackent; - mrb->c->ci = ci; - break; - } - case OP_R_NORMAL: - if (ci == mrb->c->cibase) { - if (!mrb->c->prev) { /* toplevel return */ - localjump_error(mrb, LOCALJUMP_ERROR_RETURN); - goto L_RAISE; - } - if (mrb->c->prev->ci == mrb->c->prev->cibase) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume"); - mrb->exc = mrb_obj_ptr(exc); - goto L_RAISE; - } - /* automatic yield at the end */ - mrb->c->status = MRB_FIBER_TERMINATED; - mrb->c = mrb->c->prev; - mrb->c->status = MRB_FIBER_RUNNING; - } - ci = mrb->c->ci; - break; - case OP_R_BREAK: - if (!proc->env || !MRB_ENV_STACK_SHARED_P(proc->env)) { - localjump_error(mrb, LOCALJUMP_ERROR_BREAK); - goto L_RAISE; - } - /* break from fiber block */ - if (mrb->c->ci == mrb->c->cibase && mrb->c->ci->pc) { - struct mrb_context *c = mrb->c; - - mrb->c = c->prev; - c->prev = NULL; - } - ci = mrb->c->ci; - mrb->c->stack = ci->stackent; - mrb->c->ci = mrb->c->cibase + proc->env->cioff + 1; - while (ci > mrb->c->ci) { - if (ci[-1].acc == CI_ACC_SKIP) { - mrb->c->ci = ci; - break; - } - ci--; - } - break; - default: - /* cannot happen */ - break; - } - while (eidx > mrb->c->ci[-1].eidx) { - ecall(mrb, --eidx); - } - cipop(mrb); - acc = ci->acc; - pc = ci->pc; - regs = mrb->c->stack = ci->stackent; - if (acc == CI_ACC_SKIP) { - mrb->jmp = prev_jmp; - return v; - } - DEBUG(printf("from :%s\n", mrb_sym2name(mrb, ci->mid))); - proc = mrb->c->ci->proc; - irep = proc->body.irep; - pool = irep->pool; - syms = irep->syms; - - regs[acc] = v; - } - JUMP; - } - - CASE(OP_TAILCALL) { - /* A B C return call(R(A),Syms(B),R(A+1),... ,R(A+C+1)) */ - int a = GETARG_A(i); - int n = GETARG_C(i); - struct RProc *m; - struct RClass *c; - mrb_callinfo *ci; - mrb_value recv; - mrb_sym mid = syms[GETARG_B(i)]; - - recv = regs[a]; - c = mrb_class(mrb, recv); - m = mrb_method_search_vm(mrb, &c, mid); - if (!m) { - mrb_value sym = mrb_symbol_value(mid); - - mid = mrb_intern_lit(mrb, "method_missing"); - m = mrb_method_search_vm(mrb, &c, mid); - if (n == CALL_MAXARGS) { - mrb_ary_unshift(mrb, regs[a+1], sym); - } - else { - value_move(regs+a+2, regs+a+1, ++n); - regs[a+1] = sym; - } - } - - /* replace callinfo */ - ci = mrb->c->ci; - ci->mid = mid; - ci->target_class = c; - if (n == CALL_MAXARGS) { - ci->argc = -1; - } - else { - ci->argc = n; - } - - /* move stack */ - value_move(mrb->c->stack, ®s[a], ci->argc+1); - - if (MRB_PROC_CFUNC_P(m)) { - mrb->c->stack[0] = m->body.func(mrb, recv); - mrb_gc_arena_restore(mrb, ai); - goto L_RETURN; - } - else { - /* setup environment for calling method */ - irep = m->body.irep; - pool = irep->pool; - syms = irep->syms; - if (ci->argc < 0) { - stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); - } - else { - stack_extend(mrb, irep->nregs, ci->argc+2); - } - regs = mrb->c->stack; - pc = irep->iseq; - } - JUMP; - } - - CASE(OP_BLKPUSH) { - /* A Bx R(A) := block (16=6:1:5:4) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - int m1 = (bx>>10)&0x3f; - int r = (bx>>9)&0x1; - int m2 = (bx>>4)&0x1f; - int lv = (bx>>0)&0xf; - mrb_value *stack; - - if (lv == 0) stack = regs + 1; - else { - struct REnv *e = uvenv(mrb, lv-1); - if (!e) { - localjump_error(mrb, LOCALJUMP_ERROR_YIELD); - goto L_RAISE; - } - stack = e->stack + 1; - } - regs[a] = stack[m1+r+m2]; - NEXT; - } - -#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff)) -#define OP_MATH_BODY(op,v1,v2) do {\ - v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\ -} while(0) - - CASE(OP_ADD) { - /* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/ - int a = GETARG_A(i); - - /* need to check if op is overridden */ - switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): - { - mrb_int x, y, z; - mrb_value *regs_a = regs + a; - - x = mrb_fixnum(regs_a[0]); - y = mrb_fixnum(regs_a[1]); - if (mrb_int_add_overflow(x, y, &z)) { - SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y); - break; - } - SET_INT_VALUE(regs[a], z); - } - break; - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): - { - mrb_int x = mrb_fixnum(regs[a]); - mrb_float y = mrb_float(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + y); - } - break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): -#ifdef MRB_WORD_BOXING - { - mrb_float x = mrb_float(regs[a]); - mrb_int y = mrb_fixnum(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], x + y); - } -#else - OP_MATH_BODY(+,mrb_float,mrb_fixnum); -#endif - break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): -#ifdef MRB_WORD_BOXING - { - mrb_float x = mrb_float(regs[a]); - mrb_float y = mrb_float(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], x + y); - } -#else - OP_MATH_BODY(+,mrb_float,mrb_float); -#endif - break; - case TYPES2(MRB_TT_STRING,MRB_TT_STRING): - regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); - break; - default: - goto L_SEND; - } - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_SUB) { - /* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/ - int a = GETARG_A(i); - - /* need to check if op is overridden */ - switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): - { - mrb_int x, y, z; - - x = mrb_fixnum(regs[a]); - y = mrb_fixnum(regs[a+1]); - if (mrb_int_sub_overflow(x, y, &z)) { - SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y); - break; - } - SET_INT_VALUE(regs[a], z); - } - break; - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): - { - mrb_int x = mrb_fixnum(regs[a]); - mrb_float y = mrb_float(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - y); - } - break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): -#ifdef MRB_WORD_BOXING - { - mrb_float x = mrb_float(regs[a]); - mrb_int y = mrb_fixnum(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], x - y); - } -#else - OP_MATH_BODY(-,mrb_float,mrb_fixnum); -#endif - break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): -#ifdef MRB_WORD_BOXING - { - mrb_float x = mrb_float(regs[a]); - mrb_float y = mrb_float(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], x - y); - } -#else - OP_MATH_BODY(-,mrb_float,mrb_float); -#endif - break; - default: - goto L_SEND; - } - NEXT; - } - - CASE(OP_MUL) { - /* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/ - int a = GETARG_A(i); - - /* need to check if op is overridden */ - switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): - { - mrb_value z; - - z = mrb_fixnum_mul(mrb, regs[a], regs[a+1]); - - switch (mrb_type(z)) { - case MRB_TT_FIXNUM: - { - SET_INT_VALUE(regs[a], mrb_fixnum(z)); - } - break; - case MRB_TT_FLOAT: - { - SET_FLOAT_VALUE(mrb, regs[a], mrb_float(z)); - } - break; - default: - /* cannot happen */ - break; - } - } - break; - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): - { - mrb_int x = mrb_fixnum(regs[a]); - mrb_float y = mrb_float(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * y); - } - break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): -#ifdef MRB_WORD_BOXING - { - mrb_float x = mrb_float(regs[a]); - mrb_int y = mrb_fixnum(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], x * y); - } -#else - OP_MATH_BODY(*,mrb_float,mrb_fixnum); -#endif - break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): -#ifdef MRB_WORD_BOXING - { - mrb_float x = mrb_float(regs[a]); - mrb_float y = mrb_float(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], x * y); - } -#else - OP_MATH_BODY(*,mrb_float,mrb_float); -#endif - break; - default: - goto L_SEND; - } - NEXT; - } - - CASE(OP_DIV) { - /* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/ - int a = GETARG_A(i); - - /* need to check if op is overridden */ - switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): - { - mrb_int x = mrb_fixnum(regs[a]); - mrb_int y = mrb_fixnum(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y); - } - break; - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): - { - mrb_int x = mrb_fixnum(regs[a]); - mrb_float y = mrb_float(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / y); - } - break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): -#ifdef MRB_WORD_BOXING - { - mrb_float x = mrb_float(regs[a]); - mrb_int y = mrb_fixnum(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], x / y); - } -#else - OP_MATH_BODY(/,mrb_float,mrb_fixnum); -#endif - break; - case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): -#ifdef MRB_WORD_BOXING - { - mrb_float x = mrb_float(regs[a]); - mrb_float y = mrb_float(regs[a+1]); - SET_FLOAT_VALUE(mrb, regs[a], x / y); - } -#else - OP_MATH_BODY(/,mrb_float,mrb_float); -#endif - break; - default: - goto L_SEND; - } -#ifdef MRB_NAN_BOXING - if (isnan(mrb_float(regs[a]))) { - regs[a] = mrb_float_value(mrb, mrb_float(regs[a])); - } -#endif - NEXT; - } - - CASE(OP_ADDI) { - /* A B C R(A) := R(A)+C (Syms[B]=:+)*/ - int a = GETARG_A(i); - - /* need to check if + is overridden */ - switch (mrb_type(regs[a])) { - case MRB_TT_FIXNUM: - { - mrb_int x = mrb_fixnum(regs[a]); - mrb_int y = GETARG_C(i); - mrb_int z; - - if (mrb_int_add_overflow(x, y, &z)) { - SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y); - break; - } - SET_INT_VALUE(regs[a], z); - } - break; - case MRB_TT_FLOAT: -#ifdef MRB_WORD_BOXING - { - mrb_float x = mrb_float(regs[a]); - SET_FLOAT_VALUE(mrb, regs[a], x + GETARG_C(i)); - } -#else - mrb_float(regs[a]) += GETARG_C(i); -#endif - break; - default: - SET_INT_VALUE(regs[a+1], GETARG_C(i)); - i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); - goto L_SEND; - } - NEXT; - } - - CASE(OP_SUBI) { - /* A B C R(A) := R(A)-C (Syms[B]=:-)*/ - int a = GETARG_A(i); - mrb_value *regs_a = regs + a; - - /* need to check if + is overridden */ - switch (mrb_type(regs_a[0])) { - case MRB_TT_FIXNUM: - { - mrb_int x = mrb_fixnum(regs_a[0]); - mrb_int y = GETARG_C(i); - mrb_int z; - - if (mrb_int_sub_overflow(x, y, &z)) { - SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y); - } - else { - SET_INT_VALUE(regs_a[0], z); - } - } - break; - case MRB_TT_FLOAT: -#ifdef MRB_WORD_BOXING - { - mrb_float x = mrb_float(regs[a]); - SET_FLOAT_VALUE(mrb, regs[a], x - GETARG_C(i)); - } -#else - mrb_float(regs_a[0]) -= GETARG_C(i); -#endif - break; - default: - SET_INT_VALUE(regs_a[1], GETARG_C(i)); - i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); - goto L_SEND; - } - NEXT; - } - -#define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1])) - -#define OP_CMP(op) do {\ - int result;\ - /* need to check if - is overridden */\ - switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\ - result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\ - break;\ - case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\ - result = OP_CMP_BODY(op,mrb_fixnum,mrb_float);\ - break;\ - case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\ - result = OP_CMP_BODY(op,mrb_float,mrb_fixnum);\ - break;\ - case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\ - result = OP_CMP_BODY(op,mrb_float,mrb_float);\ - break;\ - default:\ - goto L_SEND;\ - }\ - if (result) {\ - SET_TRUE_VALUE(regs[a]);\ - }\ - else {\ - SET_FALSE_VALUE(regs[a]);\ - }\ -} while(0) - - CASE(OP_EQ) { - /* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1)*/ - int a = GETARG_A(i); - if (mrb_obj_eq(mrb, regs[a], regs[a+1])) { - SET_TRUE_VALUE(regs[a]); - } - else { - OP_CMP(==); - } - NEXT; - } - - CASE(OP_LT) { - /* A B C R(A) := R(A)R(A+1) (Syms[B]=:>,C=1)*/ - int a = GETARG_A(i); - OP_CMP(>); - NEXT; - } - - CASE(OP_GE) { - /* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)*/ - int a = GETARG_A(i); - OP_CMP(>=); - NEXT; - } - - CASE(OP_ARRAY) { - /* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */ - regs[GETARG_A(i)] = mrb_ary_new_from_values(mrb, GETARG_C(i), ®s[GETARG_B(i)]); - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_ARYCAT) { - /* A B mrb_ary_concat(R(A),R(B)) */ - mrb_ary_concat(mrb, regs[GETARG_A(i)], - mrb_ary_splat(mrb, regs[GETARG_B(i)])); - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_ARYPUSH) { - /* A B R(A).push(R(B)) */ - mrb_ary_push(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]); - NEXT; - } - - CASE(OP_AREF) { - /* A B C R(A) := R(B)[C] */ - int a = GETARG_A(i); - int c = GETARG_C(i); - mrb_value v = regs[GETARG_B(i)]; - - if (!mrb_array_p(v)) { - if (c == 0) { - regs[GETARG_A(i)] = v; - } - else { - SET_NIL_VALUE(regs[a]); - } - } - else { - regs[GETARG_A(i)] = mrb_ary_ref(mrb, v, c); - } - NEXT; - } - - CASE(OP_ASET) { - /* A B C R(B)[C] := R(A) */ - mrb_ary_set(mrb, regs[GETARG_B(i)], GETARG_C(i), regs[GETARG_A(i)]); - NEXT; - } - - CASE(OP_APOST) { - /* A B C *R(A),R(A+1)..R(A+C) := R(A) */ - int a = GETARG_A(i); - mrb_value v = regs[a]; - int pre = GETARG_B(i); - int post = GETARG_C(i); - - struct RArray *ary; - int len, idx; - - if (!mrb_array_p(v)) { - v = mrb_ary_new_from_values(mrb, 1, ®s[a]); - } - ary = mrb_ary_ptr(v); - len = ary->len; - if (len > pre + post) { - regs[a++] = mrb_ary_new_from_values(mrb, len - pre - post, ary->ptr+pre); - while (post--) { - regs[a++] = ary->ptr[len-post-1]; - } - } - else { - regs[a++] = mrb_ary_new_capa(mrb, 0); - for (idx=0; idx+preptr[pre+idx]; - } - while (idx < post) { - SET_NIL_VALUE(regs[a+idx]); - idx++; - } - } - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_STRING) { - /* A Bx R(A) := str_new(Lit(Bx)) */ - regs[GETARG_A(i)] = mrb_str_dup(mrb, pool[GETARG_Bx(i)]); - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_STRCAT) { - /* A B R(A).concat(R(B)) */ - mrb_str_concat(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]); - regs = mrb->c->stack; - NEXT; - } - - CASE(OP_HASH) { - /* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */ - int b = GETARG_B(i); - int c = GETARG_C(i); - int lim = b+c*2; - mrb_value hash = mrb_hash_new_capa(mrb, c); - - while (b < lim) { - mrb_hash_set(mrb, hash, regs[b], regs[b+1]); - b+=2; - } - regs[GETARG_A(i)] = hash; - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_LAMBDA) { - /* A b c R(A) := lambda(SEQ[b],c) (b:c = 14:2) */ - struct RProc *p; - int c = GETARG_c(i); - - if (c & OP_L_CAPTURE) { - p = mrb_closure_new(mrb, irep->reps[GETARG_b(i)]); - } - else { - p = mrb_proc_new(mrb, irep->reps[GETARG_b(i)]); - } - if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT; - regs[GETARG_A(i)] = mrb_obj_value(p); - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_OCLASS) { - /* A R(A) := ::Object */ - regs[GETARG_A(i)] = mrb_obj_value(mrb->object_class); - NEXT; - } - - CASE(OP_CLASS) { - /* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */ - struct RClass *c = 0; - int a = GETARG_A(i); - mrb_value base, super; - mrb_sym id = syms[GETARG_B(i)]; - - base = regs[a]; - super = regs[a+1]; - if (mrb_nil_p(base)) { - base = mrb_obj_value(mrb->c->ci->target_class); - } - c = mrb_vm_define_class(mrb, base, super, id); - regs[a] = mrb_obj_value(c); - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_MODULE) { - /* A B R(A) := newmodule(R(A),Syms(B)) */ - struct RClass *c = 0; - int a = GETARG_A(i); - mrb_value base; - mrb_sym id = syms[GETARG_B(i)]; - - base = regs[a]; - if (mrb_nil_p(base)) { - base = mrb_obj_value(mrb->c->ci->target_class); - } - c = mrb_vm_define_module(mrb, base, id); - regs[a] = mrb_obj_value(c); - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_EXEC) { - /* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */ - int a = GETARG_A(i); - mrb_callinfo *ci; - mrb_value recv = regs[a]; - struct RProc *p; - - /* prepare stack */ - ci = cipush(mrb); - ci->pc = pc + 1; - ci->acc = a; - ci->mid = 0; - ci->stackent = mrb->c->stack; - ci->argc = 0; - ci->target_class = mrb_class_ptr(recv); - - /* prepare stack */ - mrb->c->stack += a; - - p = mrb_proc_new(mrb, irep->reps[GETARG_Bx(i)]); - p->target_class = ci->target_class; - ci->proc = p; - - if (MRB_PROC_CFUNC_P(p)) { - ci->nregs = 0; - mrb->c->stack[0] = p->body.func(mrb, recv); - mrb_gc_arena_restore(mrb, ai); - if (mrb->exc) goto L_RAISE; - /* pop stackpos */ - regs = mrb->c->stack = mrb->c->ci->stackent; - cipop(mrb); - NEXT; - } - else { - irep = p->body.irep; - pool = irep->pool; - syms = irep->syms; - stack_extend(mrb, irep->nregs, 1); - ci->nregs = irep->nregs; - regs = mrb->c->stack; - pc = irep->iseq; - JUMP; - } - } - - CASE(OP_METHOD) { - /* A B R(A).newmethod(Syms(B),R(A+1)) */ - int a = GETARG_A(i); - struct RClass *c = mrb_class_ptr(regs[a]); - struct RProc *p = mrb_proc_ptr(regs[a+1]); - - mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], p); - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_SCLASS) { - /* A B R(A) := R(B).singleton_class */ - regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]); - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_TCLASS) { - /* A R(A) := target_class */ - if (!mrb->c->ci->target_class) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module"); - mrb->exc = mrb_obj_ptr(exc); - goto L_RAISE; - } - regs[GETARG_A(i)] = mrb_obj_value(mrb->c->ci->target_class); - NEXT; - } - - CASE(OP_RANGE) { - /* A B C R(A) := range_new(R(B),R(B+1),C) */ - int b = GETARG_B(i); - regs[GETARG_A(i)] = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); - ARENA_RESTORE(mrb, ai); - NEXT; - } - - CASE(OP_DEBUG) { - /* A B C debug print R(A),R(B),R(C) */ -#ifdef MRB_ENABLE_DEBUG_HOOK - mrb->debug_op_hook(mrb, irep, pc, regs); -#else -#ifndef MRB_DISABLE_STDIO - printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i)); -#else - abort(); -#endif -#endif - NEXT; - } - - CASE(OP_STOP) { - /* stop VM */ - L_STOP: - { - int eidx_stop = mrb->c->ci == mrb->c->cibase ? 0 : mrb->c->ci[-1].eidx; - int eidx = mrb->c->ci->eidx; - while (eidx > eidx_stop) { - ecall(mrb, --eidx); - } - } - ERR_PC_CLR(mrb); - mrb->jmp = prev_jmp; - if (mrb->exc) { - return mrb_obj_value(mrb->exc); - } - return regs[irep->nlocals]; - } - - CASE(OP_ERR) { - /* Bx raise RuntimeError with message Lit(Bx) */ - mrb_value msg = mrb_str_dup(mrb, pool[GETARG_Bx(i)]); - mrb_value exc; - - if (GETARG_A(i) == 0) { - exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, msg); - } - else { - exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); - } - mrb->exc = mrb_obj_ptr(exc); - goto L_RAISE; - } - } - END_DISPATCH; - - } - MRB_CATCH(&c_jmp) { - exc_catched = TRUE; - goto RETRY_TRY_BLOCK; - } - MRB_END_EXC(&c_jmp); -} - -MRB_API mrb_value -mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) -{ - return mrb_context_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ -} - -MRB_API mrb_value -mrb_toplevel_run_keep(mrb_state *mrb, struct RProc *proc, unsigned int stack_keep) -{ - mrb_callinfo *ci; - mrb_value v; - - if (!mrb->c->cibase || mrb->c->ci == mrb->c->cibase) { - return mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep); - } - ci = cipush(mrb); - ci->nregs = 1; /* protect the receiver */ - ci->acc = CI_ACC_SKIP; - ci->target_class = mrb->object_class; - v = mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep); - cipop(mrb); - - return v; -} - -MRB_API mrb_value -mrb_toplevel_run(mrb_state *mrb, struct RProc *proc) -{ - return mrb_toplevel_run_keep(mrb, proc, 0); -} diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/benchmark.rake nghttp2-0.6.7/third-party/mruby/tasks/benchmark.rake --- nghttp2-1.13.0/third-party/mruby/tasks/benchmark.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/benchmark.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -module MRuby - BENCHMARK_REPEAT = 4 -end - -$dat_files = [] - -def bm_files - Dir.glob("#{MRUBY_ROOT}/benchmark/bm_*.rb") -end - -def build_config_name - if ENV['MRUBY_CONFIG'] - File.basename(ENV['MRUBY_CONFIG'], '.rb').gsub('build_config_', '') - else - "build" - end -end - -def plot_file - File.join(MRUBY_ROOT, 'benchmark', "#{build_config_name}.png") -end - -def plot - opts_file = "#{MRUBY_ROOT}/benchmark/plot.gpl" - opts = File.read(opts_file).each_line.to_a.map(&:strip).join(';') - - dat_files = $dat_files.group_by {|f| File.dirname(f).split(File::SEPARATOR)[-1]} - - opts += ";set output '#{plot_file}'" - - opts += ';plot ' - - opts += dat_files.keys.map do |data_file| - %Q['-' u 2:3:4:xtic(1) w hist title columnheader(1)] - end.join(',') - opts += ';' - - cmd = %Q{gnuplot -p -e "#{opts}"} - - IO.popen(cmd, 'w') do |p| - dat_files.each do |target_name, bm_files| - p.puts target_name.gsub('_', '-') - bm_files.each do |bm_file| - p.write File.read(bm_file) - end - p.puts "e" - end - end -end - - -MRuby.each_target do |target| - next if target.name == 'host' - mruby_bin = "#{target.build_dir}/bin/mruby" - - bm_files.each do |bm_file| - bm_name = File.basename bm_file, ".rb" - - dat_dir = File.join('benchmark', build_config_name, target.name) - dat_file = File.join(dat_dir, "#{bm_name}.dat") - $dat_files << dat_file - - directory dat_dir - - file dat_file => [bm_file, dat_dir, mruby_bin] do |task| - print bm_name - puts "..." - - data = (0...MRuby::BENCHMARK_REPEAT).map do |n| - str = %x{(time -f "%e %S %U" #{mruby_bin} #{bm_file}) 2>&1 >/dev/null} - str.split(' ').map(&:to_f) - end - - File.open(task.name, "w") do |f| - data = data.map {|_,r,s| (r + s) / 2.0} - min = data.min - max = data.max - avg = data.inject(&:+) / data.size - f.puts "#{bm_name.gsub('_', '-')} #{avg} #{min} #{max}" - end - end - end -end - -file plot_file => $dat_files do - plot -end - -task :benchmark => plot_file do - plot -end diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/libmruby.rake nghttp2-0.6.7/third-party/mruby/tasks/libmruby.rake --- nghttp2-1.13.0/third-party/mruby/tasks/libmruby.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/libmruby.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -MRuby.each_target do - file libfile("#{build_dir}/lib/libmruby") => libmruby.flatten do |t| - archiver.run t.name, t.prerequisites - end - - file "#{build_dir}/lib/libmruby.flags.mak" => [__FILE__, libfile("#{build_dir}/lib/libmruby")] do |t| - open(t.name, 'w') do |f| - f.puts "MRUBY_CFLAGS = #{cc.all_flags.gsub('"', '\\"')}" - - gem_flags = gems.map { |g| g.linker.flags } - gem_library_paths = gems.map { |g| g.linker.library_paths } - f.puts "MRUBY_LDFLAGS = #{linker.all_flags(gem_library_paths, gem_flags).gsub('"', '\\"')} #{linker.option_library_path % "#{build_dir}/lib"}" - - gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries } - f.puts "MRUBY_LDFLAGS_BEFORE_LIBS = #{[linker.flags_before_libraries, gem_flags_before_libraries].flatten.join(' ').gsub('"', '\\"')}" - - gem_libraries = gems.map { |g| g.linker.libraries } - f.puts "MRUBY_LIBS = #{linker.option_library % 'mruby'} #{linker.library_flags(gem_libraries).gsub('"', '\\"')}" - end - end - task :all => "#{build_dir}/lib/libmruby.flags.mak" -end diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/mrbgem_spec.rake nghttp2-0.6.7/third-party/mruby/tasks/mrbgem_spec.rake --- nghttp2-1.13.0/third-party/mruby/tasks/mrbgem_spec.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/mrbgem_spec.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,433 +0,0 @@ -require 'pathname' -require 'forwardable' -require 'tsort' - -module MRuby - module Gem - class << self - attr_accessor :current - end - LinkerConfig = Struct.new(:libraries, :library_paths, :flags, :flags_before_libraries, :flags_after_libraries) - - class Specification - include Rake::DSL - extend Forwardable - def_delegators :@build, :filename, :objfile, :libfile, :exefile - - attr_accessor :name, :dir, :build - alias mruby build - attr_accessor :build_config_initializer - - attr_accessor :version - attr_accessor :description, :summary - attr_accessor :homepage - attr_accessor :licenses, :authors - alias :license= :licenses= - alias :author= :authors= - - attr_accessor :rbfiles, :objs - attr_accessor :test_objs, :test_rbfiles, :test_args - attr_accessor :test_preload - - attr_accessor :bins - - attr_accessor :requirements - attr_reader :dependencies, :conflicts - - attr_accessor :export_include_paths - - attr_reader :generate_functions - - attr_block MRuby::Build::COMMANDS - - def initialize(name, &block) - @name = name - @initializer = block - @version = "0.0.0" - MRuby::Gem.current = self - end - - def setup - MRuby::Gem.current = self - MRuby::Build::COMMANDS.each do |command| - instance_variable_set("@#{command}", @build.send(command).clone) - end - @linker = LinkerConfig.new([], [], [], [], []) - - @rbfiles = Dir.glob("#{dir}/mrblib/**/*.rb").sort - @objs = Dir.glob("#{dir}/src/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f| - objfile(f.relative_path_from(@dir).to_s.pathmap("#{build_dir}/%X")) - end - - @generate_functions = !(@rbfiles.empty? && @objs.empty?) - @objs << objfile("#{build_dir}/gem_init") if @generate_functions - - @test_rbfiles = Dir.glob("#{dir}/test/**/*.rb") - @test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f| - objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X")) - end - @custom_test_init = !@test_objs.empty? - @test_preload = nil # 'test/assert.rb' - @test_args = {} - - @bins = [] - - @requirements = [] - @dependencies, @conflicts = [], [] - @export_include_paths = [] - @export_include_paths << "#{dir}/include" if File.directory? "#{dir}/include" - - instance_eval(&@initializer) - - if !name || !licenses || !authors - fail "#{name || dir} required to set name, license(s) and author(s)" - end - - build.libmruby << @objs - - instance_eval(&@build_config_initializer) if @build_config_initializer - - compilers.each do |compiler| - compiler.define_rules build_dir, "#{dir}" - compiler.defines << %Q[MRBGEM_#{funcname.upcase}_VERSION=#{version}] - compiler.include_paths << "#{dir}/include" if File.directory? "#{dir}/include" - end - - define_gem_init_builder if @generate_functions - end - - def add_dependency(name, *requirements) - default_gem = requirements.last.kind_of?(Hash) ? requirements.pop : nil - requirements = ['>= 0.0.0'] if requirements.empty? - requirements.flatten! - @dependencies << {:gem => name, :requirements => requirements, :default => default_gem} - end - - def add_test_dependency(*args) - add_dependency(*args) if build.test_enabled? - end - - def add_conflict(name, *req) - @conflicts << {:gem => name, :requirements => req.empty? ? nil : req} - end - - def self.bin=(bin) - @bins = [bin].flatten - end - - def build_dir - "#{build.build_dir}/mrbgems/#{name}" - end - - def test_rbireps - "#{build_dir}/gem_test.c" - end - - def funcname - @funcname ||= @name.gsub('-', '_') - end - - def compilers - MRuby::Build::COMPILERS.map do |c| - instance_variable_get("@#{c}") - end - end - - def define_gem_init_builder - file objfile("#{build_dir}/gem_init") => [ "#{build_dir}/gem_init.c", File.join(dir, "mrbgem.rake") ] - file "#{build_dir}/gem_init.c" => [build.mrbcfile, __FILE__] + [rbfiles].flatten do |t| - FileUtils.mkdir_p build_dir - generate_gem_init("#{build_dir}/gem_init.c") - end - end - - def generate_gem_init(fname) - open(fname, 'w') do |f| - print_gem_init_header f - build.mrbc.run f, rbfiles, "gem_mrblib_irep_#{funcname}" unless rbfiles.empty? - f.puts %Q[void mrb_#{funcname}_gem_init(mrb_state *mrb);] - f.puts %Q[void mrb_#{funcname}_gem_final(mrb_state *mrb);] - f.puts %Q[] - f.puts %Q[void GENERATED_TMP_mrb_#{funcname}_gem_init(mrb_state *mrb) {] - f.puts %Q[ int ai = mrb_gc_arena_save(mrb);] - f.puts %Q[ mrb_#{funcname}_gem_init(mrb);] if objs != [objfile("#{build_dir}/gem_init")] - unless rbfiles.empty? - f.puts %Q[ mrb_load_irep(mrb, gem_mrblib_irep_#{funcname});] - f.puts %Q[ if (mrb->exc) {] - f.puts %Q[ mrb_print_error(mrb);] - f.puts %Q[ exit(EXIT_FAILURE);] - f.puts %Q[ }] - end - f.puts %Q[ mrb_gc_arena_restore(mrb, ai);] - f.puts %Q[}] - f.puts %Q[] - f.puts %Q[void GENERATED_TMP_mrb_#{funcname}_gem_final(mrb_state *mrb) {] - f.puts %Q[ mrb_#{funcname}_gem_final(mrb);] if objs != [objfile("#{build_dir}/gem_init")] - f.puts %Q[}] - end - end # generate_gem_init - - def print_gem_comment(f) - f.puts %Q[/*] - f.puts %Q[ * This file is loading the irep] - f.puts %Q[ * Ruby GEM code.] - f.puts %Q[ *] - f.puts %Q[ * IMPORTANT:] - f.puts %Q[ * This file was generated!] - f.puts %Q[ * All manual changes will get lost.] - f.puts %Q[ */] - end - - def print_gem_init_header(f) - print_gem_comment(f) - f.puts %Q[#include ] unless rbfiles.empty? - f.puts %Q[#include "mruby.h"] - f.puts %Q[#include "mruby/irep.h"] unless rbfiles.empty? - end - - def print_gem_test_header(f) - print_gem_comment(f) - f.puts %Q[#include ] - f.puts %Q[#include ] - f.puts %Q[#include "mruby.h"] - f.puts %Q[#include "mruby/irep.h"] - f.puts %Q[#include "mruby/variable.h"] - f.puts %Q[#include "mruby/hash.h"] unless test_args.empty? - end - - def test_dependencies - [@name] - end - - def custom_test_init? - @custom_test_init - end - - def version_ok?(req_versions) - req_versions.map do |req| - cmp, ver = req.split - cmp_result = Version.new(version) <=> Version.new(ver) - case cmp - when '=' then cmp_result == 0 - when '!=' then cmp_result != 0 - when '>' then cmp_result == 1 - when '<' then cmp_result == -1 - when '>=' then cmp_result >= 0 - when '<=' then cmp_result <= 0 - when '~>' - Version.new(version).twiddle_wakka_ok?(Version.new(ver)) - else - fail "Comparison not possible with '#{cmp}'" - end - end.all? - end - end # Specification - - class Version - include Comparable - include Enumerable - - def <=>(other) - ret = 0 - own = to_enum - - other.each do |oth| - begin - ret = own.next <=> oth - rescue StopIteration - ret = 0 <=> oth - end - - break unless ret == 0 - end - - ret - end - - # ~> compare algorithm - # - # Example: - # ~> 2.2 means >= 2.2.0 and < 3.0.0 - # ~> 2.2.0 means >= 2.2.0 and < 2.3.0 - def twiddle_wakka_ok?(other) - gr_or_eql = (self <=> other) >= 0 - still_minor = (self <=> other.skip_minor) < 0 - gr_or_eql and still_minor - end - - def skip_minor - a = @ary.dup - a.slice!(-1) - a[-1] = a[-1].succ - a - end - - def initialize(str) - @str = str - @ary = @str.split('.').map(&:to_i) - end - - def each(&block); @ary.each(&block); end - def [](index); @ary[index]; end - def []=(index, value) - @ary[index] = value - @str = @ary.join('.') - end - def slice!(index) - @ary.slice!(index) - @str = @ary.join('.') - end - end # Version - - class List - include Enumerable - - def initialize - @ary = [] - end - - def each(&b) - @ary.each(&b) - end - - def <<(gem) - unless @ary.detect {|g| g.dir == gem.dir } - @ary << gem - else - # GEM was already added to this list - end - end - - def empty? - @ary.empty? - end - - def generate_gem_table build - gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res } - - default_gems = [] - each do |g| - g.dependencies.each do |dep| - unless gem_table.key? dep[:gem] - if dep[:default]; default_gems << dep - elsif File.exist? "#{MRUBY_ROOT}/mrbgems/#{dep[:gem]}" # check core - default_gems << { :gem => dep[:gem], :default => { :core => dep[:gem] } } - else # fallback to mgem-list - default_gems << { :gem => dep[:gem], :default => { :mgem => dep[:gem] } } - end - end - end - end - - until default_gems.empty? - def_gem = default_gems.pop - - spec = build.gem def_gem[:default] - fail "Invalid gem name: #{spec.name} (Expected: #{def_gem[:gem]})" if spec.name != def_gem[:gem] - spec.setup - - spec.dependencies.each do |dep| - unless gem_table.key? dep[:gem] - if dep[:default]; default_gems << dep - else default_gems << { :gem => dep[:gem], :default => { :mgem => dep[:gem] } } - end - end - end - gem_table[spec.name] = spec - end - - each do |g| - g.dependencies.each do |dep| - name = dep[:gem] - req_versions = dep[:requirements] - dep_g = gem_table[name] - - # check each GEM dependency against all available GEMs - if dep_g.nil? - fail "The GEM '#{g.name}' depends on the GEM '#{name}' but it could not be found" - end - unless dep_g.version_ok? req_versions - fail "#{name} version should be #{req_versions.join(' and ')} but was '#{dep_g.version}'" - end - end - - cfls = g.conflicts.select { |c| - cfl_g = gem_table[c[:gem]] - cfl_g and cfl_g.version_ok?(c[:requirements] || ['>= 0.0.0']) - }.map { |c| "#{c[:gem]}(#{gem_table[c[:gem]].version})" } - fail "Conflicts of gem `#{g.name}` found: #{cfls.join ', '}" unless cfls.empty? - end - - gem_table - end - - def tsort_dependencies ary, table, all_dependency_listed = false - unless all_dependency_listed - left = ary.dup - until left.empty? - v = left.pop - table[v].dependencies.each do |dep| - left.push dep[:gem] - ary.push dep[:gem] - end - end - end - - ary.uniq! - table.instance_variable_set :@root_gems, ary - class << table - include TSort - def tsort_each_node &b - @root_gems.each &b - end - - def tsort_each_child(n, &b) - fetch(n).dependencies.each do |v| - b.call v[:gem] - end - end - end - - begin - table.tsort.map { |v| table[v] } - rescue TSort::Cyclic => e - fail "Circular mrbgem dependency found: #{e.message}" - end - end - - def check(build) - gem_table = generate_gem_table build - - @ary = tsort_dependencies gem_table.keys, gem_table, true - - each do |g| - import_include_paths(g) - end - end - - def import_include_paths(g) - gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res } - g.dependencies.each do |dep| - dep_g = gem_table[dep[:gem]] - # We can do recursive call safely - # as circular dependency has already detected in the caller. - import_include_paths(dep_g) - - g.compilers.each do |compiler| - compiler.include_paths += dep_g.export_include_paths - g.export_include_paths += dep_g.export_include_paths - end - end - end - end # List - end # Gem - - GemBox = Object.new - class << GemBox - attr_accessor :path - - def new(&block); block.call(self); end - def config=(obj); @config = obj; end - def gem(gemdir, &block); @config.gem(gemdir, &block); end - end # GemBox -end # MRuby diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/mrbgems.rake nghttp2-0.6.7/third-party/mruby/tasks/mrbgems.rake --- nghttp2-1.13.0/third-party/mruby/tasks/mrbgems.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/mrbgems.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -MRuby.each_target do - if enable_gems? - # set up all gems - gems.each(&:setup) - gems.check self - - # loader all gems - self.libmruby << objfile("#{build_dir}/mrbgems/gem_init") - file objfile("#{build_dir}/mrbgems/gem_init") => ["#{build_dir}/mrbgems/gem_init.c", "#{build_dir}/LEGAL"] - file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG, __FILE__] do |t| - FileUtils.mkdir_p "#{build_dir}/mrbgems" - open(t.name, 'w') do |f| - gem_func_gems = gems.select { |g| g.generate_functions } - gem_func_decls = gem_func_gems.each_with_object('') do |g, s| - s << "void GENERATED_TMP_mrb_#{g.funcname}_gem_init(mrb_state*);\n" \ - "void GENERATED_TMP_mrb_#{g.funcname}_gem_final(mrb_state*);\n" - end - gem_init_calls = gem_func_gems.each_with_object('') do |g, s| - s << " GENERATED_TMP_mrb_#{g.funcname}_gem_init(mrb);\n" - end - gem_final_calls = gem_func_gems.each_with_object('') do |g, s| - s << " GENERATED_TMP_mrb_#{g.funcname}_gem_final(mrb);\n" - end - f.puts %Q[/*] - f.puts %Q[ * This file contains a list of all] - f.puts %Q[ * initializing methods which are] - f.puts %Q[ * necessary to bootstrap all gems.] - f.puts %Q[ *] - f.puts %Q[ * IMPORTANT:] - f.puts %Q[ * This file was generated!] - f.puts %Q[ * All manual changes will get lost.] - f.puts %Q[ */] - f.puts %Q[] - f.puts %Q[#include "mruby.h"] - f.puts %Q[] - f.write gem_func_decls - f.puts %Q[] - f.puts %Q[static void] - f.puts %Q[mrb_final_mrbgems(mrb_state *mrb) {] - f.write gem_final_calls - f.puts %Q[}] - f.puts %Q[] - f.puts %Q[void] - f.puts %Q[mrb_init_mrbgems(mrb_state *mrb) {] - f.write gem_init_calls - f.puts %Q[ mrb_state_atexit(mrb, mrb_final_mrbgems);] unless gem_final_calls.empty? - f.puts %Q[}] - end - end - end - - # legal documents - file "#{build_dir}/LEGAL" => [MRUBY_CONFIG, __FILE__] do |t| - open(t.name, 'w+') do |f| - f.puts < all_flags(_defineds, _include_paths, _flags), - :infile => cygwin_filename(infile), :outfile => cygwin_filename(outfile) } - else - _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags), - :infile => filename(infile), :outfile => filename(outfile) } - end - end - - def define_rules(build_dir, source_dir='') - @out_ext = build.exts.object - gemrake = File.join(source_dir, "mrbgem.rake") - rakedep = File.exist?(gemrake) ? [ gemrake ] : [] - - if build_dir.include? "mrbgems/" - generated_file_matcher = Regexp.new("^#{Regexp.escape build_dir}/(.*)#{Regexp.escape out_ext}$") - else - generated_file_matcher = Regexp.new("^#{Regexp.escape build_dir}/(?!mrbgems/.+/)(.*)#{Regexp.escape out_ext}$") - end - source_exts.each do |ext, compile| - rule generated_file_matcher => [ - proc { |file| - file.sub(generated_file_matcher, "#{source_dir}/\\1#{ext}") - }, - proc { |file| - get_dependencies(file) + rakedep - } - ] do |t| - run t.name, t.prerequisites.first - end - - rule generated_file_matcher => [ - proc { |file| - file.sub(generated_file_matcher, "#{build_dir}/\\1#{ext}") - }, - proc { |file| - get_dependencies(file) + rakedep - } - ] do |t| - run t.name, t.prerequisites.first - end - end - end - - private - def get_dependencies(file) - file = file.ext('d') unless File.extname(file) == '.d' - if File.exist?(file) - File.read(file).gsub("\\\n ", "").scan(/^\S+:\s+(.+)$/).flatten.map {|s| s.split(' ') }.flatten - else - [] - end + [ MRUBY_CONFIG ] - end - end - - class Command::Linker < Command - attr_accessor :flags, :library_paths, :flags_before_libraries, :libraries, :flags_after_libraries - attr_accessor :link_options, :option_library, :option_library_path - - def initialize(build) - super - @command = ENV['LD'] || 'ld' - @flags = (ENV['LDFLAGS'] || []) - @flags_before_libraries, @flags_after_libraries = [], [] - @libraries = [] - @library_paths = [] - @option_library = '-l%s' - @option_library_path = '-L%s' - @link_options = "%{flags} -o %{outfile} %{objs} %{flags_before_libraries} %{libs} %{flags_after_libraries}" - end - - def all_flags(_library_paths=[], _flags=[]) - library_path_flags = [library_paths, _library_paths].flatten.map do |f| - if MRUBY_BUILD_HOST_IS_CYGWIN - option_library_path % cygwin_filename(f) - else - option_library_path % filename(f) - end - end - [flags, library_path_flags, _flags].flatten.join(' ') - end - - def library_flags(_libraries) - [libraries, _libraries].flatten.map{ |d| option_library % d }.join(' ') - end - - def run(outfile, objfiles, _libraries=[], _library_paths=[], _flags=[], _flags_before_libraries=[], _flags_after_libraries=[]) - FileUtils.mkdir_p File.dirname(outfile) - library_flags = [libraries, _libraries].flatten.map { |d| option_library % d } - - _pp "LD", outfile.relative_path - if MRUBY_BUILD_HOST_IS_CYGWIN - _run link_options, { :flags => all_flags(_library_paths, _flags), - :outfile => cygwin_filename(outfile) , :objs => cygwin_filename(objfiles).join(' '), - :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '), - :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '), - :libs => library_flags.join(' ') } - else - _run link_options, { :flags => all_flags(_library_paths, _flags), - :outfile => filename(outfile) , :objs => filename(objfiles).join(' '), - :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '), - :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '), - :libs => library_flags.join(' ') } - end - end - end - - class Command::Archiver < Command - attr_accessor :archive_options - - def initialize(build) - super - @command = ENV['AR'] || 'ar' - @archive_options = 'rs %{outfile} %{objs}' - end - - def run(outfile, objfiles) - FileUtils.mkdir_p File.dirname(outfile) - _pp "AR", outfile.relative_path - if MRUBY_BUILD_HOST_IS_CYGWIN - _run archive_options, { :outfile => cygwin_filename(outfile), :objs => cygwin_filename(objfiles).join(' ') } - else - _run archive_options, { :outfile => filename(outfile), :objs => filename(objfiles).join(' ') } - end - end - end - - class Command::Yacc < Command - attr_accessor :compile_options - - def initialize(build) - super - @command = 'bison' - @compile_options = '-o %{outfile} %{infile}' - end - - def run(outfile, infile) - FileUtils.mkdir_p File.dirname(outfile) - _pp "YACC", infile.relative_path, outfile.relative_path - _run compile_options, { :outfile => filename(outfile) , :infile => filename(infile) } - end - end - - class Command::Gperf < Command - attr_accessor :compile_options - - def initialize(build) - super - @command = 'gperf' - @compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}' - end - - def run(outfile, infile) - FileUtils.mkdir_p File.dirname(outfile) - _pp "GPERF", infile.relative_path, outfile.relative_path - _run compile_options, { :outfile => filename(outfile) , :infile => filename(infile) } - end - end - - class Command::Git < Command - attr_accessor :flags - attr_accessor :clone_options, :pull_options, :checkout_options - - def initialize(build) - super - @command = 'git' - @flags = %w[] - @clone_options = "clone %{flags} %{url} %{dir}" - @pull_options = "pull" - @checkout_options = "checkout %{checksum_hash}" - end - - def run_clone(dir, url, _flags = []) - _pp "GIT", url, dir.relative_path - _run clone_options, { :flags => [flags, _flags].flatten.join(' '), :url => url, :dir => filename(dir) } - end - - def run_pull(dir, url) - root = Dir.pwd - Dir.chdir dir - _pp "GIT PULL", url, dir.relative_path - _run pull_options - Dir.chdir root - end - - def run_checkout(dir, checksum_hash) - root = Dir.pwd - Dir.chdir dir - _pp "GIT CHECKOUT", checksum_hash - _run checkout_options, { :checksum_hash => checksum_hash } - Dir.chdir root - end - end - - class Command::Mrbc < Command - attr_accessor :compile_options - - def initialize(build) - super - @command = nil - @compile_options = "-B%{funcname} -o-" - end - - def run(out, infiles, funcname) - @command ||= @build.mrbcfile - infiles = [infiles].flatten - infiles.each do |f| - _pp "MRBC", f.relative_path, nil, :indent => 2 - end - IO.popen("#{filename @command} #{@compile_options % {:funcname => funcname}} #{filename(infiles).join(' ')}", 'r+') do |io| - out.puts io.read - end - # if mrbc execution fail, drop the file - if $?.exitstatus != 0 - File.delete(out.path) - exit(-1) - end - end - end - - class Command::CrossTestRunner < Command - attr_accessor :runner_options - attr_accessor :verbose_flag - attr_accessor :flags - - def initialize(build) - super - @command = nil - @runner_options = '%{flags} %{infile}' - @verbose_flag = '' - @flags = [] - end - - def run(testbinfile) - puts "TEST for " + @build.name - _run runner_options, { :flags => [flags, verbose_flag].flatten.join(' '), :infile => testbinfile } - end - end - -end diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/mruby_build_gem.rake nghttp2-0.6.7/third-party/mruby/tasks/mruby_build_gem.rake --- nghttp2-1.13.0/third-party/mruby/tasks/mruby_build_gem.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/mruby_build_gem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,122 +0,0 @@ -module MRuby - module LoadGems - def gembox(gemboxfile) - gembox = File.expand_path("#{gemboxfile}.gembox", "#{MRUBY_ROOT}/mrbgems") - fail "Can't find gembox '#{gembox}'" unless File.exist?(gembox) - - GemBox.config = self - GemBox.path = gembox - - instance_eval File.read(gembox) - - GemBox.path = nil - end - - def gem(gemdir, &block) - caller_dir = File.expand_path(File.dirname(/^(.*?):\d/.match(caller.first).to_a[1])) - - if gemdir.is_a?(Hash) - gemdir = load_special_path_gem(gemdir) - elsif GemBox.path && gemdir.is_a?(String) - gemdir = File.expand_path(gemdir, File.dirname(GemBox.path)) - else - gemdir = File.expand_path(gemdir, caller_dir) - end - - gemrake = File.join(gemdir, "mrbgem.rake") - - fail "Can't find #{gemrake}" unless File.exist?(gemrake) - Gem.current = nil - load gemrake - return nil unless Gem.current - - Gem.current.dir = gemdir - Gem.current.build = self.is_a?(MRuby::Build) ? self : MRuby::Build.current - Gem.current.build_config_initializer = block - gems << Gem.current - - cxx_srcs = ['src', 'test', 'tools'].map do |subdir| - Dir.glob("#{Gem.current.dir}/#{subdir}/*.{cpp,cxx,cc}") - end.flatten - enable_cxx_abi unless cxx_srcs.empty? - - Gem.current - end - - def load_special_path_gem(params) - if params[:github] - params[:git] = "https://github.com/#{params[:github]}.git" - elsif params[:bitbucket] - if params[:method] == "ssh" - params[:git] = "git@bitbucket.org:#{params[:bitbucket]}.git" - else - params[:git] = "https://bitbucket.org/#{params[:bitbucket]}.git" - end - elsif params[:mgem] - mgem_list_dir = "#{gem_clone_dir}/mgem-list" - mgem_list_url = 'https://github.com/mruby/mgem-list.git' - if File.exist? mgem_list_dir - git.run_pull mgem_list_dir, mgem_list_url if $pull_gems - else - FileUtils.mkdir_p mgem_list_dir - git.run_clone mgem_list_dir, mgem_list_url, "--depth 1" - end - - require 'yaml' - - conf_path = "#{mgem_list_dir}/#{params[:mgem]}.gem" - conf_path = "#{mgem_list_dir}/mruby-#{params[:mgem]}.gem" unless File.exist? conf_path - fail "mgem not found: #{params[:mgem]}" unless File.exist? conf_path - conf = YAML.load File.read conf_path - - fail "unknown mgem protocol: #{conf['protocol']}" if conf['protocol'] != 'git' - params[:git] = conf['repository'] - params[:branch] = conf['branch'] if conf['branch'] - end - - if params[:core] - gemdir = "#{root}/mrbgems/#{params[:core]}" - elsif params[:path] - require 'pathname' - gemdir = Pathname.new(params[:path]).absolute? ? params[:path] : "#{root}/#{params[:path]}" - elsif params[:git] - url = params[:git] - gemdir = "#{gem_clone_dir}/#{url.match(/([-\w]+)(\.[-\w]+|)$/).to_a[1]}" - - # by default the 'master' branch is used - branch = params[:branch] ? params[:branch] : 'master' - - if File.exist?(gemdir) - if $pull_gems - git.run_pull gemdir, url - else - gemdir - end - else - options = [params[:options]] || [] - options << "--recursive" - options << "--branch \"#{branch}\"" - options << "--depth 1" unless params[:checksum_hash] - FileUtils.mkdir_p "#{gem_clone_dir}" - git.run_clone gemdir, url, options - end - - if params[:checksum_hash] - # Jump to the specified commit - git.run_checkout gemdir, params[:checksum_hash] - else - # Jump to the top of the branch - git.run_checkout gemdir, branch if $pull_gems - end - else - fail "unknown gem option #{params}" - end - - gemdir - end - - def enable_gems? - !@gems.empty? - end - end # LoadGems -end # MRuby diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/mruby_build.rake nghttp2-0.6.7/third-party/mruby/tasks/mruby_build.rake --- nghttp2-1.13.0/third-party/mruby/tasks/mruby_build.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/mruby_build.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,324 +0,0 @@ -load "#{MRUBY_ROOT}/tasks/mruby_build_gem.rake" -load "#{MRUBY_ROOT}/tasks/mruby_build_commands.rake" - -module MRuby - class << self - def targets - @targets ||= {} - end - - def each_target(&block) - return to_enum(:each_target) if block.nil? - @targets.each do |key, target| - target.instance_eval(&block) - end - end - end - - class Toolchain - class << self - attr_accessor :toolchains - end - - def initialize(name, &block) - @name, @initializer = name.to_s, block - MRuby::Toolchain.toolchains ||= {} - MRuby::Toolchain.toolchains[@name] = self - end - - def setup(conf,params={}) - conf.instance_exec(conf, params, &@initializer) - end - - def self.load - Dir.glob("#{MRUBY_ROOT}/tasks/toolchains/*.rake").each do |file| - Kernel.load file - end - end - end - Toolchain.load - - class Build - class << self - attr_accessor :current - end - include Rake::DSL - include LoadGems - attr_accessor :name, :bins, :exts, :file_separator, :build_dir, :gem_clone_dir - attr_reader :libmruby, :gems, :toolchains - attr_writer :enable_bintest, :enable_test - - COMPILERS = %w(cc cxx objc asm) - COMMANDS = COMPILERS + %w(linker archiver yacc gperf git exts mrbc) - attr_block MRuby::Build::COMMANDS - - Exts = Struct.new(:object, :executable, :library) - - def initialize(name='host', build_dir=nil, &block) - @name = name.to_s - - unless MRuby.targets[@name] - if ENV['OS'] == 'Windows_NT' - @exts = Exts.new('.o', '.exe', '.a') - else - @exts = Exts.new('.o', '', '.a') - end - - build_dir = build_dir || ENV['MRUBY_BUILD_DIR'] || "#{MRUBY_ROOT}/build" - - @file_separator = '/' - @build_dir = "#{build_dir}/#{@name}" - @gem_clone_dir = "#{build_dir}/mrbgems" - @cc = Command::Compiler.new(self, %w(.c)) - @cxx = Command::Compiler.new(self, %w(.cc .cxx .cpp)) - @objc = Command::Compiler.new(self, %w(.m)) - @asm = Command::Compiler.new(self, %w(.S .asm)) - @linker = Command::Linker.new(self) - @archiver = Command::Archiver.new(self) - @yacc = Command::Yacc.new(self) - @gperf = Command::Gperf.new(self) - @git = Command::Git.new(self) - @mrbc = Command::Mrbc.new(self) - - @bins = [] - @gems, @libmruby = MRuby::Gem::List.new, [] - @build_mrbtest_lib_only = false - @cxx_abi_enabled = false - @cxx_exception_disabled = false - @enable_bintest = false - @enable_test = false - @toolchains = [] - - MRuby.targets[@name] = self - end - - MRuby::Build.current = MRuby.targets[@name] - MRuby.targets[@name].instance_eval(&block) - - build_mrbc_exec if name == 'host' - build_mrbtest if test_enabled? - end - - def enable_debug - compilers.each do |c| - c.defines += %w(MRB_DEBUG) - if toolchains.any? { |toolchain| toolchain == "gcc" } - c.flags += %w(-g3 -O0) - end - end - @mrbc.compile_options += ' -g' - end - - def disable_cxx_exception - @cxx_exception_disabled = true - end - - def cxx_abi_enabled? - @cxx_abi_enabled - end - - def enable_cxx_abi - return if @cxx_exception_disabled or @cxx_abi_enabled - compilers.each { |c| c.defines += %w(MRB_ENABLE_CXX_EXCEPTION) } - linker.command = cxx.command if toolchains.find { |v| v == 'gcc' } - @cxx_abi_enabled = true - end - - def compile_as_cxx src, cxx_src, obj = nil, includes = [] - src = File.absolute_path src - cxx_src = File.absolute_path cxx_src - obj = objfile(cxx_src) if obj.nil? - - file cxx_src => [src, __FILE__] do |t| - FileUtils.mkdir_p File.dirname t.name - IO.write t.name, < cxx_src do |t| - cxx.run t.name, t.prerequisites.first, [], ["#{MRUBY_ROOT}/src"] + includes - end - - obj - end - - def enable_bintest - @enable_bintest = true - end - - def bintest_enabled? - @enable_bintest - end - - def toolchain(name, params={}) - tc = Toolchain.toolchains[name.to_s] - fail "Unknown #{name} toolchain" unless tc - tc.setup(self, params) - @toolchains.unshift name.to_s - end - - def primary_toolchain - @toolchains.first - end - - def root - MRUBY_ROOT - end - - def enable_test - @enable_test = true - end - - def test_enabled? - @enable_test - end - - def build_mrbtest - gem :core => 'mruby-test' - end - - def build_mrbc_exec - gem :core => 'mruby-bin-mrbc' - end - - def mrbcfile - return @mrbcfile if @mrbcfile - - mrbc_build = MRuby.targets['host'] - gems.each { |v| mrbc_build = self if v.name == 'mruby-bin-mrbc' } - @mrbcfile = mrbc_build.exefile("#{mrbc_build.build_dir}/bin/mrbc") - end - - def compilers - COMPILERS.map do |c| - instance_variable_get("@#{c}") - end - end - - def define_rules - compilers.each do |compiler| - if respond_to?(:enable_gems?) && enable_gems? - compiler.defines -= %w(DISABLE_GEMS) - else - compiler.defines += %w(DISABLE_GEMS) - end - compiler.define_rules build_dir, File.expand_path(File.join(File.dirname(__FILE__), '..')) - end - end - - def filename(name) - if name.is_a?(Array) - name.flatten.map { |n| filename(n) } - else - '"%s"' % name.gsub('/', file_separator) - end - end - - def cygwin_filename(name) - if name.is_a?(Array) - name.flatten.map { |n| cygwin_filename(n) } - else - '"%s"' % `cygpath -w "#{filename(name)}"`.strip - end - end - - def exefile(name) - if name.is_a?(Array) - name.flatten.map { |n| exefile(n) } - else - "#{name}#{exts.executable}" - end - end - - def objfile(name) - if name.is_a?(Array) - name.flatten.map { |n| objfile(n) } - else - "#{name}#{exts.object}" - end - end - - def libfile(name) - if name.is_a?(Array) - name.flatten.map { |n| libfile(n) } - else - "#{name}#{exts.library}" - end - end - - def build_mrbtest_lib_only - @build_mrbtest_lib_only = true - end - - def build_mrbtest_lib_only? - @build_mrbtest_lib_only - end - - def run_test - puts ">>> Test #{name} <<<" - mrbtest = exefile("#{build_dir}/bin/mrbtest") - sh "#{filename mrbtest.relative_path}#{$verbose ? ' -v' : ''}" - puts - run_bintest if bintest_enabled? - end - - def run_bintest - targets = @gems.select { |v| File.directory? "#{v.dir}/bintest" }.map { |v| filename v.dir } - targets << filename(".") if File.directory? "./bintest" - sh "ruby test/bintest.rb #{targets.join ' '}" - end - - def print_build_summary - puts "================================================" - puts " Config Name: #{@name}" - puts " Output Directory: #{self.build_dir.relative_path}" - puts " Binaries: #{@bins.join(', ')}" unless @bins.empty? - unless @gems.empty? - puts " Included Gems:" - @gems.map do |gem| - gem_version = " - #{gem.version}" if gem.version != '0.0.0' - gem_summary = " - #{gem.summary}" if gem.summary - puts " #{gem.name}#{gem_version}#{gem_summary}" - puts " - Binaries: #{gem.bins.join(', ')}" unless gem.bins.empty? - end - end - puts "================================================" - puts - end - end # Build - - class CrossBuild < Build - attr_block %w(test_runner) - # cross compiling targets for building native extensions. - # host - arch of where the built binary will run - # build - arch of the machine building the binary - attr_accessor :host_target, :build_target - - def initialize(name, build_dir=nil, &block) - @test_runner = Command::CrossTestRunner.new(self) - super - end - - def mrbcfile - MRuby.targets['host'].exefile("#{MRuby.targets['host'].build_dir}/bin/mrbc") - end - - def run_test - mrbtest = exefile("#{build_dir}/bin/mrbtest") - if (@test_runner.command == nil) - puts "You should run #{mrbtest} on target device." - puts - else - @test_runner.run(mrbtest) - end - end - end # CrossBuild -end # MRuby diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/ruby_ext.rake nghttp2-0.6.7/third-party/mruby/tasks/ruby_ext.rake --- nghttp2-1.13.0/third-party/mruby/tasks/ruby_ext.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/ruby_ext.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -class Object - class << self - def attr_block(*syms) - syms.flatten.each do |sym| - class_eval "def #{sym}(&block);block.call(@#{sym}) if block_given?;@#{sym};end" - end - end - end -end - -class String - def relative_path_from(dir) - Pathname.new(File.expand_path(self)).relative_path_from(Pathname.new(File.expand_path(dir))).to_s - end - - def relative_path - relative_path_from(Dir.pwd) - end - - # Compatible with 1.9 on 1.8 - def %(params) - if params.is_a?(Hash) - str = self.clone - params.each do |k, v| - str.gsub!("%{#{k}}") { v } - end - str - else - if params.is_a?(Array) - sprintf(self, *params) - else - sprintf(self, params) - end - end - end -end - -class Symbol - # Compatible with 1.9 on 1.8 - def to_proc - proc { |obj, *args| obj.send(self, *args) } - end -end - -module Enumerable - # Compatible with 1.9 on 1.8 - def each_with_object(memo) - return to_enum :each_with_object, memo unless block_given? - each { |obj| yield obj, memo } - memo - end -end - -$pp_show = true - -if $verbose.nil? - if Rake.respond_to?(:verbose) && !Rake.verbose.nil? - if Rake.verbose.class == TrueClass - # verbose message logging - $pp_show = false - else - $pp_show = true - Rake.verbose(false) - end - else - # could not identify rake version - $pp_show = false - end -else - $pp_show = false if $verbose -end - -def _pp(cmd, src, tgt=nil, options={}) - return unless $pp_show - - width = 5 - template = options[:indent] ? "%#{width*options[:indent]}s %s %s" : "%-#{width}s %s %s" - puts template % [cmd, src, tgt ? "-> #{tgt}" : nil] -end diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/toolchains/android.rake nghttp2-0.6.7/third-party/mruby/tasks/toolchains/android.rake --- nghttp2-1.13.0/third-party/mruby/tasks/toolchains/android.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/toolchains/android.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,216 +0,0 @@ -class MRuby::Toolchain::Android - DEFAULT_ARCH = 'armeabi' - DEFAULT_PLATFORM = 'android-14' - DEFAULT_TOOLCHAIN = :gcc - DEFAULT_NDK_HOMES = %w{ - /usr/local/opt/android-ndk - } - TOOLCHAINS = [:gcc, :clang] - ARCHITECTURES = %w{ - armeabi armeabi-v7a arm64-v8a - mips mips64 - x86 x86_64 - } - - class AndroidNDKHomeNotFound < StandardError - def message - <<-EOM -Couldn't find Android NDK Home. -Set ANDROID_NDK_HOME environment variable or set :ndk_home parameter - EOM - end - end - - attr_reader :params - - def initialize(params) - @params = params - end - - def home_path - @home_path ||= Pathname( - params[:ndk_home] || - ENV['ANDROID_NDK_HOME'] || - DEFAULT_NDK_HOMES.find{ |path| File.directory?(path) } || - raise(AndroidNDKHomeNotFound) - ) - end - - def arch - params.fetch(:arch){ DEFAULT_ARCH } - end - - def platform - params.fetch(:platform){ DEFAULT_PLATFORM } - end - - def toolchain - params.fetch(:toolchain){ DEFAULT_TOOLCHAIN } - end - - def toolchain_version - params.fetch(:toolchain_version) do - test = case toolchain - when :gcc - case arch - when /armeabi/ - 'arm-linux-androideabi-*' - when /arm64/ - 'aarch64-linux-android-*' - when /mips64/ - 'mips64el-linux-android-*' - when /mips/ - 'mipsel-linux-android-*' - when /x86_64/ - 'x86_64-*' - when /x86/ - 'x86-*' - end - when :clang - 'llvm-*' - end - - Dir[home_path.join('toolchains',test)].map{|t| t.match(/-(\d+\.\d+)$/); $1.to_f }.max - end - end - - def toolchain_path - prefix = case toolchain - when :clang then 'llvm-' - when :gcc - case arch - when /armeabi/ then 'arm-linux-androideabi-' - when /arm64/ then 'aarch64-linux-android-' - when /x86_64/ then 'x86_64-' - when /x86/ then 'x86-' - when /mips64/ then 'mips64el-linux-android-' - when /mips/ then 'mipsel-linux-android-' - end - end - home_path.join('toolchains', prefix + toolchain_version.to_s, 'prebuilt', host_platform) - end - - def sysroot - path = case arch - when /armeabi/ then 'arch-arm' - when /arm64/ then 'arch-arm64' - when /x86_64/ then 'arch-x86_64' - when /x86/ then 'arch-x86' - when /mips64/ then 'arch-mips64' - when /mips/ then 'arch-mips' - end - - home_path.join('platforms', platform, path).to_s - end - - def bin(command) - command = command.to_s - - if toolchain == :gcc - command = case arch - when /armeabi/ then 'arm-linux-androideabi-' - when /arm64/ then 'aarch64-linux-android-' - when /x86_64/ then 'x86_64-linux-android-' - when /x86/ then 'i686-linux-android-' - when /mips64/ then 'mips64el-linux-android-' - when /mips/ then 'mipsel-linux-android-' - end + command - end - - toolchain_path.join('bin',command).to_s - end - - def cc - case toolchain - when :gcc then bin(:gcc) - when :clang then bin(:clang) - end - end - - def cflags - flags = [] - - case toolchain - when :gcc - flags += %W(-ffunction-sections -funwind-tables -no-canonical-prefixes) - flags += %W(-D__android__ -mandroid --sysroot="#{sysroot}") - case arch - when /arm64/ - flags += %W(-fpic -fstack-protector-strong) - when 'armeabi-v7a-hard' - flags += %W(-fpic -fstack-protector-strong -march=armv7-a -mhard-float -D_NDK_MATH_NO_SOFTFP=1 -mfpu=vfpv3-d16) - when 'armeabi-v7a' - flags += %W(-fpic -fstack-protector-strong -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16) - when /arm/ - flags += %W(-fpic -fstack-protector-strong -march=armv5te -mtune=xscale -msoft-float) - when /mips/ - flags += %W(-fpic -fno-strict-aliasing -finline-functions -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers) - when /x86/ - flags += %W(-fstack-protector-strong) - end - when :clang - end - - flags - end - - def ld - cc - end - - def ldflags - flags = [] - case toolchain - when :gcc - flags += %W(-no-canonical-prefixes) - flags += %W(-D__android__ -mandroid --sysroot="#{sysroot}") - case arch - when 'armeabi-v7a-hard' - flags += %W(-march=armv7-a -Wl,--fix-cortex-a8 -Wl,--no-warn-mismatch -lm_hard) - when 'armeabi-v7a' - flags += %W(-march=armv7-a -Wl,--fix-cortex-a8) - end - end - - flags - end - - def ar - case toolchain - when :gcc then bin(:ar) - when :clang then bin('llvm-ar') - end - end - - def host_platform - case RUBY_PLATFORM - when /cygwin|mswin|mingw|bccwin|wince|emx/i - 'windows' - when /x86_64-darwin/i - 'darwin-x86_64' - when /darwin/i - 'darwin-x86' - when /x86_64-linux/i - 'linux-x86_64' - when /linux/i - 'linux-x86' - else - raise NotImplementedError, "Unknown host platform (#{RUBY_PLATFORM})" - end - end -end - -MRuby::Toolchain.new(:android) do |conf, params| - ndk = MRuby::Toolchain::Android.new(params) - - toolchain ndk.toolchain - - [conf.cc, conf.cxx, conf.objc, conf.asm].each do |cc| - cc.command = ndk.cc - cc.flags = ndk.cflags - end - conf.linker.command = ndk.ld - conf.linker.flags = ndk.ldflags - conf.archiver.command = ndk.ar -end - diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/toolchains/clang.rake nghttp2-0.6.7/third-party/mruby/tasks/toolchains/clang.rake --- nghttp2-1.13.0/third-party/mruby/tasks/toolchains/clang.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/toolchains/clang.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -MRuby::Toolchain.new(:clang) do |conf| - toolchain :gcc - - [conf.cc, conf.objc, conf.asm].each do |cc| - cc.command = ENV['CC'] || 'clang' - end - conf.cxx.command = ENV['CXX'] || 'clang++' - conf.linker.command = ENV['LD'] || 'clang' -end diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/toolchains/gcc.rake nghttp2-0.6.7/third-party/mruby/tasks/toolchains/gcc.rake --- nghttp2-1.13.0/third-party/mruby/tasks/toolchains/gcc.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/toolchains/gcc.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -MRuby::Toolchain.new(:gcc) do |conf| - [conf.cc, conf.objc, conf.asm].each do |cc| - cc.command = ENV['CC'] || 'gcc' - cc.flags = [ENV['CFLAGS'] || %w(-g -std=gnu99 -O3 -Wall -Werror-implicit-function-declaration -Wdeclaration-after-statement -Wwrite-strings)] - cc.defines = %w(DISABLE_GEMS) - cc.option_include_path = '-I%s' - cc.option_define = '-D%s' - cc.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}' - end - - [conf.cxx].each do |cxx| - cxx.command = ENV['CXX'] || 'g++' - cxx.flags = [ENV['CXXFLAGS'] || ENV['CFLAGS'] || %w(-g -O3 -Wall -Werror-implicit-function-declaration)] - cxx.defines = %w(DISABLE_GEMS) - cxx.option_include_path = '-I%s' - cxx.option_define = '-D%s' - cxx.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}' - end - - conf.linker do |linker| - linker.command = ENV['LD'] || 'gcc' - linker.flags = [ENV['LDFLAGS'] || %w()] - linker.libraries = %w(m) - linker.library_paths = [] - linker.option_library = '-l%s' - linker.option_library_path = '-L%s' - linker.link_options = '%{flags} -o %{outfile} %{objs} %{flags_before_libraries} %{libs} %{flags_after_libraries}' - end - - [[conf.cc, 'c'], [conf.cxx, 'c++']].each do |cc, lang| - cc.instance_variable_set :@header_search_language, lang - def cc.header_search_paths - if @header_search_command != command - result = `echo | #{build.filename command} -x#{@header_search_language} -Wp,-v - -fsyntax-only 2>&1` - result = `echo | #{command} -x#{@header_search_language} -Wp,-v - -fsyntax-only 2>&1` if $?.exitstatus != 0 - return include_paths if $?.exitstatus != 0 - - @frameworks = [] - @header_search_paths = result.lines.map { |v| - framework = v.match(/^ (.*)(?: \(framework directory\))$/) - if framework - @frameworks << framework[1] - next nil - end - - v.match(/^ (.*)$/) - }.compact.map { |v| v[1] }.select { |v| File.directory? v } - @header_search_paths += include_paths - @header_search_command = command - end - @header_search_paths - end - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/tasks/toolchains/visualcpp.rake nghttp2-0.6.7/third-party/mruby/tasks/toolchains/visualcpp.rake --- nghttp2-1.13.0/third-party/mruby/tasks/toolchains/visualcpp.rake 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/tasks/toolchains/visualcpp.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -MRuby::Toolchain.new(:visualcpp) do |conf| - [conf.cc].each do |cc| - cc.command = ENV['CC'] || 'cl.exe' - # C4013: implicit function declaration - cc.flags = [ENV['CFLAGS'] || %w(/c /nologo /W3 /we4013 /Zi /MD /O2 /D_CRT_SECURE_NO_WARNINGS)] - cc.defines = %w(DISABLE_GEMS MRB_STACK_EXTEND_DOUBLING) - cc.option_include_path = '/I%s' - cc.option_define = '/D%s' - cc.compile_options = "%{flags} /Fo%{outfile} %{infile}" - end - - [conf.cxx].each do |cxx| - cxx.command = ENV['CXX'] || 'cl.exe' - cxx.flags = [ENV['CXXFLAGS'] || ENV['CFLAGS'] || %w(/c /nologo /W3 /Zi /MD /O2 /EHs /D_CRT_SECURE_NO_WARNINGS)] - cxx.defines = %w(DISABLE_GEMS MRB_STACK_EXTEND_DOUBLING) - cxx.option_include_path = '/I%s' - cxx.option_define = '/D%s' - cxx.compile_options = "%{flags} /Fo%{outfile} %{infile}" - end - - conf.linker do |linker| - linker.command = ENV['LD'] || 'link.exe' - linker.flags = [ENV['LDFLAGS'] || %w(/NOLOGO /DEBUG /INCREMENTAL:NO /OPT:ICF /OPT:REF)] - linker.libraries = %w() - linker.library_paths = %w() - linker.option_library = '%s.lib' - linker.option_library_path = '/LIBPATH:%s' - linker.link_options = "%{flags} /OUT:%{outfile} %{objs} %{flags_before_libraries} %{libs} %{flags_after_libraries}" - end - - conf.archiver do |archiver| - archiver.command = ENV['AR'] || 'lib.exe' - archiver.archive_options = '/nologo /OUT:%{outfile} %{objs}' - end - - conf.yacc do |yacc| - yacc.command = ENV['YACC'] || 'bison.exe' - yacc.compile_options = '-o %{outfile} %{infile}' - end - - conf.gperf do |gperf| - gperf.command = 'gperf.exe' - gperf.compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}' - end - - conf.exts do |exts| - exts.object = '.obj' - exts.executable = '.exe' - exts.library = '.lib' - end - - conf.file_separator = '\\' -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/assert.rb nghttp2-0.6.7/third-party/mruby/test/assert.rb --- nghttp2-1.13.0/third-party/mruby/test/assert.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/assert.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,260 +0,0 @@ -$ok_test = 0 -$ko_test = 0 -$kill_test = 0 -$asserts = [] -$test_start = Time.now if Object.const_defined?(:Time) - -# Implementation of print due to the reason that there might be no print -def t_print(*args) - i = 0 - len = args.size - while i < len - str = args[i].to_s - begin - __printstr__ str - rescue NoMethodError - __t_printstr__ str rescue print str - end - i += 1 - end -end - -## -# Create the assertion in a readable way -def assertion_string(err, str, iso=nil, e=nil, bt=nil) - msg = "#{err}#{str}" - msg += " [#{iso}]" if iso && iso != '' - msg += " => #{e.message}" if e - msg += " (mrbgems: #{GEMNAME})" if Object.const_defined?(:GEMNAME) - if $mrbtest_assert && $mrbtest_assert.size > 0 - $mrbtest_assert.each do |idx, str, diff| - msg += "\n - Assertion[#{idx}] Failed: #{str}\n#{diff}" - end - end - msg += "\nbacktrace:\n\t#{bt.join("\n\t")}" if bt - msg -end - -## -# Verify a code block. -# -# str : A remark which will be printed in case -# this assertion fails -# iso : The ISO reference code of the feature -# which will be tested by this -# assertion -def assert(str = 'Assertion failed', iso = '') - t_print(str, (iso != '' ? " [#{iso}]" : ''), ' : ') if $mrbtest_verbose - begin - $mrbtest_assert = [] - $mrbtest_assert_idx = 0 - if(!yield || $mrbtest_assert.size > 0) - $asserts.push(assertion_string('Fail: ', str, iso, nil)) - $ko_test += 1 - t_print('F') - else - $ok_test += 1 - t_print('.') - end - rescue Exception => e - bt = e.backtrace if $mrbtest_verbose - if e.class.to_s == 'MRubyTestSkip' - $asserts.push "Skip: #{str} #{iso} #{e.cause}" - t_print('?') - else - $asserts.push(assertion_string("#{e.class}: ", str, iso, e, bt)) - $kill_test += 1 - t_print('X') - end - ensure - $mrbtest_assert = nil - end - t_print("\n") if $mrbtest_verbose -end - -def assertion_diff(exp, act) - " Expected: #{exp.inspect}\n" + - " Actual: #{act.inspect}" -end - -def assert_true(ret, msg = nil, diff = nil) - if $mrbtest_assert - $mrbtest_assert_idx += 1 - unless ret - msg = "Expected #{ret.inspect} to be true" unless msg - diff = assertion_diff(true, ret) unless diff - $mrbtest_assert.push([$mrbtest_assert_idx, msg, diff]) - end - end - ret -end - -def assert_false(ret, msg = nil, diff = nil) - if $mrbtest_assert - $mrbtest_assert_idx += 1 - if ret - msg = "Expected #{ret.inspect} to be false" unless msg - diff = assertion_diff(false, ret) unless diff - - $mrbtest_assert.push([$mrbtest_assert_idx, msg, diff]) - end - end - !ret -end - -def assert_equal(arg1, arg2 = nil, arg3 = nil) - if block_given? - exp, act, msg = arg1, yield, arg2 - else - exp, act, msg = arg1, arg2, arg3 - end - - msg = "Expected to be equal" unless msg - diff = assertion_diff(exp, act) - assert_true(exp == act, msg, diff) -end - -def assert_not_equal(arg1, arg2 = nil, arg3 = nil) - if block_given? - exp, act, msg = arg1, yield, arg2 - else - exp, act, msg = arg1, arg2, arg3 - end - - msg = "Expected to be not equal" unless msg - diff = assertion_diff(exp, act) - assert_false(exp == act, msg, diff) -end - -def assert_nil(obj, msg = nil) - msg = "Expected #{obj.inspect} to be nil" unless msg - diff = assertion_diff(nil, obj) - assert_true(obj.nil?, msg, diff) -end - -def assert_include(collection, obj, msg = nil) - msg = "Expected #{collection.inspect} to include #{obj.inspect}" unless msg - diff = " Collection: #{collection.inspect}\n" + - " Object: #{obj.inspect}" - assert_true(collection.include?(obj), msg, diff) -end - -def assert_not_include(collection, obj, msg = nil) - msg = "Expected #{collection.inspect} to not include #{obj.inspect}" unless msg - diff = " Collection: #{collection.inspect}\n" + - " Object: #{obj.inspect}" - assert_false(collection.include?(obj), msg, diff) -end - -def assert_raise(*exp) - ret = true - if $mrbtest_assert - $mrbtest_assert_idx += 1 - msg = exp.last.class == String ? exp.pop : nil - msg = msg.to_s + " : " if msg - should_raise = false - begin - yield - should_raise = true - rescue Exception => e - msg = "#{msg}#{exp.inspect} exception expected, not" - diff = " Class: <#{e.class}>\n" + - " Message: #{e.message}" - if not exp.any?{|ex| ex.instance_of?(Module) ? e.kind_of?(ex) : ex == e.class } - $mrbtest_assert.push([$mrbtest_assert_idx, msg, diff]) - ret = false - end - end - - exp = exp.first if exp.first - if should_raise - msg = "#{msg}#{exp.inspect} expected but nothing was raised." - $mrbtest_assert.push([$mrbtest_assert_idx, msg, nil]) - ret = false - end - end - ret -end - -def assert_nothing_raised(*exp) - ret = true - if $mrbtest_assert - $mrbtest_assert_idx += 1 - msg = exp.last.class == String ? exp.pop : "" - begin - yield - rescue Exception => e - msg = "#{msg} exception raised." - diff = " Class: <#{e.class}>\n" + - " Message: #{e.message}" - $mrbtest_assert.push([$mrbtest_assert_idx, msg, diff]) - ret = false - end - end - ret -end - -## -# Fails unless +obj+ is a kind of +cls+. -def assert_kind_of(cls, obj, msg = nil) - msg = "Expected #{obj.inspect} to be a kind of #{cls}, not #{obj.class}" unless msg - diff = assertion_diff(cls, obj.class) - assert_true(obj.kind_of?(cls), msg, diff) -end - -## -# Fails unless +exp+ is equal to +act+ in terms of a Float -def assert_float(exp, act, msg = nil) - msg = "Float #{exp} expected to be equal to float #{act}" unless msg - diff = assertion_diff(exp, act) - assert_true check_float(exp, act), msg, diff -end - -## -# Report the test result and print all assertions -# which were reported broken. -def report() - t_print("\n") - - $asserts.each do |msg| - puts msg - end - - $total_test = $ok_test+$ko_test+$kill_test - t_print("Total: #{$total_test}\n") - - t_print(" OK: #{$ok_test}\n") - t_print(" KO: #{$ko_test}\n") - t_print("Crash: #{$kill_test}\n") - - if Object.const_defined?(:Time) - t_time = Time.now - $test_start - t_print(" Time: #{t_time.round(2)} seconds\n") - end -end - -## -# Performs fuzzy check for equality on methods returning floats -def check_float(a, b) - tolerance = 1e-12 - a = a.to_f - b = b.to_f - if a.finite? and b.finite? - (a-b).abs < tolerance - else - true - end -end - -## -# Skip the test -class MRubyTestSkip < NotImplementedError - attr_accessor :cause - def initialize(cause) - @cause = cause - end -end - -def skip(cause = "") - raise MRubyTestSkip.new(cause) -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/bintest.rb nghttp2-0.6.7/third-party/mruby/test/bintest.rb --- nghttp2-1.13.0/third-party/mruby/test/bintest.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/bintest.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -$:.unshift File.dirname(File.dirname(File.expand_path(__FILE__))) -require 'test/assert.rb' - -def cmd(s) - case RbConfig::CONFIG['host_os'] - when /mswin(?!ce)|mingw|cygwin|bccwin/ - "bin\\#{s}.exe" - else - "bin/#{s}" - end -end - -def shellquote(s) - case RbConfig::CONFIG['host_os'] - when /mswin(?!ce)|mingw|cygwin|bccwin/ - "\"#{s}\"" - else - "'#{s}'" - end -end - -ARGV.each do |gem| - Dir["#{gem}/bintest/**/*.rb"].each do |file| - load file - end -end - -load 'test/report.rb' diff -Nru nghttp2-1.13.0/third-party/mruby/test/report.rb nghttp2-0.6.7/third-party/mruby/test/report.rb --- nghttp2-1.13.0/third-party/mruby/test/report.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/report.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -report -if $ko_test > 0 or $kill_test > 0 - raise "mrbtest failed (KO:#{$ko_test}, Crash:#{$kill_test})" -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/argumenterror.rb nghttp2-0.6.7/third-party/mruby/test/t/argumenterror.rb --- nghttp2-1.13.0/third-party/mruby/test/t/argumenterror.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/argumenterror.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -## -# ArgumentError ISO Test - -assert('ArgumentError', '15.2.24') do - e2 = nil - a = [] - begin - # this will cause an exception due to the wrong arguments - a[] - rescue => e1 - e2 = e1 - end - - assert_equal(Class, ArgumentError.class) - assert_equal(ArgumentError, e2.class) -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/array.rb nghttp2-0.6.7/third-party/mruby/test/t/array.rb --- nghttp2-1.13.0/third-party/mruby/test/t/array.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/array.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,349 +0,0 @@ -## -# Array ISO Test - -assert('Array', '15.2.12') do - assert_equal(Class, Array.class) -end - -assert('Array inclueded modules', '15.2.12.3') do - assert_true(Array.include?(Enumerable)) -end - -assert('Array.[]', '15.2.12.4.1') do - assert_equal([1, 2, 3], Array.[](1,2,3)) -end - -assert('Array#+', '15.2.12.5.1') do - assert_equal([1, 1], [1].+([1])) -end - -assert('Array#*', '15.2.12.5.2') do - assert_raise(ArgumentError) do - # this will cause an exception due to the wrong argument - [1].*(-1) - end - assert_equal([1, 1, 1], [1].*(3)) - assert_equal([], [1].*(0)) -end - -assert('Array#<<', '15.2.12.5.3') do - assert_equal([1, 1], [1].<<(1)) -end - -assert('Array#[]', '15.2.12.5.4') do - a = Array.new - assert_raise(ArgumentError) do - # this will cause an exception due to the wrong arguments - a.[]() - end - assert_raise(ArgumentError) do - # this will cause an exception due to the wrong arguments - a.[](1,2,3) - end - - assert_equal(2, [1,2,3].[](1)) - assert_equal(nil, [1,2,3].[](4)) - assert_equal(3, [1,2,3].[](-1)) - assert_equal(nil, [1,2,3].[](-4)) - - a = [ "a", "b", "c", "d", "e" ] - assert_equal("b", a[1.1]) - assert_equal(["b", "c"], a[1,2]) - assert_equal(["b", "c", "d"], a[1..-2]) -end - -assert('Array#[]=', '15.2.12.5.5') do - a = Array.new - assert_raise(ArgumentError) do - # this will cause an exception due to the wrong arguments - a.[]=() - end - assert_raise(ArgumentError) do - # this will cause an exception due to the wrong arguments - a.[]=(1,2,3,4) - end - assert_raise(IndexError) do - # this will cause an exception due to the wrong arguments - a = [1,2,3,4,5] - a[1, -1] = 10 - end - - assert_equal(4, [1,2,3].[]=(1,4)) - assert_equal(3, [1,2,3].[]=(1,2,3)) - - a = [1,2,3,4,5] - a[3..-1] = 6 - assert_equal([1,2,3,6], a) - - a = [1,2,3,4,5] - a[3..-1] = [] - assert_equal([1,2,3], a) - - a = [1,2,3,4,5] - a[2...4] = 6 - assert_equal([1,2,6,5], a) -end - -assert('Array#clear', '15.2.12.5.6') do - a = [1] - a.clear - assert_equal([], a) -end - -assert('Array#collect!', '15.2.12.5.7') do - a = [1,2,3] - a.collect! { |i| i + i } - assert_equal([2,4,6], a) -end - -assert('Array#concat', '15.2.12.5.8') do - assert_equal([1,2,3,4], [1, 2].concat([3, 4])) -end - -assert('Array#delete_at', '15.2.12.5.9') do - a = [1,2,3] - assert_equal(2, a.delete_at(1)) - assert_equal([1,3], a) - assert_equal(nil, a.delete_at(3)) - assert_equal([1,3], a) - assert_equal(nil, a.delete_at(-3)) - assert_equal([1,3], a) - assert_equal(3, a.delete_at(-1)) - assert_equal([1], a) -end - -assert('Array#each', '15.2.12.5.10') do - a = [1,2,3] - b = 0 - a.each {|i| b += i} - assert_equal(6, b) -end - -assert('Array#each_index', '15.2.12.5.11') do - a = [1] - b = nil - a.each_index {|i| b = i} - assert_equal(0, b) -end - -assert('Array#empty?', '15.2.12.5.12') do - a = [] - b = [b] - assert_true([].empty?) - assert_false([1].empty?) -end - -assert('Array#first', '15.2.12.5.13') do - assert_raise(ArgumentError) do - # this will cause an exception due to the wrong argument - [1,2,3].first(-1) - end - assert_raise(ArgumentError) do - # this will cause an exception due to the wrong argument - [1,2,3].first(1,2) - end - - assert_nil([].first) - - b = [1,2,3] - assert_equal(1, b.first) - assert_equal([], b.first(0)) - assert_equal([1], b.first(1)) - assert_equal([1,2,3], b.first(4)) -end - -assert('Array#index', '15.2.12.5.14') do - a = [1,2,3] - - assert_equal(1, a.index(2)) - assert_equal(nil, a.index(0)) -end - -assert('Array#initialize', '15.2.12.5.15') do - a = [].initialize(1) - b = [].initialize(2) - c = [].initialize(2, 1) - d = [].initialize(2) {|i| i} - - assert_equal([nil], a) - assert_equal([nil,nil], b) - assert_equal([1,1], c) - assert_equal([0,1], d) -end - -assert('Array#initialize_copy', '15.2.12.5.16') do - a = [1,2,3] - b = [].initialize_copy(a) - - assert_equal([1,2,3], b) -end - -assert('Array#join', '15.2.12.5.17') do - a = [1,2,3].join - b = [1,2,3].join(',') - - assert_equal('123', a) - assert_equal('1,2,3', b) -end - -assert('Array#last', '15.2.12.5.18') do - assert_raise(ArgumentError) do - # this will cause an exception due to the wrong argument - [1,2,3].last(-1) - end - - a = [1,2,3] - assert_equal(3, a.last) - assert_nil([].last) -end - -assert('Array#length', '15.2.12.5.19') do - a = [1,2,3] - - assert_equal(3, a.length) -end - -assert('Array#map!', '15.2.12.5.20') do - a = [1,2,3] - a.map! { |i| i + i } - assert_equal([2,4,6], a) -end - -assert('Array#pop', '15.2.12.5.21') do - a = [1,2,3] - b = a.pop - - assert_nil([].pop) - assert_equal([1,2], a) - assert_equal(3, b) -end - -assert('Array#push', '15.2.12.5.22') do - a = [1,2,3] - b = a.push(4) - - assert_equal([1,2,3,4], a) - assert_equal([1,2,3,4], b) -end - -assert('Array#replace', '15.2.12.5.23') do - a = [1,2,3] - b = [].replace(a) - - assert_equal([1,2,3], b) -end - -assert('Array#reverse', '15.2.12.5.24') do - a = [1,2,3] - b = a.reverse - - assert_equal([1,2,3], a) - assert_equal([3,2,1], b) -end - -assert('Array#reverse!', '15.2.12.5.25') do - a = [1,2,3] - b = a.reverse! - - assert_equal([3,2,1], a) - assert_equal([3,2,1], b) -end - -assert('Array#rindex', '15.2.12.5.26') do - a = [1,2,3] - - assert_equal(1, a.rindex(2)) - assert_equal(nil, a.rindex(0)) -end - -assert('Array#shift', '15.2.12.5.27') do - a = [1,2,3] - b = a.shift - - assert_nil([].shift) - assert_equal([2,3], a) - assert_equal(1, b) -end - -assert('Array#size', '15.2.12.5.28') do - a = [1,2,3] - - assert_equal(3, a.size) -end - -assert('Array#slice', '15.2.12.5.29') do - a = "12345".slice(1, 3) - b = a.slice(0) - - assert_equal("2:", "#{b}:") - assert_equal(2, [1,2,3].[](1)) -end - -assert('Array#unshift', '15.2.12.5.30') do - a = [2,3] - b = a.unshift(1) - c = [2,3] - d = c.unshift(0, 1) - - assert_equal([1,2,3], a) - assert_equal([1,2,3], b) - assert_equal([0,1,2,3], c) - assert_equal([0,1,2,3], d) -end - -assert('Array#to_s', '15.2.12.5.31 / 15.2.12.5.32') do - a = [2, 3, 4, 5] - r1 = a.to_s - r2 = a.inspect - - assert_equal(r2, r1) - assert_equal("[2, 3, 4, 5]", r1) -end - -assert('Array#==', '15.2.12.5.33') do - assert_false(["a", "c"] == ["a", "c", 7]) - assert_true(["a", "c", 7] == ["a", "c", 7]) - assert_false(["a", "c", 7] == ["a", "d", "f"]) -end - -assert('Array#eql?', '15.2.12.5.34') do - a1 = [ 1, 2, 3 ] - a2 = [ 1, 2, 3 ] - a3 = [ 1.0, 2.0, 3.0 ] - - assert_true(a1.eql? a2) - assert_false(a1.eql? a3) -end - -assert('Array#hash', '15.2.12.5.35') do - a = [ 1, 2, 3 ] - - assert_true(a.hash.is_a? Integer) - assert_equal([1,2].hash, [1,2].hash) -end - -assert('Array#<=>', '15.2.12.5.36') do - r1 = [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1 - r2 = [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1 - r3 = [ "a", "b", "c" ] <=> [ "a", "b", "c" ] #=> 0 - - assert_equal(-1, r1) - assert_equal(+1, r2) - assert_equal(0, r3) -end - -# Not ISO specified - -assert("Array (Shared Array Corruption)") do - a = [ "a", "b", "c", "d", "e", "f" ] - b = a.slice(1, 3) - a.clear - b.clear -end - -assert("Array (Longish inline array)") do - ary = [[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7], [8, 8], [9, 9], [10, 10], [11, 11], [12, 12], [13, 13], [14, 14], [15, 15], [16, 16], [17, 17], [18, 18], [19, 19], [20, 20], [21, 21], [22, 22], [23, 23], [24, 24], [25, 25], [26, 26], [27, 27], [28, 28], [29, 29], [30, 30], [31, 31], [32, 32], [33, 33], [34, 34], [35, 35], [36, 36], [37, 37], [38, 38], [39, 39], [40, 40], [41, 41], [42, 42], [43, 43], [44, 44], [45, 45], [46, 46], [47, 47], [48, 48], [49, 49], [50, 50], [51, 51], [52, 52], [53, 53], [54, 54], [55, 55], [56, 56], [57, 57], [58, 58], [59, 59], [60, 60], [61, 61], [62, 62], [63, 63], [64, 64], [65, 65], [66, 66], [67, 67], [68, 68], [69, 69], [70, 70], [71, 71], [72, 72], [73, 73], [74, 74], [75, 75], [76, 76], [77, 77], [78, 78], [79, 79], [80, 80], [81, 81], [82, 82], [83, 83], [84, 84], [85, 85], [86, 86], [87, 87], [88, 88], [89, 89], [90, 90], [91, 91], [92, 92], [93, 93], [94, 94], [95, 95], [96, 96], [97, 97], [98, 98], [99, 99], [100, 100], [101, 101], [102, 102], [103, 103], [104, 104], [105, 105], [106, 106], [107, 107], [108, 108], [109, 109], [110, 110], [111, 111], [112, 112], [113, 113], [114, 114], [115, 115], [116, 116], [117, 117], [118, 118], [119, 119], [120, 120], [121, 121], [122, 122], [123, 123], [124, 124], [125, 125], [126, 126], [127, 127], [128, 128], [129, 129], [130, 130], [131, 131], [132, 132], [133, 133], [134, 134], [135, 135], [136, 136], [137, 137], [138, 138], [139, 139], [140, 140], [141, 141], [142, 142], [143, 143], [144, 144], [145, 145], [146, 146], [147, 147], [148, 148], [149, 149], [150, 150], [151, 151], [152, 152], [153, 153], [154, 154], [155, 155], [156, 156], [157, 157], [158, 158], [159, 159], [160, 160], [161, 161], [162, 162], [163, 163], [164, 164], [165, 165], [166, 166], [167, 167], [168, 168], [169, 169], [170, 170], [171, 171], [172, 172], [173, 173], [174, 174], [175, 175], [176, 176], [177, 177], [178, 178], [179, 179], [180, 180], [181, 181], [182, 182], [183, 183], [184, 184], [185, 185], [186, 186], [187, 187], [188, 188], [189, 189], [190, 190], [191, 191], [192, 192], [193, 193], [194, 194], [195, 195], [196, 196], [197, 197], [198, 198], [199, 199]] - h = Hash.new(0) - ary.each {|p| h[p.class] += 1} - assert_equal({Array=>200}, h) -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/basicobject.rb nghttp2-0.6.7/third-party/mruby/test/t/basicobject.rb --- nghttp2-1.13.0/third-party/mruby/test/t/basicobject.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/basicobject.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -## -# BasicObject - -assert('BasicObject') do - assert_equal(Class, BasicObject.class) -end - -assert('BasicObject superclass') do - assert_nil(BasicObject.superclass) -end - diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/bs_block.rb nghttp2-0.6.7/third-party/mruby/test/t/bs_block.rb --- nghttp2-1.13.0/third-party/mruby/test/t/bs_block.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/bs_block.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,521 +0,0 @@ -## -# Bootstrap tests for blocks - -assert('BS Block 1') do - assert_equal(1) do - 1.times{ - begin - a = 1 - ensure - foo = nil - end - } - end -end - -assert('BS Block 2') do - assert_equal 2, [1,2,3].find{|x| x == 2} -end - -assert('BS Block 3') do - class E - include Enumerable - def each(&block) - [1, 2, 3].each(&block) - end - end - assert_equal 2, E.new.find {|x| x == 2 } -end - -assert('BS Block 3') do - sum = 0 - for x in [1, 2, 3] - sum += x - end - assert_equal 6, sum -end - -assert('BS Block 4') do - sum = 0 - for x in (1..5) - sum += x - end - assert_equal 15, sum -end - -assert('BS Block 5') do - sum = 0 - for x in [] - sum += x - end - assert_equal 0, sum -end - -assert('BS Block 6') do - ans = [] - assert_equal(1) do - 1.times{ - for n in 1..3 - a = n - ans << a - end - } - end -end - -assert('BS Block 7') do - ans = [] - assert_equal((1..3)) do - for m in 1..3 - for n in 2..4 - a = [m, n] - ans << a - end - end - end -end - -assert('BS Block 8') do - assert_equal [1, 2, 3], (1..3).to_a -end - -assert('BS Block 9') do - assert_equal([4, 8, 12]) do - (1..3).map{|e| - e * 4 - } - end -end - -assert('BS Block 10') do - def m - yield - end - def n - yield - end - - assert_equal(100) do - m{ - n{ - 100 - } - } - end -end - -assert('BS Block 11') do - def m - yield 1 - end - - assert_equal(20) do - m{|ib| - m{|jb| - i = 20 - } - } - end -end - -assert('BS Block 12') do - def m - yield 1 - end - - assert_equal(2) do - m{|ib| - m{|jb| - ib = 20 - kb = 2 - } - } - end -end - -assert('BS Block 13') do - def iter1 - iter2{ - yield - } - end - - def iter2 - yield - end - - assert_equal(3) do - iter1{ - jb = 2 - iter1{ - jb = 3 - } - jb - } - end -end - -assert('BS Block 14') do - def iter1 - iter2{ - yield - } - end - - def iter2 - yield - end - - assert_equal(2) do - iter1{ - jb = 2 - iter1{ - jb - } - jb - } - end -end - -assert('BS Block 15') do - def m - yield 1 - end - assert_equal(2) do - m{|ib| - ib*2 - } - end -end - -assert('BS Block 16') do - def m - yield 12345, 67890 - end - assert_equal(92580) do - m{|ib,jb| - ib*2+jb - } - end -end - -assert('BS Block 17') do - def iter - yield 10 - end - - a = nil - assert_equal [10, nil] do - [iter{|a| - a - }, a] - end -end - -assert('BS Block 18') do - def iter - yield 10 - end - - assert_equal(21) do - iter{|a| - iter{|a| - a + 1 - } + a - } - end -end - -assert('BS Block 19') do - def iter - yield 10, 20, 30, 40 - end - - a = b = c = d = nil - assert_equal([10, 20, 30, 40, nil, nil, nil, nil]) do - iter{|a, b, c, d| - [a, b, c, d] - } + [a, b, c, d] - end -end - -assert('BS Block 20') do - def iter - yield 10, 20, 30, 40 - end - - a = b = nil - assert_equal([10, 20, 30, 40, nil, nil]) do - iter{|a, b, c, d| - [a, b, c, d] - } + [a, b] - end -end - -assert('BS Block 21') do - def iter - yield 1, 2 - end - - assert_equal([1, [2]]) do - iter{|a, *b| - [a, b] - } - end -end - -assert('BS Block 22') do - def iter - yield 1, 2 - end - - assert_equal([[1, 2]]) do - iter{|*a| - [a] - } - end -end - -assert('BS Block 23') do - def iter - yield 1, 2 - end - - assert_equal([1, 2, []]) do - iter{|a, b, *c| - [a, b, c] - } - end -end - -assert('BS Block 24') do - def m - yield - end - assert_equal(1) do - m{ - 1 - } - end -end - -assert('BS Block 25') do - def m - yield 123 - end - assert_equal(15129) do - m{|ib| - m{|jb| - ib*jb - } - } - end -end - -assert('BS Block 26') do - def m a - yield a - end - assert_equal(2) do - m(1){|ib| - m(2){|jb| - ib*jb - } - } - end -end - -assert('BS Block 27') do - sum = 0 - 3.times{|ib| - 2.times{|jb| - sum += ib + jb - }} - assert_equal sum, 9 -end - -assert('BS Block 28') do - assert_equal(10) do - 3.times{|bl| - break 10 - } - end -end - -assert('BS Block 29') do - def iter - yield 1,2,3 - end - - assert_equal([1, 2]) do - iter{|i, j| - [i, j] - } - end -end - -assert('BS Block 30') do - def iter - yield 1 - end - - assert_equal([1, nil]) do - iter{|i, j| - [i, j] - } - end -end - -assert('BS Block [ruby-dev:31147]') do - def m - yield - end - assert_nil m{|&b| b} -end - -assert('BS Block [ruby-dev:31160]') do - def m() - yield - end - assert_nil m {|(v,(*))|} -end - -assert('BS Block [issue #750]') do - def m(a, *b) - yield - end - args = [1, 2, 3] - assert_equal m(*args){ 1 }, 1 -end - -assert('BS Block 31') do - def m() - yield - end - assert_nil m {|((*))|} -end - -assert('BS Block [ruby-dev:31440]') do - def m - yield [0] - end - assert_equal m{|v, &b| v}, [0] -end - -assert('BS Block 32') do - r = false; 1.times{|&b| r = b} - assert_equal NilClass, r.class -end - -assert('BS Block [ruby-core:14395]') do - class Controller - def respond_to(&block) - responder = Responder.new - block.call(responder) - responder.respond - end - def test_for_bug - respond_to{|format| - format.js{ - "in test" - render{|obj| - obj - } - } - } - end - def render(&block) - "in render" - end - end - - class Responder - def method_missing(symbol, &block) - "enter method_missing" - @response = Proc.new{ - 'in method missing' - block.call - } - "leave method_missing" - end - def respond - @response.call - end - end - t = Controller.new - assert_true t.test_for_bug -end - -assert("BS Block 33") do - module TestReturnFromNestedBlock - def self.test - 1.times do - 1.times do - return :ok - end - end - :bad - end - end - assert_equal :ok, TestReturnFromNestedBlock.test -end - -assert("BS Block 34") do - module TestReturnFromNestedBlock_BSBlock34 - def self.test - 1.times do - while true - return :ok - end - end - :bad - end - end - assert_equal :ok, TestReturnFromNestedBlock_BSBlock34.test -end - -assert("BS Block 35") do - module TestReturnFromNestedBlock_BSBlock35 - def self.test - 1.times do - until false - return :ok - end - end - :bad - end - end - assert_equal :ok, TestReturnFromNestedBlock_BSBlock35.test -end - -assert('BS Block 36') do - def iter - yield 1, 2, 3, 4, 5 - end - - assert_equal([1, 2, [3, 4], 5]) do - iter{|a, b, *c, d| - [a, b, c, d] - } - end -end - -assert('BS Block 37') do - def iter - yield 1, 2, 3 - end - - assert_equal([1, 2, [], 3]) do - iter{|a, b, *c, d| - [a, b, c, d] - } - end -end - -assert('BS Block 38') do - def iter - yield 1,2,3,4,5,6 - end - - assert_equal [1,2,3,4,5], iter{|a,b,c=:c,d,e| [a,b,c,d,e]} -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/bs_literal.rb nghttp2-0.6.7/third-party/mruby/test/t/bs_literal.rb --- nghttp2-1.13.0/third-party/mruby/test/t/bs_literal.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/bs_literal.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -## -# Bootstrap test for literals - -assert('BS Literal 1') do - assert_true true -end - -assert('BS Literal 2') do - assert_equal TrueClass, true.class -end - -assert('BS Literal 3') do - assert_false false -end - -assert('BS Literal 4') do - assert_equal FalseClass, false.class -end - -assert('BS Literal 5') do - assert_equal 'nil', nil.inspect -end - -assert('BS Literal 6') do - assert_equal NilClass, nil.class -end - -assert('BS Literal 7') do - assert_equal Symbol, :sym.class -end - -assert('BS Literal 8') do - assert_equal 1234, 1234 -end - -assert('BS Literal 9') do - assert_equal Fixnum, 1234.class -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/class.rb nghttp2-0.6.7/third-party/mruby/test/t/class.rb --- nghttp2-1.13.0/third-party/mruby/test/t/class.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/class.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,390 +0,0 @@ -## -# Class ISO Test - -assert('Class', '15.2.3') do - assert_equal(Class, Class.class) -end - -assert('Class#initialize', '15.2.3.3.1') do - c = Class.new do - def test - :test - end - end.new - - assert_equal(c.test, :test) -end - -assert('Class#initialize_copy', '15.2.3.3.2') do - class TestClass - attr_accessor :n - def initialize(n) - @n = n - end - def initialize_copy(obj) - @n = n - end - end - - c1 = TestClass.new('Foo') - c2 = c1.dup - c3 = TestClass.new('Bar') - - assert_equal(c1.n, c2.n) - assert_not_equal(c1.n, c3.n) -end - -assert('Class#new', '15.2.3.3.3') do - assert_raise(TypeError, 'Singleton should raise TypeError') do - "a".singleton_class.new - end - - class TestClass - def initialize args, &block - @result = if not args.nil? and block.nil? - # only arguments - :only_args - elsif not args.nil? and not block.nil? - # args and block is given - :args_and_block - else - # this should never happen - :broken - end - end - - def result; @result; end - end - - assert_equal(:only_args, TestClass.new(:arg).result) - # with block doesn't work yet -end - -assert('Class#superclass', '15.2.3.3.4') do - class SubClass < String; end - assert_equal(String, SubClass.superclass) -end - -# Not ISO specified - -assert('Class 1') do - class C1; end - assert_equal(Class, C1.class) -end - -assert('Class 2') do - class C2; end - assert_equal(C2, C2.new.class) -end - -assert('Class 3') do - class C3; end - assert_equal(Class, C3.new.class.class) -end - -assert('Class 4') do - class C4_A; end - class C4 < C4_A; end - assert_equal(Class, C4.class) -end - -assert('Class 5') do - class C5_A; end - class C5 < C5_A; end - assert_equal(C5, C5.new.class) -end - -assert('Class 6') do - class C6_A; end - class C6 < C6_A; end - assert_equal(Class, C6.new.class.class) -end - -assert('Class 7') do - class C7_A; end - class C7_B; end - - class C7 < C7_A; end - - assert_raise(TypeError) do - # Different superclass. - class C7 < C7_B; end - end -end - -assert('Class 8') do - class C8_A; end - - class C8; end # superclass is Object - - assert_raise(TypeError) do - # Different superclass. - class C8 < C8_A; end - end -end - -assert('Class 9') do - Class9Const = "a" - - assert_raise(TypeError) do - class Class9Const; end - end -end - -assert('Class Module 1') do - module M; end - assert_equal(Module, M.class) -end - -assert('Class Module 2') do - module M; end - class C; include M; end - assert_equal(C, C.new.class) -end - -# nested class -assert('Class Nested 1') do - class A; end - class A::B; end - assert_equal(A::B, A::B) -end - -assert('Class Nested 2') do - class A; end - class A::B; end - assert_equal(A::B, A::B.new.class) -end - -assert('Class Nested 3') do - class A; end - class A::B; end - assert_equal(Class, A::B.new.class.class) -end - -assert('Class Nested 4') do - class A; end - class A::B; end - class A::B::C; end - assert_equal(A::B::C, A::B::C) -end - -assert('Class Nested 5') do - class A; end - class A::B; end - class A::B::C; end - assert_equal(Class, A::B::C.class) -end - -assert('Class Nested 6') do - class A; end - class A::B; end - class A::B::C; end - assert_equal(A::B::C, A::B::C.new.class) -end - -assert('Class Nested 7') do - class A; end - class A::B; end - class A::B2 < A::B; end - assert_equal(A::B2, A::B2) -end - -assert('Class Nested 8') do - class A; end - class A::B; end - class A::B2 < A::B; end - assert_equal(Class, A::B2.class) -end - -assert('Class Colon 1') do - class A; end - A::C = 1 - assert_equal(1, A::C) -end - -assert('Class Colon 2') do - class A; class ::C; end end - assert_equal(C, C) -end - -assert('Class Colon 3') do - class A; class ::C; end end - assert_equal(Class, C.class) -end - -assert('Class Dup 1') do - class C; end - assert_equal(Class, C.dup.class) -end - -assert('Class Dup 2') do - module M; end - assert_equal(Module, M.dup.class) -end - -assert('Class.new') do - assert_equal(Class, Class.new.class) - a = [] - klass = Class.new do |c| - a << c - end - assert_equal([klass], a) -end - -assert('class to return the last value') do - m = class C; :m end - assert_equal(m, :m) -end - -assert('raise when superclass is not a class') do - module FirstModule; end - assert_raise(TypeError, 'should raise TypeError') do - class FirstClass < FirstModule; end - end - - class SecondClass; end - assert_raise(TypeError, 'should raise TypeError') do - class SecondClass < false; end - end - - class ThirdClass; end - assert_raise(TypeError, 'should raise TypeError') do - class ThirdClass < ThirdClass; end - end -end - -assert('Class#inherited') do - class Foo - @@subclass_name = nil - def self.inherited(subclass) - @@subclass_name = subclass - end - def self.subclass_name - @@subclass_name - end - end - - assert_equal(nil, Foo.subclass_name) - - class Bar < Foo - end - - assert_equal(Bar, Foo.subclass_name) - - class Baz < Bar - end - - assert_equal(Baz, Foo.subclass_name) -end - -assert('singleton tests') do - module FooMod - def run_foo_mod - 100 - end - end - - bar = String.new - - baz = class << bar - extend FooMod - def self.run_baz - 200 - end - end - - assert_false baz.singleton_methods.include? :run_foo_mod - assert_false baz.singleton_methods.include? :run_baz - - assert_raise(NoMethodError, 'should raise NoMethodError') do - baz.run_foo_mod - end - assert_raise(NoMethodError, 'should raise NoMethodError') do - baz.run_baz - end - - assert_raise(NoMethodError, 'should raise NoMethodError') do - bar.run_foo_mod - end - assert_raise(NoMethodError, 'should raise NoMethodError') do - bar.run_baz - end - - baz = class << bar - extend FooMod - def self.run_baz - 300 - end - self - end - - assert_true baz.singleton_methods.include? :run_baz - assert_true baz.singleton_methods.include? :run_foo_mod - assert_equal 100, baz.run_foo_mod - assert_equal 300, baz.run_baz - - assert_raise(NoMethodError, 'should raise NoMethodError') do - bar.run_foo_mod - end - assert_raise(NoMethodError, 'should raise NoMethodError') do - bar.run_baz - end - - fv = false - class << fv - def self.run_false - 5 - end - end - - nv = nil - class << nv - def self.run_nil - 6 - end - end - - tv = true - class << tv - def self.run_nil - 7 - end - end - - assert_raise(TypeError, 'should raise TypeError') do - num = 1.0 - class << num - def self.run_nil - 7 - end - end - end -end - -assert('clone Class') do - class Foo - def func - true - end - end - - Foo.clone.new.func -end - -assert('class variable and class << self style class method') do - class ClassVariableTest - @@class_variable = "value" - class << self - def class_variable - @@class_variable - end - end - end - - assert_equal("value", ClassVariableTest.class_variable) -end - -assert('class with non-class/module outer raises TypeError') do - assert_raise(TypeError) { class 0::C1; end } - assert_raise(TypeError) { class []::C2; end } -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/comparable.rb nghttp2-0.6.7/third-party/mruby/test/t/comparable.rb --- nghttp2-1.13.0/third-party/mruby/test/t/comparable.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/comparable.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ - -assert('Comparable#<', '15.3.3.2.1') do - class Foo - include Comparable - def <=>(x) - x - end - end - assert_false(Foo.new < 0) - assert_false(Foo.new < 1) - assert_true(Foo.new < -1) - assert_raise(ArgumentError){ Foo.new < nil } -end - -assert('Comparable#<=', '15.3.3.2.2') do - class Foo - include Comparable - def <=>(x) - x - end - end - assert_true(Foo.new <= 0) - assert_false(Foo.new <= 1) - assert_true(Foo.new <= -1) - assert_raise(ArgumentError){ Foo.new <= nil } -end - -assert('Comparable#==', '15.3.3.2.3') do - class Foo - include Comparable - def <=>(x) - 0 - end - end - - assert_true(Foo.new == Foo.new) -end - -assert('Comparable#>', '15.3.3.2.4') do - class Foo - include Comparable - def <=>(x) - x - end - end - assert_false(Foo.new > 0) - assert_true(Foo.new > 1) - assert_false(Foo.new > -1) - assert_raise(ArgumentError){ Foo.new > nil } -end - -assert('Comparable#>=', '15.3.3.2.5') do - class Foo - include Comparable - def <=>(x) - x - end - end - assert_true(Foo.new >= 0) - assert_true(Foo.new >= 1) - assert_false(Foo.new >= -1) - assert_raise(ArgumentError){ Foo.new >= nil } -end - -assert('Comparable#between?', '15.3.3.2.6') do - class Foo - include Comparable - def <=>(x) - x - end - end - - c = Foo.new - - assert_false(c.between?(-1, 1)) - assert_false(c.between?(-1, -1)) - assert_false(c.between?( 1, 1)) - assert_true(c.between?( 1, -1)) - assert_true(c.between?(0, 0)) -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/ensure.rb nghttp2-0.6.7/third-party/mruby/test/t/ensure.rb --- nghttp2-1.13.0/third-party/mruby/test/t/ensure.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/ensure.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -## -# ensure Test - -assert('ensure - context - yield') do - class EnsureYieldBreak - attr_reader :ensure_context - def try - yield - ensure - @ensure_context = self - end - end - - yielder = EnsureYieldBreak.new - yielder.try do - end - assert_equal yielder, yielder.ensure_context -end - -assert('ensure - context - yield and break') do - class EnsureYieldBreak - attr_reader :ensure_context - def try - yield - ensure - @ensure_context = self - end - end - - yielder = EnsureYieldBreak.new - yielder.try do - break - end - assert_equal yielder, yielder.ensure_context -end - -assert('ensure - context - yield and return') do - class EnsureYieldBreak - attr_reader :ensure_context - def try - yield - ensure - @ensure_context = self - end - end - - yielder = EnsureYieldBreak.new - lambda do - yielder.try do - return - end - end.call - assert_equal yielder, yielder.ensure_context -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/enumerable.rb nghttp2-0.6.7/third-party/mruby/test/t/enumerable.rb --- nghttp2-1.13.0/third-party/mruby/test/t/enumerable.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/enumerable.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -## -# Enumerable ISO Test - -assert('Enumerable', '15.3.2') do - assert_equal(Module, Enumerable.class) -end - -assert('Enumerable#all?', '15.3.2.2.1') do - assert_true([1,2,3].all?) - assert_false([1,false,3].all?) - - a = [2,4,6] - all = a.all? do |e| - e % 2 == 0 - end - assert_true(all) - - a = [2,4,7] - all = a.all? do |e| - e % 2 == 0 - end - assert_false(all) -end - -assert('Enumerable#any?', '15.3.2.2.2') do - assert_true([false,true,false].any?) - assert_false([false,false,false].any?) - - a = [1,3,6] - any = a.any? do |e| - e % 2 == 0 - end - assert_true(any) - - a = [1,3,5] - any = a.any? do |e| - e % 2 == 0 - end - assert_false(any) -end - -assert('Enumerable#collect', '15.3.2.2.3') do - assert_true [1,2,3].collect { |i| i + i } == [2,4,6] -end - -assert('Enumerable#detect', '15.3.2.2.4') do - assert_equal 1, [1,2,3].detect() { true } - assert_equal 'a', [1,2,3].detect("a") { false } -end - -assert('Array#each_with_index', '15.3.2.2.5') do - a = nil - b = nil - - [1].each_with_index {|e,i| a = e; b = i} - - assert_equal(1, a) - assert_equal(0, b) -end - -assert('Enumerable#entries', '15.3.2.2.6') do - assert_equal([1], [1].entries) -end - -assert('Enumerable#find', '15.3.2.2.7') do - assert_equal 1, [1,2,3].find() { true } - assert_equal 'a', [1,2,3].find("a") { false } -end - -assert('Enumerable#find_all', '15.3.2.2.8') do - assert_true [1,2,3,4,5,6,7,8,9].find_all() {|i| i%2 == 0}, [2,4,6,8] -end - -assert('Enumerable#grep', '15.3.2.2.9') do - assert_equal [4,5,6], [1,2,3,4,5,6,7,8,9].grep(4..6) -end - -assert('Enumerable#include?', '15.3.2.2.10') do - assert_true [1,2,3,4,5,6,7,8,9].include?(5) - assert_false [1,2,3,4,5,6,7,8,9].include?(0) -end - -assert('Enumerable#inject', '15.3.2.2.11') do - assert_equal 21, [1,2,3,4,5,6].inject() {|s, n| s + n} - assert_equal 22, [1,2,3,4,5,6].inject(1) {|s, n| s + n} -end - -assert('Enumerable#map', '15.3.2.2.12') do - assert_equal [2,4,6], [1,2,3].map { |i| i + i } -end - -assert('Enumerable#max', '15.3.2.2.13') do - a = ['aaa', 'bb', 'c'] - assert_equal 'c', a.max - assert_equal 'aaa', a.max {|i1,i2| i1.length <=> i2.length} -end - -assert('Enumerable#min', '15.3.2.2.14') do - a = ['aaa', 'bb', 'c'] - assert_equal 'aaa', a.min - assert_equal 'c', a.min {|i1,i2| i1.length <=> i2.length} -end - -assert('Enumerable#member?', '15.3.2.2.15') do - assert_true [1,2,3,4,5,6,7,8,9].member?(5) - assert_false [1,2,3,4,5,6,7,8,9].member?(0) -end - -assert('Enumerable#partition', '15.3.2.2.16') do - partition = [0,1,2,3,4,5,6,7,8,9].partition do |i| - i % 2 == 0 - end - assert_equal [[0,2,4,6,8], [1,3,5,7,9]], partition -end - -assert('Enumerable#reject', '15.3.2.2.17') do - reject = [0,1,2,3,4,5,6,7,8,9].reject do |i| - i % 2 == 0 - end - assert_equal [1,3,5,7,9], reject -end - -assert('Enumerable#select', '15.3.2.2.18') do - assert_equal [2,4,6,8], [1,2,3,4,5,6,7,8,9].select() {|i| i%2 == 0} -end - -assert('Enumerable#sort', '15.3.2.2.19') do - assert_equal [1,2,3,4,6,7], [7,3,1,2,6,4].sort - assert_equal [7,6,4,3,2,1], [7,3,1,2,6,4].sort {|e1,e2|e2<=>e1} -end - -assert('Enumerable#to_a', '15.3.2.2.20') do - assert_equal [1], [1].to_a -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/exception.rb nghttp2-0.6.7/third-party/mruby/test/t/exception.rb --- nghttp2-1.13.0/third-party/mruby/test/t/exception.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/exception.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,384 +0,0 @@ -## -# Exception ISO Test - -assert('Exception', '15.2.22') do - assert_equal Class, Exception.class -end - -assert('Exception.exception', '15.2.22.4.1') do - e = Exception.exception('a') - - assert_equal Exception, e.class -end - -assert('Exception#exception', '15.2.22.5.1') do - e = Exception.new - re = RuntimeError.new - assert_equal e, e.exception - assert_equal e, e.exception(e) - assert_equal re, re.exception(re) - changed_re = re.exception('message has changed') - assert_not_equal re, changed_re - assert_equal 'message has changed', changed_re.message -end - -assert('Exception#message', '15.2.22.5.2') do - e = Exception.exception('a') - - assert_equal 'a', e.message -end - -assert('Exception#to_s', '15.2.22.5.3') do - e = Exception.exception('a') - - assert_equal 'a', e.to_s -end - -assert('Exception.exception', '15.2.22.4.1') do - e = Exception.exception() - e.initialize('a') - - assert_equal 'a', e.message -end - -assert('NameError', '15.2.31') do - assert_raise(NameError) do - raise NameError.new - end - - e = NameError.new "msg", "name" - assert_equal "msg", e.message - assert_equal "name", e.name -end - -assert('ScriptError', '15.2.37') do - assert_raise(ScriptError) do - raise ScriptError.new - end -end - -assert('SyntaxError', '15.2.38') do - assert_raise(SyntaxError) do - raise SyntaxError.new - end -end - -# Not ISO specified - -assert('Exception 1') do -r=begin - 1+1 - ensure - 2+2 - end - assert_equal 2, r -end - -assert('Exception 2') do -r=begin - 1+1 - begin - 2+2 - ensure - 3+3 - end - ensure - 4+4 - end - assert_equal 4, r -end - -assert('Exception 3') do -r=begin - 1+1 - begin - 2+2 - ensure - 3+3 - end - ensure - 4+4 - begin - 5+5 - ensure - 6+6 - end - end - assert_equal 4, r -end - -assert('Exception 4') do - a = nil - 1.times{|e| - begin - rescue => err - end - a = err.class - } - assert_equal NilClass, a -end - -assert('Exception 5') do - $ans = [] - def m - $! - end - def m2 - 1.times{ - begin - return - ensure - $ans << m - end - } - end - m2 - assert_equal [nil], $ans -end - -assert('Exception 6') do - $i = 0 - def m - iter{ - begin - $i += 1 - begin - $i += 2 - break - ensure - - end - ensure - $i += 4 - end - $i = 0 - } - end - - def iter - yield - end - m - assert_equal 7, $i -end - -assert('Exception 7') do - $i = 0 - def m - begin - $i += 1 - begin - $i += 2 - return - ensure - $i += 3 - end - ensure - $i += 4 - end - p :end - end - m - assert_equal 10, $i -end - -assert('Exception 8') do -r=begin - 1 - rescue - 2 - else - 3 - end - assert_equal 3, r -end - -assert('Exception 9') do -r=begin - 1+1 - rescue - 2+2 - else - 3+3 - ensure - 4+4 - end - assert_equal 6, r -end - -assert('Exception 10') do -r=begin - 1+1 - begin - 2+2 - rescue - 3+3 - else - 4+4 - end - rescue - 5+5 - else - 6+6 - ensure - 7+7 - end - assert_equal 12, r -end - -assert('Exception 11') do - a = :ok - begin - begin - raise Exception - rescue - a = :ng - end - rescue Exception - end - assert_equal :ok, a -end - -assert('Exception 12') do - a = :ok - begin - raise Exception rescue a = :ng - rescue Exception - end - assert_equal :ok, a -end - -assert('Exception 13') do - a = :ng - begin - raise StandardError - rescue TypeError, ArgumentError - a = :ng - rescue - a = :ok - else - a = :ng - end - assert_equal :ok, a -end - -assert('Exception 14') do - def exception_test14; UnknownConstant; end - a = :ng - begin - send(:exception_test14) - rescue - a = :ok - end - - assert_equal :ok, a -end - -assert('Exception 15') do - a = begin - :ok - rescue - :ko - end - assert_equal :ok, a -end - -assert('Exception 16') do - begin - raise "foo" - false - rescue => e - assert_equal "foo", e.message - end -end - -assert('Exception 17') do -r=begin - raise "a" # RuntimeError - rescue ArgumentError - 1 - rescue StandardError - 2 - else - 3 - ensure - 4 - end - assert_equal 2, r -end - -assert('Exception 18') do -r=begin - 0 - rescue ArgumentError - 1 - rescue StandardError - 2 - else - 3 - ensure - 4 - end - assert_equal 3, r -end - -assert('Exception 19') do - class Class4Exception19 - def a - r = @e = false - begin - b - rescue TypeError - r = self.z - end - [ r, @e ] - end - - def b - begin - 1 * "b" - ensure - @e = self.z - end - end - - def z - true - end - end - assert_equal [true, true], Class4Exception19.new.a -end - -assert('Exception#inspect without message') do - assert_equal "Exception: Exception", Exception.new.inspect -end - -assert('Exception#backtrace') do - assert_nothing_raised do - begin - raise "get backtrace" - rescue => e - e.backtrace - end - end -end - -assert('Raise in ensure') do - assert_raise(ArgumentError) do - begin - raise "" # RuntimeError - ensure - raise ArgumentError - end - end -end - -assert('Raise in rescue') do - assert_raise(ArgumentError) do - begin - raise "" # RuntimeError - rescue - raise ArgumentError - end - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/false.rb nghttp2-0.6.7/third-party/mruby/test/t/false.rb --- nghttp2-1.13.0/third-party/mruby/test/t/false.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/false.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -## -# FalseClass ISO Test - -assert('FalseClass', '15.2.6') do - assert_equal Class, FalseClass.class -end - -assert('FalseClass false', '15.2.6.1') do - assert_false false - assert_equal FalseClass, false.class - assert_false FalseClass.method_defined? :new -end - -assert('FalseClass#&', '15.2.6.3.1') do - assert_false false.&(true) - assert_false false.&(false) -end - -assert('FalseClass#^', '15.2.6.3.2') do - assert_true false.^(true) - assert_false false.^(false) -end - -assert('FalseClass#to_s', '15.2.6.3.3') do - assert_equal 'false', false.to_s -end - -assert('FalseClass#|', '15.2.6.3.4') do - assert_true false.|(true) - assert_false false.|(false) -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/float.rb nghttp2-0.6.7/third-party/mruby/test/t/float.rb --- nghttp2-1.13.0/third-party/mruby/test/t/float.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/float.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,202 +0,0 @@ -## -# Float ISO Test - -assert('Float', '15.2.9') do - assert_equal Class, Float.class -end - -assert('Float#+', '15.2.9.3.1') do - a = 3.123456788 + 0.000000001 - b = 3.123456789 + 1 - - assert_float(3.123456789, a) - assert_float(4.123456789, b) - - assert_raise(TypeError){ 0.0+nil } - assert_raise(TypeError){ 1.0+nil } -end - -assert('Float#-', '15.2.9.3.2') do - a = 3.123456790 - 0.000000001 - b = 5.123456789 - 1 - - assert_float(3.123456789, a) - assert_float(4.123456789, b) -end - -assert('Float#*', '15.2.9.3.3') do - a = 3.125 * 3.125 - b = 3.125 * 1 - - assert_float(9.765625, a) - assert_float(3.125 , b) -end - -assert('Float#/', '15.2.9.3.4') do - a = 3.123456789 / 3.123456789 - b = 3.123456789 / 1 - - assert_float(1.0 , a) - assert_float(3.123456789, b) -end - -assert('Float#%', '15.2.9.3.5') do - a = 3.125 % 3.125 - b = 3.125 % 1 - - assert_float(0.0 , a) - assert_float(0.125, b) -end - -assert('Float#<=>', '15.2.9.3.6') do - a = 3.125 <=> 3.123 - b = 3.125 <=> 3.125 - c = 3.125 <=> 3.126 - a2 = 3.125 <=> 3 - c2 = 3.125 <=> 4 - - assert_equal( 1, a) - assert_equal( 0, b) - assert_equal(-1, c) - assert_equal( 1, a2) - assert_equal(-1, c2) -end - -assert('Float#==', '15.2.9.3.7') do - assert_true 3.1 == 3.1 - assert_false 3.1 == 3.2 -end - -assert('Float#ceil', '15.2.9.3.8') do - a = 3.123456789.ceil - b = 3.0.ceil - c = -3.123456789.ceil - d = -3.0.ceil - - assert_equal( 4, a) - assert_equal( 3, b) - assert_equal(-3, c) - assert_equal(-3, d) -end - -assert('Float#finite?', '15.2.9.3.9') do - assert_true 3.123456789.finite? - assert_false (1.0 / 0.0).finite? -end - -assert('Float#floor', '15.2.9.3.10') do - a = 3.123456789.floor - b = 3.0.floor - c = -3.123456789.floor - d = -3.0.floor - - assert_equal( 3, a) - assert_equal( 3, b) - assert_equal(-4, c) - assert_equal(-3, d) -end - -assert('Float#infinite?', '15.2.9.3.11') do - a = 3.123456789.infinite? - b = (1.0 / 0.0).infinite? - c = (-1.0 / 0.0).infinite? - - assert_nil a - assert_equal( 1, b) - assert_equal(-1, c) -end - -assert('Float#round', '15.2.9.3.12') do - a = 3.123456789.round - b = 3.5.round - c = 3.4999.round - d = (-3.123456789).round - e = (-3.5).round - f = 12345.67.round(-1) - g = 3.423456789.round(0) - h = 3.423456789.round(1) - i = 3.423456789.round(3) - - assert_equal( 3, a) - assert_equal( 4, b) - assert_equal( 3, c) - assert_equal( -3, d) - assert_equal( -4, e) - assert_equal(12350, f) - assert_equal( 3, g) - assert_float( 3.4, h) - assert_float(3.423, i) - - assert_equal(42.0, 42.0.round(307)) - assert_equal(1.0e307, 1.0e307.round(2)) - - inf = 1.0/0.0 - assert_raise(FloatDomainError){ inf.round } - assert_raise(FloatDomainError){ inf.round(-1) } - assert_equal(inf, inf.round(1)) - nan = 0.0/0.0 - assert_raise(FloatDomainError){ nan.round } - assert_raise(FloatDomainError){ nan.round(-1) } - assert_true(nan.round(1).nan?) -end - -assert('Float#to_f', '15.2.9.3.13') do - a = 3.123456789 - - assert_float(a, a.to_f) -end - -assert('Float#to_i', '15.2.9.3.14') do - assert_equal(3, 3.123456789.to_i) -end - -assert('Float#truncate', '15.2.9.3.15') do - assert_equal( 3, 3.123456789.truncate) - assert_equal(-3, -3.1.truncate) -end - -assert('Float#divmod') do - def check_floats exp, act - assert_float exp[0], act[0] - assert_float exp[1], act[1] - end - - # Note: quotients are Float because mruby does not have Bignum. - check_floats [ 0, 0.0], 0.0.divmod(1) - check_floats [ 0, 1.1], 1.1.divmod(3) - check_floats [ 3, 0.2], 3.2.divmod(1) - check_floats [ 2, 6.3], 20.3.divmod(7) - check_floats [-1, 1.6], -3.4.divmod(5) - check_floats [-2, -0.5], 25.5.divmod(-13) - check_floats [ 1, -6.6], -13.6.divmod(-7) - check_floats [ 3, 0.2], 9.8.divmod(3.2) -end - -assert('Float#nan?') do - assert_true (0.0/0.0).nan? - assert_false 0.0.nan? - assert_false (1.0/0.0).nan? - assert_false (-1.0/0.0).nan? -end - -assert('Float#<<') do - # Left Shift by one - assert_equal 46, 23.0 << 1 - - # Left Shift by a negative is Right Shift - assert_equal 23, 46.0 << -1 -end - -assert('Float#>>') do - # Right Shift by one - assert_equal 23, 46.0 >> 1 - - # Right Shift by a negative is Left Shift - assert_equal 46, 23.0 >> -1 - - # Don't raise on large Right Shift - assert_equal 0, 23.0 >> 128 - - # Don't raise on large Right Shift - assert_equal(-1, -23.0 >> 128) -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/gc.rb nghttp2-0.6.7/third-party/mruby/test/t/gc.rb --- nghttp2-1.13.0/third-party/mruby/test/t/gc.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/gc.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -# Not ISO specified - -assert('GC.enable') do - assert_false GC.disable - assert_true GC.enable - assert_false GC.enable -end - -assert('GC.disable') do - begin - assert_false GC.disable - assert_true GC.disable - ensure - GC.enable - end -end - -assert('GC.interval_ratio=') do - origin = GC.interval_ratio - begin - assert_equal 150, (GC.interval_ratio = 150) - ensure - GC.interval_ratio = origin - end -end - -assert('GC.step_ratio=') do - origin = GC.step_ratio - begin - assert_equal 150, (GC.step_ratio = 150) - ensure - GC.step_ratio = origin - end -end - -assert('GC.generational_mode=') do - origin = GC.generational_mode - begin - assert_false (GC.generational_mode = false) - assert_true (GC.generational_mode = true) - assert_true (GC.generational_mode = true) - ensure - GC.generational_mode = origin - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/hash.rb nghttp2-0.6.7/third-party/mruby/test/t/hash.rb --- nghttp2-1.13.0/third-party/mruby/test/t/hash.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/hash.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,353 +0,0 @@ -## -# Hash ISO Test - -assert('Hash', '15.2.13') do - assert_equal Class, Hash.class -end - -assert('Hash#==', '15.2.13.4.1') do - assert_true({ 'abc' => 'abc' } == { 'abc' => 'abc' }) - assert_false({ 'abc' => 'abc' } == { 'cba' => 'cba' }) - assert_true({ :equal => 1 } == { :equal => 1.0 }) - assert_false({ :a => 1 } == true) -end - -assert('Hash#[]', '15.2.13.4.2') do - a = { 'abc' => 'abc' } - - assert_equal 'abc', a['abc'] -end - -assert('Hash#[]=', '15.2.13.4.3') do - a = Hash.new - a['abc'] = 'abc' - - assert_equal 'abc', a['abc'] -end - -assert('Hash#clear', '15.2.13.4.4') do - a = { 'abc' => 'abc' } - a.clear - - assert_equal({ }, a) -end - -assert('Hash#dup') do - a = { 'a' => 1 } - b = a.dup - a['a'] = 2 - assert_equal({'a' => 1}, b) -end - -assert('Hash#default', '15.2.13.4.5') do - a = Hash.new - b = Hash.new('abc') - c = Hash.new {|s,k| s[k] = k} - - assert_nil a.default - assert_equal 'abc', b.default - assert_nil c.default - assert_equal 'abc', c.default('abc') -end - -assert('Hash#default=', '15.2.13.4.6') do - a = { 'abc' => 'abc' } - a.default = 'cba' - - assert_equal 'abc', a['abc'] - assert_equal 'cba', a['notexist'] -end - -assert('Hash#default_proc', '15.2.13.4.7') do - a = Hash.new - b = Hash.new {|s,k| s[k] = k + k} - c = b[2] - d = b['cat'] - - assert_nil a.default_proc - assert_equal Proc, b.default_proc.class - assert_equal 4, c - assert_equal 'catcat', d -end - -assert('Hash#delete', '15.2.13.4.8') do - a = { 'abc' => 'abc' } - b = { 'abc' => 'abc' } - b_tmp_1 = false - b_tmp_2 = false - - a.delete('abc') - b.delete('abc') do |k| - b_tmp_1 = true - end - b.delete('abc') do |k| - b_tmp_2 = true - end - - assert_nil a.delete('cba') - assert_false a.has_key?('abc') - assert_false b_tmp_1 - assert_true b_tmp_2 -end - -assert('Hash#each', '15.2.13.4.9') do - a = { 'abc_key' => 'abc_value' } - key = nil - value = nil - - a.each do |k,v| - key = k - value = v - end - - assert_equal 'abc_key', key - assert_equal 'abc_value', value -end - -assert('Hash#each_key', '15.2.13.4.10') do - a = { 'abc_key' => 'abc_value' } - key = nil - - a.each_key do |k| - key = k - end - - assert_equal 'abc_key', key -end - -assert('Hash#each_value', '15.2.13.4.11') do - a = { 'abc_key' => 'abc_value' } - value = nil - - a.each_value do |v| - value = v - end - - assert_equal 'abc_value', value -end - -assert('Hash#empty?', '15.2.13.4.12') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new - - assert_false a.empty? - assert_true b.empty? -end - -assert('Hash#has_key?', '15.2.13.4.13') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new - - assert_true a.has_key?('abc_key') - assert_false b.has_key?('cba') -end - -assert('Hash#has_value?', '15.2.13.4.14') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new - - assert_true a.has_value?('abc_value') - assert_false b.has_value?('cba') -end - -assert('Hash#include?', '15.2.13.4.15') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new - - assert_true a.include?('abc_key') - assert_false b.include?('cba') -end - -assert('Hash#initialize', '15.2.13.4.16') do - # Testing initialize by new. - h = Hash.new - h2 = Hash.new(:not_found) - - assert_true h.is_a? Hash - assert_equal({ }, h) - assert_nil h["hello"] - assert_equal :not_found, h2["hello"] -end - -assert('Hash#initialize_copy', '15.2.13.4.17') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new.initialize_copy(a) - - assert_equal({ 'abc_key' => 'abc_value' }, b) -end - -assert('Hash#key?', '15.2.13.4.18') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new - - assert_true a.key?('abc_key') - assert_false b.key?('cba') -end - -assert('Hash#keys', '15.2.13.4.19') do - a = { 'abc_key' => 'abc_value' } - - assert_equal ['abc_key'], a.keys -end - -assert('Hash#length', '15.2.13.4.20') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new - - assert_equal 1, a.length - assert_equal 0, b.length -end - -assert('Hash#member?', '15.2.13.4.21') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new - - assert_true a.member?('abc_key') - assert_false b.member?('cba') -end - -assert('Hash#merge', '15.2.13.4.22') do - a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' } - b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' } - - result_1 = a.merge b - result_2 = a.merge(b) do |key, original, new| - original - end - - assert_equal({'abc_key' => 'abc_value', 'cba_key' => 'XXX', - 'xyz_key' => 'xyz_value' }, result_1) - assert_equal({'abc_key' => 'abc_value', 'cba_key' => 'cba_value', - 'xyz_key' => 'xyz_value' }, result_2) - - assert_raise(TypeError) do - { 'abc_key' => 'abc_value' }.merge "a" - end -end - -assert('Hash#replace', '15.2.13.4.23') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new.replace(a) - - assert_equal({ 'abc_key' => 'abc_value' }, b) - - a = Hash.new(42) - b = {} - b.replace(a) - assert_equal(42, b[1]) - - a = Hash.new{|h,x| x} - b.replace(a) - assert_equal(127, b[127]) -end - -assert('Hash#shift', '15.2.13.4.24') do - a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' } - b = a.shift - - assert_equal Array, b.class - assert_equal 2, b.size - assert_equal 1, a.size - - b = a.shift - - assert_equal Array, b.class - assert_equal 2, b.size - assert_equal 0, a.size -end - -assert('Hash#size', '15.2.13.4.25') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new - - assert_equal 1, a.size - assert_equal 0, b.size -end - -assert('Hash#store', '15.2.13.4.26') do - a = Hash.new - a.store('abc', 'abc') - - assert_equal 'abc', a['abc'] -end - -assert('Hash#value?', '15.2.13.4.27') do - a = { 'abc_key' => 'abc_value' } - b = Hash.new - - assert_true a.value?('abc_value') - assert_false b.value?('cba') -end - -assert('Hash#values', '15.2.13.4.28') do - a = { 'abc_key' => 'abc_value' } - - assert_equal ['abc_value'], a.values -end - -# Not ISO specified - -assert('Hash#eql?') do - a = { 'a' => 1, 'b' => 2, 'c' => 3 } - b = { 'a' => 1, 'b' => 2, 'c' => 3 } - c = { 'a' => 1.0, 'b' => 2, 'c' => 3 } - assert_true(a.eql?(b)) - assert_false(a.eql?(c)) - assert_false(a.eql?(true)) -end - -assert('Hash#reject') do - h = {:one => 1, :two => 2, :three => 3, :four => 4} - ret = h.reject do |k,v| - v % 2 == 0 - end - assert_equal({:one => 1, :three => 3}, ret) - assert_equal({:one => 1, :two => 2, :three => 3, :four => 4}, h) -end - -assert('Hash#reject!') do - h = {:one => 1, :two => 2, :three => 3, :four => 4} - ret = h.reject! do |k,v| - v % 2 == 0 - end - assert_equal({:one => 1, :three => 3}, ret) - assert_equal({:one => 1, :three => 3}, h) -end - -assert('Hash#select') do - h = {:one => 1, :two => 2, :three => 3, :four => 4} - ret = h.select do |k,v| - v % 2 == 0 - end - assert_equal({:two => 2, :four => 4}, ret) - assert_equal({:one => 1, :two => 2, :three => 3, :four => 4}, h) -end - -assert('Hash#select!') do - h = {:one => 1, :two => 2, :three => 3, :four => 4} - ret = h.select! do |k,v| - v % 2 == 0 - end - assert_equal({:two => 2, :four => 4}, ret) - assert_equal({:two => 2, :four => 4}, h) -end - -# Not ISO specified - -assert('Hash#inspect') do - h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 } - ret = h.to_s - - assert_include ret, '"c"=>300' - assert_include ret, '"a"=>100' - assert_include ret, '"d"=>400' -end - -assert('Hash#rehash') do - h = {[:a] => "b"} - # hash key modified - h.keys[0][0] = :b - # h[[:b]] => nil - h.rehash - assert_equal("b", h[[:b]]) -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/indexerror.rb nghttp2-0.6.7/third-party/mruby/test/t/indexerror.rb --- nghttp2-1.13.0/third-party/mruby/test/t/indexerror.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/indexerror.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -## -# IndexError ISO Test - -assert('IndexError', '15.2.33') do - assert_equal Class, IndexError.class -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/integer.rb nghttp2-0.6.7/third-party/mruby/test/t/integer.rb --- nghttp2-1.13.0/third-party/mruby/test/t/integer.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/integer.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,262 +0,0 @@ -## -# Integer ISO Test - -assert('Integer', '15.2.8') do - assert_equal Class, Integer.class -end - -assert('Integer#+', '15.2.8.3.1') do - a = 1+1 - b = 1+1.0 - - assert_equal 2, a - assert_equal 2.0, b - - assert_raise(TypeError){ 0+nil } - assert_raise(TypeError){ 1+nil } - - c = Mrbtest::FIXNUM_MAX + 1 - d = Mrbtest::FIXNUM_MAX.__send__(:+, 1) - e = Mrbtest::FIXNUM_MAX + 1.0 - assert_equal Float, c.class - assert_equal Float, d.class - assert_float e, c - assert_float e, d -end - -assert('Integer#-', '15.2.8.3.2') do - a = 2-1 - b = 2-1.0 - - assert_equal 1, a - assert_equal 1.0, b - - c = Mrbtest::FIXNUM_MIN - 1 - d = Mrbtest::FIXNUM_MIN.__send__(:-, 1) - e = Mrbtest::FIXNUM_MIN - 1.0 - assert_equal Float, c.class - assert_equal Float, d.class - assert_float e, c - assert_float e, d -end - -assert('Integer#*', '15.2.8.3.3') do - a = 1*1 - b = 1*1.0 - - assert_equal 1, a - assert_equal 1.0, b - - assert_raise(TypeError){ 0*nil } - assert_raise(TypeError){ 1*nil } - - c = Mrbtest::FIXNUM_MAX * 2 - d = Mrbtest::FIXNUM_MAX.__send__(:*, 2) - e = Mrbtest::FIXNUM_MAX * 2.0 - assert_equal Float, c.class - assert_equal Float, d.class - assert_float e, c - assert_float e, d -end - -assert('Integer#/', '15.2.8.3.4') do - a = 2/1 - b = 2/1.0 - - assert_equal 2, a - assert_equal 2.0, b -end - -assert('Integer#%', '15.2.8.3.5') do - a = 1%1 - b = 1%1.0 - c = 2%4 - d = 2%5 - e = 2%-5 - f = -2%5 - g = -2%-5 - h = 2%-2 - i = -2%2 - j = -2%-2 - - assert_equal 0, a - assert_equal 0.0, b - assert_equal 2, c - assert_equal 2, d - assert_equal(-3, e) - assert_equal 3, f - assert_equal(-2, g) - assert_equal 0, h - assert_equal 0, i - assert_equal 0, j -end - -assert('Integer#<=>', '15.2.9.3.6') do - a = 1<=>0 - b = 1<=>1 - c = 1<=>2 - - assert_equal 1, a - assert_equal 0, b - assert_equal(-1, c) -end - -assert('Integer#==', '15.2.8.3.7') do - a = 1==0 - b = 1==1 - - assert_false a - assert_true b -end - -assert('Integer#~', '15.2.8.3.8') do - # Complement - assert_equal(-1, ~0) - assert_equal(-3, ~2) -end - -assert('Integer#&', '15.2.8.3.9') do - # Bitwise AND - # 0101 (5) - # & 0011 (3) - # = 0001 (1) - assert_equal 1, 5 & 3 -end - -assert('Integer#|', '15.2.8.3.10') do - # Bitwise OR - # 0101 (5) - # | 0011 (3) - # = 0111 (7) - assert_equal 7, 5 | 3 -end - -assert('Integer#^', '15.2.8.3.11') do - # Bitwise XOR - # 0101 (5) - # ^ 0011 (3) - # = 0110 (6) - assert_equal 6, 5 ^ 3 -end - -assert('Integer#<<', '15.2.8.3.12') do - # Left Shift by one - # 00010111 (23) - # = 00101110 (46) - assert_equal 46, 23 << 1 - - # Left Shift by a negative is Right Shift - assert_equal 23, 46 << -1 -end - -assert('Integer#>>', '15.2.8.3.13') do - # Right Shift by one - # 00101110 (46) - # = 00010111 (23) - assert_equal 23, 46 >> 1 - - # Right Shift by a negative is Left Shift - assert_equal 46, 23 >> -1 - - # Don't raise on large Right Shift - assert_equal 0, 23 >> 128 -end - -assert('Integer#ceil', '15.2.8.3.14') do - assert_equal 10, 10.ceil -end - -assert('Integer#downto', '15.2.8.3.15') do - a = 0 - 3.downto(1) do |i| - a += i - end - assert_equal 6, a -end - -assert('Integer#eql?', '15.2.8.3.16') do - a = 1.eql?(1) - b = 1.eql?(2) - c = 1.eql?(nil) - - assert_true a - assert_false b - assert_false c -end - -assert('Integer#floor', '15.2.8.3.17') do - a = 1.floor - - assert_equal 1, a -end - -assert('Integer#next', '15.2.8.3.19') do - assert_equal 2, 1.next -end - -assert('Integer#round', '15.2.8.3.20') do - assert_equal 1, 1.round -end - -assert('Integer#succ', '15.2.8.3.21') do - assert_equal 2, 1.succ -end - -assert('Integer#times', '15.2.8.3.22') do - a = 0 - 3.times do - a += 1 - end - assert_equal 3, a -end - -assert('Integer#to_f', '15.2.8.3.23') do - assert_equal 1.0, 1.to_f -end - -assert('Integer#to_i', '15.2.8.3.24') do - assert_equal 1, 1.to_i -end - -assert('Integer#to_s', '15.2.8.3.25') do - assert_equal '1', 1.to_s - assert_equal("-1", -1.to_s) -end - -assert('Integer#truncate', '15.2.8.3.26') do - assert_equal 1, 1.truncate -end - -assert('Integer#upto', '15.2.8.3.27') do - a = 0 - 1.upto(3) do |i| - a += i - end - assert_equal 6, a -end - -assert('Integer#divmod', '15.2.8.3.30') do - assert_equal [ 0, 0], 0.divmod(1) - assert_equal [ 0, 1], 1.divmod(3) - assert_equal [ 3, 0], 3.divmod(1) - assert_equal [ 2, 6], 20.divmod(7) - assert_equal [-1, 2], -3.divmod(5) - assert_equal [-2, -1], 25.divmod(-13) - assert_equal [ 1, -6], -13.divmod(-7) -end - -# Not ISO specified - -assert('Integer#step') do - a = [] - b = [] - 1.step(3) do |i| - a << i - end - 1.step(6, 2) do |i| - b << i - end - - assert_equal [1, 2, 3], a - assert_equal [1, 3, 5], b -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/kernel.rb nghttp2-0.6.7/third-party/mruby/test/t/kernel.rb --- nghttp2-1.13.0/third-party/mruby/test/t/kernel.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/kernel.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,590 +0,0 @@ -## -# Kernel ISO Test - -assert('Kernel', '15.3.1') do - assert_equal Module, Kernel.class -end - -assert('Kernel.block_given?', '15.3.1.2.2') do - def bg_try(&b) - if Kernel.block_given? - yield - else - "no block" - end - end - - assert_false Kernel.block_given? - # test without block - assert_equal "no block", bg_try - # test with block - assert_equal "block" do - bg_try { "block" } - end - # test with block - assert_equal "block" do - bg_try do - "block" - end - end -end - -# Kernel.eval is provided by the mruby-gem mrbgem. '15.3.1.2.3' - -assert('Kernel.global_variables', '15.3.1.2.4') do - assert_equal Array, Kernel.global_variables.class -end - -assert('Kernel.iterator?', '15.3.1.2.5') do - assert_false Kernel.iterator? -end - -assert('Kernel.lambda', '15.3.1.2.6') do - l = Kernel.lambda do - true - end - - m = Kernel.lambda(&l) - - assert_true l.call - assert_equal Proc, l.class - assert_true m.call - assert_equal Proc, m.class -end - -# Not implemented at the moment -#assert('Kernel.local_variables', '15.3.1.2.7') do -# Kernel.local_variables.class == Array -#end - -assert('Kernel.loop', '15.3.1.2.8') do - i = 0 - - Kernel.loop do - i += 1 - break if i == 100 - end - - assert_equal 100, i -end - -assert('Kernel.p', '15.3.1.2.9') do - # TODO search for a way to test p to stdio - assert_true true -end - -assert('Kernel.print', '15.3.1.2.10') do - # TODO search for a way to test print to stdio - assert_true true -end - -assert('Kernel.puts', '15.3.1.2.11') do - # TODO search for a way to test puts to stdio - assert_true true -end - -assert('Kernel.raise', '15.3.1.2.12') do - assert_raise RuntimeError do - Kernel.raise - end - - assert_raise RuntimeError do - Kernel.raise RuntimeError.new - end -end - -assert('Kernel#__id__', '15.3.1.3.3') do - assert_equal Fixnum, __id__.class -end - -assert('Kernel#__send__', '15.3.1.3.4') do - # test with block - l = __send__(:lambda) do - true - end - - assert_true l.call - assert_equal Proc, l.class - # test with argument - assert_true __send__(:respond_to?, :nil?) - # test without argument and without block - assert_equal Array, __send__(:public_methods).class -end - -assert('Kernel#block_given?', '15.3.1.3.6') do - def bg_try(&b) - if block_given? - yield - else - "no block" - end - end - - assert_false block_given? - assert_equal "no block", bg_try - assert_equal "block" do - bg_try { "block" } - end - assert_equal "block" do - bg_try do - "block" - end - end -end - -assert('Kernel#class', '15.3.1.3.7') do - assert_equal Module, Kernel.class -end - -assert('Kernel#clone', '15.3.1.3.8') do - class KernelCloneTest - def initialize - @v = 0 - end - - def get - @v - end - - def set(v) - @v = v - end - end - - a = KernelCloneTest.new - a.set(1) - b = a.clone - - def a.test - end - a.set(2) - c = a.clone - - immutables = [ 1, :foo, true, false, nil ] - error_count = 0 - immutables.each do |i| - begin - i.clone - rescue TypeError - error_count += 1 - end - end - - assert_equal 2, a.get - assert_equal 1, b.get - assert_equal 2, c.get - assert_true a.respond_to?(:test) - assert_false b.respond_to?(:test) - assert_true c.respond_to?(:test) -end - -assert('Kernel#dup', '15.3.1.3.9') do - class KernelDupTest - def initialize - @v = 0 - end - - def get - @v - end - - def set(v) - @v = v - end - end - - a = KernelDupTest.new - a.set(1) - b = a.dup - - def a.test - end - a.set(2) - c = a.dup - - immutables = [ 1, :foo, true, false, nil ] - error_count = 0 - immutables.each do |i| - begin - i.dup - rescue TypeError - error_count += 1 - end - end - - assert_equal immutables.size, error_count - assert_equal 2, a.get - assert_equal 1, b.get - assert_equal 2, c.get - assert_true a.respond_to?(:test) - assert_false b.respond_to?(:test) - assert_false c.respond_to?(:test) -end - -# Kernel#eval is provided by mruby-eval mrbgem '15.3.1.3.12' - -assert('Kernel#extend', '15.3.1.3.13') do - class Test4ExtendClass - end - - module Test4ExtendModule - def test_method; end - end - - a = Test4ExtendClass.new - a.extend(Test4ExtendModule) - b = Test4ExtendClass.new - - assert_true a.respond_to?(:test_method) - assert_false b.respond_to?(:test_method) -end - -assert('Kernel#extend works on toplevel', '15.3.1.3.13') do - module Test4ExtendModule - def test_method; end - end - # This would crash... - extend(Test4ExtendModule) - - assert_true respond_to?(:test_method) -end - -assert('Kernel#global_variables', '15.3.1.3.14') do - assert_equal Array, global_variables.class -end - -assert('Kernel#hash', '15.3.1.3.15') do - assert_equal hash, hash -end - -assert('Kernel#inspect', '15.3.1.3.17') do - s = inspect - - assert_equal String, s.class - assert_equal "main", s -end - -assert('Kernel#instance_variable_defined?', '15.3.1.3.20') do - o = Object.new - o.instance_variable_set(:@a, 1) - - assert_true o.instance_variable_defined?("@a") - assert_false o.instance_variable_defined?("@b") - assert_true o.instance_variable_defined?("@a"[0,2]) - assert_true o.instance_variable_defined?("@abc"[0,2]) -end - -assert('Kernel#instance_variables', '15.3.1.3.23') do - o = Object.new - o.instance_eval do - @a = 11 - @b = 12 - end - ivars = o.instance_variables - - assert_equal Array, ivars.class, - assert_equal(2, ivars.size) - assert_true ivars.include?(:@a) - assert_true ivars.include?(:@b) -end - -assert('Kernel#is_a?', '15.3.1.3.24') do - assert_true is_a?(Kernel) - assert_false is_a?(Array) - - assert_raise TypeError do - 42.is_a?(42) - end -end - -assert('Kernel#iterator?', '15.3.1.3.25') do - assert_false iterator? -end - -assert('Kernel#kind_of?', '15.3.1.3.26') do - assert_true kind_of?(Kernel) - assert_false kind_of?(Array) -end - -assert('Kernel#lambda', '15.3.1.3.27') do - l = lambda do - true - end - - m = lambda(&l) - - assert_true l.call - assert_equal Proc, l.class - assert_true m.call - assert_equal Proc, m.class -end - -# Not implemented yet -#assert('Kernel#local_variables', '15.3.1.3.28') do -# local_variables.class == Array -#end - -assert('Kernel#loop', '15.3.1.3.29') do - i = 0 - - loop do - i += 1 - break if i == 100 - end - - assert_equal i, 100 -end - -assert('Kernel#method_missing', '15.3.1.3.30') do - class MMTestClass - def method_missing(sym) - "A call to #{sym}" - end - end - mm_test = MMTestClass.new - assert_equal 'A call to no_method_named_this', mm_test.no_method_named_this - - a = String.new - begin - a.no_method_named_this - rescue NoMethodError => e - assert_equal "undefined method 'no_method_named_this' for \"\"", e.message - end - - class ShortInspectClass - def inspect - 'An inspect string' - end - end - b = ShortInspectClass.new - begin - b.no_method_named_this - rescue NoMethodError => e - assert_equal "undefined method 'no_method_named_this' for An inspect string", e.message - end - - class LongInspectClass - def inspect - "A" * 70 - end - end - c = LongInspectClass.new - begin - c.no_method_named_this - rescue NoMethodError => e - assert_equal "undefined method 'no_method_named_this' for #{c.to_s}", e.message - end - - class NoInspectClass - undef inspect - end - d = NoInspectClass.new - begin - d.no_method_named_this - rescue NoMethodError => e - assert_equal "undefined method 'no_method_named_this' for #{d.to_s}", e.message - end -end - -assert('Kernel#methods', '15.3.1.3.31') do - assert_equal Array, methods.class -end - -assert('Kernel#nil?', '15.3.1.3.32') do - assert_false nil? -end - -assert('Kernel#object_id', '15.3.1.3.33') do - a = "" - b = "" - assert_not_equal a.object_id, b.object_id - - assert_kind_of Numeric, object_id - assert_kind_of Numeric, "".object_id - assert_kind_of Numeric, true.object_id - assert_kind_of Numeric, false.object_id - assert_kind_of Numeric, nil.object_id - assert_kind_of Numeric, :no.object_id - assert_kind_of Numeric, 1.object_id - assert_kind_of Numeric, 1.0.object_id -end - -# Kernel#p is defined in mruby-print mrbgem. '15.3.1.3.34' - -# Kernel#print is defined in mruby-print mrbgem. '15.3.1.3.35' - -assert('Kernel#private_methods', '15.3.1.3.36') do - assert_equal Array, private_methods.class -end - -assert('Kernel#protected_methods', '15.3.1.3.37') do - assert_equal Array, protected_methods.class -end - -assert('Kernel#public_methods', '15.3.1.3.38') do - assert_equal Array, public_methods.class -end - -# Kernel#puts is defined in mruby-print mrbgem. '15.3.1.3.39' - -assert('Kernel#raise', '15.3.1.3.40') do - assert_raise RuntimeError do - raise - end - - assert_raise RuntimeError do - raise RuntimeError.new - end -end - -assert('Kernel#remove_instance_variable', '15.3.1.3.41') do - class Test4RemoveInstanceVar - attr_reader :var - def initialize - @var = 99 - end - def remove - remove_instance_variable(:@var) - end - end - - tri = Test4RemoveInstanceVar.new - assert_equal 99, tri.var - tri.remove - assert_equal nil, tri.var - assert_raise NameError do - tri.remove - end -end - -# Kernel#require is defined in mruby-require. '15.3.1.3.42' - -assert('Kernel#respond_to?', '15.3.1.3.43') do - class Test4RespondTo - def valid_method; end - - def test_method; end - undef test_method - end - - assert_raise TypeError do - Test4RespondTo.new.respond_to?(1) - end - - assert_raise ArgumentError do - Test4RespondTo.new.respond_to? - end - - assert_raise ArgumentError do - Test4RespondTo.new.respond_to? :a, true, :aa - end - - assert_true respond_to?(:nil?) - assert_true Test4RespondTo.new.respond_to?(:valid_method) - assert_true Test4RespondTo.new.respond_to?('valid_method') - assert_false Test4RespondTo.new.respond_to?(:test_method) -end - -assert('Kernel#send', '15.3.1.3.44') do - # test with block - l = send(:lambda) do - true - end - - assert_true l.call - assert_equal l.class, Proc - # test with argument - assert_true send(:respond_to?, :nil?) - # test without argument and without block - assert_equal send(:public_methods).class, Array -end - -assert('Kernel#singleton_methods', '15.3.1.3.45') do - assert_equal singleton_methods.class, Array -end - -assert('Kernel#to_s', '15.3.1.3.46') do - assert_equal to_s.class, String -end - -assert('Kernel.local_variables', '15.3.1.2.7') do - a, b = 0, 1 - a += b - - vars = Kernel.local_variables.sort - assert_equal [:a, :b, :vars], vars - - Proc.new { - c = 2 - vars = Kernel.local_variables.sort - assert_equal [:a, :b, :c, :vars], vars - }.call -end - -assert('Kernel#!=') do - str1 = "hello" - str2 = str1 - str3 = "world" - - assert_false (str1[1] != 'e') - assert_true (str1 != str3) - assert_false (str2 != str1) -end - -# operator "!~" is defined in ISO Ruby 11.4.4. -assert('Kernel#!~') do - x = "x" - def x.=~(other) - other == "x" - end - assert_false x !~ "x" - assert_true x !~ "z" - - y = "y" - def y.=~(other) - other == "y" - end - def y.!~(other) - other == "not y" - end - assert_false y !~ "y" - assert_false y !~ "z" - assert_true y !~ "not y" -end - -assert('Kernel#respond_to_missing?') do - class Test4RespondToMissing - def respond_to_missing?(method_name, include_private = false) - method_name == :a_method - end - end - - assert_true Test4RespondToMissing.new.respond_to?(:a_method) - assert_false Test4RespondToMissing.new.respond_to?(:no_method) -end - -assert('Kernel#global_variables') do - variables = global_variables - 1.upto(9) do |i| - assert_equal variables.include?(:"$#{i}"), true - end -end - -assert('Kernel#define_singleton_method') do - o = Object.new - ret = o.define_singleton_method(:test_method) do - :singleton_method_ok - end - assert_equal :test_method, ret - assert_equal :singleton_method_ok, o.test_method -end - -assert('stack extend') do - def recurse(count, stop) - return count if count > stop - recurse(count+1, stop) - end - - assert_equal 6, recurse(0, 5) -end - diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/literals.rb nghttp2-0.6.7/third-party/mruby/test/t/literals.rb --- nghttp2-1.13.0/third-party/mruby/test/t/literals.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/literals.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,337 +0,0 @@ -## -# Literals ISO Test - -assert('Literals Numerical', '8.7.6.2') do - # signed and unsigned integer - assert_equal 1, 1 - assert_equal(-1, -1) - assert_equal(+1, +1) - # signed and unsigned float - assert_equal 1.0, 1.0 - assert_equal(-1.0, -1.0) - # binary - assert_equal 128, 0b10000000 - assert_equal 128, 0B10000000 - # octal - assert_equal 8, 0o10 - assert_equal 8, 0O10 - assert_equal 8, 0_10 - # hex - assert_equal 255, 0xff - assert_equal 255, 0Xff - # decimal - assert_equal 999, 0d999 - assert_equal 999, 0D999 - # decimal seperator - assert_equal 10000000, 10_000_000 - assert_equal 10, 1_0 - # integer with exponent - assert_equal 10.0, 1e1, - assert_equal(0.1, 1e-1) - assert_equal 10.0, 1e+1 - # float with exponent - assert_equal 10.0, 1.0e1 - assert_equal(0.1, 1.0e-1) - assert_equal 10.0, 1.0e+1 -end - -assert('Literals Strings Single Quoted', '8.7.6.3.2') do - assert_equal 'abc', 'abc' - assert_equal '\'', '\'' - assert_equal '\\', '\\' -end - -assert('Literals Strings Double Quoted', '8.7.6.3.3') do - a = "abc" - - assert_equal "abc", "abc" - assert_equal "\"", "\"" - assert_equal "\\", "\\" - assert_equal "abc", "#{a}" -end - -assert('Literals Strings Quoted Non-Expanded', '8.7.6.3.4') do - a = %q{abc} - b = %q(abc) - c = %q[abc] - d = %q - e = %q/abc/ - f = %q/ab\/c/ - g = %q{#{a}} - - assert_equal 'abc', a - assert_equal 'abc', b - assert_equal 'abc', c - assert_equal 'abc', d - assert_equal 'abc', e - assert_equal 'ab/c', f - assert_equal '#{a}', g -end - -assert('Literals Strings Quoted Expanded', '8.7.6.3.5') do - a = %Q{abc} - b = %Q(abc) - c = %Q[abc] - d = %Q - e = %Q/abc/ - f = %Q/ab\/c/ - g = %Q{#{a}} - - assert_equal 'abc', a - assert_equal 'abc', b - assert_equal 'abc', c - assert_equal 'abc', d - assert_equal 'abc', e - assert_equal 'ab/c', f - assert_equal 'abc', g -end - -assert('Literals Strings Here documents', '8.7.6.3.6') do - a = <\"mm3\\n\"}y\nmm1\n", "mm2\n"], m - assert_equal ({:x=>"mm3\n"}), m2 - assert_equal [1, "nn1\n", 3, 4], n - assert_equal "a $ q\n $ c $ d", q1 - assert_equal "l $ mqq\nn $ o", q2 - assert_equal ["1", "www\n", "3", "4", "5"], w - assert_equal [1, "foo 222 333\n 444\n5\n bar\n6\n", 9], x - assert_equal "", z - -end - - -assert('Literals Array', '8.7.6.4') do - a = %W{abc#{1+2}def \}g} - b = %W(abc #{2+3} def \(g) - c = %W[#{3+4}] - d = %W< #{4+5} > - e = %W// - f = %W[[ab cd][ef]] - g = %W{ - ab - #{-1}1 - 2#{2} - } - h = %W(a\nb - test\ abc - c\ -d - x\y x\\y x\\\y) - - assert_equal ['abc3def', '}g'], a - assert_equal ['abc', '5', 'def', '(g'], b - assert_equal ['7'],c - assert_equal ['9'], d - assert_equal [], e - assert_equal ['[ab', 'cd][ef]'], f - assert_equal ['ab', '-11', '22'], g - assert_equal ["a\nb", 'test abc', "c\nd", "xy", "x\\y", "x\\y"], h - - a = %w{abc#{1+2}def \}g} - b = %w(abc #{2+3} def \(g) - c = %w[#{3+4}] - d = %w< #{4+5} > - e = %w// - f = %w[[ab cd][ef]] - g = %w{ - ab - #{-1}1 - 2#{2} - } - h = %w(a\nb - test\ abc - c\ -d - x\y x\\y x\\\y) - - assert_equal ['abc#{1+2}def', '}g'], a - assert_equal ['abc', '#{2+3}', 'def', '(g'], b - assert_equal ['#{3+4}'], c - assert_equal ['#{4+5}'], d - assert_equal [], e - assert_equal ['[ab', 'cd][ef]'], f - assert_equal ['ab', '#{-1}1', '2#{2}'], g - assert_equal ["a\\nb", "test abc", "c\nd", "x\\y", "x\\y", "x\\\\y"], h -end - - -assert('Literals Array of symbols') do - a = %I{abc#{1+2}def \}g} - b = %I(abc #{2+3} def \(g) - c = %I[#{3+4}] - d = %I< #{4+5} > - e = %I// - f = %I[[ab cd][ef]] - g = %I{ - ab - #{-1}1 - 2#{2} - } - - assert_equal [:'abc3def', :'}g'], a - assert_equal [:'abc', :'5', :'def', :'(g'], b - assert_equal [:'7'],c - assert_equal [:'9'], d - assert_equal [], e - assert_equal [:'[ab', :'cd][ef]'], f - assert_equal [:'ab', :'-11', :'22'], g - - a = %i{abc#{1+2}def \}g} - b = %i(abc #{2+3} def \(g) - c = %i[#{3+4}] - d = %i< #{4+5} > - e = %i// - f = %i[[ab cd][ef]] - g = %i{ - ab - #{-1}1 - 2#{2} - } - - assert_equal [:'abc#{1+2}def', :'}g'], a - assert_equal [:'abc', :'#{2+3}', :'def', :'(g'], b - assert_equal [:'#{3+4}'], c - assert_equal [:'#{4+5}'], d - assert_equal [] ,e - assert_equal [:'[ab', :'cd][ef]'], f - assert_equal [:'ab', :'#{-1}1', :'2#{2}'], g -end - -assert('Literals Symbol', '8.7.6.6') do - # do not compile error - :$asd - :@asd - :@@asd - :asd= - :asd! - :asd? - :+ - :+@ - :if - :BEGIN - - a = :"asd qwe" - b = :'foo bar' - c = :"a#{1+2}b" - d = %s(asd) - e = %s( foo \)) - f = %s[asd \[ -qwe] - g = %s/foo#{1+2}bar/ - h = %s{{foo bar}} - - assert_equal :'asd qwe', a - assert_equal :"foo bar", b - assert_equal :a3b, c - assert_equal :asd, d - assert_equal :' foo )', e - assert_equal :"asd [\nqwe", f - assert_equal :'foo#{1+2}bar', g - assert_equal :'{foo bar}', h -end - -# Not Implemented ATM assert('Literals Regular expression', '8.7.6.5') do diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/localjumperror.rb nghttp2-0.6.7/third-party/mruby/test/t/localjumperror.rb --- nghttp2-1.13.0/third-party/mruby/test/t/localjumperror.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/localjumperror.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -## -# LocalJumpError ISO Test - -assert('LocalJumpError', '15.2.25') do - assert_equal Class, LocalJumpError.class -# assert_raise LocalJumpError do -# # this will cause an exception due to the wrong location -# retry -# end -end - -# TODO 15.2.25.2.1 LocalJumpError#exit_value -# TODO 15.2.25.2.2 LocalJumpError#reason diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/methods.rb nghttp2-0.6.7/third-party/mruby/test/t/methods.rb --- nghttp2-1.13.0/third-party/mruby/test/t/methods.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/methods.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ -## -# Chapter 13.3 "Methods" ISO Test - -assert('The alias statement', '13.3.6 a) 4)') do - # check aliasing in all possible ways - - def alias_test_method_original; true; end - - alias alias_test_method_a alias_test_method_original - alias :alias_test_method_b :alias_test_method_original - - assert_true(alias_test_method_original) - assert_true(alias_test_method_a) - assert_true(alias_test_method_b) -end - -assert('The alias statement (overwrite original)', '13.3.6 a) 4)') do - # check that an aliased method can be overwritten - # without side effect - - def alias_test_method_original; true; end - - alias alias_test_method_a alias_test_method_original - alias :alias_test_method_b :alias_test_method_original - - assert_true(alias_test_method_original) - - def alias_test_method_original; false; end - - assert_false(alias_test_method_original) - assert_true(alias_test_method_a) - assert_true(alias_test_method_b) -end - -assert('The alias statement', '13.3.6 a) 5)') do - # check that alias is raising NameError if - # non-existing method should be undefined - - assert_raise(NameError) do - alias new_name_a non_existing_method - end - - assert_raise(NameError) do - alias :new_name_b :non_existing_method - end -end - -assert('The undef statement', '13.3.7 a) 4)') do - # check that undef is undefining method - # based on the method name - - def existing_method_a; true; end - def existing_method_b; true; end - def existing_method_c; true; end - def existing_method_d; true; end - def existing_method_e; true; end - def existing_method_f; true; end - - # check that methods are defined - - assert_true(existing_method_a, 'Method should be defined') - assert_true(existing_method_b, 'Method should be defined') - assert_true(existing_method_c, 'Method should be defined') - assert_true(existing_method_d, 'Method should be defined') - assert_true(existing_method_e, 'Method should be defined') - assert_true(existing_method_f, 'Method should be defined') - - # undefine in all possible ways and check that method - # is undefined - - undef existing_method_a - assert_raise(NoMethodError) do - existing_method_a - end - - undef :existing_method_b - assert_raise(NoMethodError) do - existing_method_b - end - - undef existing_method_c, existing_method_d - assert_raise(NoMethodError) do - existing_method_c - end - assert_raise(NoMethodError) do - existing_method_d - end - - undef :existing_method_e, :existing_method_f - assert_raise(NoMethodError) do - existing_method_e - end - assert_raise(NoMethodError) do - existing_method_f - end -end - -assert('The undef statement (method undefined)', '13.3.7 a) 5)') do - # check that undef is raising NameError if - # non-existing method should be undefined - - assert_raise(NameError) do - undef non_existing_method - end - - assert_raise(NameError) do - undef :non_existing_method - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/module.rb nghttp2-0.6.7/third-party/mruby/test/t/module.rb --- nghttp2-1.13.0/third-party/mruby/test/t/module.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/module.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,839 +0,0 @@ -## -# Module ISO Test - -def labeled_module(name, &block) - Module.new do - singleton_class.class_eval do - define_method(:to_s) { name } - alias_method :inspect, :to_s - end - class_eval(&block) if block - end -end - -def labeled_class(name, supklass = Object, &block) - Class.new(supklass) do - singleton_class.class_eval do - define_method(:to_s) { name } - alias_method :inspect, :to_s - end - class_eval(&block) if block - end -end - -assert('Module', '15.2.2') do - assert_equal Class, Module.class -end - -# TODO not implemented ATM assert('Module.constants', '15.2.2.3.1') do - -# TODO not implemented ATM assert('Module.nesting', '15.2.2.3.2') do - -assert('Module#ancestors', '15.2.2.4.9') do - class Test4ModuleAncestors - end - sc = Test4ModuleAncestors.singleton_class - r = String.ancestors - - assert_equal Array, r.class - assert_true r.include?(String) - assert_true r.include?(Object) -end - -assert('Module#append_features', '15.2.2.4.10') do - module Test4AppendFeatures - def self.append_features(mod) - Test4AppendFeatures2.const_set(:Const4AppendFeatures2, mod) - end - end - module Test4AppendFeatures2 - include Test4AppendFeatures - end - - assert_equal Test4AppendFeatures2, Test4AppendFeatures2.const_get(:Const4AppendFeatures2) -end - -assert('Module#attr NameError') do - %w[ - foo? - @foo - @@foo - $foo - ].each do |name| - module NameTest; end - - assert_raise(NameError) do - NameTest.module_eval { attr_reader name.to_sym } - end - - assert_raise(NameError) do - NameTest.module_eval { attr_writer name.to_sym } - end - - assert_raise(NameError) do - NameTest.module_eval { attr name.to_sym } - end - - assert_raise(NameError) do - NameTest.module_eval { attr_accessor name.to_sym } - end - end - -end - -assert('Module#attr', '15.2.2.4.11') do - class AttrTest - class << self - attr :cattr - def cattr_val=(val) - @cattr = val - end - end - attr :iattr - def iattr_val=(val) - @iattr = val - end - end - - test = AttrTest.new - assert_true AttrTest.respond_to?(:cattr) - assert_true test.respond_to?(:iattr) - - assert_false AttrTest.respond_to?(:cattr=) - assert_false test.respond_to?(:iattr=) - - test.iattr_val = 'test' - assert_equal 'test', test.iattr - - AttrTest.cattr_val = 'test' - assert_equal 'test', AttrTest.cattr -end - -assert('Module#attr_accessor', '15.2.2.4.12') do - class AttrTestAccessor - class << self - attr_accessor :cattr - end - attr_accessor :iattr, 'iattr2' - end - - attr_instance = AttrTestAccessor.new - assert_true AttrTestAccessor.respond_to?(:cattr=) - assert_true attr_instance.respond_to?(:iattr=) - assert_true attr_instance.respond_to?(:iattr2=) - assert_true AttrTestAccessor.respond_to?(:cattr) - assert_true attr_instance.respond_to?(:iattr) - assert_true attr_instance.respond_to?(:iattr2) - - attr_instance.iattr = 'test' - assert_equal 'test', attr_instance.iattr - - AttrTestAccessor.cattr = 'test' - assert_equal 'test', AttrTestAccessor.cattr -end - -assert('Module#attr_reader', '15.2.2.4.13') do - class AttrTestReader - class << self - attr_reader :cattr - def cattr_val=(val) - @cattr = val - end - end - attr_reader :iattr, 'iattr2' - def iattr_val=(val) - @iattr = val - end - end - - attr_instance = AttrTestReader.new - assert_true AttrTestReader.respond_to?(:cattr) - assert_true attr_instance.respond_to?(:iattr) - assert_true attr_instance.respond_to?(:iattr2) - - assert_false AttrTestReader.respond_to?(:cattr=) - assert_false attr_instance.respond_to?(:iattr=) - assert_false attr_instance.respond_to?(:iattr2=) - - attr_instance.iattr_val = 'test' - assert_equal 'test', attr_instance.iattr - - AttrTestReader.cattr_val = 'test' - assert_equal 'test', AttrTestReader.cattr -end - -assert('Module#attr_writer', '15.2.2.4.14') do - class AttrTestWriter - class << self - attr_writer :cattr - def cattr_val - @cattr - end - end - attr_writer :iattr, 'iattr2' - def iattr_val - @iattr - end - end - - attr_instance = AttrTestWriter.new - assert_true AttrTestWriter.respond_to?(:cattr=) - assert_true attr_instance.respond_to?(:iattr=) - assert_true attr_instance.respond_to?(:iattr2=) - - assert_false AttrTestWriter.respond_to?(:cattr) - assert_false attr_instance.respond_to?(:iattr) - assert_false attr_instance.respond_to?(:iattr2) - - attr_instance.iattr = 'test' - assert_equal 'test', attr_instance.iattr_val - - AttrTestWriter.cattr = 'test' - assert_equal 'test', AttrTestWriter.cattr_val -end - -assert('Module#class_eval', '15.2.2.4.15') do - class Test4ClassEval - @a = 11 - @b = 12 - end - Test4ClassEval.class_eval do - def method1 - end - end - r = Test4ClassEval.instance_methods - - assert_equal 11, Test4ClassEval.class_eval{ @a } - assert_equal 12, Test4ClassEval.class_eval{ @b } - assert_equal Array, r.class - assert_true r.include?(:method1) -end - -assert('Module#class_variable_defined?', '15.2.2.4.16') do - class Test4ClassVariableDefined - @@cv = 99 - end - - assert_true Test4ClassVariableDefined.class_variable_defined?(:@@cv) - assert_false Test4ClassVariableDefined.class_variable_defined?(:@@noexisting) -end - -assert('Module#class_variable_get', '15.2.2.4.17') do - class Test4ClassVariableGet - @@cv = 99 - end - - assert_equal 99, Test4ClassVariableGet.class_variable_get(:@@cv) -end - -assert('Module#class_variable_set', '15.2.2.4.18') do - class Test4ClassVariableSet - @@foo = 100 - def foo - @@foo - end - end - - assert_true Test4ClassVariableSet.class_variable_set(:@@cv, 99) - assert_true Test4ClassVariableSet.class_variable_set(:@@foo, 101) - assert_true Test4ClassVariableSet.class_variables.include? :@@cv - assert_equal 99, Test4ClassVariableSet.class_variable_get(:@@cv) - assert_equal 101, Test4ClassVariableSet.new.foo -end - -assert('Module#class_variables', '15.2.2.4.19') do - class Test4ClassVariables1 - @@var1 = 1 - end - class Test4ClassVariables2 < Test4ClassVariables1 - @@var2 = 2 - end - - assert_equal [:@@var1], Test4ClassVariables1.class_variables - assert_equal [:@@var2, :@@var1], Test4ClassVariables2.class_variables -end - -assert('Module#const_defined?', '15.2.2.4.20') do - module Test4ConstDefined - Const4Test4ConstDefined = true - end - - assert_true Test4ConstDefined.const_defined?(:Const4Test4ConstDefined) - assert_false Test4ConstDefined.const_defined?(:NotExisting) -end - -assert('Module#const_get', '15.2.2.4.21') do - module Test4ConstGet - Const4Test4ConstGet = 42 - end - - assert_equal 42, Test4ConstGet.const_get(:Const4Test4ConstGet) -end - -assert('Module#const_missing', '15.2.2.4.22') do - module Test4ConstMissing - def self.const_missing(sym) - 42 # the answer to everything - end - end - - assert_equal 42, Test4ConstMissing.const_get(:ConstDoesntExist) -end - -assert('Module#const_get', '15.2.2.4.23') do - module Test4ConstSet - Const4Test4ConstSet = 42 - end - - assert_true Test4ConstSet.const_set(:Const4Test4ConstSet, 23) - assert_equal 23, Test4ConstSet.const_get(:Const4Test4ConstSet) -end - -assert('Module#constants', '15.2.2.4.24') do - $n = [] - module TestA - C = 1 - end - class TestB - include TestA - C2 = 1 - $n = constants.sort - end - - assert_equal [ :C ], TestA.constants - assert_equal [ :C, :C2 ], $n -end - -assert('Module#include', '15.2.2.4.27') do - module Test4Include - Const4Include = 42 - end - module Test4Include2 - include Test4Include - end - - assert_equal 42, Test4Include2.const_get(:Const4Include) -end - -assert('Module#include?', '15.2.2.4.28') do - module Test4IncludeP - end - class Test4IncludeP2 - include Test4IncludeP - end - class Test4IncludeP3 < Test4IncludeP2 - end - - assert_true Test4IncludeP2.include?(Test4IncludeP) - assert_true Test4IncludeP3.include?(Test4IncludeP) - assert_false Test4IncludeP.include?(Test4IncludeP) -end - -assert('Module#included', '15.2.2.4.29') do - module Test4Included - Const4Included = 42 - def self.included mod - Test4Included.const_set(:Const4Included2, mod) - end - end - module Test4Included2 - include Test4Included - end - - assert_equal 42, Test4Included2.const_get(:Const4Included) - assert_equal Test4Included2, Test4Included2.const_get(:Const4Included2) -end - -assert('Module#included_modules', '15.2.2.4.30') do - module Test4includedModules - end - module Test4includedModules2 - include Test4includedModules - end - r = Test4includedModules2.included_modules - - assert_equal Array, r.class - assert_true r.include?(Test4includedModules) -end - -assert('Module#initialize', '15.2.2.4.31') do - assert_kind_of Module, Module.new - mod = Module.new { def hello; "hello"; end } - assert_equal [:hello], mod.instance_methods - a = nil - mod = Module.new { |m| a = m } - assert_equal mod, a -end - -assert('Module#instance_methods', '15.2.2.4.33') do - module Test4InstanceMethodsA - def method1() end - end - class Test4InstanceMethodsB - def method2() end - end - class Test4InstanceMethodsC < Test4InstanceMethodsB - def method3() end - end - - r = Test4InstanceMethodsC.instance_methods(true) - - assert_equal [:method1], Test4InstanceMethodsA.instance_methods - assert_equal [:method2], Test4InstanceMethodsB.instance_methods(false) - assert_equal [:method3], Test4InstanceMethodsC.instance_methods(false) - assert_equal Array, r.class - assert_true r.include?(:method3) - assert_true r.include?(:method2) -end - -assert('Module#method_defined?', '15.2.2.4.34') do - module Test4MethodDefined - module A - def method1() end - end - - class B - def method2() end - end - - class C < B - include A - def method3() end - end - end - - assert_true Test4MethodDefined::A.method_defined? :method1 - assert_true Test4MethodDefined::C.method_defined? :method1 - assert_true Test4MethodDefined::C.method_defined? "method2" - assert_true Test4MethodDefined::C.method_defined? "method3" - assert_false Test4MethodDefined::C.method_defined? "method4" -end - - -assert('Module#module_eval', '15.2.2.4.35') do - module Test4ModuleEval - @a = 11 - @b = 12 - end - - assert_equal 11, Test4ModuleEval.module_eval{ @a } - assert_equal 12, Test4ModuleEval.module_eval{ @b } -end - -assert('Module#remove_class_variable', '15.2.2.4.39') do - class Test4RemoveClassVariable - @@cv = 99 - end - - assert_equal 99, Test4RemoveClassVariable.remove_class_variable(:@@cv) - assert_false Test4RemoveClassVariable.class_variables.include? :@@cv -end - -assert('Module#remove_const', '15.2.2.4.40') do - module Test4RemoveConst - ExistingConst = 23 - end - - result = Test4RemoveConst.module_eval { remove_const :ExistingConst } - - name_error = false - begin - Test4RemoveConst.module_eval { remove_const :NonExistingConst } - rescue NameError - name_error = true - end - - # Constant removed from Module - assert_false Test4RemoveConst.const_defined? :ExistingConst - # Return value of binding - assert_equal 23, result - # Name Error raised when Constant doesn't exist - assert_true name_error -end - -assert('Module#remove_method', '15.2.2.4.41') do - module Test4RemoveMethod - class Parent - def hello - end - end - - class Child < Parent - def hello - end - end - end - - assert_true Test4RemoveMethod::Child.class_eval{ remove_method :hello } - assert_true Test4RemoveMethod::Child.instance_methods.include? :hello - assert_false Test4RemoveMethod::Child.instance_methods(false).include? :hello -end - -assert('Module#undef_method', '15.2.2.4.42') do - module Test4UndefMethod - class Parent - def hello - end - end - - class Child < Parent - def hello - end - end - - class GrandChild < Child - end - end - Test4UndefMethod::Child.class_eval{ undef_method :hello } - - assert_true Test4UndefMethod::Parent.new.respond_to?(:hello) - assert_false Test4UndefMethod::Child.new.respond_to?(:hello) - assert_false Test4UndefMethod::GrandChild.new.respond_to?(:hello) - assert_false Test4UndefMethod::Child.instance_methods(false).include? :hello -end - -# Not ISO specified - -# @!group prepend - assert('Module#prepend') do - module M0 - def m1; [:M0] end - end - module M1 - def m1; [:M1, super, :M1] end - end - module M2 - def m1; [:M2, super, :M2] end - end - M3 = Module.new do - def m1; [:M3, super, :M3] end - end - module M4 - def m1; [:M4, super, :M4] end - end - - class P0 - include M0 - prepend M1 - def m1; [:C0, super, :C0] end - end - class P1 < P0 - prepend M2, M3 - include M4 - def m1; [:C1, super, :C1] end - end - - obj = P1.new - expected = [:M2,[:M3,[:C1,[:M4,[:M1,[:C0,[:M0],:C0],:M1],:M4],:C1],:M3],:M2] - assert_equal(expected, obj.m1) - end - - # mruby shouldn't be affected by this since there is - # no visibility control (yet) - assert('Module#prepend public') do - assert_nothing_raised('ruby/ruby #8846') do - Class.new.prepend(Module.new) - end - end - - assert('Module#prepend inheritance') do - bug6654 = '[ruby-core:45914]' - a = labeled_module('a') - b = labeled_module('b') { include a } - c = labeled_module('c') { prepend b } - - #assert bug6654 do - # the Module#< operator should be used here instead, but we don't have it - assert_include(c.ancestors, a) - assert_include(c.ancestors, b) - #end - - bug8357 = '[ruby-core:54736] [Bug #8357]' - b = labeled_module('b') { prepend a } - c = labeled_class('c') { include b } - - #assert bug8357 do - # the Module#< operator should be used here instead, but we don't have it - assert_include(c.ancestors, a) - assert_include(c.ancestors, b) - #end - - bug8357 = '[ruby-core:54742] [Bug #8357]' - assert_kind_of(b, c.new, bug8357) - end - - assert('Moduler#prepend + #instance_methods') do - bug6655 = '[ruby-core:45915]' - assert_equal(Object.instance_methods, Class.new {prepend Module.new}.instance_methods, bug6655) - end - - assert 'Module#prepend + #singleton_methods' do - o = Object.new - o.singleton_class.class_eval {prepend Module.new} - assert_equal([], o.singleton_methods) - end - - assert 'Module#prepend + #remove_method' do - c = Class.new do - prepend Module.new { def foo; end } - end - assert_raise(NameError) do - c.class_eval do - remove_method(:foo) - end - end - c.class_eval do - def foo; end - end - removed = nil - c.singleton_class.class_eval do - define_method(:method_removed) {|id| removed = id} - end - assert_nothing_raised(NoMethodError, NameError, '[Bug #7843]') do - c.class_eval do - remove_method(:foo) - end - end - assert_equal(:foo, removed) - end - - assert 'Module#prepend + Class#ancestors' do - bug6658 = '[ruby-core:45919]' - m = labeled_module("m") - c = labeled_class("c") {prepend m} - assert_equal([m, c], c.ancestors[0, 2], bug6658) - - bug6662 = '[ruby-dev:45868]' - c2 = labeled_class("c2", c) - anc = c2.ancestors - assert_equal([c2, m, c, Object], anc[0..anc.index(Object)], bug6662) - end - - assert 'Module#prepend + Module#ancestors' do - bug6659 = '[ruby-dev:45861]' - m0 = labeled_module("m0") { def x; [:m0, *super] end } - m1 = labeled_module("m1") { def x; [:m1, *super] end; prepend m0 } - m2 = labeled_module("m2") { def x; [:m2, *super] end; prepend m1 } - c0 = labeled_class("c0") { def x; [:c0] end } - c1 = labeled_class("c1") { def x; [:c1] end; prepend m2 } - c2 = labeled_class("c2", c0) { def x; [:c2, *super] end; include m2 } - # - assert_equal([m0, m1], m1.ancestors, bug6659) - # - bug6662 = '[ruby-dev:45868]' - assert_equal([m0, m1, m2], m2.ancestors, bug6662) - assert_equal([m0, m1, m2, c1], c1.ancestors[0, 4], bug6662) - assert_equal([:m0, :m1, :m2, :c1], c1.new.x) - assert_equal([c2, m0, m1, m2, c0], c2.ancestors[0, 5], bug6662) - assert_equal([:c2, :m0, :m1, :m2, :c0], c2.new.x) - # - m3 = labeled_module("m3") { include m1; prepend m1 } - assert_equal([m3, m0, m1], m3.ancestors) - m3 = labeled_module("m3") { prepend m1; include m1 } - assert_equal([m0, m1, m3], m3.ancestors) - m3 = labeled_module("m3") { prepend m1; prepend m1 } - assert_equal([m0, m1, m3], m3.ancestors) - m3 = labeled_module("m3") { include m1; include m1 } - assert_equal([m3, m0, m1], m3.ancestors) - end - - assert 'Module#prepend #instance_methods(false)' do - bug6660 = '[ruby-dev:45863]' - assert_equal([:m1], Class.new{ prepend Module.new; def m1; end }.instance_methods(false), bug6660) - assert_equal([:m1], Class.new(Class.new{def m2;end}){ prepend Module.new; def m1; end }.instance_methods(false), bug6660) - end - - assert 'cyclic Module#prepend' do - bug7841 = '[ruby-core:52205] [Bug #7841]' - m1 = Module.new - m2 = Module.new - m1.instance_eval { prepend(m2) } - assert_raise(ArgumentError, bug7841) do - m2.instance_eval { prepend(m1) } - end - end - - # these assertions will not run without a #assert_seperately method - #assert 'test_prepend_optmethod' do - # bug7983 = '[ruby-dev:47124] [Bug #7983]' - # assert_separately [], %{ - # module M - # def /(other) - # to_f / other - # end - # end - # Fixnum.send(:prepend, M) - # assert_equal(0.5, 1 / 2, "#{bug7983}") - # } - # assert_equal(0, 1 / 2) - #end - - # mruby has no visibility control - assert 'Module#prepend visibility' do - bug8005 = '[ruby-core:53106] [Bug #8005]' - c = Class.new do - prepend Module.new {} - def foo() end - protected :foo - end - a = c.new - assert_true a.respond_to?(:foo), bug8005 - assert_nothing_raised(NoMethodError, bug8005) {a.send :foo} - end - - # mruby has no visibility control - assert 'Module#prepend inherited visibility' do - bug8238 = '[ruby-core:54105] [Bug #8238]' - module Test4PrependVisibilityInherited - class A - def foo() A; end - private :foo - end - class B < A - public :foo - prepend Module.new - end - end - assert_equal(Test4PrependVisibilityInherited::A, Test4PrependVisibilityInherited::B.new.foo, "#{bug8238}") - end - - assert 'Module#prepend + #included_modules' do - bug8025 = '[ruby-core:53158] [Bug #8025]' - mixin = labeled_module("mixin") - c = labeled_module("c") {prepend mixin} - im = c.included_modules - assert_not_include(im, c, bug8025) - assert_include(im, mixin, bug8025) - c1 = labeled_class("c1") {prepend mixin} - c2 = labeled_class("c2", c1) - im = c2.included_modules - assert_not_include(im, c1, bug8025) - assert_not_include(im, c2, bug8025) - assert_include(im, mixin, bug8025) - end - - assert 'Module#prepend super in alias' do - skip "super does not currently work in aliased methods" - bug7842 = '[Bug #7842]' - - p = labeled_module("P") do - def m; "P"+super; end - end - - a = labeled_class("A") do - def m; "A"; end - end - - b = labeled_class("B", a) do - def m; "B"+super; end - alias m2 m - prepend p - alias m3 m - end - - assert_nothing_raised do - assert_equal("BA", b.new.m2, bug7842) - end - - assert_nothing_raised do - assert_equal("PBA", b.new.m3, bug7842) - end - end - - assert 'Module#prepend each class' do - m = labeled_module("M") - c1 = labeled_class("C1") {prepend m} - c2 = labeled_class("C2", c1) {prepend m} - assert_equal([m, c2, m, c1], c2.ancestors[0, 4], "should be able to prepend each class") - end - - assert 'Module#prepend no duplication' do - m = labeled_module("M") - c = labeled_class("C") {prepend m; prepend m} - assert_equal([m, c], c.ancestors[0, 2], "should never duplicate") - end - - assert 'Module#prepend in superclass' do - m = labeled_module("M") - c1 = labeled_class("C1") - c2 = labeled_class("C2", c1) {prepend m} - c1.class_eval {prepend m} - assert_equal([m, c2, m, c1], c2.ancestors[0, 4], "should accesisble prepended module in superclass") - end - - # requires #assert_seperately - #assert 'Module#prepend call super' do - # assert_separately([], <<-'end;') #do - # bug10847 = '[ruby-core:68093] [Bug #10847]' - # module M; end - # Float.prepend M - # assert_nothing_raised(SystemStackError, bug10847) do - # 0.3.numerator - # end - # end; - #end -# @!endgroup prepend - -assert('Module#to_s') do - module Test4to_sModules - end - - assert_equal 'Test4to_sModules', Test4to_sModules.to_s -end - -assert('Module#inspect') do - module Test4to_sModules - end - - assert_equal 'Test4to_sModules', Test4to_sModules.inspect -end - -assert('Issue 1467') do - module M1 - def initialize() - super() - end - end - - class C1 - include M1 - def initialize() - super() - end - end - - class C2 - include M1 - end - - C1.new - C2.new -end - -assert('clone Module') do - module M1 - def foo - true - end - end - - class B - include M1.clone - end - - B.new.foo -end - -assert('Module#module_function') do - module M - def modfunc; end - module_function :modfunc - end - - assert_true M.respond_to?(:modfunc) -end - -assert('module with non-class/module outer raises TypeError') do - assert_raise(TypeError) { module 0::M1 end } - assert_raise(TypeError) { module []::M2 end } -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/nameerror.rb nghttp2-0.6.7/third-party/mruby/test/t/nameerror.rb --- nghttp2-1.13.0/third-party/mruby/test/t/nameerror.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/nameerror.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -## -# NameError ISO Test - -assert('NameError', '15.2.31') do - assert_equal Class, NameError.class -end - -assert('NameError#name', '15.2.31.2.1') do - - # This check is not duplicate with 15.2.31.2.2 check. - # Because the NameError in this test is generated in - # C API. - class TestDummy - alias foo bar - rescue NameError => e - $test_dummy_result = e.name - end - - assert_equal :bar, $test_dummy_result -end - -assert('NameError#initialize', '15.2.31.2.2') do - e = NameError.new('a', :foo) - - assert_equal NameError, e.class - assert_equal 'a', e.message - assert_equal :foo, e.name -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/nil.rb nghttp2-0.6.7/third-party/mruby/test/t/nil.rb --- nghttp2-1.13.0/third-party/mruby/test/t/nil.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/nil.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -## -# NilClass ISO Test - -assert('NilClass', '15.2.4') do - assert_equal Class, NilClass.class -end - -assert('NilClass', '15.2.4.1') do - assert_equal NilClass, nil.class - assert_false NilClass.method_defined? :new -end - -assert('NilClass#&', '15.2.4.3.1') do - assert_false nil.&(true) - assert_false nil.&(nil) -end - -assert('NilClass#^', '15.2.4.3.2') do - assert_true nil.^(true) - assert_false nil.^(false) -end - -assert('NilClass#|', '15.2.4.3.3') do - assert_true nil.|(true) - assert_false nil.|(false) -end - -assert('NilClass#nil?', '15.2.4.3.4') do - assert_true nil.nil? -end - -assert('NilClass#to_s', '15.2.4.3.5') do - assert_equal '', nil.to_s -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/nomethoderror.rb nghttp2-0.6.7/third-party/mruby/test/t/nomethoderror.rb --- nghttp2-1.13.0/third-party/mruby/test/t/nomethoderror.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/nomethoderror.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -## -# NoMethodError ISO Test - -assert('NoMethodError', '15.2.32') do - NoMethodError.class == Class - assert_raise NoMethodError do - doesNotExistAsAMethodNameForVerySure("") - end -end - -assert('NoMethodError#args', '15.2.32.2.1') do - a = NoMethodError.new 'test', :test, [1, 2] - assert_equal [1, 2], a.args - - assert_nothing_raised do - begin - doesNotExistAsAMethodNameForVerySure 3, 1, 4 - rescue NoMethodError => e - assert_equal [3, 1, 4], e.args - end - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/numeric.rb nghttp2-0.6.7/third-party/mruby/test/t/numeric.rb --- nghttp2-1.13.0/third-party/mruby/test/t/numeric.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/numeric.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -## -# Numeric ISO Test - -assert('Numeric', '15.2.7') do - assert_equal Class, Numeric.class -end - -assert('Numeric#+@', '15.2.7.4.1') do - assert_equal(+1, +1) -end - -assert('Numeric#-@', '15.2.7.4.2') do - assert_equal(-1, -1) -end - -assert('Numeric#abs', '15.2.7.4.3') do - assert_equal(1, 1.abs) - assert_equal(1.0, -1.abs) -end - -assert('Numeric#pow') do - assert_equal(8, 2 ** 3) - assert_equal(-8, -2 ** 3) - assert_equal(1, 2 ** 0) - assert_equal(1, 2.2 ** 0) - assert_equal(0.5, 2 ** -1) -end - -assert('Numeric#/', '15.2.8.3.4') do - n = Class.new(Numeric){ def /(x); 15.1;end }.new - - assert_equal(2, 10/5) - assert_equal(0.0625, 1/16) - assert_equal(15.1, n/10) - assert_raise(TypeError){ 1/n } - assert_raise(TypeError){ 1/nil } -end - -# Not ISO specified - -assert('Numeric#**') do - assert_equal 8.0, 2.0**3 -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/object.rb nghttp2-0.6.7/third-party/mruby/test/t/object.rb --- nghttp2-1.13.0/third-party/mruby/test/t/object.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/object.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -## -# Object ISO Test - -assert('Object', '15.2.1') do - assert_equal Class, Object.class -end - -assert('Object superclass', '15.2.1.2') do - assert_equal BasicObject, Object.superclass -end - diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/proc.rb nghttp2-0.6.7/third-party/mruby/test/t/proc.rb --- nghttp2-1.13.0/third-party/mruby/test/t/proc.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/proc.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,154 +0,0 @@ -## -# Proc ISO Test - -assert('Proc', '15.2.17') do - assert_equal Class, Proc.class -end - -assert('Proc.new', '15.2.17.3.1') do - assert_raise ArgumentError do - Proc.new - end - - assert_equal (Proc.new {}).class, Proc -end - -assert('Proc#[]', '15.2.17.4.1') do - a = 0 - b = Proc.new { a += 1 } - b.[] - - a2 = 0 - b2 = Proc.new { |i| a2 += i } - b2.[](5) - - assert_equal 1, a - assert_equal 5, a2 -end - -assert('Proc#arity', '15.2.17.4.2') do - a = Proc.new {|x, y|}.arity - b = Proc.new {|x, *y, z|}.arity - c = Proc.new {|x=0, y|}.arity - d = Proc.new {|(x, y), z=0|}.arity - - assert_equal 2, a - assert_equal(-3, b) - assert_equal 1, c - assert_equal 1, d - - e = ->(x=0, y){}.arity - f = ->((x, y), z=0){}.arity - g = ->(x=0){}.arity - - assert_equal(-2, e) - assert_equal(-2, f) - assert_equal(-1, g) -end - -assert('Proc#call', '15.2.17.4.3') do - a = 0 - b = Proc.new { a += 1 } - b.call - - a2 = 0 - b2 = Proc.new { |i| a2 += i } - b2.call(5) - - assert_equal 1, a - assert_equal 5, a2 -end - -assert('Proc#call proc args pos block') do - pr = Proc.new {|a,b,&c| - [a, b, c.class, c&&c.call(:x)] - } - assert_equal [nil, nil, Proc, :proc], (pr.call(){ :proc }) - assert_equal [1, nil, Proc, :proc], (pr.call(1){ :proc }) - assert_equal [1, 2, Proc, :proc], (pr.call(1, 2){ :proc }) - assert_equal [1, 2, Proc, :proc], (pr.call(1, 2, 3){ :proc }) - assert_equal [1, 2, Proc, :proc], (pr.call(1, 2, 3, 4){ :proc }) - - assert_equal [nil, nil, Proc, :x], (pr.call(){|x| x}) - assert_equal [1, nil, Proc, :x], (pr.call(1){|x| x}) - assert_equal [1, 2, Proc, :x], (pr.call(1, 2){|x| x}) - assert_equal [1, 2, Proc, :x], (pr.call(1, 2, 3){|x| x}) - assert_equal [1, 2, Proc, :x], (pr.call(1, 2, 3, 4){|x| x}) -end - -assert('Proc#call proc args pos rest post') do - pr = Proc.new {|a,b,*c,d,e| - [a,b,c,d,e] - } - assert_equal [nil, nil, [], nil, nil], pr.call() - assert_equal [1, nil, [], nil, nil], pr.call(1) - assert_equal [1, 2, [], nil, nil], pr.call(1,2) - assert_equal [1, 2, [], 3, nil], pr.call(1,2,3) - assert_equal [1, 2, [], 3, 4], pr.call(1,2,3,4) - assert_equal [1, 2, [3], 4, 5], pr.call(1,2,3,4,5) - assert_equal [1, 2, [3, 4], 5, 6], pr.call(1,2,3,4,5,6) - assert_equal [1, 2, [3, 4, 5], 6,7], pr.call(1,2,3,4,5,6,7) - - assert_equal [nil, nil, [], nil, nil], pr.call([]) - assert_equal [1, nil, [], nil, nil], pr.call([1]) - assert_equal [1, 2, [], nil, nil], pr.call([1,2]) - assert_equal [1, 2, [], 3, nil], pr.call([1,2,3]) - assert_equal [1, 2, [], 3, 4], pr.call([1,2,3,4]) - assert_equal [1, 2, [3], 4, 5], pr.call([1,2,3,4,5]) - assert_equal [1, 2, [3, 4], 5, 6], pr.call([1,2,3,4,5,6]) - assert_equal [1, 2, [3, 4, 5], 6,7], pr.call([1,2,3,4,5,6,7]) -end - -assert('Proc#return_does_not_break_self') do - class TestClass - attr_accessor :block - def initialize - end - def return_array - @block = Proc.new { self } - return [] - end - def return_instance_variable - @block = Proc.new { self } - return @block - end - def return_const_fixnum - @block = Proc.new { self } - return 123 - end - def return_nil - @block = Proc.new { self } - return nil - end - end - - c = TestClass.new - assert_equal [], c.return_array - assert_equal c, c.block.call - - c.return_instance_variable - assert_equal c, c.block.call - - assert_equal 123, c.return_const_fixnum - assert_equal c, c.block.call - - assert_equal nil, c.return_nil - assert_equal c, c.block.call -end - -assert('&obj call to_proc if defined') do - pr = Proc.new{} - def mock(&b) - b - end - assert_equal pr.object_id, mock(&pr).object_id - assert_equal pr, mock(&pr) - - obj = Object.new - def obj.to_proc - Proc.new{ :from_to_proc } - end - assert_equal :from_to_proc, mock(&obj).call - - assert_raise(TypeError){ mock(&(Object.new)) } -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/rangeerror.rb nghttp2-0.6.7/third-party/mruby/test/t/rangeerror.rb --- nghttp2-1.13.0/third-party/mruby/test/t/rangeerror.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/rangeerror.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -## -# RangeError ISO Test - -assert('RangeError', '15.2.26') do - assert_equal Class, RangeError.class -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/range.rb nghttp2-0.6.7/third-party/mruby/test/t/range.rb --- nghttp2-1.13.0/third-party/mruby/test/t/range.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/range.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -## -# Range ISO Test - -assert('Range', '15.2.14') do - assert_equal Class, Range.class -end - -assert('Range#==', '15.2.14.4.1') do - assert_true (1..10) == (1..10) - assert_false (1..10) == (1..100) - assert_true (1..10) == Range.new(1.0, 10.0) -end - -assert('Range#===', '15.2.14.4.2') do - a = (1..10) - - assert_true a === 5 - assert_false a === 20 -end - -assert('Range#begin', '15.2.14.4.3') do - assert_equal 1, (1..10).begin -end - -assert('Range#each', '15.2.14.4.4') do - a = (1..3) - b = 0 - a.each {|i| b += i} - assert_equal 6, b -end - -assert('Range#end', '15.2.14.4.5') do - assert_equal 10, (1..10).end -end - -assert('Range#exclude_end?', '15.2.14.4.6') do - assert_true (1...10).exclude_end? - assert_false (1..10).exclude_end? -end - -assert('Range#first', '15.2.14.4.7') do - assert_equal 1, (1..10).first -end - -assert('Range#include?', '15.2.14.4.8') do - a = (1..10) - - assert_true a.include?(5) - assert_false a.include?(20) -end - -assert('Range#initialize', '15.2.14.4.9') do - a = Range.new(1, 10, true) - b = Range.new(1, 10, false) - - assert_equal (1...10), a - assert_true a.exclude_end? - assert_equal (1..10), b - assert_false b.exclude_end? -end - -assert('Range#last', '15.2.14.4.10') do - assert_equal 10, (1..10).last -end - -assert('Range#member?', '15.2.14.4.11') do - a = (1..10) - - assert_true a.member?(5) - assert_false a.member?(20) -end - -assert('Range#to_s', '15.2.14.4.12') do - assert_equal "0..1", (0..1).to_s - assert_equal "0...1", (0...1).to_s - assert_equal "a..b", ("a".."b").to_s - assert_equal "a...b", ("a"..."b").to_s -end - -assert('Range#inspect', '15.2.14.4.13') do - assert_equal "0..1", (0..1).inspect - assert_equal "0...1", (0...1).inspect - assert_equal "\"a\"..\"b\"", ("a".."b").inspect - assert_equal "\"a\"...\"b\"", ("a"..."b").inspect -end - -assert('Range#eql?', '15.2.14.4.14') do - assert_true (1..10).eql? (1..10) - assert_false (1..10).eql? (1..100) - assert_false (1..10).eql? (Range.new(1.0, 10.0)) - assert_false (1..10).eql? "1..10" -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/regexperror.rb nghttp2-0.6.7/third-party/mruby/test/t/regexperror.rb --- nghttp2-1.13.0/third-party/mruby/test/t/regexperror.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/regexperror.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -## -# RegexpError ISO Test - -# TODO broken ATM assert('RegexpError', '15.2.27') do diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/runtimeerror.rb nghttp2-0.6.7/third-party/mruby/test/t/runtimeerror.rb --- nghttp2-1.13.0/third-party/mruby/test/t/runtimeerror.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/runtimeerror.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -## -# RuntimeError ISO Test - -assert('RuntimeError', '15.2.28') do - assert_equal Class, RuntimeError.class -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/standarderror.rb nghttp2-0.6.7/third-party/mruby/test/t/standarderror.rb --- nghttp2-1.13.0/third-party/mruby/test/t/standarderror.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/standarderror.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -## -# StandardError ISO Test - -assert('StandardError', '15.2.23') do - assert_equal Class, StandardError.class -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/string.rb nghttp2-0.6.7/third-party/mruby/test/t/string.rb --- nghttp2-1.13.0/third-party/mruby/test/t/string.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/string.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,688 +0,0 @@ -# coding: utf-8 -## -# String ISO Test - -UTF8STRING = ("\343\201\202".size == 1) - -assert('String', '15.2.10') do - assert_equal Class, String.class -end - -assert('String#<=>', '15.2.10.5.1') do - a = '' <=> '' - b = '' <=> 'not empty' - c = 'not empty' <=> '' - d = 'abc' <=> 'cba' - e = 'cba' <=> 'abc' - - assert_equal 0, a - assert_equal(-1, b) - assert_equal 1, c - assert_equal(-1, d) - assert_equal 1, e -end - -assert('String#==', '15.2.10.5.2') do - assert_equal 'abc', 'abc' - assert_not_equal 'abc', 'cba' -end - -# 'String#=~', '15.2.10.5.3' will be tested in mrbgems. - -assert('String#+', '15.2.10.5.4') do - assert_equal 'ab', 'a' + 'b' -end - -assert('String#*', '15.2.10.5.5') do - assert_equal 'aaaaa', 'a' * 5 - assert_equal '', 'a' * 0 - assert_raise(ArgumentError) do - 'a' * -1 - end -end - -assert('String#[]', '15.2.10.5.6') do - # length of args is 1 - a = 'abc'[0] - b = 'abc'[-1] - c = 'abc'[10] - d = 'abc'[-10] - e = 'abc'[1.1] - - # length of args is 2 - a1 = 'abc'[0, -1] - b1 = 'abc'[10, 0] - c1 = 'abc'[-10, 0] - d1 = 'abc'[0, 0] - e1 = 'abc'[1, 2] - - # args is RegExp - # It will be tested in mrbgems. - - # args is String - a3 = 'abc'['bc'] - b3 = 'abc'['XX'] - - assert_equal 'a', 'a' - # assert_equal 'c', b - # assert_nil c - # assert_nil d - # assert_equal 'b', e - # assert_nil a1 - # assert_nil b1 - # assert_nil c1 - # assert_equal '', d1 - # assert_equal 'bc', e1 - # assert_equal 'bc', a3 - # assert_nil b3 - - # assert_raise(TypeError) do - # a[nil] - # end -end - -assert('String#[](UTF-8)', '15.2.10.5.6') do - assert_equal "ち", "こんにちは世界"[3] - assert_equal nil, "こんにちは世界"[20] - assert_equal "世", "こんにちは世界"[-2] - assert_equal "世界", "こんにちは世界"[-2..-1] - assert_equal "んに", "こんにちは世界"[1,2] - assert_equal "世", "こんにちは世界"["世"] -end if UTF8STRING - -assert('String#[] with Range') do - a1 = 'abc'[1..0] - b1 = 'abc'[1..1] - c1 = 'abc'[1..2] - d1 = 'abc'[1..3] - e1 = 'abc'[1..4] - f1 = 'abc'[0..-2] - g1 = 'abc'[-2..3] - h1 = 'abc'[3..4] - i1 = 'abc'[4..5] - j1 = 'abcdefghijklmnopqrstuvwxyz'[1..3] - a2 = 'abc'[1...0] - b2 = 'abc'[1...1] - c2 = 'abc'[1...2] - d2 = 'abc'[1...3] - e2 = 'abc'[1...4] - f2 = 'abc'[0...-2] - g2 = 'abc'[-2...3] - h2 = 'abc'[3...4] - i2 = 'abc'[4...5] - j2 = 'abcdefghijklmnopqrstuvwxyz'[1...3] - - assert_equal '', a1 - assert_equal 'b', b1 - assert_equal 'bc', c1 - assert_equal 'bc', d1 - assert_equal 'bc', e1 - assert_equal 'ab', f1 - assert_equal 'bc', g1 - assert_equal '', h1 - assert_nil i2 - assert_equal 'bcd', j1 - assert_equal '', a2 - assert_equal '', b2 - assert_equal 'b', c2 - assert_equal 'bc', d2 - assert_equal 'bc', e2 - assert_equal 'a', f2 - assert_equal 'bc', g2 - assert_equal '', h2 - assert_nil i2 - assert_equal 'bc', j2 -end - -assert('String#[]=') do - # length of args is 1 - a = 'abc' - a[0] = 'X' - assert_equal 'Xbc', a - - b = 'abc' - b[-1] = 'X' - assert_equal 'abX', b - - c = 'abc' - assert_raise(IndexError) do - c[10] = 'X' - end - - d = 'abc' - assert_raise(IndexError) do - d[-10] = 'X' - end - - e = 'abc' - e[1.1] = 'X' - assert_equal 'aXc', e - - - # length of args is 2 - a1 = 'abc' - assert_raise(IndexError) do - a1[0, -1] = 'X' - end - - b1 = 'abc' - assert_raise(IndexError) do - b1[10, 0] = 'X' - end - - c1 = 'abc' - assert_raise(IndexError) do - c1[-10, 0] = 'X' - end - - d1 = 'abc' - d1[0, 0] = 'X' - assert_equal 'Xabc', d1 - - e1 = 'abc' - e1[1, 3] = 'X' - assert_equal 'aX', e1 - - # args is RegExp - # It will be tested in mrbgems. - - # args is String - a3 = 'abc' - a3['bc'] = 'X' - assert_equal a3, 'aX' - - b3 = 'abc' - assert_raise(IndexError) do - b3['XX'] = 'Y' - end -end - -assert('String#capitalize', '15.2.10.5.7') do - a = 'abc' - a.capitalize - - assert_equal 'abc', a - assert_equal 'Abc', 'abc'.capitalize -end - -assert('String#capitalize!', '15.2.10.5.8') do - a = 'abc' - a.capitalize! - - assert_equal 'Abc', a - assert_equal nil, 'Abc'.capitalize! -end - -assert('String#chomp', '15.2.10.5.9') do - a = 'abc'.chomp - b = ''.chomp - c = "abc\n".chomp - d = "abc\n\n".chomp - e = "abc\t".chomp("\t") - f = "abc\n" - - f.chomp - - assert_equal 'abc', a - assert_equal '', b - assert_equal 'abc', c - assert_equal "abc\n", d - assert_equal 'abc', e - assert_equal "abc\n", f -end - -assert('String#chomp!', '15.2.10.5.10') do - a = 'abc' - b = '' - c = "abc\n" - d = "abc\n\n" - e = "abc\t" - - a.chomp! - b.chomp! - c.chomp! - d.chomp! - e.chomp!("\t") - - assert_equal 'abc', a - assert_equal '', b - assert_equal 'abc', c - assert_equal "abc\n", d - assert_equal 'abc', e -end - -assert('String#chop', '15.2.10.5.11') do - a = ''.chop - b = 'abc'.chop - c = 'abc' - - c.chop - - assert_equal '', a - assert_equal 'ab', b - assert_equal 'abc', c -end - -assert('String#chop(UTF-8)', '15.2.10.5.11') do - a = ''.chop - b = 'あいう'.chop - c = "あ\nい".chop.chop - - assert_equal '', a - assert_equal 'あい', b - assert_equal 'あ', c -end if UTF8STRING - -assert('String#chop!', '15.2.10.5.12') do - a = '' - b = 'abc' - - a.chop! - b.chop! - - assert_equal a, '' - assert_equal b, 'ab' -end - -assert('String#chop!(UTF-8)', '15.2.10.5.12') do - a = '' - b = "あいうえ\n" - c = "あいうえ\n" - - a.chop! - b.chop! - c.chop! - c.chop! - - assert_equal a, '' - assert_equal b, 'あいうえ' - assert_equal c, 'あいう' -end if UTF8STRING - -assert('String#downcase', '15.2.10.5.13') do - a = 'ABC'.downcase - b = 'ABC' - - b.downcase - - assert_equal 'abc', a - assert_equal 'ABC', b -end - -assert('String#downcase!', '15.2.10.5.14') do - a = 'ABC' - - a.downcase! - - assert_equal 'abc', a - assert_equal nil, 'abc'.downcase! -end - -assert('String#each_line', '15.2.10.5.15') do - a = "first line\nsecond line\nthird line" - list = ["first line\n", "second line\n", "third line"] - n_list = [] - - a.each_line do |line| - n_list << line - end - - assert_equal list, n_list -end - -assert('String#empty?', '15.2.10.5.16') do - a = '' - b = 'not empty' - - assert_true a.empty? - assert_false b.empty? -end - -assert('String#eql?', '15.2.10.5.17') do - assert_true 'abc'.eql?('abc') - assert_false 'abc'.eql?('cba') -end - -assert('String#gsub', '15.2.10.5.18') do - assert_equal('aBcaBc', 'abcabc'.gsub('b', 'B'), 'gsub without block') - assert_equal('aBcaBc', 'abcabc'.gsub('b'){|w| w.capitalize }, 'gsub with block') - assert_equal('$a$a$', '#a#a#'.gsub('#', '$'), 'mruby/mruby#847') - assert_equal('$a$a$', '#a#a#'.gsub('#'){|w| '$' }, 'mruby/mruby#847 with block') - assert_equal('$$a$$', '##a##'.gsub('##', '$$'), 'mruby/mruby#847 another case') - assert_equal('$$a$$', '##a##'.gsub('##'){|w| '$$' }, 'mruby/mruby#847 another case with block') - assert_equal('A', 'a'.gsub('a', 'A')) - assert_equal('A', 'a'.gsub('a'){|w| w.capitalize }) -end - -assert('String#gsub with backslash') do - s = 'abXcdXef' - assert_equal 'ab<\\>cd<\\>ef', s.gsub('X', '<\\\\>') - assert_equal 'abcdef', s.gsub('X', '<\\&>') - assert_equal 'abcdef', s.gsub('X', '<\\0>') - assert_equal 'abcdef', s.gsub('X', '<\\`>') - assert_equal 'abcdef', s.gsub('X', '<\\\'>') -end - -assert('String#gsub!', '15.2.10.5.19') do - a = 'abcabc' - a.gsub!('b', 'B') - - b = 'abcabc' - b.gsub!('b') { |w| w.capitalize } - - assert_equal 'aBcaBc', a - assert_equal 'aBcaBc', b -end - -assert('String#hash', '15.2.10.5.20') do - a = 'abc' - - assert_equal 'abc'.hash, a.hash -end - -assert('String#include?', '15.2.10.5.21') do - assert_true 'abc'.include?(97) - assert_false 'abc'.include?(100) - assert_true 'abc'.include?('a') - assert_false 'abc'.include?('d') -end - -assert('String#index', '15.2.10.5.22') do - assert_equal 0, 'abc'.index('a') - assert_nil 'abc'.index('d') - assert_equal 3, 'abcabc'.index('a', 1) -end - -assert('String#initialize', '15.2.10.5.23') do - a = '' - a.initialize('abc') - assert_equal 'abc', a - - a.initialize('abcdefghijklmnopqrstuvwxyz') - assert_equal 'abcdefghijklmnopqrstuvwxyz', a -end - -assert('String#initialize_copy', '15.2.10.5.24') do - a = '' - a.initialize_copy('abc') - - assert_equal 'abc', a -end - -assert('String#intern', '15.2.10.5.25') do - assert_equal :abc, 'abc'.intern -end - -assert('String#length', '15.2.10.5.26') do - assert_equal 3, 'abc'.length -end - -# 'String#match', '15.2.10.5.27' will be tested in mrbgems. - -assert('String#replace', '15.2.10.5.28') do - a = '' - a.replace('abc') - - assert_equal 'abc', a - assert_equal 'abc', 'cba'.replace(a) - - b = 'abc' * 10 - c = ('cba' * 10).dup - b.replace(c); - c.replace(b); - assert_equal c, b - - # shared string - s = "foo" * 100 - a = s[10, 90] # create shared string - assert_equal("", s.replace("")) # clear - assert_equal("", s) # s is cleared - assert_not_equal("", a) # a should not be affected -end - -assert('String#reverse', '15.2.10.5.29') do - a = 'abc' - a.reverse - - assert_equal 'abc', a - assert_equal 'cba', 'abc'.reverse -end - -assert('String#reverse(UTF-8)', '15.2.10.5.29') do - assert_equal "ち", "こんにちは世界"[3] - assert_equal nil, "こんにちは世界"[20] - assert_equal "世", "こんにちは世界"[-2] - assert_equal "世界", "こんにちは世界"[-2..-1] - assert_equal "んに", "こんにちは世界"[1,2] - assert_equal "世", "こんにちは世界"["世"] -end if UTF8STRING - -assert('String#reverse!', '15.2.10.5.30') do - a = 'abc' - a.reverse! - - assert_equal 'cba', a - assert_equal 'cba', 'abc'.reverse! -end - -assert('String#reverse!(UTF-8)', '15.2.10.5.30') do - a = 'こんにちは世界!' - a.reverse! - - assert_equal '!界世はちにんこ', a - assert_equal '!界世はちにんこ', 'こんにちは世界!'.reverse! -end if UTF8STRING - -assert('String#rindex', '15.2.10.5.31') do - assert_equal 0, 'abc'.rindex('a') - assert_nil 'abc'.rindex('d') - assert_equal 0, 'abcabc'.rindex('a', 1) - assert_equal 3, 'abcabc'.rindex('a', 4) -end - -assert('String#rindex(UTF-8)', '15.2.10.5.31') do - str = "こんにちは世界!\nこんにちは世界!" - assert_nil str.index('さ') - assert_equal 3, str.index('ち') - assert_equal 12, str.index('ち', 10) - assert_equal nil, str.index("さ") -end if UTF8STRING - -# 'String#scan', '15.2.10.5.32' will be tested in mrbgems. - -assert('String#size', '15.2.10.5.33') do - assert_equal 3, 'abc'.size -end - -assert('String#size(UTF-8)', '15.2.10.5.33') do - str = 'こんにちは世界!' - assert_equal 8, str.size - assert_not_equal str.bytesize, str.size - assert_equal 2, str[1, 2].size -end if UTF8STRING - -assert('String#slice', '15.2.10.5.34') do - # length of args is 1 - a = 'abc'.slice(0) - b = 'abc'.slice(-1) - c = 'abc'.slice(10) - d = 'abc'.slice(-10) - - # length of args is 2 - a1 = 'abc'.slice(0, -1) - b1 = 'abc'.slice(10, 0) - c1 = 'abc'.slice(-10, 0) - d1 = 'abc'.slice(0, 0) - e1 = 'abc'.slice(1, 2) - - # slice of shared string - e11 = e1.slice(0) - - # args is RegExp - # It will be tested in mrbgems. - - # args is String - a3 = 'abc'.slice('bc') - b3 = 'abc'.slice('XX') - - assert_equal 'a', a - assert_equal 'c', b - assert_nil c - assert_nil d - assert_nil a1 - assert_nil b1 - assert_nil c1 - assert_equal '', d1 - assert_equal 'bc', e1 - assert_equal 'b', e11 - assert_equal 'bc', a3 - assert_nil b3 -end - -# TODO Broken ATM -assert('String#split', '15.2.10.5.35') do - # without RegExp behavior is actually unspecified - assert_equal ['abc', 'abc', 'abc'], 'abc abc abc'.split - assert_equal ["a", "b", "c", "", "d"], 'a,b,c,,d'.split(',') - assert_equal ['abc', 'abc', 'abc'], 'abc abc abc'.split(nil) - assert_equal ['a', 'b', 'c'], 'abc'.split("") -end - -assert('String#split(UTF-8)', '15.2.10.5.35') do - got = "こんにちは世界!".split('') - assert_equal ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'], got - got = "こんにちは世界!".split('に') - assert_equal ['こん', 'ちは世界!'], got -end if UTF8STRING - -assert('String#sub', '15.2.10.5.36') do - assert_equal 'aBcabc', 'abcabc'.sub('b', 'B') - assert_equal 'aBcabc', 'abcabc'.sub('b') { |w| w.capitalize } - assert_equal 'aa$', 'aa#'.sub('#', '$') -end - -assert('String#sub with backslash') do - s = 'abXcdXef' - assert_equal 'ab<\\>cdXef', s.sub('X', '<\\\\>') - assert_equal 'abcdXef', s.sub('X', '<\\&>') - assert_equal 'abcdXef', s.sub('X', '<\\0>') - assert_equal 'abcdXef', s.sub('X', '<\\`>') - assert_equal 'abcdXef', s.sub('X', '<\\\'>') -end - -assert('String#sub!', '15.2.10.5.37') do - a = 'abcabc' - a.sub!('b', 'B') - - b = 'abcabc' - b.sub!('b') { |w| w.capitalize } - - assert_equal 'aBcabc', a - assert_equal 'aBcabc', b -end - -assert('String#to_f', '15.2.10.5.38') do - a = ''.to_f - b = '123456789'.to_f - c = '12345.6789'.to_f - - assert_float(0.0, a) - assert_float(123456789.0, b) - assert_float(12345.6789, c) -end - -assert('String#to_i', '15.2.10.5.39') do - a = ''.to_i - b = '32143'.to_i - c = 'a'.to_i(16) - d = '100'.to_i(2) - e = '1_000'.to_i - - assert_equal 0, a - assert_equal 32143, b - assert_equal 10, c - assert_equal 4, d - assert_equal 1_000, e -end - -assert('String#to_s', '15.2.10.5.40') do - assert_equal 'abc', 'abc'.to_s -end - -assert('String#to_sym', '15.2.10.5.41') do - assert_equal :abc, 'abc'.to_sym -end - -assert('String#upcase', '15.2.10.5.42') do - a = 'abc'.upcase - b = 'abc' - - b.upcase - - assert_equal 'ABC', a - assert_equal 'abc', b -end - -assert('String#upcase!', '15.2.10.5.43') do - a = 'abc' - - a.upcase! - - assert_equal 'ABC', a - assert_equal nil, 'ABC'.upcase! - - a = 'abcdefghijklmnopqrstuvwxyz' - b = a.dup - a.upcase! - b.upcase! - assert_equal 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', b -end - -assert('String#inspect', '15.2.10.5.46') do - # should not raise an exception - regress #1210 - assert_nothing_raised do - ("\1" * 100).inspect - end - - assert_equal "\"\\000\"", "\0".inspect -end - -# Not ISO specified - -assert('String interpolation (mrb_str_concat for shared strings)') do - a = "A" * 32 - assert_equal "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:", "#{a}:" -end - -assert('Check the usage of a NUL character') do - "qqq\0ppp" -end - -assert('String#bytes') do - str1 = "hello" - bytes1 = [104, 101, 108, 108, 111] - - str2 = "\xFF" - bytes2 = [0xFF] - - assert_equal bytes1, str1.bytes - assert_equal bytes2, str2.bytes -end - -assert('String#each_byte') do - str1 = "hello" - bytes1 = [104, 101, 108, 108, 111] - bytes2 = [] - - str1.each_byte {|b| bytes2 << b } - - assert_equal bytes1, bytes2 -end - -assert('String#freeze') do - str = "hello" - str.freeze - - assert_raise(RuntimeError) { str.upcase! } -end - diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/superclass.rb nghttp2-0.6.7/third-party/mruby/test/t/superclass.rb --- nghttp2-1.13.0/third-party/mruby/test/t/superclass.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/superclass.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -[ - # [:Object, :implementation_defined_value, '15.2.2.1'], - [:Module, :Object, '15.2.2.2'], - [:Class, :Module, '15.2.3.2'], - [:NilClass, :Object, '15.2.4.2'], - [:TrueClass, :Object, '15.2.5.2'], - [:FalseClass, :Object, '15.2.6.2'], - [:Numeric, :Object, '15.2.7.2'], - [:Integer, :Numeric, '15.2.8.2'], - [:Float, :Numeric, '15.2.9.2'], - [:String, :Object, '15.2.10.2'], - [:Symbol, :Object, '15.2.11.2'], - [:Array, :Object, '15.2.12.2'], - [:Hash, :Object, '15.2.13.2'], - [:Range, :Object, '15.2.14.2'], -# [:Regexp, :Object, '15.2.15.2'], #No Regexp in mruby core -# [:MatchData, :Object, '15.2.16.2'], - [:Proc, :Object, '15.2.17.2'], -# [:Struct, :Object, '15.2.18.2'], -# [:Time, :Object, '15.2.19.2'], -# [:IO, :Object, '15.2.20.2'], -# [:File, :IO, '15.2.21.2'], - [:Exception, :Object, '15.2.22.2'], - [:StandardError, :Exception, '15.2.23.2'], - [:ArgumentError, :StandardError, '15.2.24.2'], - [:LocalJumpError, :StandardError, '15.2.25.2'], - [:RangeError, :StandardError, '12.2.26.2'], - [:RegexpError, :StandardError, '12.2.27.2'], - [:RuntimeError, :StandardError, '12.2.28.2'], - [:TypeError, :StandardError, '12.2.29.2'], -# [:ZeroDivisionError, :StandardError, '12.2.30.2'], # No ZeroDivisionError in mruby - [:NameError, :StandardError, '15.2.31.2'], - [:NoMethodError, :NameError, '15.2.32.2'], - [:IndexError, :StandardError, '15.2.33.2'], -# [:IOError, :StandardError, '12.2.34.2'], -# [:EOFError, :IOError, '12.2.35.2'], -# [:SystemCallError, :StandardError, '15.2.36.2'], - [:ScriptError, :Exception, '12.2.37.2'], - [:SyntaxError, :ScriptError, '12.2.38.2'], -# [:LoadError, :ScriptError, '12.2.39,2'], -].each do |cls, super_cls, iso| - assert "Direct superclass of #{cls}", iso do - skip "#{cls} isn't defined" unless Object.const_defined? cls - assert_equal Object.const_get(super_cls), Object.const_get(cls).superclass - end -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/symbol.rb nghttp2-0.6.7/third-party/mruby/test/t/symbol.rb --- nghttp2-1.13.0/third-party/mruby/test/t/symbol.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/symbol.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -## -# Symbol ISO Test - -assert('Symbol', '15.2.11') do - assert_equal Class, Symbol.class -end - -assert('Symbol#===', '15.2.11.3.1') do - assert_true :abc == :abc - assert_false :abc == :cba -end - -assert('Symbol#id2name', '15.2.11.3.2') do - assert_equal 'abc', :abc.id2name -end - -assert('Symbol#to_s', '15.2.11.3.3') do - assert_equal 'abc', :abc.to_s -end - -assert('Symbol#to_sym', '15.2.11.3.4') do - assert_equal :abc, :abc.to_sym -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/syntax.rb nghttp2-0.6.7/third-party/mruby/test/t/syntax.rb --- nghttp2-1.13.0/third-party/mruby/test/t/syntax.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/syntax.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,411 +0,0 @@ -assert('__FILE__') do - file = __FILE__[-9, 9] - assert_equal 'syntax.rb', file -end - -assert('__LINE__') do - assert_equal 7, __LINE__ -end - -assert('super', '11.3.4') do - assert_raise NoMethodError do - super - end - - class SuperFoo - def foo - true - end - def bar(*a) - a - end - end - class SuperBar < SuperFoo - def foo - super - end - def bar(*a) - super(*a) - end - end - bar = SuperBar.new - - assert_true bar.foo - assert_equal [1,2,3], bar.bar(1,2,3) -end - -assert('yield', '11.3.5') do - assert_raise LocalJumpError do - yield - end -end - -assert('Abbreviated variable assignment', '11.4.2.3.2') do - a ||= 1 - b &&= 1 - c = 1 - c += 2 - - assert_equal 1, a - assert_nil b - assert_equal 3, c -end - -assert('case expression', '11.5.2.2.4') do - # case-expression-with-expression, one when-clause - x = 0 - case "a" - when "a" - x = 1 - end - assert_equal 1, x - - # case-expression-with-expression, multiple when-clauses - x = 0 - case "b" - when "a" - x = 1 - when "b" - x = 2 - end - assert_equal 2, x - - # no matching when-clause - x = 0 - case "c" - when "a" - x = 1 - when "b" - x = 2 - end - assert_equal 0, x - - # case-expression-with-expression, one when-clause and one else-clause - a = 0 - case "c" - when "a" - x = 1 - else - x = 3 - end - assert_equal 3, x - - # case-expression-without-expression, one when-clause - x = 0 - case - when true - x = 1 - end - assert_equal 1, x - - # case-expression-without-expression, multiple when-clauses - x = 0 - case - when 0 == 1 - x = 1 - when 1 == 1 - x = 2 - end - assert_equal 2, x - - # case-expression-without-expression, one when-clause and one else-clause - x = 0 - case - when 0 == 1 - x = 1 - else - x = 3 - end - assert_equal 3, x - - # multiple when-arguments - x = 0 - case 4 - when 1, 3, 5 - x = 1 - when 2, 4, 6 - x = 2 - end - assert_equal 2, x - - # when-argument with splatting argument - x = :integer - odds = [ 1, 3, 5, 7, 9 ] - evens = [ 2, 4, 6, 8 ] - case 5 - when *odds - x = :odd - when *evens - x = :even - end - assert_equal :odd, x - - true -end - -assert('Nested const reference') do - module Syntax4Const - CONST1 = "hello world" - class Const2 - def const1 - CONST1 - end - end - end - assert_equal "hello world", Syntax4Const::CONST1 - assert_equal "hello world", Syntax4Const::Const2.new.const1 -end - -assert('Abbreviated variable assignment as returns') do - module Syntax4AbbrVarAsgnAsReturns - class A - def b - @c ||= 1 - end - end - end - assert_equal 1, Syntax4AbbrVarAsgnAsReturns::A.new.b -end - -assert('Splat and multiple assignment') do - *a = *[1,2,3] - b, *c = *[7,8,9] - - assert_equal [1,2,3], a - assert_equal 7, b - assert_equal [8,9], c - - (a, b), c = [1,2],3 - assert_equal [1,2,3], [a,b,c] - (a, b), c = 1,2,3 - assert_equal [1,nil,2], [a,b,c] -end - -assert('Splat and multiple assignment from variable') do - a = [1, 2, 3] - b, *c = a - - assert_equal 1, b - assert_equal [2, 3], c -end - -assert('Splat and multiple assignment from variables') do - a = [1, 2, 3] - b = [4, 5, 6, 7] - c, d, *e, f, g = *a, *b - - assert_equal 1, c - assert_equal 2, d - assert_equal [3, 4, 5], e - assert_equal 6, f - assert_equal 7, g -end - -assert('Splat and multiple assignment in for') do - a = [1, 2, 3, 4, 5, 6, 7] - for b, c, *d, e, f in [a] do - end - - assert_equal 1, b - assert_equal 2, c - assert_equal [3, 4, 5], d - assert_equal 6, e - assert_equal 7, f -end - -assert('Splat without assignment') do - * = [0] - a, * = [1, 2] - assert_equal 1, a -end - -assert('multiple assignment (rest)') do - *a = 0 - assert_equal [0], a -end - -assert('multiple assignment (rest+post)') do - *a, b = 0, 1, 2 - *c, d = 3 - - assert_equal [0, 1], a - assert_equal 2, b - assert_equal [], c - assert_equal 3, d -end - -assert('multiple assignment (nosplat array rhs)') do - a, *b = [] - *c, d = [0] - e, *f, g = [1, 2] - - assert_nil a - assert_equal [], b - assert_equal [], c - assert_equal 0, d - assert_equal 1, e - assert_equal [], f - assert_equal 2, g -end - -assert('Return values of case statements') do - a = [] << case 1 - when 3 then 2 - when 2 then 2 - when 1 then 2 - end - - b = [] << case 1 - when 2 then 2 - else - end - - def fb - n = 0 - Proc.new do - n += 1 - case - when n % 15 == 0 - else n - end - end - end - - assert_equal [2], a - assert_equal [nil], b - assert_equal 1, fb.call -end - -assert('Return values of if and case statements') do - true_clause_value = - if true - 1 - else - case 2 - when 3 - end - 4 - end - - assert_equal 1, true_clause_value -end - -assert('Return values of no expression case statement') do - when_value = - case - when true - 1 - end - - assert_equal 1, when_value -end - -assert('splat in case statement') do - values = [3,5,1,7,8] - testa = [1,2,7] - testb = [5,6] - resulta = [] - resultb = [] - resultc = [] - values.each do |value| - case value - when *testa - resulta << value - when *testb - resultb << value - else - resultc << value - end - end - - assert_equal [1,7], resulta - assert_equal [5], resultb - assert_equal [3,8], resultc -end - -assert('External command execution.') do - class << Kernel - sym = '`'.to_sym - alias_method :old_cmd, sym - - results = [] - define_method(sym) do |str| - results.push str - str - end - - `test` # NOVAL NODE_XSTR - `test dynamic #{sym}` # NOVAL NODE_DXSTR - assert_equal ['test', 'test dynamic `'], results - - t = `test` # VAL NODE_XSTR - assert_equal 'test', t - assert_equal ['test', 'test dynamic `', 'test'], results - - t = `test dynamic #{sym}` # VAL NODE_DXSTR - assert_equal 'test dynamic `', t - assert_equal ['test', 'test dynamic `', 'test', 'test dynamic `'], results - - alias_method sym, :old_cmd - end - true -end - -assert('parenthesed do-block in cmdarg') do - class ParenDoBlockCmdArg - def test(block) - block.call - end - end - x = ParenDoBlockCmdArg.new - result = x.test (Proc.new do :ok; end) - assert_equal :ok, result -end - -assert('method definition in cmdarg') do - if false - bar def foo; self.each do end end - end - true -end - -assert('optional argument in the rhs default expressions') do - class OptArgInRHS - def foo - "method called" - end - def t(foo = foo) - foo - end - def t2(foo = foo()) - foo - end - end - o = OptArgInRHS.new - assert_nil(o.t) - assert_equal("method called", o.t2) -end - -assert('optional block argument in the rhs default expressions') do - assert_nil(Proc.new {|foo = foo| foo}.call) -end - -assert('multiline comments work correctly') do -=begin -this is a comment with nothing after begin and end -=end -=begin this is a comment -this is a comment with extra after =begin -=end -=begin -this is a comment that has =end with spaces after it -=end -=begin this is a comment -this is a comment that has extra after =begin and =end with spaces after it -=end - line = __LINE__ -=begin this is a comment -this is a comment that has extra after =begin and =end with tabs after it -=end xxxxxxxxxxxxxxxxxxxxxxxxxx - assert_equal(line + 4, __LINE__) -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/true.rb nghttp2-0.6.7/third-party/mruby/test/t/true.rb --- nghttp2-1.13.0/third-party/mruby/test/t/true.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/true.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -## -# TrueClass ISO Test - -assert('TrueClass', '15.2.5') do - assert_equal Class, TrueClass.class -end - -assert('TrueClass true', '15.2.5.1') do - assert_true true - assert_equal TrueClass, true.class - assert_false TrueClass.method_defined? :new -end - -assert('TrueClass#&', '15.2.5.3.1') do - assert_true true.&(true) - assert_false true.&(false) -end - -assert('TrueClass#^', '15.2.5.3.2') do - assert_false true.^(true) - assert_true true.^(false) -end - -assert('TrueClass#to_s', '15.2.5.3.3') do - assert_equal 'true', true.to_s -end - -assert('TrueClass#|', '15.2.5.3.4') do - assert_true true.|(true) - assert_true true.|(false) -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/typeerror.rb nghttp2-0.6.7/third-party/mruby/test/t/typeerror.rb --- nghttp2-1.13.0/third-party/mruby/test/t/typeerror.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/typeerror.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -## -# TypeError ISO Test - -assert('TypeError', '15.2.29') do - assert_equal Class, TypeError.class -end diff -Nru nghttp2-1.13.0/third-party/mruby/test/t/unicode.rb nghttp2-0.6.7/third-party/mruby/test/t/unicode.rb --- nghttp2-1.13.0/third-party/mruby/test/t/unicode.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/test/t/unicode.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -# Test of the \u notation - -assert('bare \u notation test') do - # Mininum and maximum one byte characters - assert_equal("\u0000", "\x00") - assert_equal("\u007F", "\x7F") - - # Mininum and maximum two byte characters - assert_equal("\u0080", "\xC2\x80") - assert_equal("\u07FF", "\xDF\xBF") - - # Mininum and maximum three byte characters - assert_equal("\u0800", "\xE0\xA0\x80") - assert_equal("\uFFFF", "\xEF\xBF\xBF") - - # Four byte characters require the \U notation -end - -assert('braced \u notation test') do - # Mininum and maximum one byte characters - assert_equal("\u{0000}", "\x00") - assert_equal("\u{007F}", "\x7F") - - # Mininum and maximum two byte characters - assert_equal("\u{0080}", "\xC2\x80") - assert_equal("\u{07FF}", "\xDF\xBF") - - # Mininum and maximum three byte characters - assert_equal("\u{0800}", "\xE0\xA0\x80") - assert_equal("\u{FFFF}", "\xEF\xBF\xBF") - - # Mininum and maximum four byte characters - assert_equal("\u{10000}", "\xF0\x90\x80\x80") - assert_equal("\u{10FFFF}", "\xF4\x8F\xBF\xBF") -end diff -Nru nghttp2-1.13.0/third-party/mruby/TODO nghttp2-0.6.7/third-party/mruby/TODO --- nghttp2-1.13.0/third-party/mruby/TODO 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/TODO 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -Things to do (Things that are not done yet) - -* special variables ($1,$2..) -* super in aliased methods -* multi-assignment decomposing -* keyword arguments in def statement - -Things to improve (Done but things to fix) - -* Make additions as they are noticed. diff -Nru nghttp2-1.13.0/third-party/mruby/travis_config.rb nghttp2-0.6.7/third-party/mruby/travis_config.rb --- nghttp2-1.13.0/third-party/mruby/travis_config.rb 2016-07-21 13:47:53.000000000 +0000 +++ nghttp2-0.6.7/third-party/mruby/travis_config.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -MRuby::Build.new('debug') do |conf| - toolchain :gcc - enable_debug - - # include all core GEMs - conf.gembox 'full-core' - conf.cc.flags += %w(-Werror=declaration-after-statement) - conf.compilers.each do |c| - c.defines += %w(MRB_GC_STRESS MRB_GC_FIXED_ARENA) - end - - build_mrbc_exec -end - -MRuby::Build.new('full-debug') do |conf| - toolchain :gcc - enable_debug - - # include all core GEMs - conf.gembox 'full-core' - conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK) - - conf.enable_test -end - -MRuby::Build.new do |conf| - toolchain :gcc - - # include all core GEMs - conf.gembox 'full-core' - conf.cc.flags += %w(-Werror=declaration-after-statement) - conf.compilers.each do |c| - c.defines += %w(MRB_GC_FIXED_ARENA) - end - conf.enable_bintest - conf.enable_test -end - -MRuby::Build.new('cxx_abi') do |conf| - toolchain :gcc - - conf.gembox 'full-core' - conf.cc.flags += %w(-Werror=declaration-after-statement) - conf.compilers.each do |c| - c.defines += %w(MRB_GC_FIXED_ARENA) - end - conf.enable_bintest - conf.enable_test - - enable_cxx_abi - - build_mrbc_exec -end diff -Nru nghttp2-1.13.0/third-party/neverbleed/neverbleed.c nghttp2-0.6.7/third-party/neverbleed/neverbleed.c --- nghttp2-1.13.0/third-party/neverbleed/neverbleed.c 2016-07-21 13:47:55.000000000 +0000 +++ nghttp2-0.6.7/third-party/neverbleed/neverbleed.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,940 +0,0 @@ -/* - * Copyright (c) 2015 Kazuho Oku, DeNA Co., Ltd. - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __linux__ -#include -#endif -#include "neverbleed.h" - -struct expbuf_t { - char *buf; - char *start; - char *end; - size_t capacity; -}; - -struct st_neverbleed_rsa_exdata_t { - neverbleed_t *nb; - size_t key_index; -}; - -struct st_neverbleed_thread_data_t { - pid_t self_pid; - int fd; -}; - -static void warnvf(const char *fmt, va_list args) -{ - char errbuf[256]; - - if (errno != 0) { - strerror_r(errno, errbuf, sizeof(errbuf)); - } else { - errbuf[0] = '\0'; - } - - fprintf(stderr, "[openssl-privsep] "); - vfprintf(stderr, fmt, args); - if (errbuf[0] != '\0') - fputs(errbuf, stderr); - fputc('\n', stderr); -} - -__attribute__((format(printf, 1, 2))) static void warnf(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - warnvf(fmt, args); - va_end(args); -} - -__attribute__((format(printf, 1, 2), noreturn)) static void dief(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - warnvf(fmt, args); - va_end(args); - - abort(); -} - -static char *dirname(const char *path) -{ - const char *last_slash = strrchr(path, '/'); - char *ret; - - if (last_slash == NULL) { - errno = 0; - dief("dirname: no slash in given path:%s", path); - } - if ((ret = malloc(last_slash + 1 - path)) == NULL) - dief("no memory"); - memcpy(ret, path, last_slash - path); - ret[last_slash - path] = '\0'; - return ret; -} - -static void set_cloexec(int fd) -{ - if (fcntl(fd, F_SETFD, O_CLOEXEC) == -1) - dief("failed to set O_CLOEXEC to fd %d", fd); -} - -static int read_nbytes(int fd, void *p, size_t sz) -{ - while (sz != 0) { - ssize_t r; - while ((r = read(fd, p, sz)) == -1 && errno == EINTR) - ; - if (r == -1) { - return -1; - } else if (r == 0) { - errno = 0; - return -1; - } - p = (char *)p + r; - sz -= r; - } - return 0; -} - -static size_t expbuf_size(struct expbuf_t *buf) -{ - return buf->end - buf->start; -} - -static void expbuf_dispose(struct expbuf_t *buf) -{ - if (buf->capacity != 0) - OPENSSL_cleanse(buf->buf, buf->capacity); - free(buf->buf); - memset(buf, 0, sizeof(*buf)); -} - -static void expbuf_reserve(struct expbuf_t *buf, size_t extra) -{ - char *n; - - if (extra <= buf->buf + buf->capacity - buf->end) - return; - - if (buf->capacity == 0) - buf->capacity = 4096; - while (buf->buf + buf->capacity - buf->end < extra) - buf->capacity *= 2; - if ((n = realloc(buf->buf, buf->capacity)) == NULL) - dief("realloc failed"); - buf->start += n - buf->buf; - buf->end += n - buf->buf; - buf->buf = n; -} - -static void expbuf_push_num(struct expbuf_t *buf, size_t v) -{ - expbuf_reserve(buf, sizeof(v)); - memcpy(buf->end, &v, sizeof(v)); - buf->end += sizeof(v); -} - -static void expbuf_push_str(struct expbuf_t *buf, const char *s) -{ - size_t l = strlen(s) + 1; - expbuf_reserve(buf, l); - memcpy(buf->end, s, l); - buf->end += l; -} - -static void expbuf_push_bytes(struct expbuf_t *buf, const void *p, size_t l) -{ - expbuf_push_num(buf, l); - expbuf_reserve(buf, l); - memcpy(buf->end, p, l); - buf->end += l; -} - -static int expbuf_shift_num(struct expbuf_t *buf, size_t *v) -{ - if (expbuf_size(buf) < sizeof(*v)) - return -1; - memcpy(v, buf->start, sizeof(*v)); - buf->start += sizeof(*v); - return 0; -} - -static char *expbuf_shift_str(struct expbuf_t *buf) -{ - char *nul = memchr(buf->start, '\0', expbuf_size(buf)), *ret; - if (nul == NULL) - return NULL; - ret = buf->start; - buf->start = nul + 1; - return ret; -} - -static void *expbuf_shift_bytes(struct expbuf_t *buf, size_t *l) -{ - void *ret; - if (expbuf_shift_num(buf, l) != 0) - return NULL; - if (expbuf_size(buf) < *l) - return NULL; - ret = buf->start; - buf->start += *l; - return ret; -} - -static int expbuf_write(struct expbuf_t *buf, int fd) -{ - struct iovec vecs[2] = {}; - size_t bufsz = expbuf_size(buf); - int vecindex; - ssize_t r; - - vecs[0].iov_base = &bufsz; - vecs[0].iov_len = sizeof(bufsz); - vecs[1].iov_base = buf->start; - vecs[1].iov_len = bufsz; - - for (vecindex = 0; vecindex != sizeof(vecs) / sizeof(vecs[0]);) { - while ((r = writev(fd, vecs + vecindex, sizeof(vecs) / sizeof(vecs[0]) - vecindex)) == -1 && errno == EINTR) - ; - if (r == -1) - return -1; - assert(r != 0); - while (r != 0 && r >= vecs[vecindex].iov_len) { - r -= vecs[vecindex].iov_len; - ++vecindex; - } - if (r != 0) { - vecs[vecindex].iov_base += r; - vecs[vecindex].iov_len -= r; - } - } - - return 0; -} - -static int expbuf_read(struct expbuf_t *buf, int fd) -{ - size_t sz; - - if (read_nbytes(fd, &sz, sizeof(sz)) != 0) - return -1; - expbuf_reserve(buf, sz); - if (read_nbytes(fd, buf->end, sz) != 0) - return -1; - buf->end += sz; - return 0; -} - -static void unlink_dir(const char *path) -{ - DIR *dp; - char buf[PATH_MAX]; - - if ((dp = opendir(path)) != NULL) { - struct dirent entbuf, *entp; - while (readdir_r(dp, &entbuf, &entp) == 0 && entp != NULL) { - if (strcmp(entp->d_name, ".") == 0 || strcmp(entp->d_name, "..") == 0) - continue; - snprintf(buf, sizeof(buf), "%s/%s", path, entp->d_name); - unlink_dir(buf); - } - closedir(dp); - } - unlink(path); - rmdir(path); -} - -void dispose_thread_data(void *_thdata) -{ - struct st_neverbleed_thread_data_t *thdata = _thdata; - assert(thdata->fd >= 0); - close(thdata->fd); - thdata->fd = -1; -} - -struct st_neverbleed_thread_data_t *get_thread_data(neverbleed_t *nb) -{ - struct st_neverbleed_thread_data_t *thdata; - pid_t self_pid = getpid(); - ssize_t r; - - if ((thdata = pthread_getspecific(nb->thread_key)) != NULL) { - if (thdata->self_pid == self_pid) - return thdata; - /* we have been forked! */ - close(thdata->fd); - } else { - if ((thdata = malloc(sizeof(*thdata))) == NULL) - dief("malloc failed"); - } - - thdata->self_pid = self_pid; -#ifdef SOCK_CLOEXEC - if ((thdata->fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) - dief("socket(2) failed"); -#else - if ((thdata->fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) - dief("socket(2) failed"); - set_cloexec(thdata->fd); -#endif - while (connect(thdata->fd, (void *)&nb->sun_, sizeof(nb->sun_)) != 0) - if (errno != EINTR) - dief("failed to connect to privsep daemon"); - while ((r = write(thdata->fd, nb->auth_token, sizeof(nb->auth_token))) == -1 && errno == EINTR) - ; - if (r != sizeof(nb->auth_token)) - dief("failed to send authentication token"); - pthread_setspecific(nb->thread_key, thdata); - - return thdata; -} - -static void get_privsep_data(const RSA *rsa, struct st_neverbleed_rsa_exdata_t **exdata, - struct st_neverbleed_thread_data_t **thdata) -{ - *exdata = RSA_get_ex_data(rsa, 0); - if (*exdata == NULL) { - errno = 0; - dief("invalid internal ref"); - } - *thdata = get_thread_data((*exdata)->nb); -} - -static struct { - struct { - pthread_mutex_t lock; - size_t size; - RSA **keys; - } keys; - neverbleed_t *nb; -} daemon_vars = {{PTHREAD_MUTEX_INITIALIZER}}; - -static RSA *daemon_get_rsa(size_t key_index) -{ - RSA *rsa; - - pthread_mutex_lock(&daemon_vars.keys.lock); - rsa = daemon_vars.keys.keys[key_index]; - pthread_mutex_unlock(&daemon_vars.keys.lock); - - return rsa; -} - -static size_t daemon_set_rsa(RSA *rsa) -{ - size_t index; - - pthread_mutex_lock(&daemon_vars.keys.lock); - if ((daemon_vars.keys.keys = realloc(daemon_vars.keys.keys, sizeof(*daemon_vars.keys.keys) * (daemon_vars.keys.size + 1))) == - NULL) - dief("no memory"); - index = daemon_vars.keys.size++; - daemon_vars.keys.keys[index] = rsa; - RSA_up_ref(rsa); - pthread_mutex_unlock(&daemon_vars.keys.lock); - - return index; -} - -static int priv_encdec_proxy(const char *cmd, int flen, const unsigned char *from, unsigned char *_to, RSA *rsa, int padding) -{ - struct st_neverbleed_rsa_exdata_t *exdata; - struct st_neverbleed_thread_data_t *thdata; - struct expbuf_t buf = {}; - size_t ret; - unsigned char *to; - size_t tolen; - - get_privsep_data(rsa, &exdata, &thdata); - - expbuf_push_str(&buf, cmd); - expbuf_push_bytes(&buf, from, flen); - expbuf_push_num(&buf, exdata->key_index); - expbuf_push_num(&buf, padding); - if (expbuf_write(&buf, thdata->fd) != 0) - dief(errno != 0 ? "write error" : "connection closed by daemon"); - expbuf_dispose(&buf); - - if (expbuf_read(&buf, thdata->fd) != 0) - dief(errno != 0 ? "read error" : "connection closed by daemon"); - if (expbuf_shift_num(&buf, &ret) != 0 || (to = expbuf_shift_bytes(&buf, &tolen)) == NULL) { - errno = 0; - dief("failed to parse response"); - } - memcpy(_to, to, tolen); - expbuf_dispose(&buf); - - return (int)ret; -} - -static int priv_encdec_stub(const char *name, - int (*func)(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding), - struct expbuf_t *buf) -{ - unsigned char *from, to[4096]; - size_t flen; - size_t key_index, padding; - RSA *rsa; - int ret; - - if ((from = expbuf_shift_bytes(buf, &flen)) == NULL || expbuf_shift_num(buf, &key_index) != 0 || - expbuf_shift_num(buf, &padding) != 0) { - errno = 0; - warnf("%s: failed to parse request", name); - return -1; - } - if ((rsa = daemon_get_rsa(key_index)) == NULL) { - errno = 0; - warnf("%s: invalid key index:%zu\n", name, key_index); - return -1; - } - ret = func((int)flen, from, to, rsa, (int)padding); - expbuf_dispose(buf); - - expbuf_push_num(buf, ret); - expbuf_push_bytes(buf, to, ret > 0 ? ret : 0); - - return 0; -} - -static int priv_enc_proxy(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) -{ - return priv_encdec_proxy("priv_enc", flen, from, to, rsa, padding); -} - -static int priv_enc_stub(struct expbuf_t *buf) -{ - return priv_encdec_stub(__FUNCTION__, RSA_private_encrypt, buf); -} - -static int priv_dec_proxy(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) -{ - return priv_encdec_proxy("priv_dec", flen, from, to, rsa, padding); -} - -static int priv_dec_stub(struct expbuf_t *buf) -{ - return priv_encdec_stub(__FUNCTION__, RSA_private_decrypt, buf); -} - -static int sign_proxy(int type, const unsigned char *m, unsigned int m_len, unsigned char *_sigret, unsigned *_siglen, - const RSA *rsa) -{ - struct st_neverbleed_rsa_exdata_t *exdata; - struct st_neverbleed_thread_data_t *thdata; - struct expbuf_t buf = {}; - size_t ret, siglen; - unsigned char *sigret; - - get_privsep_data(rsa, &exdata, &thdata); - - expbuf_push_str(&buf, "sign"); - expbuf_push_num(&buf, type); - expbuf_push_bytes(&buf, m, m_len); - expbuf_push_num(&buf, exdata->key_index); - if (expbuf_write(&buf, thdata->fd) != 0) - dief(errno != 0 ? "write error" : "connection closed by daemon"); - expbuf_dispose(&buf); - - if (expbuf_read(&buf, thdata->fd) != 0) - dief(errno != 0 ? "read error" : "connection closed by daemon"); - if (expbuf_shift_num(&buf, &ret) != 0 || (sigret = expbuf_shift_bytes(&buf, &siglen)) == NULL) { - errno = 0; - dief("failed to parse response"); - } - memcpy(_sigret, sigret, siglen); - *_siglen = (unsigned)siglen; - expbuf_dispose(&buf); - - return (int)ret; -} - -static int sign_stub(struct expbuf_t *buf) -{ - unsigned char *m, sigret[4096]; - size_t type, m_len, key_index; - RSA *rsa; - unsigned siglen = 0; - int ret; - - if (expbuf_shift_num(buf, &type) != 0 || (m = expbuf_shift_bytes(buf, &m_len)) == NULL || - expbuf_shift_num(buf, &key_index) != 0) { - errno = 0; - warnf("%s: failed to parse request", __FUNCTION__); - return -1; - } - if ((rsa = daemon_get_rsa(key_index)) == NULL) { - errno = 0; - warnf("%s: invalid key index:%zu", __FUNCTION__, key_index); - return -1; - } - ret = RSA_sign((int)type, m, (unsigned)m_len, sigret, &siglen, rsa); - expbuf_dispose(buf); - - expbuf_push_num(buf, ret); - expbuf_push_bytes(buf, sigret, ret == 1 ? siglen : 0); - - return 0; -} - -static EVP_PKEY *create_pkey(neverbleed_t *nb, size_t key_index, const char *ebuf, const char *nbuf) -{ - struct st_neverbleed_rsa_exdata_t *exdata; - RSA *rsa; - EVP_PKEY *pkey; - - if ((exdata = malloc(sizeof(*exdata))) == NULL) { - fprintf(stderr, "no memory\n"); - abort(); - } - exdata->nb = nb; - exdata->key_index = key_index; - - rsa = RSA_new_method(nb->engine); - RSA_set_ex_data(rsa, 0, exdata); - if (BN_hex2bn(&rsa->e, ebuf) == 0) { - fprintf(stderr, "failed to parse e:%s\n", ebuf); - abort(); - } - if (BN_hex2bn(&rsa->n, nbuf) == 0) { - fprintf(stderr, "failed to parse n:%s\n", nbuf); - abort(); - } - rsa->flags |= RSA_FLAG_EXT_PKEY; - - pkey = EVP_PKEY_new(); - EVP_PKEY_set1_RSA(pkey, rsa); - RSA_free(rsa); - - return pkey; -} - -int neverbleed_load_private_key_file(neverbleed_t *nb, SSL_CTX *ctx, const char *fn, char *errbuf) -{ - struct st_neverbleed_thread_data_t *thdata = get_thread_data(nb); - struct expbuf_t buf = {}; - size_t ret, key_index; - char *estr, *nstr, *errstr; - EVP_PKEY *pkey; - - expbuf_push_str(&buf, "load_key"); - expbuf_push_str(&buf, fn); - if (expbuf_write(&buf, thdata->fd) != 0) - dief(errno != 0 ? "write error" : "connection closed by daemon"); - expbuf_dispose(&buf); - - if (expbuf_read(&buf, thdata->fd) != 0) - dief(errno != 0 ? "read error" : "connection closed by daemon"); - if (expbuf_shift_num(&buf, &ret) != 0 || expbuf_shift_num(&buf, &key_index) != 0 || (estr = expbuf_shift_str(&buf)) == NULL || - (nstr = expbuf_shift_str(&buf)) == NULL || (errstr = expbuf_shift_str(&buf)) == NULL) { - errno = 0; - dief("failed to parse response"); - } - - if (ret != 1) { - snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "%s", errstr); - return -1; - } - - /* success */ - pkey = create_pkey(nb, key_index, estr, nstr); - if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) { - snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "SSL_CTX_use_PrivateKey failed"); - ret = 0; - } - EVP_PKEY_free(pkey); - return (int)ret; -} - -static int load_key_stub(struct expbuf_t *buf) -{ - char *fn; - FILE *fp = NULL; - RSA *rsa = NULL; - size_t key_index = SIZE_MAX; - char *estr = NULL, *nstr = NULL, errbuf[NEVERBLEED_ERRBUF_SIZE] = ""; - - if ((fn = expbuf_shift_str(buf)) == NULL) { - warnf("%s: failed to parse request", __FUNCTION__); - return -1; - } - - if ((fp = fopen(fn, "rt")) == NULL) { - strerror_r(errno, errbuf, sizeof(errbuf)); - goto Respond; - } - if ((rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)) == NULL) { - snprintf(errbuf, sizeof(errbuf), "failed to parse the private key"); - goto Respond; - } - key_index = daemon_set_rsa(rsa); - estr = BN_bn2hex(rsa->e); - nstr = BN_bn2hex(rsa->n); - -Respond: - expbuf_dispose(buf); - expbuf_push_num(buf, rsa != NULL); - expbuf_push_num(buf, key_index); - expbuf_push_str(buf, estr != NULL ? estr : ""); - expbuf_push_str(buf, nstr != NULL ? nstr : ""); - expbuf_push_str(buf, errbuf); - if (rsa != NULL) - RSA_free(rsa); - if (estr != NULL) - OPENSSL_free(estr); - if (nstr != NULL) - OPENSSL_free(nstr); - if (fp != NULL) - fclose(fp); - - return 0; -} - -int neverbleed_setuidgid(neverbleed_t *nb, const char *user, int change_socket_ownership) -{ - struct st_neverbleed_thread_data_t *thdata = get_thread_data(nb); - struct expbuf_t buf = {}; - size_t ret; - - expbuf_push_str(&buf, "setuidgid"); - expbuf_push_str(&buf, user); - expbuf_push_num(&buf, change_socket_ownership); - if (expbuf_write(&buf, thdata->fd) != 0) - dief(errno != 0 ? "write error" : "connection closed by daemon"); - expbuf_dispose(&buf); - - if (expbuf_read(&buf, thdata->fd) != 0) - dief(errno != 0 ? "read error" : "connection closed by daemon"); - if (expbuf_shift_num(&buf, &ret) != 0) { - errno = 0; - dief("failed to parse response"); - } - expbuf_dispose(&buf); - - return (int)ret; -} - -static int setuidgid_stub(struct expbuf_t *buf) -{ - const char *user; - size_t change_socket_ownership; - struct passwd pwbuf, *pw; - char pwstrbuf[65536]; /* should be large enough */ - int ret = -1; - - if ((user = expbuf_shift_str(buf)) == NULL || expbuf_shift_num(buf, &change_socket_ownership) != 0) { - errno = 0; - warnf("%s: failed to parse request", __FUNCTION__); - return -1; - } - - errno = 0; - if (getpwnam_r(user, &pwbuf, pwstrbuf, sizeof(pwstrbuf), &pw) != 0) { - warnf("%s: getpwnam_r failed", __FUNCTION__); - goto Respond; - } - if (pw == NULL) { - warnf("%s: failed to obtain information of user:%s", __FUNCTION__, user); - goto Respond; - } - - if (change_socket_ownership) { - char *dir; - if (chown(daemon_vars.nb->sun_.sun_path, pw->pw_uid, pw->pw_gid) != 0) - dief("chown failed for:%s", daemon_vars.nb->sun_.sun_path); - dir = dirname(daemon_vars.nb->sun_.sun_path); - if (chown(dir, pw->pw_uid, pw->pw_gid) != 0) - dief("chown failed for:%s", dir); - free(dir); - } - - /* setuidgid */ - if (setgid(pw->pw_gid) != 0) { - warnf("%s: setgid(%d) failed", __FUNCTION__, (int)pw->pw_gid); - goto Respond; - } - if (initgroups(pw->pw_name, pw->pw_gid) != 0) { - warnf("%s: initgroups(%s, %d) failed", __FUNCTION__, pw->pw_name, (int)pw->pw_gid); - goto Respond; - } - if (setuid(pw->pw_uid) != 0) { - warnf("%s: setuid(%d) failed\n", __FUNCTION__, (int)pw->pw_uid); - goto Respond; - } - ret = 0; - -Respond: - expbuf_dispose(buf); - expbuf_push_num(buf, ret); - return 0; -} - -__attribute__((noreturn)) static void *daemon_close_notify_thread(void *_close_notify_fd) -{ - int close_notify_fd = (int)((char *)_close_notify_fd - (char *)NULL); - char b; - ssize_t r; - -Redo: - r = read(close_notify_fd, &b, 1); - if (r == -1 && errno == EINTR) - goto Redo; - if (r > 0) - goto Redo; - /* close or error */ - - /* unlink the temporary directory and socket file */ - unlink_dir(dirname(daemon_vars.nb->sun_.sun_path)); - - _exit(0); -} - -static void *daemon_conn_thread(void *_sock_fd) -{ - int sock_fd = (int)((char *)_sock_fd - (char *)NULL); - struct expbuf_t buf = {}; - unsigned char auth_token[NEVERBLEED_AUTH_TOKEN_SIZE]; - - /* authenticate */ - if (read_nbytes(sock_fd, &auth_token, sizeof(auth_token)) != 0) { - warnf("failed to receive authencication token from client"); - goto Exit; - } - if (memcmp(auth_token, daemon_vars.nb->auth_token, NEVERBLEED_AUTH_TOKEN_SIZE) != 0) { - warnf("client authentication failed"); - goto Exit; - } - - while (1) { - char *cmd; - if (expbuf_read(&buf, sock_fd) != 0) { - if (errno != 0) - warnf("read error"); - break; - } - if ((cmd = expbuf_shift_str(&buf)) == NULL) { - errno = 0; - warnf("failed to parse request"); - break; - } - if (strcmp(cmd, "priv_enc") == 0) { - if (priv_enc_stub(&buf) != 0) - break; - } else if (strcmp(cmd, "priv_dec") == 0) { - if (priv_dec_stub(&buf) != 0) - break; - } else if (strcmp(cmd, "sign") == 0) { - if (sign_stub(&buf) != 0) - break; - } else if (strcmp(cmd, "load_key") == 0) { - if (load_key_stub(&buf) != 0) - break; - } else if (strcmp(cmd, "setuidgid") == 0) { - if (setuidgid_stub(&buf) != 0) - break; - } else { - warnf("unknown command:%s", cmd); - break; - } - if (expbuf_write(&buf, sock_fd) != 0) { - warnf(errno != 0 ? "write error" : "connection closed by client"); - break; - } - expbuf_dispose(&buf); - } - -Exit: - expbuf_dispose(&buf); - close(sock_fd); - - return NULL; -} - -__attribute__((noreturn)) static void daemon_main(int listen_fd, int close_notify_fd, const char *tempdir) -{ - pthread_t tid; - pthread_attr_t thattr; - int sock_fd; - - { /* close all descriptors (except STDIN, STDOUT, STRERR, listen_fd, close_notify_fd) */ - int fd = (int)sysconf(_SC_OPEN_MAX) - 1; - for (; fd > 2; --fd) { - if (fd == listen_fd || fd == close_notify_fd) - continue; - close(fd); - } - } - - pthread_attr_init(&thattr); - pthread_attr_setdetachstate(&thattr, 1); - - if (pthread_create(&tid, &thattr, daemon_close_notify_thread, (char *)NULL + close_notify_fd) != 0) - dief("pthread_create failed"); - - while (1) { - while ((sock_fd = accept(listen_fd, NULL, NULL)) == -1) - ; - if (pthread_create(&tid, &thattr, daemon_conn_thread, (char *)NULL + sock_fd) != 0) - dief("pthread_create failed"); - } -} - -static RSA_METHOD rsa_method = { - "privsep RSA method", /* name */ - NULL, /* rsa_pub_enc */ - NULL, /* rsa_pub_dec */ - priv_enc_proxy, /* rsa_priv_enc */ - priv_dec_proxy, /* rsa_priv_dec */ - NULL, /* rsa_mod_exp */ - NULL, /* bn_mod_exp */ - NULL, /* init */ - NULL, /* finish */ -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100001L - 0, /* flags */ -#else - RSA_FLAG_SIGN_VER, /* flags */ -#endif - NULL, /* app data */ - sign_proxy, /* rsa_sign */ - NULL, /* rsa_verify */ - NULL /* rsa_keygen */ -}; - -int neverbleed_init(neverbleed_t *nb, char *errbuf) -{ - int pipe_fds[2] = {-1, -1}, listen_fd = -1; - char *tempdir = NULL; - -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100001L - const RSA_METHOD *default_method = RSA_PKCS1_OpenSSL(); -#else - const RSA_METHOD *default_method = RSA_PKCS1_SSLeay(); -#endif - rsa_method.rsa_pub_enc = default_method->rsa_pub_enc; - rsa_method.rsa_pub_dec = default_method->rsa_pub_dec; - rsa_method.rsa_verify = default_method->rsa_verify; - - /* setup the daemon */ - if (pipe(pipe_fds) != 0) { - snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "pipe(2) failed:%s", strerror(errno)); - goto Fail; - } - set_cloexec(pipe_fds[1]); - if ((tempdir = strdup("/tmp/openssl-privsep.XXXXXX")) == NULL) { - snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "no memory"); - goto Fail; - } - if (mkdtemp(tempdir) == NULL) { - snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to create temporary directory under /tmp:%s", strerror(errno)); - goto Fail; - } - memset(&nb->sun_, 0, sizeof(nb->sun_)); - nb->sun_.sun_family = AF_UNIX; - snprintf(nb->sun_.sun_path, sizeof(nb->sun_.sun_path), "%s/_", tempdir); - RAND_bytes(nb->auth_token, sizeof(nb->auth_token)); - if ((listen_fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { - snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "socket(2) failed:%s", strerror(errno)); - goto Fail; - } - if (bind(listen_fd, (void *)&nb->sun_, sizeof(nb->sun_)) != 0) { - snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to bind to %s:%s", nb->sun_.sun_path, strerror(errno)); - goto Fail; - } - if (listen(listen_fd, SOMAXCONN) != 0) { - snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "listen(2) failed:%s", strerror(errno)); - goto Fail; - } - nb->daemon_pid = fork(); - switch (nb->daemon_pid) { - case -1: - snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "fork(2) failed:%s", strerror(errno)); - goto Fail; - case 0: - close(pipe_fds[1]); -#ifdef __linux__ - prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); -#endif - daemon_vars.nb = nb; - daemon_main(listen_fd, pipe_fds[0], tempdir); - break; - default: - break; - } - close(listen_fd); - listen_fd = -1; - close(pipe_fds[0]); - pipe_fds[0] = -1; - - /* setup engine */ - if ((nb->engine = ENGINE_new()) == NULL || !ENGINE_set_id(nb->engine, "neverbleed") || - !ENGINE_set_name(nb->engine, "privilege separation software engine") || !ENGINE_set_RSA(nb->engine, &rsa_method)) { - snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to initialize the OpenSSL engine"); - goto Fail; - } - ENGINE_add(nb->engine); - - /* setup thread key */ - pthread_key_create(&nb->thread_key, dispose_thread_data); - - free(tempdir); - return 0; -Fail: - if (pipe_fds[0] != -1) - close(pipe_fds[0]); - if (pipe_fds[1] != -1) - close(pipe_fds[1]); - if (tempdir != NULL) { - unlink_dir(tempdir); - free(tempdir); - } - if (listen_fd != -1) - close(listen_fd); - if (nb->engine != NULL) { - ENGINE_free(nb->engine); - nb->engine = NULL; - } - return -1; -} diff -Nru nghttp2-1.13.0/third-party/neverbleed/neverbleed.h nghttp2-0.6.7/third-party/neverbleed/neverbleed.h --- nghttp2-1.13.0/third-party/neverbleed/neverbleed.h 2016-07-21 13:47:55.000000000 +0000 +++ nghttp2-0.6.7/third-party/neverbleed/neverbleed.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2015 Kazuho Oku, DeNA Co., Ltd. - * - * 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 NEVERBLEED_H -#define NEVERBLEED_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define NEVERBLEED_ERRBUF_SIZE (256) -#define NEVERBLEED_AUTH_TOKEN_SIZE 32 - -typedef struct st_neverbleed_t { - ENGINE *engine; - pid_t daemon_pid; - struct sockaddr_un sun_; - pthread_key_t thread_key; - unsigned char auth_token[NEVERBLEED_AUTH_TOKEN_SIZE]; -} neverbleed_t; - -/** - * initializes the privilege separation engine (returns 0 if successful) - */ -int neverbleed_init(neverbleed_t *nb, char *errbuf); -/** - * loads a private key file (returns 1 if successful) - */ -int neverbleed_load_private_key_file(neverbleed_t *nb, SSL_CTX *ctx, const char *fn, char *errbuf); -/** - * setuidgid (also changes the file permissions so that `user` can connect to the daemon, if change_socket_ownership is non-zero) - */ -int neverbleed_setuidgid(neverbleed_t *nb, const char *user, int change_socket_ownership); - -#ifdef __cplusplus -} -#endif - -#endif