From fee5d2bcfdf355a543c69e2dd1e3ae30d19c1841 Mon Sep 17 00:00:00 2001 From: stefanocasazza Date: Fri, 24 Feb 2017 19:00:25 +0100 Subject: [PATCH] load balance implementation --- configure | 39 +- configure.ac | 19 +- fuzz/Makefile.am | 4 +- fuzz/Makefile.in | 4 +- fuzz/build_libFuzzer.sh | 2 +- include/ulib/base/utility.h | 41 +- include/ulib/container/gen_hash_map.h | 56 +- include/ulib/container/hash_map.h | 35 +- include/ulib/container/vector.h | 50 +- include/ulib/examples/wi_auth_declaration.h | 5 +- include/ulib/internal/config.h.in | 3 + include/ulib/internal/memory_pool.h | 6 +- include/ulib/net/client/client.h | 27 + include/ulib/net/client/http.h | 2 + include/ulib/net/ipaddress.h | 16 +- include/ulib/net/server/client_image.h | 31 +- include/ulib/net/server/plugin/mod_nocat.h | 19 +- include/ulib/net/server/server.h | 24 +- include/ulib/net/socket.h | 2 + include/ulib/orm/driver/orm_driver_sqlite.h | 2 +- include/ulib/string.h | 8 +- include/ulib/utility/bit_array.h | 211 ++++++ include/ulib/utility/http2.h | 228 ++++-- include/ulib/utility/uhttp.h | 51 +- m4/ac_compilation_options.m4 | 11 + src/ulib/Makefile.am | 2 +- src/ulib/Makefile.in | 23 +- src/ulib/all_cpp.cpp | 1 + src/ulib/base/utility.c | 36 + src/ulib/internal/memory_pool.cpp | 11 +- src/ulib/json/value.cpp | 4 + src/ulib/net/client/http.cpp | 9 +- src/ulib/net/ipaddress.cpp | 147 ++-- src/ulib/net/server/client_image.cpp | 14 +- src/ulib/net/server/plugin/mod_nocat.cpp | 26 +- src/ulib/net/server/plugin/usp/businesses.usp | 73 +- .../net/server/plugin/usp/usp_translator.cpp | 166 +++-- src/ulib/net/server/server.cpp | 148 +++- src/ulib/net/socket.cpp | 8 +- src/ulib/net/socket_address.cpp | 48 +- src/ulib/utility/bit_array.cpp | 56 ++ src/ulib/utility/http2.cpp | 669 ++++++++++++------ src/ulib/utility/uhttp.cpp | 103 ++- .../benchmark/docroot/uploads/web_server.test | 245 ------- tests/examples/businesses.test | 4 + tests/examples/inp/http/businesses4.req | 7 + tests/examples/ok/businesses.ok | 23 +- tests/examples/tsa_https.test | 1 + tests/examples/tsa_rpc.test | 3 +- tests/examples/web_server.sh | 4 +- tests/examples/web_server_multiclient.test | 2 +- tests/ulib/Makefile.am | 13 +- tests/ulib/Makefile.in | 255 +++---- tests/ulib/bit_array.test | 18 + tests/ulib/http2/hencode.cpp | 6 +- tests/ulib/ok/bit_array.ok | 0 tests/ulib/rdb_client_server.test | 1 + tests/ulib/server.test | 3 +- tests/ulib/server_rpc.test | 1 + tests/ulib/test_bit_array.cpp | 63 ++ tests/ulib/test_cdb.cpp | 2 +- tests/ulib/test_elasticsearch.cpp | 2 +- tests/ulib/test_entity.cpp | 2 +- tests/ulib/test_file_config.cpp | 2 +- tests/ulib/test_header.cpp | 2 +- tests/ulib/test_http.cpp | 2 +- tests/ulib/test_https.cpp | 2 +- tests/ulib/test_json.cpp | 2 +- tests/ulib/test_log.cpp | 2 +- tests/ulib/test_pkcs7.cpp | 2 +- tests/ulib/test_rdb.cpp | 2 +- tests/ulib/test_rdb_client.cpp | 2 +- tests/ulib/test_rdb_server.cpp | 2 +- tests/ulib/test_redis.cpp | 2 +- tests/ulib/test_server.cpp | 2 +- tests/ulib/test_soap_client.cpp | 2 +- tests/ulib/test_soap_server.cpp | 2 +- tests/ulib/test_ssl_client.cpp | 2 +- tests/ulib/test_ssl_server.cpp | 2 +- tests/ulib/test_tokenizer.cpp | 2 +- tests/ulib/test_unixsocket_client.cpp | 2 +- tests/ulib/test_unixsocket_server.cpp | 2 +- 82 files changed, 2039 insertions(+), 1094 deletions(-) create mode 100644 include/ulib/utility/bit_array.h create mode 100644 src/ulib/utility/bit_array.cpp delete mode 100644 tests/examples/benchmark/docroot/uploads/web_server.test create mode 100644 tests/examples/inp/http/businesses4.req create mode 100755 tests/ulib/bit_array.test create mode 100644 tests/ulib/ok/bit_array.ok create mode 100644 tests/ulib/test_bit_array.cpp diff --git a/configure b/configure index ee499fccb..d31f4e0d2 100755 --- a/configure +++ b/configure @@ -1054,6 +1054,7 @@ enable_ACL enable_RFC1918 enable_HSTS enable_HPS +enable_load_balance with_parser with_distcc with_libz @@ -1796,6 +1797,7 @@ Optional Features: --enable-RFC1918 enable RFC1918 filtering support [default=no] --enable-HSTS enable HTTP Strict Transport Security support [default=no] --enable-HPS enable HTML Pagination Support [default=no] + --enable-load-balance enable load balance support between physical server via udp brodcast [default=no] --enable-zip enable build of ZIP support - require libz [default: use if present libz] --enable-ssl-staticlib-deps link with dependencies of OpenSSL's static libraries. Must be specified in addition to --with-ssl [default=no] --enable-curl-staticlib-deps link with dependencies of cURL's static libraries. Must be specified in addition to --with-curl [default=no] @@ -26593,6 +26595,24 @@ $as_echo "#define U_HTML_PAGINATION_SUPPORT 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_HPS" >&5 $as_echo "$enable_HPS" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if you want to enable load balance support between physical server via udp brodcast" >&5 +$as_echo_n "checking if you want to enable load balance support between physical server via udp brodcast... " >&6; } + # Check whether --enable-load-balance was given. +if test "${enable_load_balance+set}" = set; then : + enableval=$enable_load_balance; +fi + + if test -z "$enable_load_balance"; then + enable_load_balance="no" + fi + if test "$enable_load_balance" = "yes"; then + +$as_echo "#define USE_LOAD_BALANCE 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_load_balance" >&5 +$as_echo "$enable_load_balance" >&6; } + # SECTION 3: check for programs @@ -36605,14 +36625,14 @@ if test -n "$AWK"; then cd ../../.. fi -# Verify the integrity of the current configuration - echo echo "***" -CPPFLAGS="-DHAVE_CONFIG_H -I${srcdir}/include $CPPFLAGS" +# Verify the integrity of the current configuration +if test "$cross_compiling" != "yes"; then + CPPFLAGS="-DHAVE_CONFIG_H -I${srcdir}/include $CPPFLAGS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if generated configuration is usable" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if generated configuration is usable" >&5 $as_echo_n "checking if generated configuration is usable... " >&6; } if ${ac_cv_configuration_is_usable+:} false; then : $as_echo_n "(cached) " >&6 @@ -36641,11 +36661,12 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_configuration_is_usable" >&5 $as_echo "$ac_cv_configuration_is_usable" >&6; } -if test "$ac_cv_configuration_is_usable" = "no" ; then - # It appears that ulib/internal/common.cpp not compiled. If it didn't compile then there would be no chance that the rest would compile. - as_fn_error $? "The generated configuration appears to be unusable. - Please verify that your system path and environment variables are correct." "$LINENO" 5 - exit 1 + if test "$ac_cv_configuration_is_usable" = "no" ; then + # It appears that ulib/internal/common.cpp not compiled. If it didn't compile then there would be no chance that the rest would compile. + as_fn_error $? "The generated configuration appears to be unusable. + Please verify that your system path and environment variables are correct." "$LINENO" 5 + exit 1 + fi fi echo diff --git a/configure.ac b/configure.ac index d48275b06..3176f1a8e 100644 --- a/configure.ac +++ b/configure.ac @@ -2744,24 +2744,25 @@ if test -n "$AWK"; then cd ../../.. fi -# Verify the integrity of the current configuration - echo echo "***" -CPPFLAGS="-DHAVE_CONFIG_H -I${srcdir}/include $CPPFLAGS" +# Verify the integrity of the current configuration +if test "$cross_compiling" != "yes"; then + CPPFLAGS="-DHAVE_CONFIG_H -I${srcdir}/include $CPPFLAGS" -AC_CACHE_CHECK([if generated configuration is usable], ac_cv_configuration_is_usable, + AC_CACHE_CHECK([if generated configuration is usable], ac_cv_configuration_is_usable, [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include "src/ulib/internal/common.cpp" ]], [[int a = 0; a += 1;]])],[ac_cv_configuration_is_usable="yes"],[ac_cv_configuration_is_usable="no"]) ]) -if test "$ac_cv_configuration_is_usable" = "no" ; then - # It appears that ulib/internal/common.cpp not compiled. If it didn't compile then there would be no chance that the rest would compile. - AC_MSG_ERROR([The generated configuration appears to be unusable. - Please verify that your system path and environment variables are correct.]) - exit 1 + if test "$ac_cv_configuration_is_usable" = "no" ; then + # It appears that ulib/internal/common.cpp not compiled. If it didn't compile then there would be no chance that the rest would compile. + AC_MSG_ERROR([The generated configuration appears to be unusable. + Please verify that your system path and environment variables are correct.]) + exit 1 + fi fi echo diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am index f03cf837f..26108a0b7 100644 --- a/fuzz/Makefile.am +++ b/fuzz/Makefile.am @@ -7,11 +7,11 @@ DEFAULT_INCLUDES = -I. -I$(top_srcdir)/include uclient_fuzzer_CC = clang uclient_fuzzer_CXX = clang++ uclient_fuzzer_CPPFLAGS = -D_GLIBCXX_GCC_GTHR_H +uclient_fuzzer_SOURCES = uclient_fuzzer.cpp +uclient_fuzzer_LDADD = $(ulib_la) libFuzzer.a uclient_fuzzer_CFLAGS = -fno-omit-frame-pointer -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters uclient_fuzzer_CXXFLAGS = -fno-omit-frame-pointer -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters uclient_fuzzer_LDFLAGS = -fsanitize=address -uclient_fuzzer_SOURCES = uclient_fuzzer.cpp -uclient_fuzzer_LDADD = $(ulib_la) libFuzzer.a if CLANG noinst_PROGRAMS = uclient_fuzzer diff --git a/fuzz/Makefile.in b/fuzz/Makefile.in index 58faad329..5af5db07b 100644 --- a/fuzz/Makefile.in +++ b/fuzz/Makefile.in @@ -382,11 +382,11 @@ DEFAULT_INCLUDES = -I. -I$(top_srcdir)/include uclient_fuzzer_CC = clang uclient_fuzzer_CXX = clang++ uclient_fuzzer_CPPFLAGS = -D_GLIBCXX_GCC_GTHR_H +uclient_fuzzer_SOURCES = uclient_fuzzer.cpp +uclient_fuzzer_LDADD = $(ulib_la) libFuzzer.a uclient_fuzzer_CFLAGS = -fno-omit-frame-pointer -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters uclient_fuzzer_CXXFLAGS = -fno-omit-frame-pointer -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters uclient_fuzzer_LDFLAGS = -fsanitize=address -uclient_fuzzer_SOURCES = uclient_fuzzer.cpp -uclient_fuzzer_LDADD = $(ulib_la) libFuzzer.a all: all-am .SUFFIXES: diff --git a/fuzz/build_libFuzzer.sh b/fuzz/build_libFuzzer.sh index 67a64c9ac..a2737f15c 100755 --- a/fuzz/build_libFuzzer.sh +++ b/fuzz/build_libFuzzer.sh @@ -3,6 +3,6 @@ [ -e libFuzzer.a ] && exit 0 [ -d Fuzzer ] || git clone https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer cd Fuzzer -git checkout 29d1659edabe4ba2396f9697915bb7a0880cbd2f +#git checkout 29d1659edabe4ba2396f9697915bb7a0880cbd2f cd .. Fuzzer/build.sh diff --git a/include/ulib/base/utility.h b/include/ulib/base/utility.h index 69cdf9a3c..6652ca37c 100644 --- a/include/ulib/base/utility.h +++ b/include/ulib/base/utility.h @@ -303,37 +303,16 @@ static inline bool u_dosmatch_ext_with_OR(const char* restrict s, uint32_t n1, c return u_match_with_OR(u_dosmatch_ext, s, n1, pattern, n2, flags); } -/* Change the current working directory to the `user` user's home dir, and downgrade security to that user account */ - -U_EXPORT bool u_runAsUser(const char* restrict user, bool change_dir); - -/* Verifies that the passed string is actually an e-mail address */ - -U_EXPORT bool u_validate_email_address(const char* restrict address, uint32_t address_len) __pure; - -/* Perform 'natural order' comparisons of strings. */ - -U_EXPORT int u_strnatcmp(char const* restrict a, char const* restrict b) __pure; - -/* Get address space and rss (resident set size) usage */ - -U_EXPORT void u_get_memusage(unsigned long* vsz, unsigned long* rss); - -/* Get the uptime of the system (seconds) */ - -U_EXPORT uint32_t u_get_uptime(void); - -/* Get the number of the processors including offline CPUs */ - -U_EXPORT int u_get_num_cpu(void); - -/* Pin the process to a particular core */ - -U_EXPORT void u_bind2cpu(cpu_set_t* cpuset, int n); - -/* Set the process to maximum priority that can be used with the scheduling algorithm */ - -U_EXPORT void u_switch_to_realtime_priority(void); +U_EXPORT uint8_t u_get_loadavg(void); /* Get the load average of the system (over last 1 minute) */ +U_EXPORT uint32_t u_get_uptime(void); /* Get the uptime of the system (seconds) */ + +U_EXPORT int u_get_num_cpu(void); /* Get the number of the processors including offline CPUs */ +U_EXPORT int u_strnatcmp(char const* restrict a, char const* restrict b) __pure; /* Perform 'natural order' comparisons of strings. */ +U_EXPORT void u_switch_to_realtime_priority(void); /* Set the process to maximum priority that can be used with the scheduling algorithm */ +U_EXPORT void u_bind2cpu(cpu_set_t* cpuset, int n); /* Pin the process to a particular core */ +U_EXPORT void u_get_memusage(unsigned long* vsz, unsigned long* rss); /* Get address space and rss (resident set size) usage */ +U_EXPORT bool u_runAsUser(const char* restrict user, bool change_dir); /* Change the current working directory to the `user` user's home dir, and downgrade security to that user account */ +U_EXPORT bool u_validate_email_address(const char* restrict address, uint32_t address_len) __pure; /* Verifies that the passed string is actually an e-mail address */ /** * Canonicalize PATH, and build a new path. The new path differs from PATH in that: diff --git a/include/ulib/container/gen_hash_map.h b/include/ulib/container/gen_hash_map.h index c40cb667f..9a5fc8ae1 100644 --- a/include/ulib/container/gen_hash_map.h +++ b/include/ulib/container/gen_hash_map.h @@ -16,6 +16,8 @@ #include +class UNotifier; + /** * Functor used by UGenericHashMap class to generate a hashcode for an object of type T. It must be specialized for your own class */ @@ -107,31 +109,6 @@ template ::allocate(%u)", n) - - U_CHECK_MEMORY - - table = (UGenericHashMapNode**) UMemoryPool::_malloc(&n, sizeof(UGenericHashMapNode*), true); - _capacity = n; - } - - void deallocate() - { - U_TRACE_NO_PARAM(0, "UGenericHashMap::deallocate()") - - U_CHECK_MEMORY - - U_INTERNAL_ASSERT_MAJOR(_capacity,0) - - UMemoryPool::_free(table, _capacity, sizeof(UGenericHashMapNode*)); - - _capacity = 0; - } - // Size and capacity uint32_t size() const @@ -504,6 +481,33 @@ template ::allocate(%u)", n) + + U_CHECK_MEMORY + + table = (UGenericHashMapNode**) UMemoryPool::_malloc(&n, sizeof(UGenericHashMapNode*), true); + _capacity = n; + } + + void deallocate() + { + U_TRACE_NO_PARAM(0, "UGenericHashMap::deallocate()") + + U_CHECK_MEMORY + + U_INTERNAL_ASSERT_MAJOR(_capacity,0) + + UMemoryPool::_free(table, _capacity, sizeof(UGenericHashMapNode*)); + + _capacity = 0; + } + + private: #ifdef U_COMPILER_DELETE_MEMBERS UGenericHashMap(const UGenericHashMap&) = delete; @@ -516,6 +520,8 @@ template UGenericHashMap(const UGenericHashMap&) {} template UGenericHashMap& operator=(const UGenericHashMap&) { return *this; } #endif + + friend class UNotifier; }; // Functor used by UGenericHashMap class to generate a hashcode for an object of type diff --git a/include/ulib/container/hash_map.h b/include/ulib/container/hash_map.h index f01095727..760c1f3e8 100644 --- a/include/ulib/container/hash_map.h +++ b/include/ulib/container/hash_map.h @@ -25,6 +25,7 @@ typedef bool (*bPFptpcu) (UHashMap*,const char*,uint32_t); class UCDB; class UHTTP; class UHTTP2; +class UDirWalk; class WeightWord; class UMimeHeader; class UFileConfig; @@ -116,22 +117,6 @@ template <> class U_EXPORT UHashMap { if (_capacity) _deallocate(); } - // allocate and deallocate methods - - void deallocate() - { - U_TRACE_NO_PARAM(0, "UHashMap::deallocate()") - - if (_capacity) - { - _deallocate(); - - _capacity = 0; - } - } - - void allocate(uint32_t n); - // size and capacity uint32_t size() const @@ -252,7 +237,8 @@ template <> class U_EXPORT UHashMap { // make room for a total of n element - void reserve(uint32_t n); + void reserve( uint32_t n); + void allocate(uint32_t n); // Traverse the hash table for all entry @@ -304,6 +290,8 @@ template <> class U_EXPORT UHashMap { bool check_memory() const; // check all element #endif + // allocate and deallocate methods + void _allocate(uint32_t n) { U_TRACE(0, "UHashMap::_allocate(%u)", n) @@ -325,6 +313,18 @@ template <> class U_EXPORT UHashMap { UMemoryPool::_free(table, _capacity, sizeof(UHashMapNode*)); } + void deallocate() + { + U_TRACE_NO_PARAM(0, "UHashMap::deallocate()") + + if (_capacity) + { + _deallocate(); + + _capacity = 0; + } + } + void init(uint32_t n) { U_TRACE(0, "UHashMap::init(%u)", n) @@ -406,6 +406,7 @@ template <> class U_EXPORT UHashMap { friend class UHTTP2; friend class UValue; friend class UString; + friend class UDirWalk; friend class WeightWord; friend class UFileConfig; friend class UCertificate; diff --git a/include/ulib/container/vector.h b/include/ulib/container/vector.h index ce9cb306e..b6458f213 100644 --- a/include/ulib/container/vector.h +++ b/include/ulib/container/vector.h @@ -50,31 +50,6 @@ template <> class U_EXPORT UVector { U_MEMORY_ALLOCATOR U_MEMORY_DEALLOCATOR - // allocate and deallocate methods - - void allocate(uint32_t n) - { - U_TRACE(0, "UVector::allocate(%u)", n) - - U_CHECK_MEMORY - - U_INTERNAL_ASSERT_MINOR(n, ((0xfffffff / sizeof(void*)) - sizeof(UVector))) - - vec = (const void**) UMemoryPool::_malloc(&n, sizeof(void*)); - _capacity = n; - } - - void deallocate() - { - U_TRACE_NO_PARAM(0, "UVector::deallocate()") - - U_CHECK_MEMORY - - U_INTERNAL_ASSERT_RANGE(1, _capacity, ((0xfffffff / sizeof(void*)) - sizeof(UVector))) - - UMemoryPool::_free(vec, _capacity, sizeof(void*)); - } - UVector(uint32_t n = 64U) // create an empty vector with a size estimate { U_TRACE_REGISTER_OBJECT(0, UVector, "%u", n) @@ -427,6 +402,31 @@ template <> class U_EXPORT UVector { volatile uint32_t head; // output index #endif + // allocate and deallocate methods + + void allocate(uint32_t n) + { + U_TRACE(0, "UVector::allocate(%u)", n) + + U_CHECK_MEMORY + + U_INTERNAL_ASSERT_MINOR(n, ((0xfffffff / sizeof(void*)) - sizeof(UVector))) + + vec = (const void**) UMemoryPool::_malloc(&n, sizeof(void*)); + _capacity = n; + } + + void deallocate() + { + U_TRACE_NO_PARAM(0, "UVector::deallocate()") + + U_CHECK_MEMORY + + U_INTERNAL_ASSERT_RANGE(1, _capacity, ((0xfffffff / sizeof(void*)) - sizeof(UVector))) + + UMemoryPool::_free(vec, _capacity, sizeof(void*)); + } + private: U_DISALLOW_ASSIGN(UVector) diff --git a/include/ulib/examples/wi_auth_declaration.h b/include/ulib/examples/wi_auth_declaration.h index 1ed93d9e9..f093678cb 100644 --- a/include/ulib/examples/wi_auth_declaration.h +++ b/include/ulib/examples/wi_auth_declaration.h @@ -5661,6 +5661,7 @@ static void GET_get_users_info() { if (UServer_Base::startParallelization()) return; // parent + // ------------------------------------------------ // child // ------------------------------------------------ // $1 -> ap (without localization => '@') @@ -5670,8 +5671,8 @@ static void GET_get_users_info() if (setAccessPoint(false, false)) { UTimeVal to_sleep(U_TIME_FOR_ARPING_ASYNC_COMPLETION + 2); -loop: - (void) nodog_rec->sendRequestToNodog(U_CONSTANT_TO_PARAM("check"), 0); + +loop: (void) nodog_rec->sendRequestToNodog(U_CONSTANT_TO_PARAM("check"), 0); if (U_http_info.nResponseCode == HTTP_NO_CONTENT) { diff --git a/include/ulib/internal/config.h.in b/include/ulib/internal/config.h.in index 503a5c96c..031015073 100644 --- a/include/ulib/internal/config.h.in +++ b/include/ulib/internal/config.h.in @@ -738,6 +738,9 @@ /* Define if enable libzopfli support */ #undef USE_LIBZOPFLI +/* enable load balance support between physical server via udp brodcast */ +#undef USE_LOAD_BALANCE + /* Define if enable mongodb support */ #undef USE_MONGODB diff --git a/include/ulib/internal/memory_pool.h b/include/ulib/internal/memory_pool.h index d5f97221e..b15f4b83f 100644 --- a/include/ulib/internal/memory_pool.h +++ b/include/ulib/internal/memory_pool.h @@ -485,7 +485,7 @@ class U_EXPORT UMemoryPool { U_SYSCALL_VOID(free, "%p", ptr); } - static void _free(void* ptr, uint32_t num, uint32_t type_size = 1) + static void _free(void* ptr, uint32_t num, uint32_t type_size = sizeof(char)) { U_TRACE(1, "UMemoryPool::_free(%p,%u,%u)", ptr, num, type_size) @@ -500,8 +500,8 @@ class U_EXPORT UMemoryPool { } #endif - static void* _malloc(uint32_t num, uint32_t type_size = 1, bool bzero = false); - static void* _malloc(uint32_t* pnum, uint32_t type_size = 1, bool bzero = false); + static void* _malloc(uint32_t num, uint32_t type_size = sizeof(char), bool bzero = false); + static void* _malloc(uint32_t* pnum, uint32_t type_size = sizeof(char), bool bzero = false); #ifdef DEBUG static const char* obj_class; diff --git a/include/ulib/net/client/client.h b/include/ulib/net/client/client.h index 39355ae85..bdb1779eb 100644 --- a/include/ulib/net/client/client.h +++ b/include/ulib/net/client/client.h @@ -30,6 +30,7 @@ */ class ULog; +class UHTTP; class USSLSocket; class UHttpPlugIn; class UFileConfig; @@ -153,6 +154,31 @@ class U_EXPORT UClient_Base { void prepareRequest(const UString& req) { request = req; prepareRequest(U_STRING_TO_PARAM(req)); } + void prepareRequest(const UString& header, const UString& body) + { + U_TRACE(0, "UClient_Base::prepareRequest(%V,%V)", header.rep, body.rep) + + if (body.empty()) prepareRequest(header); + else + { + request = header; + + iovcnt = 2; + + iov[0].iov_base = (caddr_t)header.data(); + iov[0].iov_len = header.size(); + iov[1].iov_base = (caddr_t) body.data(); + iov[1].iov_len = body.size(); + + (void) U_SYSCALL(memset, "%p,%d,%u", iov+2, 0, sizeof(struct iovec) * 4); + + U_INTERNAL_ASSERT_EQUALS(iov[2].iov_len, 0) + U_INTERNAL_ASSERT_EQUALS(iov[3].iov_len, 0) + U_INTERNAL_ASSERT_EQUALS(iov[4].iov_len, 0) + U_INTERNAL_ASSERT_EQUALS(iov[5].iov_len, 0) + } + } + // LOG static void closeLog(); @@ -270,6 +296,7 @@ class U_EXPORT UClient_Base { private: U_DISALLOW_COPY_AND_ASSIGN(UClient_Base) + friend class UHTTP; friend class USSLSocket; friend class UFCGIPlugIn; friend class USCGIPlugIn; diff --git a/include/ulib/net/client/http.h b/include/ulib/net/client/http.h index e8ad96c9f..21fe30517 100644 --- a/include/ulib/net/client/http.h +++ b/include/ulib/net/client/http.h @@ -32,6 +32,7 @@ * persistent connections which can make more effective use of TCP/IP */ +class UHTTP; class UMimeHeader; class Application; class WiAuthNodog; @@ -220,6 +221,7 @@ class U_EXPORT UHttpClient_Base : public UClient_Base { private: U_DISALLOW_COPY_AND_ASSIGN(UHttpClient_Base) + friend class UHTTP; friend class USSLSocket; friend class Application; friend class WiAuthNodog; diff --git a/include/ulib/net/ipaddress.h b/include/ulib/net/ipaddress.h index df3188bdd..46f2a60a6 100644 --- a/include/ulib/net/ipaddress.h +++ b/include/ulib/net/ipaddress.h @@ -276,6 +276,8 @@ class U_EXPORT UIPAddress { return *(u.addr); } + uint32_t get_addr() const { return pcAddress.i; } + // Returns a string of the hostname of the represented IP Address UString& getHostName() { resolveHostName(); return strHostName; } @@ -283,6 +285,18 @@ class U_EXPORT UIPAddress { // Returns a constant string pointer to the string // representation of the IP Address suitable for visual presentation + static const char* getAddressString(uint32_t addr) + { + union uuaddr { + in_addr addr; + uint32_t generic; + }; + + union uuaddr tmp; tmp.generic = addr; return inet_ntoa(tmp.addr); + } + + static bool setBroadcastAddress(uusockaddr& addr, const UString& ifname); + const char* getAddressString() { if (U_ipaddress_StrAddressUnresolved(this)) resolveStrAddress(); return pcStrAddress; } // Check equality with an existing UIPAddress object @@ -352,7 +366,7 @@ class U_EXPORT UIPAddress { void setAddress(const char* pcNewAddress, int iNewAddressLength); -private: + private: friend class UHTTP; friend class USocket; friend class USocketExt; diff --git a/include/ulib/net/server/client_image.h b/include/ulib/net/server/client_image.h index f3446e062..a84e46223 100644 --- a/include/ulib/net/server/client_image.h +++ b/include/ulib/net/server/client_image.h @@ -81,12 +81,15 @@ class U_EXPORT UClientImage_Base : public UEventFd { virtual int handlerTimeout() U_DECL_FINAL; virtual void handlerDelete() U_DECL_FINAL; - static void setNoHeaderForResponse() - { - U_TRACE_NO_PARAM(0, "UClientImage_Base::setNoHeaderForResponse()") + static void init(); + static void clear(); - iov_vec[1].iov_len = 0; - } + static void close(); + static void abortive_close(); + + static const char* getRequestUri(uint32_t& len); + + static bool isAllowed(UVector& vallow_IP) __pure; // Check whether the ip address client ought to be allowed static void setHeaderForResponse(uint32_t len) { @@ -95,15 +98,21 @@ class U_EXPORT UClientImage_Base : public UEventFd { iov_vec[1].iov_len = len; } - static void init(); - static void clear(); + static void setNoHeaderForResponse() + { + U_TRACE_NO_PARAM(0, "UClientImage_Base::setNoHeaderForResponse()") - static void close(); - static void abortive_close(); + iov_vec[1].iov_len = 0; + } - static const char* getRequestUri(uint32_t& len); + static bool isNoHeaderForResponse() + { + U_TRACE_NO_PARAM(0, "UClientImage_Base::isNoHeaderForResponse()") - static bool isAllowed(UVector& vallow_IP) __pure; // Check whether the ip address client ought to be allowed + if (UNLIKELY(iov_vec[1].iov_len == 0)) U_RETURN(true); + + U_RETURN(false); + } // manage if other data already available... (pipelining) diff --git a/include/ulib/net/server/plugin/mod_nocat.h b/include/ulib/net/server/plugin/mod_nocat.h index 6ec77b2bb..c01ca1950 100644 --- a/include/ulib/net/server/plugin/mod_nocat.h +++ b/include/ulib/net/server/plugin/mod_nocat.h @@ -34,6 +34,7 @@ enum LogoutType { }; class UDirWalk; +class UBitArray; class UIptAccount; class UNoCatPlugIn; @@ -194,9 +195,10 @@ class U_EXPORT UNoCatPlugIn : public UServerPlugIn, UEventTime { static void* pdata; static UCommand* fw; static UPing** sockp; - static fd_set addrmask; - static fd_set* paddrmask; static UIptAccount* ipt; + static UBitArray* pmask; + static fd_set addrmask; + static fd_set* paddrmask; static UDirWalk* dirwalk; static UModNoCatPeer* peer; static bool flag_check_system; @@ -274,9 +276,18 @@ class U_EXPORT UNoCatPlugIn : public UServerPlugIn, UEventTime { U_INTERNAL_DUMP("check_type = %B nfds = %u paddrmask = %p", check_type, nfds, paddrmask) - bool result = (((check_type & U_CHECK_ARP_PING) != 0) && nfds && paddrmask == 0); + if (nfds && + paddrmask == 0 && + ((check_type & U_CHECK_ARP_PING) != 0)) + { + U_DEBUG("Pending arping in process (%u), waiting for completion...", nfds); + + U_SRV_LOG("Pending arping in process (%u), waiting for completion...", nfds); + + U_RETURN(true); + } - U_RETURN(result); + U_RETURN(false); } static void executeCommand(int type) diff --git a/include/ulib/net/server/server.h b/include/ulib/net/server/server.h index d6dc75c5b..9e073f3d2 100644 --- a/include/ulib/net/server/server.h +++ b/include/ulib/net/server/server.h @@ -280,9 +280,15 @@ class U_EXPORT UServer_Base : public UEventFd { char buffer4[512]; char buffer5[512]; char buffer6[512]; - char buffer7[512]; + char buffer7[439]; // --------------------------------- - sig_atomic_t cnt_connection; + uint8_t flag_sigterm; + // --------------------------------- + uint8_t my_load; + uint8_t min_load_remote; + uint32_t min_load_remote_ip; + // --------------------------------- + sig_atomic_t tot_connection; sig_atomic_t cnt_parallelization; // --------------------------------- sem_t lock_user1; @@ -332,7 +338,11 @@ class U_EXPORT UServer_Base : public UEventFd { #define U_SRV_CNT_USR7 UServer_Base::ptr_shared_data->cnt_usr7 #define U_SRV_CNT_USR8 UServer_Base::ptr_shared_data->cnt_usr8 #define U_SRV_CNT_USR9 UServer_Base::ptr_shared_data->cnt_usr9 -#define U_SRV_TOT_CONNECTION UServer_Base::ptr_shared_data->cnt_connection +#define U_SRV_MY_LOAD UServer_Base::ptr_shared_data->my_load +#define U_SRV_FLAG_SIGTERM UServer_Base::ptr_shared_data->flag_sigterm +#define U_SRV_MIN_LOAD_REMOTE UServer_Base::ptr_shared_data->min_load_remote +#define U_SRV_MIN_LOAD_REMOTE_IP UServer_Base::ptr_shared_data->min_load_remote_ip +#define U_SRV_TOT_CONNECTION UServer_Base::ptr_shared_data->tot_connection #define U_SRV_CNT_PARALLELIZATION UServer_Base::ptr_shared_data->cnt_parallelization #define U_SRV_LOCK_USER1 &(UServer_Base::ptr_shared_data->lock_user1) #define U_SRV_LOCK_USER2 &(UServer_Base::ptr_shared_data->lock_user2) @@ -356,6 +366,10 @@ class U_EXPORT UServer_Base : public UEventFd { static uint32_t shared_data_add, map_size; static bool update_date, update_date1, update_date2, update_date3; +#if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) + static uint8_t loadavg_threshold; +#endif + static void setLockUser1() { U_TRACE_NO_PARAM(0, "UServer_Base::setLockUser1()") @@ -364,7 +378,7 @@ class U_EXPORT UServer_Base : public UEventFd { U_NEW(ULock, lock_user1, ULock); - lock_user1->init(&(ptr_shared_data->lock_user1), ptr_shared_data->spinlock_user1); + lock_user1->init(U_SRV_LOCK_USER1, U_SRV_SPINLOCK_USER1); } static void setLockUser2() @@ -375,7 +389,7 @@ class U_EXPORT UServer_Base : public UEventFd { U_NEW(ULock, lock_user2, ULock); - lock_user2->init(&(ptr_shared_data->lock_user2), ptr_shared_data->spinlock_user2); + lock_user2->init(U_SRV_LOCK_USER2, U_SRV_SPINLOCK_USER2); } // NB: two step shared memory acquisition - first we get the offset, after the pointer... diff --git a/include/ulib/net/socket.h b/include/ulib/net/socket.h index 4a34d0caa..1b618eaa2 100644 --- a/include/ulib/net/socket.h +++ b/include/ulib/net/socket.h @@ -61,6 +61,7 @@ class UHTTP2; class UNotifier; class USocketExt; class UFtpClient; +class UTimeThread; class UClient_Base; class UServer_Base; class SocketAddress; @@ -687,6 +688,7 @@ class U_EXPORT USocket { friend class UNotifier; friend class USocketExt; friend class UFtpClient; + friend class UTimeThread; friend class UClient_Base; friend class UServer_Base; friend class UStreamPlugIn; diff --git a/include/ulib/orm/driver/orm_driver_sqlite.h b/include/ulib/orm/driver/orm_driver_sqlite.h index fc8c07606..5b05e9071 100644 --- a/include/ulib/orm/driver/orm_driver_sqlite.h +++ b/include/ulib/orm/driver/orm_driver_sqlite.h @@ -293,7 +293,7 @@ class U_EXPORT USqliteStatement : public USqlStatement { { U_TRACE_NO_PARAM(0, "USqliteStatement::reset()") - U_ASSERT_EQUALS(num_bind_param, vparam.size()) + U_ASSERT_EQUALS(num_bind_param, vparam.size()) U_ASSERT_EQUALS(num_bind_result, vresult.size()) param_binded = false; diff --git a/include/ulib/string.h b/include/ulib/string.h index 68c861ab2..a5de7a476 100644 --- a/include/ulib/string.h +++ b/include/ulib/string.h @@ -896,6 +896,7 @@ class U_EXPORT UStringRep { friend class UTDB; friend class UDES3; friend class UHTTP; + friend class UHTTP2; friend class UCache; friend class UValue; friend class UString; @@ -1155,7 +1156,8 @@ class U_EXPORT UString { { U_TRACE(0, "UString::_set(%V)", r) - U_INTERNAL_ASSERT_DIFFERS(rep,r) + U_INTERNAL_ASSERT_POINTER(r) + U_INTERNAL_ASSERT_DIFFERS(rep, r) rep->release(); // 1. release existing resource rep = r; // 2. bind copy to self @@ -1167,6 +1169,8 @@ class U_EXPORT UString { { U_TRACE(0, "UString::_copy(%V)", r) + U_INTERNAL_ASSERT_POINTER(r) + rep = r; // bind copy to self rep->hold(); @@ -1178,6 +1182,8 @@ class U_EXPORT UString { { U_TRACE(0, "UString::_assign(%V)", r) + U_INTERNAL_ASSERT_POINTER(r) + // NB: it works also in the case of (rep == r)... r->hold(); // 1. take a copy of new resource diff --git a/include/ulib/utility/bit_array.h b/include/ulib/utility/bit_array.h new file mode 100644 index 000000000..f10983f1b --- /dev/null +++ b/include/ulib/utility/bit_array.h @@ -0,0 +1,211 @@ +// ============================================================================ +// +// = LIBRARY +// ULib - c++ library +// +// = FILENAME +// bit_array.h +// +// = AUTHOR +// Stefano Casazza +// +// ============================================================================ + +#ifndef ULIB_BIT_ARRAY_H +#define ULIB_BIT_ARRAY_H 1 + +#include + +class U_EXPORT UBitArray { +public: + + // Check for memory error + U_MEMORY_TEST + + // Allocator e Deallocator + U_MEMORY_ALLOCATOR + U_MEMORY_DEALLOCATOR + + // allocate and deallocate methods + + UBitArray(uint32_t nbits = 1024U) + { + U_TRACE_REGISTER_OBJECT(0, UBitArray, "%u", nbits) + + allocate((nbits+31)/32); + } + + ~UBitArray() + { + U_TRACE_UNREGISTER_OBJECT(0, UBitArray) + + deallocate(); + } + + // Capacity + + uint32_t capacity() const + { + U_TRACE_NO_PARAM(0, "UBitArray::capacity()") + + U_RETURN(_capacity); + } + + // SERVICES + + uint32_t count() const __pure // get the number of bits set + { + U_TRACE_NO_PARAM(0, "UBitArray::count()") + + U_CHECK_MEMORY + + uint32_t num_of_bits_set = 0; + + for (uint32_t v, i = 0; i < _capacity; ++i) + { + v = vec[i]; + +# if !defined(HAVE_OLD_IOSTREAM) && !defined(_MSWINDOWS_) + num_of_bits_set += __builtin_popcountl(v); +# else + uint32_t c = v - ((v >> 1) & 0x55555555); + + c = ((c >> 2) & 0x33333333) + (c & 0x33333333); + c = ((c >> 4) + c) & 0x0F0F0F0F; + c = ((c >> 8) + c) & 0x00FF00FF; + + num_of_bits_set += ((c >> 16) + c) & 0x0000FFFF; + # endif + } + + U_RETURN(num_of_bits_set); + } + + uint32_t getNumBits() const { return _capacity * 4 * 8; } + uint32_t getNumBytes() const { return _capacity * 4; } + + void setAll() // set all elements of data to one + { + U_TRACE_NO_PARAM(0, "UBitArray:setAll()") + + U_CHECK_MEMORY + + U_INTERNAL_ASSERT_MAJOR(_capacity, 0) + + (void) U_SYSCALL(memset, "%p,%d,%u", vec, 0xff, getNumBytes()); + } + + void clearAll() // set all elements of data to zero + { + U_TRACE_NO_PARAM(0, "UBitArray:clearAll()") + + U_CHECK_MEMORY + + U_INTERNAL_ASSERT_MAJOR(_capacity, 0) + + (void) U_SYSCALL(memset, "%p,%d,%u", vec, 0x00, getNumBytes()); + } + + // ELEMENT ACCESS + + uint32_t bindex( uint32_t i) const { return (i / 32); } + uint32_t boffset(uint32_t i) const { return (i % 32); } + + void set(uint32_t i) + { + U_TRACE(0, "UBitArray:set(%u)", i) + + U_CHECK_MEMORY + + U_INTERNAL_ASSERT_MAJOR(_capacity, 0) + + uint32_t idx = bindex(i); + + U_INTERNAL_DUMP("idx = %u _capacity = %u", idx, _capacity) + + if (idx >= _capacity) + { + reserve(getNumBits() * 2); + + U_INTERNAL_ASSERT_MAJOR(_capacity, idx) + } + + vec[idx] |= (1U << boffset(i)); + } + + void clear(uint32_t i) + { + U_TRACE(0, "UBitArray::clear(%u)", i) + + U_CHECK_MEMORY + + U_INTERNAL_ASSERT_MAJOR(_capacity, 0) + U_INTERNAL_ASSERT_MINOR(i, getNumBits()) + + vec[bindex(i)] &= ~(1U << boffset(i)); + } + + void toggle(uint32_t i) + { + U_TRACE(0, "UBitArray:toggle(%u)", i) + + U_CHECK_MEMORY + + U_INTERNAL_ASSERT_MAJOR(_capacity, 0) + U_INTERNAL_ASSERT_MINOR(i, getNumBits()) + + vec[bindex(i)] ^= (1U << boffset(i)); + } + + bool isSet(uint32_t i) const + { + U_TRACE(0, "UBitArray::isSet(%u)", i) + + U_CHECK_MEMORY + + U_INTERNAL_ASSERT_MAJOR(_capacity, 0) + U_INTERNAL_ASSERT_MINOR(i, getNumBits()) + + if ((vec[bindex(i)] & (1U << boffset(i))) != 0) U_RETURN(true); + + U_RETURN(false); + } + + bool operator[](uint32_t i) const { return isSet(i); } + +#if defined(DEBUG) && defined(U_STDCPP_ENABLE) + const char* dump(bool reset) const; +#endif + +protected: + uint32_t* vec; + uint32_t _capacity; + + void reserve(uint32_t nbits); + + void allocate(uint32_t nuint) + { + U_TRACE(0, "UBitArray::allocate(%u)", nuint) + + U_CHECK_MEMORY + + U_INTERNAL_ASSERT_MAJOR(nuint, 0) + + vec = (uint32_t*) UMemoryPool::_malloc(&nuint, sizeof(uint32_t), true); + _capacity = nuint; + } + + void deallocate() + { + U_TRACE_NO_PARAM(0, "UBitArray::deallocate()") + + U_CHECK_MEMORY + + UMemoryPool::_free(vec, _capacity, sizeof(uint32_t)); + } + +private: + U_DISALLOW_ASSIGN(UBitArray) +}; + +#endif diff --git a/include/ulib/utility/http2.h b/include/ulib/utility/http2.h index d8a584453..5cb2b82f2 100644 --- a/include/ulib/utility/http2.h +++ b/include/ulib/utility/http2.h @@ -18,6 +18,10 @@ #include #include +#if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) +# include +#endif + #define HTTP2_FRAME_HEADER_SIZE 9 // The number of bytes of the frame header #define HTTP2_DEFAULT_WINDOW_SIZE 65535 #define HTTP2_HEADER_TABLE_OFFSET 62 @@ -65,11 +69,11 @@ class U_EXPORT UHTTP2 { }; struct HpackHeaderTableEntry { - const UString* name; - const UString* value; + UStringRep* name; + UStringRep* value; }; - struct HpackDynamicTable { + struct HpackDynamicTable { // (Last In First Out) uint32_t num_entries, entry_capacity, entry_start_index; @@ -149,6 +153,10 @@ class U_EXPORT UHTTP2 { U_DISALLOW_COPY_AND_ASSIGN(Connection) }; +#ifdef DEBUG + static void testHpackDynTbl(); +#endif + protected: enum FrameTypesId { DATA = 0x00, @@ -281,9 +289,9 @@ class U_EXPORT UHTTP2 { static void sendResetStream(); static void sendWindowUpdate(); - static void handlerDelete(UClientImage_Base* pclient); static void updateSetting(unsigned char* ptr, uint32_t len); static void writeData(struct iovec* iov, bool bdata, bool flag); + static void handlerDelete(UClientImage_Base* pclient, bool& bsocket_open); static void startRequest() { @@ -327,9 +335,7 @@ class U_EXPORT UHTTP2 { U_ASSERT(pStream->body.empty()) U_ASSERT(pStream->headers.empty()) - U_INTERNAL_ASSERT_EQUALS(pStream->id, 0) U_INTERNAL_ASSERT_EQUALS(pStream->clength, 0) - U_INTERNAL_ASSERT_EQUALS(pStream->state, STREAM_STATE_IDLE) } # endif } @@ -424,13 +430,37 @@ class U_EXPORT UHTTP2 { } else { - if (frame.type != WINDOW_UPDATE) nerror = STREAM_CLOSED; + if (frame.type != RST_STREAM && + frame.type != WINDOW_UPDATE) + { + nerror = STREAM_CLOSED; + } } } - static bool eraseHeaders(UStringRep* key, void* elem) // callWithDeleteForAllEntry()... + /** + * +-------+-----------------------------+---------------+ + * | 1 | :authority | | + * | 2 | :method | GET | + * | 3 | :method | POST | + * | 4 | :path | / | + * | 5 | :path | /index.html | + * | 6 | :scheme | http | + * | 7 | :scheme | https | + * | 8 | :status | 200 | + * | 9 | :status | 204 | + * | 10 | :status | 206 | + * | 11 | :status | 304 | + * | 12 | :status | 400 | + * | 13 | :status | 404 | + * | 14 | :status | 500 | + * | ... | ... | ... | + * +-------+-----------------------------+---------------+ + */ + + static bool isHeaderToErase(UStringRep* key) { - U_TRACE(0, "UHTTP2::eraseHeaders(%V,%p)", key, elem) + U_TRACE(0, "UHTTP2::isHeaderToErase(%V)", key) if (key == UString::str_path->rep || key == UString::str_method->rep || @@ -441,10 +471,79 @@ class U_EXPORT UHTTP2 { U_RETURN(false); } - U_INTERNAL_DUMP("key = %p", key) + U_RETURN(true); + } + + static bool isHeaderToCopy(UStringRep* key) + { + U_TRACE(0, "UHTTP2::isHeaderToCopy(%V)", key) + + if (isHeaderToErase(key) == false && + key != UString::str_cookie->rep && + key != UString::str_accept->rep && + key != UString::str_referer->rep && + key != UString::str_content_type->rep && + key != UString::str_content_length->rep && + key != UString::str_accept_language->rep) + { + U_RETURN(true); + } + + U_RETURN(false); + } + + static bool eraseHeaders(UStringRep* key, void* elem) // callWithDeleteForAllEntry()... + { + U_TRACE(0, "UHTTP2::eraseHeaders(%V,%p)", key, elem) + + if (isHeaderToErase(key)) U_RETURN(true); + + U_RETURN(false); + } + + static bool copyHeaders(UStringRep* key, void* elem) + { + U_TRACE(0, "UHTTP2::copyHeaders(%V,%p)", key, elem) + + if (isHeaderToCopy(key)) UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("%v: %v\r\n"), key, (const UStringRep*)elem); + + U_RETURN(true); + } + + // HTTP/1.1 conversion + +#if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) + static void wrapRequest(); + + static void wrapResponse() + { + U_TRACE_NO_PARAM(0, "UHTTP2::wrapResponse()") + + U_INTERNAL_DUMP("U_http_info.nResponseCode = %u U_http_info.clength = %u U_http_version = %C", U_http_info.nResponseCode, U_http_info.clength, U_http_version) + + U_http_version = '2'; + + UHTTP::ext->setBuffer(U_CAPACITY); + + UHTTP::client_http->getResponseHeader()->table.callForAllEntry(wrapHeaders); + + handlerResponse(); + } + + static bool wrapHeaders(UStringRep* key, void* elem) + { + U_TRACE(0, "UHTTP2::wrapHeaders(%V,%p)", key, elem) + + if (key->equal(U_CONSTANT_TO_PARAM("Date")) == false && + key->equal(U_CONSTANT_TO_PARAM("Server")) == false) + { + if (key->equal(U_CONSTANT_TO_PARAM("Set-Cookie"))) UHTTP::set_cookie->_assign(key); + else UHTTP::ext->snprintf_add(U_CONSTANT_TO_PARAM("%v: %v\r\n"), key, (const UStringRep*)elem); + } U_RETURN(true); } +#endif static bool setIndexStaticTable(UHashMap* table, const char* key, uint32_t length) { @@ -479,42 +578,6 @@ class U_EXPORT UHTTP2 { U_RETURN(false); } - static void clearHpackDynTbl( HpackDynamicTable* dyntbl); - static void addHpackDynTblEntry(HpackDynamicTable* dyntbl, const UString& name, const UString& value); - - static HpackHeaderTableEntry* getHpackDynTblEntry(const HpackDynamicTable* dyntbl, uint32_t index) - { - U_TRACE(0, "UHTTP2::getHpackDynTblEntry(%p,%u)", dyntbl, index) - - U_INTERNAL_DUMP("dyntbl->entry_start_index = %u dyntbl->entry_capacity = %u", dyntbl->entry_start_index, dyntbl->entry_capacity) - - uint32_t entry_index = (dyntbl->entry_start_index + index) % dyntbl->entry_capacity; - - HpackHeaderTableEntry* entry = dyntbl->entries + entry_index; - - U_INTERNAL_ASSERT_POINTER(entry->name) - - U_INTERNAL_DUMP("entry->name = %V entry->value = %V", entry->name->rep, entry->value->rep) - - U_RETURN_POINTER(entry, HpackHeaderTableEntry); - } - - static void evictHpackDynTblEntry(HpackDynamicTable* dyntbl, HpackHeaderTableEntry* entry) - { - U_TRACE(0, "UHTTP2::evictHpackDynTblEntry(%p,%p)", dyntbl, entry) - - U_INTERNAL_ASSERT_MAJOR(dyntbl->num_entries, 0) - - dyntbl->num_entries--; - - dyntbl->hpack_size -= entry->name->size() + entry->value->size() + HTTP2_HEADER_TABLE_ENTRY_SIZE_OFFSET; - - delete entry->name; - delete entry->value; - } - - static void evictHpackDynTblEntry(HpackDynamicTable* dyntbl) { evictHpackDynTblEntry(dyntbl, getHpackDynTblEntry(dyntbl, dyntbl->num_entries-1)); } - static void setHpackDynTblCapacity(HpackDynamicTable* dyntbl, uint32_t value) { U_TRACE(0, "UHTTP2::setHpackDynTblCapacity(%p,%u)", dyntbl, value) @@ -527,10 +590,10 @@ class U_EXPORT UHTTP2 { // adjust the size - while (dyntbl->num_entries != 0 && + while (dyntbl->num_entries > 0 && dyntbl->hpack_size > dyntbl->hpack_capacity) { - evictHpackDynTblEntry(dyntbl); + evictHpackDynTblFirstEntry(dyntbl); } } @@ -570,6 +633,67 @@ class U_EXPORT UHTTP2 { U_RETURN_POINTER(dst, unsigned char); } + static HpackHeaderTableEntry* getHpackDynTblEntry(HpackDynamicTable* dyntbl, uint32_t index) + { + U_TRACE(0, "UHTTP2::getHpackDynTblEntry(%p,%u)", dyntbl, index) + + U_INTERNAL_DUMP("dyntbl->entry_start_index = %u dyntbl->entry_capacity = %u dyntbl->num_entries = %u", dyntbl->entry_start_index, dyntbl->entry_capacity, dyntbl->num_entries) + + U_INTERNAL_ASSERT_MAJOR(dyntbl->num_entries, 0) + U_INTERNAL_ASSERT_MINOR(index, dyntbl->num_entries) + + HpackHeaderTableEntry* entry = dyntbl->entries + ((dyntbl->entry_start_index+index) % dyntbl->entry_capacity); + + U_INTERNAL_ASSERT_POINTER(entry->name) + U_INTERNAL_ASSERT_POINTER(entry->value) + + U_INTERNAL_DUMP("entry->name = %V entry->value = %V", entry->name, entry->value) + + U_RETURN_POINTER(entry, HpackHeaderTableEntry); + } + + static void evictHpackDynTblEntry(HpackDynamicTable* dyntbl, HpackHeaderTableEntry* entry) + { + U_TRACE(0, "UHTTP2::evictHpackDynTblEntry(%p,%p)", dyntbl, entry) + + dyntbl->num_entries--; + + dyntbl->hpack_size -= entry->name->size() + entry->value->size() + HTTP2_HEADER_TABLE_ENTRY_SIZE_OFFSET; + + U_INTERNAL_ASSERT_POINTER(entry->name) + U_INTERNAL_ASSERT_POINTER(entry->value) + + // NB: we decreases the reference string... + + U_INTERNAL_DUMP("entry->name = %V entry->value = %V", entry->name, entry->value) + + entry->name->release(); + entry->value->release(); + + entry->name = + entry->value = 0; + } + + static void evictHpackDynTblFirstEntry(HpackDynamicTable* dyntbl) + { + U_TRACE(0, "UHTTP2::evictHpackDynTblFirstEntry(%p)", dyntbl) + + evictHpackDynTblEntry(dyntbl, getHpackDynTblEntry(dyntbl, dyntbl->num_entries-1)); + } + + static void evictHpackDynTblLastEntry(HpackDynamicTable* dyntbl) + { + U_TRACE(0, "UHTTP2::evictHpackDynTblLastEntry(%p)", dyntbl) + + evictHpackDynTblEntry(dyntbl, getHpackDynTblEntry(dyntbl, 0)); + + dyntbl->entry_start_index = (dyntbl->entry_start_index+1+dyntbl->entry_capacity) % dyntbl->entry_capacity; + } + + static void clearHpackDynTbl( HpackDynamicTable* dyntbl); + static void addHpackDynTblEntry(HpackDynamicTable* dyntbl, const UString& name, const UString& value); + static void evictHpackDynTblEntry(HpackDynamicTable* dyntbl, HpackHeaderTableEntry* entry, uint32_t index); + static void addHpackOutputDynTblEntry(const UString& name, const UString& value) { addHpackDynTblEntry(&(pConnection->odyntbl), name, value); } static unsigned char* hpackDecodeInt( unsigned char* src, unsigned char* src_end, int32_t& value, uint8_t prefix_max); @@ -679,7 +803,7 @@ class U_EXPORT UHTTP2 { table->hash = hash_static_table[index]; - table->lookup(hpack_static_table[index].name->rep); + table->lookup(hpack_static_table[index].name); if (table->node) U_RETURN(true); @@ -690,13 +814,13 @@ class U_EXPORT UHTTP2 { static const char* getConnectionStatusDescription(); static const char* getFrameTypeDescription(char type); - static void printHpackDynamicTable(const HpackDynamicTable* dyntbl, ostream& os); + static void printHpackDynamicTable(HpackDynamicTable* dyntbl, ostream& os); static void printHpackInputDynTable() { printHpackDynamicTable(&(pConnection->idyntbl), cout); } static void printHpackOutputDynTable() { printHpackDynamicTable(&(pConnection->odyntbl), cout); } # ifdef U_STDCPP_ENABLE - friend ostream& operator<<(ostream& os, const HpackDynamicTable& v) + friend ostream& operator<<(ostream& os, HpackDynamicTable& v) { U_TRACE(0+256, "HpackDynamicTable::operator<<(%p,%p)", &os, &v) @@ -715,7 +839,7 @@ class U_EXPORT UHTTP2 { * * table->hash = hash_static_table[index]; * - * table->lookup(hpack_static_table[index].name->rep); + * table->lookup(hpack_static_table[index].name); * * if (table->node) table->eraseAfterFind(); * } diff --git a/include/ulib/utility/uhttp.h b/include/ulib/utility/uhttp.h index edbc566e4..7bd3f2ffc 100644 --- a/include/ulib/utility/uhttp.h +++ b/include/ulib/utility/uhttp.h @@ -47,6 +47,7 @@ class USSLSession; class UMimeMultipart; class UModProxyService; +template class UHttpClient; template class URDBObjectHandler; class U_EXPORT UHTTP { @@ -208,52 +209,14 @@ class U_EXPORT UHTTP { static bool readBodyResponse(USocket* socket, UString* buffer, UString& body); #ifndef U_HTTP2_DISABLE - static bool copyHeaders(UStringRep* key, void* elem) - { - U_TRACE(0, "UHTTP::copyHeaders(%V,%p)", key, elem) - - U_INTERNAL_ASSERT_POINTER(prequestHeader) - U_INTERNAL_ASSERT_EQUALS(U_http_version, '2') - - /** - * +-------+-----------------------------+---------------+ - * | 1 | :authority | | - * | 2 | :method | GET | - * | 3 | :method | POST | - * | 4 | :path | / | - * | 5 | :path | /index.html | - * | 6 | :scheme | http | - * | 7 | :scheme | https | - * | 8 | :status | 200 | - * | 9 | :status | 204 | - * | 10 | :status | 206 | - * | 11 | :status | 304 | - * | 12 | :status | 400 | - * | 13 | :status | 404 | - * | 14 | :status | 500 | - * | ... | ... | ... | - * +-------+-----------------------------+---------------+ - */ - - if (key != UString::str_path->rep && - key != UString::str_cookie->rep && - key != UString::str_accept->rep && - key != UString::str_method->rep && - key != UString::str_referer->rep && - key != UString::str_authority->rep && - key != UString::str_user_agent->rep && - key != UString::str_content_type->rep && - key != UString::str_content_length->rep && - key != UString::str_accept_language->rep) - { - prequestHeader->insert(key, (const UStringRep*)elem); - } + static bool copyHeaders(UStringRep* key, void* elem); +#endif - U_INTERNAL_DUMP("key = %p", key) +#if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) + static UHttpClient* client_http; - U_RETURN(true); - } -# endif + static bool manageRequestOnRemoteServer(); +#endif static void setHostname(const char* ptr, uint32_t len); diff --git a/m4/ac_compilation_options.m4 b/m4/ac_compilation_options.m4 index c3b91a1d6..7f45a292e 100644 --- a/m4/ac_compilation_options.m4 +++ b/m4/ac_compilation_options.m4 @@ -320,4 +320,15 @@ AC_DEFUN([AC_COMPILATION_OPTIONS],[ AC_DEFINE(U_HTML_PAGINATION_SUPPORT, 1, [enable HTML pagination support]) fi AC_MSG_RESULT([$enable_HPS]) + + AC_MSG_CHECKING(if you want to enable load balance support between physical server via udp brodcast) + AC_ARG_ENABLE(load-balance, + [ --enable-load-balance enable load balance support between physical server via udp brodcast [[default=no]]]) + if test -z "$enable_load_balance"; then + enable_load_balance="no" + fi + if test "$enable_load_balance" = "yes"; then + AC_DEFINE(USE_LOAD_BALANCE, 1, [enable load balance support between physical server via udp brodcast]) + fi + AC_MSG_RESULT([$enable_load_balance]) ]) diff --git a/src/ulib/Makefile.am b/src/ulib/Makefile.am index fc82b4eee..d21cb6131 100644 --- a/src/ulib/Makefile.am +++ b/src/ulib/Makefile.am @@ -27,7 +27,7 @@ SRC_CPP = internal/common.cpp internal/error.cpp \ container/vector.cpp container/hash_map.cpp container/tree.cpp \ utility/interrupt.cpp utility/services.cpp utility/semaphore.cpp utility/base64.cpp \ utility/lock.cpp utility/string_ext.cpp utility/socket_ext.cpp utility/uhttp.cpp \ - utility/data_session.cpp utility/ring_buffer.cpp utility/websocket.cpp utility/dir_walk.cpp \ + utility/data_session.cpp utility/ring_buffer.cpp utility/websocket.cpp utility/dir_walk.cpp utility/bit_array.cpp \ lemon/expression.cpp \ orm/orm.cpp orm/orm_driver.cpp \ net/ipaddress.cpp net/socket.cpp net/ping.cpp \ diff --git a/src/ulib/Makefile.in b/src/ulib/Makefile.in index fb0de494c..7504b3cc3 100644 --- a/src/ulib/Makefile.in +++ b/src/ulib/Makefile.in @@ -245,9 +245,10 @@ am__lib@ULIB@_la_SOURCES_DIST = base/base.c base/base_error.c \ utility/string_ext.cpp utility/socket_ext.cpp \ utility/uhttp.cpp utility/data_session.cpp \ utility/ring_buffer.cpp utility/websocket.cpp \ - utility/dir_walk.cpp lemon/expression.cpp orm/orm.cpp \ - orm/orm_driver.cpp net/ipaddress.cpp net/socket.cpp \ - net/ping.cpp net/server/server.cpp net/server/client_image.cpp \ + utility/dir_walk.cpp utility/bit_array.cpp \ + lemon/expression.cpp orm/orm.cpp orm/orm_driver.cpp \ + net/ipaddress.cpp net/socket.cpp net/ping.cpp \ + net/server/server.cpp net/server/client_image.cpp \ net/client/client_rdb.cpp net/server/client_image_rdb.cpp \ net/server/server_rdb.cpp \ net/server/plugin/mod_proxy_service.cpp net/rpc/rpc.cpp \ @@ -404,9 +405,9 @@ am__objects_67 = internal/common.lo internal/error.lo ui/dialog.lo \ utility/base64.lo utility/lock.lo utility/string_ext.lo \ utility/socket_ext.lo utility/uhttp.lo utility/data_session.lo \ utility/ring_buffer.lo utility/websocket.lo \ - utility/dir_walk.lo lemon/expression.lo orm/orm.lo \ - orm/orm_driver.lo net/ipaddress.lo net/socket.lo net/ping.lo \ - net/server/server.lo net/server/client_image.lo \ + utility/dir_walk.lo utility/bit_array.lo lemon/expression.lo \ + orm/orm.lo orm/orm_driver.lo net/ipaddress.lo net/socket.lo \ + net/ping.lo net/server/server.lo net/server/client_image.lo \ net/client/client_rdb.lo net/server/client_image_rdb.lo \ net/server/server_rdb.lo \ net/server/plugin/mod_proxy_service.lo net/rpc/rpc.lo \ @@ -729,9 +730,10 @@ SRC_CPP = internal/common.cpp internal/error.cpp ui/dialog.cpp \ utility/string_ext.cpp utility/socket_ext.cpp \ utility/uhttp.cpp utility/data_session.cpp \ utility/ring_buffer.cpp utility/websocket.cpp \ - utility/dir_walk.cpp lemon/expression.cpp orm/orm.cpp \ - orm/orm_driver.cpp net/ipaddress.cpp net/socket.cpp \ - net/ping.cpp net/server/server.cpp net/server/client_image.cpp \ + utility/dir_walk.cpp utility/bit_array.cpp \ + lemon/expression.cpp orm/orm.cpp orm/orm_driver.cpp \ + net/ipaddress.cpp net/socket.cpp net/ping.cpp \ + net/server/server.cpp net/server/client_image.cpp \ net/client/client_rdb.cpp net/server/client_image_rdb.cpp \ net/server/server_rdb.cpp \ net/server/plugin/mod_proxy_service.cpp net/rpc/rpc.cpp \ @@ -1063,6 +1065,8 @@ utility/websocket.lo: utility/$(am__dirstamp) \ utility/$(DEPDIR)/$(am__dirstamp) utility/dir_walk.lo: utility/$(am__dirstamp) \ utility/$(DEPDIR)/$(am__dirstamp) +utility/bit_array.lo: utility/$(am__dirstamp) \ + utility/$(DEPDIR)/$(am__dirstamp) lemon/$(am__dirstamp): @$(MKDIR_P) lemon @: > lemon/$(am__dirstamp) @@ -1654,6 +1658,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@ssl/net/$(DEPDIR)/sslsocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ui/$(DEPDIR)/dialog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utility/$(DEPDIR)/base64.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@utility/$(DEPDIR)/bit_array.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utility/$(DEPDIR)/data_session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utility/$(DEPDIR)/des3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utility/$(DEPDIR)/dir_walk.Plo@am__quote@ diff --git a/src/ulib/all_cpp.cpp b/src/ulib/all_cpp.cpp index c904ad25a..7a79cdaf3 100644 --- a/src/ulib/all_cpp.cpp +++ b/src/ulib/all_cpp.cpp @@ -82,6 +82,7 @@ #include "utility/uhttp.cpp" #include "utility/base64.cpp" #include "utility/dir_walk.cpp" +#include "utility/bit_array.cpp" #include "utility/interrupt.cpp" #include "utility/services.cpp" #include "utility/semaphore.cpp" diff --git a/src/ulib/base/utility.c b/src/ulib/base/utility.c index 96f099515..e79c3fa4b 100644 --- a/src/ulib/base/utility.c +++ b/src/ulib/base/utility.c @@ -1089,6 +1089,7 @@ void u_switch_to_realtime_priority(void) void u_get_memusage(unsigned long* vsz, unsigned long* rss) { +#ifndef _MSWINDOWS_ FILE* fp = fopen("/proc/self/stat", "r"); U_INTERNAL_TRACE("u_get_memusage(%p,%p)", vsz, rss) @@ -1134,10 +1135,12 @@ void u_get_memusage(unsigned long* vsz, unsigned long* rss) *rss *= PAGESIZE; } +#endif } uint32_t u_get_uptime(void) { +#ifndef _MSWINDOWS_ FILE* fp = fopen("/proc/uptime", "r"); U_INTERNAL_TRACE("u_get_uptime()") @@ -1152,10 +1155,43 @@ uint32_t u_get_uptime(void) return sec; } +#endif return 0; } +uint8_t u_get_loadavg(void) +{ + /** + * /proc/loadavg (ex: 0.19 1.37 0.97 1/263 26041) + * + * The first three fields in this file are load average figures giving the number of jobs in the run queue (state R) or waiting for disk I/O (state D) + * averaged over 1, 5, and 15 minutes. They are the same as the load average numbers given by uptime(1) and other programs. The fourth field consists + * of two numbers separated by a slash (/). The first of these is the number of currently runnable kernel scheduling entities (processes, threads). + * The value after the slash is the number of kernel scheduling entities that currently exist on the system. The fifth field is the PID of the process + * that was most recently created on the system + */ + +#ifndef _MSWINDOWS_ + FILE* fp = fopen("/proc/loadavg", "r"); + + U_INTERNAL_TRACE("u_get_loadavg()") + + if (fp) + { + char buffer[8]; + + (void) fscanf(fp, "%s", buffer); + + (void) fclose(fp); + + if (buffer[1] == '.') return (((buffer[0]-'0') * 10) + (buffer[2]-'0') + (buffer[3] > '5')); // 0.19 => 2, 4.56 => 46, ... + } +#endif + + return 255; +} + __pure bool u_rmatch(const char* restrict haystack, uint32_t haystack_len, const char* restrict needle, uint32_t needle_len) { U_INTERNAL_TRACE("u_rmatch(%.*s,%u,%.*s,%u)", U_min(haystack_len,128), haystack, haystack_len, diff --git a/src/ulib/internal/memory_pool.cpp b/src/ulib/internal/memory_pool.cpp index c26aa6b59..594352d72 100644 --- a/src/ulib/internal/memory_pool.cpp +++ b/src/ulib/internal/memory_pool.cpp @@ -364,8 +364,9 @@ void UMemoryPool::_free(void* ptr, uint32_t num, uint32_t type_size) U_INTERNAL_ASSERT_POINTER(ptr) U_INTERNAL_ASSERT_MAJOR(num, 0) + U_INTERNAL_ASSERT_MAJOR(type_size, 0) - uint32_t length = (num * type_size); + uint32_t length = (num * type_size); // in bytes U_INTERNAL_DUMP("length = %u", length) @@ -437,9 +438,10 @@ void* UMemoryPool::_malloc(uint32_t num, uint32_t type_size, bool bzero) U_TRACE(0, "UMemoryPool::_malloc(%u,%u,%b)", num, type_size, bzero) U_INTERNAL_ASSERT_MAJOR(num, 0) + U_INTERNAL_ASSERT_MAJOR(type_size, 0) void* ptr; - uint32_t length = (num * type_size); + uint32_t length = (num * type_size); // in bytes U_INTERNAL_DUMP("length = %u", length) @@ -474,9 +476,10 @@ void* UMemoryPool::_malloc(uint32_t* pnum, uint32_t type_size, bool bzero) U_TRACE(1, "UMemoryPool::_malloc(%p,%u,%b)", pnum, type_size, bzero) U_INTERNAL_ASSERT_POINTER(pnum) + U_INTERNAL_ASSERT_MAJOR(type_size, 0) void* ptr; - uint32_t length = (*pnum * type_size); + uint32_t length = (*pnum * type_size); // in bytes U_INTERNAL_DUMP("length = %u", length) @@ -484,6 +487,8 @@ void* UMemoryPool::_malloc(uint32_t* pnum, uint32_t type_size, bool bzero) # ifndef HAVE_ARCH64 U_INTERNAL_ASSERT_MINOR(length, 1U * 1024U * 1024U * 1024U) // NB: over 1G is very suspect on 32bit... # endif + if (length == 0) length = type_size; + ptr = U_SYSCALL(malloc, "%u", length); #else if (length > U_MAX_SIZE_PREALLOCATE) ptr = UFile::mmap(&length, -1, PROT_READ | PROT_WRITE, MAP_PRIVATE | U_MAP_ANON, 0); diff --git a/src/ulib/json/value.cpp b/src/ulib/json/value.cpp index 45d10e3c1..c1f1819b7 100644 --- a/src/ulib/json/value.cpp +++ b/src/ulib/json/value.cpp @@ -2170,6 +2170,10 @@ bool UValue::jfind(const UString& json, const char* query, uint32_t query_len, U U_INTERNAL_ASSERT(u__isquote(*end)) } + else if (u__isquote(*end)) + { + U_RETURN(false); + } (void) result.assign(start, end-start); diff --git a/src/ulib/net/client/http.cpp b/src/ulib/net/client/http.cpp index 6fd2d5907..4d3a52506 100644 --- a/src/ulib/net/client/http.cpp +++ b/src/ulib/net/client/http.cpp @@ -472,7 +472,8 @@ int UHttpClient_Base::checkResponse(int& redirectCount) bool connection_close = (UClient_Base::isClosed() || responseHeader->isClose()); - // General category of response: + // ------------------------------------------------------------ + // general category of HTTP/1.x response: // ------------------------------------------------------------ // 1xx indicates an informational message only // 2xx indicates success of some kind @@ -873,9 +874,9 @@ bool UHttpClient_Base::sendRequestEngine() ? checkResponse(redirectCount) : -1); - if (result == 1) continue; // redirection, use the same socket connection... - if (result == -2) U_RETURN(true); // pass HTTP_UNAUTHORISED response to the HTTP client... - if (result == 2) // no redirection, read body... + if (result == 1) continue; // redirection, we use the same socket connection... + if (result == -2) U_RETURN(true); // we must pass HTTP_UNAUTHORISED response to the HTTP client... + if (result == 2) // no redirection, we must read body... { U_INTERNAL_DUMP("SERVER RETURNED HTTP RESPONSE: %d", U_http_info.nResponseCode) diff --git a/src/ulib/net/ipaddress.cpp b/src/ulib/net/ipaddress.cpp index ee30a0721..c7d244ef6 100644 --- a/src/ulib/net/ipaddress.cpp +++ b/src/ulib/net/ipaddress.cpp @@ -245,6 +245,7 @@ bool UIPAddress::setHostName(const UString& pcNewHostName, bool bIPv6) struct addrinfo hints; struct addrinfo* result = 0; + // ----------------------------------------------------------------- // setup hints structure // ----------------------------------------------------------------- // struct addrinfo { @@ -594,7 +595,7 @@ __pure bool UIPAddress::isWildCard() { // static const struct in6_addr in6addr_any = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /* :: */ - if (memcmp(pcAddress.p, in6addr_any, sizeof(in6_addr)) == 0) U_RETURN(true); + if (memcmp(pcAddress.p, (const void*)&in6addr_any, sizeof(in6_addr)) == 0) U_RETURN(true); U_RETURN(false); } @@ -604,7 +605,7 @@ __pure bool UIPAddress::isWildCard() U_INTERNAL_ASSERT_EQUALS(iAddressType, AF_INET) U_INTERNAL_ASSERT_EQUALS(iAddressLength, sizeof(in_addr)) - U_DUMP("htonl(pcAddress.i) = 0x%X %S", htonl(pcAddress.i), UIPAddress::toString(getInAddr()).data()) + U_DUMP("htonl(pcAddress.i) = 0x%X %V", htonl(pcAddress.i), UIPAddress::toString(getInAddr()).rep) if (htonl(pcAddress.i) == 0x00000000) U_RETURN(true); @@ -740,10 +741,7 @@ bool UIPAllow::parseMask(const UString& _spec) network = addr & mask; - U_DUMP("addr = %S mask = %S network = %S", - UIPAddress::toString(addr).data(), - UIPAddress::toString(mask).data(), - UIPAddress::toString(network).data()) + U_DUMP("addr = %V mask = %V network = %V", UIPAddress::toString(addr).rep, UIPAddress::toString(mask).rep, UIPAddress::toString(network).rep) } U_INTERNAL_DUMP("addr = 0x%08x %B mask = 0x%08x %B network = 0x%08x %B", addr, addr, mask, mask, network, network) @@ -776,19 +774,13 @@ __pure bool UIPAllow::isAllowed(in_addr_t client) { U_TRACE(0, "UIPAllow::isAllowed(%u)", client) - U_DUMP("addr = %S mask = %S network = %S", - UIPAddress::toString(addr).data(), - UIPAddress::toString(mask).data(), - UIPAddress::toString(network).data()) + U_DUMP("addr = %V mask = %V network = %V", UIPAddress::toString(addr).rep, UIPAddress::toString(mask).rep, UIPAddress::toString(network).rep) U_INTERNAL_ASSERT_EQUALS(network, addr & mask) bool result = ((client & mask) == network); - U_DUMP("client = %S mask = %S network = %S", - UIPAddress::toString(client).data(), - UIPAddress::toString(mask).data(), - UIPAddress::toString(client & mask).data()) + U_DUMP("client = %V mask = %V network = %V", UIPAddress::toString(client).rep, UIPAddress::toString(mask).rep, UIPAddress::toString(client & mask).rep) if (bnot) U_RETURN(!result); @@ -799,19 +791,13 @@ __pure bool UIPAllow::isAllowed(in_addr_t ifa_addr, in_addr_t ifa_netmask) { U_TRACE(0, "UIPAllow::isAllowed(%u,%u)", ifa_addr, ifa_netmask) - U_DUMP("addr = %S mask = %S network = %S", - UIPAddress::toString(addr).data(), - UIPAddress::toString(mask).data(), - UIPAddress::toString(network).data()) + U_DUMP("addr = %V mask = %V network = %V", UIPAddress::toString(addr).rep, UIPAddress::toString(mask).rep, UIPAddress::toString(network).rep) U_INTERNAL_ASSERT_EQUALS(network, addr & mask) bool result = ((ifa_addr & ifa_netmask) == network); - U_DUMP("ifa_addr = %S ifa_netmask = %S network = %S", - UIPAddress::toString(ifa_addr).data(), - UIPAddress::toString(ifa_netmask).data(), - UIPAddress::toString(ifa_addr & ifa_netmask).data()) + U_DUMP("ifa_addr = %V ifa_netmask = %V network = %V", UIPAddress::toString(ifa_addr).rep, UIPAddress::toString(ifa_netmask).rep, UIPAddress::toString(ifa_addr & ifa_netmask).rep) U_RETURN(result); } @@ -878,6 +864,74 @@ __pure uint32_t UIPAllow::find(const UString& ip_client, UVector& vip U_RETURN(U_NOT_FOUND); } +bool UIPAddress::setBroadcastAddress(uusockaddr& addr, const UString& ifname) +{ + U_TRACE(0, "UIPAddress::setBroadcastAddress(%p,%V)", &addr, ifname.rep) + + U_INTERNAL_ASSERT(ifname) + + bool result = false; + +#ifdef HAVE_IFADDRS_H + struct ifaddrs* ifaddr; + + if (U_SYSCALL(getifaddrs, "%p", &ifaddr) == 0) + { + for (struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == 0) continue; + + int family = ifa->ifa_addr->sa_family; + +# ifdef U_LINUX + U_INTERNAL_DUMP("%s => family: %d%s", ifa->ifa_name, family, + (family == AF_PACKET) ? " (AF_PACKET)" : + (family == AF_INET) ? " (AF_INET)" : + (family == AF_INET6) ? " (AF_INET6)" : "") +# endif + + if (family == AF_INET && + u_get_unalignedp16(ifa->ifa_name) != U_MULTICHAR_CONSTANT16('l','o') && + ifname.equal(ifa->ifa_name)) // Name of interface + { + result = true; + + addr.psaIP4Addr.sin_addr.s_addr = ((struct sockaddr_in*)ifa->ifa_broadaddr)->sin_addr.s_addr; // 0x0AFFFFFF send message to 10.255.255.255 + +# if defined(DEBUG) && defined(HAVE_GETNAMEINFO) + char host[NI_MAXHOST]; + int gai_err = U_SYSCALL(getnameinfo, "%p,%d,%p,%d,%p,%d,%d", ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, 0, 0, NI_NUMERICHOST); + + if (gai_err) + { + U_WARNING("getnameinfo() error: %s", gai_strerror(gai_err)); + } + else + { + U_INTERNAL_DUMP("%s => address: <%s>", ifa->ifa_name, host) + + U_DUMP("ifa_addr = %V ifa_netmask = %V ifa_network = %V ifa_broadaddr = %V", + UIPAddress::toString(((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr).rep, + UIPAddress::toString(((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr).rep, + UIPAddress::toString(((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr & ((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr).rep, + UIPAddress::toString(((struct sockaddr_in*)ifa->ifa_broadaddr)->sin_addr.s_addr).rep) + + U_INTERNAL_ASSERT_EQUALS(ifa->ifa_addr->sa_family, AF_INET) + U_INTERNAL_ASSERT_EQUALS(ifa->ifa_netmask->sa_family, AF_INET) + } +# endif + + break; + } + } + + U_SYSCALL_VOID(freeifaddrs, "%p", ifaddr); + } +#endif + + U_RETURN(result); +} + bool UIPAllow::getNetworkInterface(UVector& vipallow) { U_TRACE(0, "UIPAllow::getNetworkInterface(%p)", &vipallow) @@ -890,28 +944,26 @@ bool UIPAllow::getNetworkInterface(UVector& vipallow) if (U_SYSCALL(getifaddrs, "%p", &ifaddr) == 0) { UIPAllow* pallow; - int family, gai_err; - char host[NI_MAXHOST]; - uusockaddr ifa_addr, ifa_netmask; uint32_t i, vlen = vipallow.size(); for (struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr == 0) continue; - family = ifa->ifa_addr->sa_family; + int family = ifa->ifa_addr->sa_family; # ifdef U_LINUX U_INTERNAL_DUMP("%s => family: %d%s", ifa->ifa_name, family, - (family == AF_PACKET) ? " (AF_PACKET)" : - (family == AF_INET) ? " (AF_INET)" : - (family == AF_INET6) ? " (AF_INET6)" : "") + (family == AF_PACKET) ? " (AF_PACKET)" : + (family == AF_INET) ? " (AF_INET)" : + (family == AF_INET6) ? " (AF_INET6)" : "") # endif if (family == AF_INET && u_get_unalignedp16(ifa->ifa_name) != U_MULTICHAR_CONSTANT16('l','o')) // Name of interface { - gai_err = U_SYSCALL(getnameinfo, "%p,%d,%p,%d,%p,%d,%d", ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, 0, 0, NI_NUMERICHOST); + char host[NI_MAXHOST]; + int gai_err = U_SYSCALL(getnameinfo, "%p,%d,%p,%d,%p,%d,%d", ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, 0, 0, NI_NUMERICHOST); if (gai_err) { @@ -921,30 +973,29 @@ bool UIPAllow::getNetworkInterface(UVector& vipallow) { U_INTERNAL_DUMP("%s => address: <%s>", ifa->ifa_name, host) - U_MEMCPY(&ifa_addr, ifa->ifa_addr, sizeof(struct sockaddr)); // Address of interface - U_MEMCPY(&ifa_netmask, ifa->ifa_netmask, sizeof(struct sockaddr)); // Netmask of interface + U_DUMP("ifa_addr = %V ifa_netmask = %V ifa_network = %V ifa_broadaddr = %V", + UIPAddress::toString(((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr).rep, + UIPAddress::toString(((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr).rep, + UIPAddress::toString(((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr & ((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr).rep, + UIPAddress::toString(((struct sockaddr_in*)ifa->ifa_broadaddr)->sin_addr.s_addr).rep) - U_DUMP("ifa_addr = %S ifa_netmask = %S ifa_network = %S", - UIPAddress::toString(ifa_addr.psaIP4Addr.sin_addr.s_addr).data(), - UIPAddress::toString(ifa_netmask.psaIP4Addr.sin_addr.s_addr).data(), - UIPAddress::toString(ifa_addr.psaIP4Addr.sin_addr.s_addr & ifa_netmask.psaIP4Addr.sin_addr.s_addr).data()) + U_INTERNAL_ASSERT_EQUALS(ifa->ifa_addr->sa_family, AF_INET) + U_INTERNAL_ASSERT_EQUALS(ifa->ifa_netmask->sa_family, AF_INET) + } - U_INTERNAL_ASSERT_EQUALS(ifa_addr.psaIP4Addr.sin_family, AF_INET) - U_INTERNAL_ASSERT_EQUALS(ifa_netmask.psaIP4Addr.sin_family, AF_INET) + for (i = 0; i < vlen; ++i) + { + pallow = vipallow[i]; - for (i = 0; i < vlen; ++i) + if (pallow->isAllowed(((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr, // Address of interface + ((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr.s_addr)) // Netmask of interface { - pallow = vipallow[i]; - - if (pallow->isAllowed(ifa_addr.psaIP4Addr.sin_addr.s_addr, ifa_netmask.psaIP4Addr.sin_addr.s_addr)) - { - result = true; + result = true; - (void) pallow->device.replace(ifa->ifa_name); - (void) pallow->host.replace(host); + (void) pallow->host.replace(host); + (void) pallow->device.replace(ifa->ifa_name); - break; - } + break; } } } diff --git a/src/ulib/net/server/client_image.cpp b/src/ulib/net/server/client_image.cpp index e5c022ef4..2b2ab2593 100644 --- a/src/ulib/net/server/client_image.cpp +++ b/src/ulib/net/server/client_image.cpp @@ -469,12 +469,7 @@ void UClientImage_Base::handlerDelete() #ifndef U_HTTP2_DISABLE U_INTERNAL_DUMP("U_ClientImage_http = %C U_http_version = %C", U_ClientImage_http(this), U_http_version) - if (U_ClientImage_http(this) == '2') - { - UHTTP2::handlerDelete(this); - - if (socket->isTimeout()) bsocket_open = false; - } + if (U_ClientImage_http(this) == '2') UHTTP2::handlerDelete(this, bsocket_open); #endif if (bsocket_open) socket->close(); @@ -560,7 +555,10 @@ int UClientImage_Base::handlerTimeout() U_RETURN(U_NOTIFIER_OK); } - U_INTERNAL_ASSERT_EQUALS(socket->iSockDesc, UEventFd::fd) + if (socket->iSockDesc != UEventFd::fd) + { + U_WARNING("handlerTimeout(): UEventFd::fd = %d socket->iSockDesc = %d", UEventFd::fd, socket->iSockDesc); + } #endif U_INTERNAL_DUMP("U_ClientImage_idle(this) = %d %B", U_ClientImage_idle(this), U_ClientImage_idle(this)) @@ -1471,7 +1469,7 @@ bool UClientImage_Base::writeResponse() ncount = sz1 + sz2; - if (UNLIKELY(iov_vec[1].iov_len == 0)) + if (isNoHeaderForResponse()) { U_INTERNAL_ASSERT_EQUALS(nrequest, 0) diff --git a/src/ulib/net/server/plugin/mod_nocat.cpp b/src/ulib/net/server/plugin/mod_nocat.cpp index 820e2f9a7..bbc9cef3f 100644 --- a/src/ulib/net/server/plugin/mod_nocat.cpp +++ b/src/ulib/net/server/plugin/mod_nocat.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -40,9 +41,9 @@ bool UNoCatPlugIn::flag_check_system; long UNoCatPlugIn::last_request_check; long UNoCatPlugIn::last_request_firewall; void* UNoCatPlugIn::pdata; -UPing** UNoCatPlugIn::sockp; fd_set UNoCatPlugIn::addrmask; fd_set* UNoCatPlugIn::paddrmask; +UPing** UNoCatPlugIn::sockp; uint32_t UNoCatPlugIn::nfds; uint32_t UNoCatPlugIn::num_radio; uint32_t UNoCatPlugIn::check_expire; @@ -71,6 +72,7 @@ UString* UNoCatPlugIn::IP_address_trust; UString* UNoCatPlugIn::peer_present_in_arp_cache; UCommand* UNoCatPlugIn::fw; UDirWalk* UNoCatPlugIn::dirwalk; +UBitArray* UNoCatPlugIn::pmask; UIptAccount* UNoCatPlugIn::ipt; UModNoCatPeer* UNoCatPlugIn::peer; UModNoCatPeer* UNoCatPlugIn::peers_delete; @@ -175,6 +177,7 @@ UNoCatPlugIn::UNoCatPlugIn() U_TRACE_REGISTER_OBJECT(0, UNoCatPlugIn, "") U_NEW(UCommand, fw, UCommand); + U_NEW(UBitArray, pmask, UBitArray(4096)); U_NEW(UString, label, UString); U_NEW(UString, input, UString(U_CAPACITY)); @@ -217,6 +220,7 @@ UNoCatPlugIn::~UNoCatPlugIn() delete fw; delete label; delete input; + delete pmask; delete fw_cmd; delete fw_env; delete extdev; @@ -793,6 +797,7 @@ void UNoCatPlugIn::checkSystem() { U_TRACE_NO_PARAM(1, "UNoCatPlugIn::checkSystem()") + bool bset; uint32_t i, n; long check_interval; @@ -830,8 +835,6 @@ void UNoCatPlugIn::checkSystem() if (isPingAsyncPending()) { - U_SRV_LOG("Pending arping in process (%u), waiting for completion...", nfds); - paddrmask = UPing::checkForPingAsyncCompletion(nfds); if (paddrmask) goto result; @@ -843,6 +846,8 @@ void UNoCatPlugIn::checkSystem() for (nfds = i = 0; i < num_radio; ++i) vaddr[i]->clear(); + pmask->clearAll(); + FD_ZERO(&addrmask); U_SRV_LOG("Checking peers for info"); @@ -876,11 +881,19 @@ void UNoCatPlugIn::checkSystem() result: U_INTERNAL_ASSERT_MAJOR(nfds, 0) +# ifdef DEBUG + if (nfds < FD_SETSIZE) U_ASSERT_EQUALS(pmask->count(), 0) + else U_ASSERT_EQUALS(pmask->count(), nfds-FD_SETSIZE+1) +# endif + for (i = 0; i < nfds; ++i) { if (getPeer(i)) { - if (FD_ISSET(i, paddrmask)) addPeerInfo(0); + bset = (nfds < FD_SETSIZE ? FD_ISSET(i, paddrmask) + : pmask->isSet(i-FD_SETSIZE)); + + if (bset) addPeerInfo(0); else { # ifdef HAVE_NETPACKET_PACKET_H @@ -1725,7 +1738,8 @@ bool UNoCatPlugIn::checkPeerInfo(UStringRep* key, void* value) if (index_device != U_NOT_FOUND) { - FD_SET(nfds, &addrmask); + if (nfds < FD_SETSIZE) FD_SET(nfds, &addrmask); + else pmask->set(nfds-FD_SETSIZE); ++nfds; @@ -1748,7 +1762,7 @@ __pure bool UNoCatPlugIn::getPeer(uint32_t n) { U_TRACE(0, "UNoCatPlugIn::getPeer(%u)", n) - U_INTERNAL_ASSERT_MAJOR(nfds,0) + U_INTERNAL_ASSERT_MAJOR(nfds, 0) int32_t index = -1; diff --git a/src/ulib/net/server/plugin/usp/businesses.usp b/src/ulib/net/server/plugin/usp/businesses.usp index b6db6155b..91b026432 100644 --- a/src/ulib/net/server/plugin/usp/businesses.usp +++ b/src/ulib/net/server/plugin/usp/businesses.usp @@ -408,58 +408,63 @@ static void usp_end_businesses() - + diff --git a/src/ulib/net/server/plugin/usp/usp_translator.cpp b/src/ulib/net/server/plugin/usp/usp_translator.cpp index a33f00287..fb2b7a834 100644 --- a/src/ulib/net/server/plugin/usp/usp_translator.cpp +++ b/src/ulib/net/server/plugin/usp/usp_translator.cpp @@ -63,11 +63,10 @@ "%s" \ "%s" \ "%s" \ -"%s" \ "\t\t}\n" \ "\t\n" \ "%v" \ -"%s" \ +"%v" \ "\t\n" \ "%v" \ "%v" \ @@ -124,9 +123,8 @@ class Application : public UApplication { const char* ptr; uint32_t i, n, size; - UString token, declaration, http_header(U_CAPACITY), buffer(U_CAPACITY), bufname(100U), output(U_CAPACITY), output1(U_CAPACITY), xoutput(U_CAPACITY); - bool bgroup, binit = false, bend = false, bsighup = false, bfork = false, bcomment = false, bvar = false, bform = false, test_if_html = false, is_html = false, - bsession = false, bstorage = false, bparallelization = false; + UString token, declaration, http_header(U_CAPACITY), buffer(U_CAPACITY), bufname(100U), vcode(U_CAPACITY), output(U_CAPACITY), output1(U_CAPACITY), output2(U_CAPACITY); + bool bgroup, binit = false, bend = false, bsighup = false, bfork = false, bcomment = false, bvar = false, test_if_html = false, is_html = false, bsession = false, bstorage = false; // Anything that is not enclosed in tags is assumed to be HTML @@ -196,9 +194,30 @@ class Application : public UApplication { U_INTERNAL_DUMP("directive(10) = %.*S", 10, directive) + /** + * token list: + * + * (comment) + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + if (strncmp(directive, U_CONSTANT_TO_PARAM("declaration")) == 0) { - U_ASSERT(declaration.empty()) // NB: must be at the beginning... + U_ASSERT(vcode.empty()) + U_ASSERT(declaration.empty()) // NB: must be at the beginning and uniq... n = token.size() - U_CONSTANT_SIZE("declaration") - 2; @@ -211,16 +230,10 @@ class Application : public UApplication { declaration = UStringExt::substitute(declaration, '\n', U_CONSTANT_TO_PARAM("\n\t")); } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("header")) == 0) - { - U_ASSERT(http_header.empty()) - - n = token.size() - U_CONSTANT_SIZE("header") - 2; - - http_header = UStringExt::trim(directive + U_CONSTANT_SIZE("header"), n); - } else if (strncmp(directive, U_CONSTANT_TO_PARAM("session")) == 0) { + U_ASSERT(vcode.empty()) + bsession = true; n = token.size() - U_CONSTANT_SIZE("session") - 2; @@ -269,6 +282,8 @@ class Application : public UApplication { } else if (strncmp(directive, U_CONSTANT_TO_PARAM("storage")) == 0) { + U_ASSERT(vcode.empty()) + bstorage = true; n = token.size() - U_CONSTANT_SIZE("storage") - 2; @@ -317,12 +332,14 @@ class Application : public UApplication { } else if (strncmp(directive, U_CONSTANT_TO_PARAM("args")) == 0) { - bform = true; + U_ASSERT(vcode.empty()) n = token.size() - U_CONSTANT_SIZE("args") - 2; token = UStringExt::trim(directive + U_CONSTANT_SIZE("args"), n); + (void) output.append(U_CONSTANT_TO_PARAM("\t\n\t\tif (UHTTP::isGETorPOST()) (void) UHTTP::processForm();\n")); + UString tmp, name; UVector vec(token, "\t\n;"); @@ -348,6 +365,64 @@ class Application : public UApplication { (void) output.append(buffer); } } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("header")) == 0) + { + U_ASSERT(vcode.empty()) + U_ASSERT(http_header.empty()) + + n = token.size() - U_CONSTANT_SIZE("header") - 2; + + http_header = UStringExt::trim(directive + U_CONSTANT_SIZE("header"), n); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("code")) == 0) // generic code + { + n = token.size() - U_CONSTANT_SIZE("code") - 2; + + token = UStringExt::trim(directive + U_CONSTANT_SIZE("code"), n); + + (void) output.append(U_CONSTANT_TO_PARAM("\n\t")); + (void) output.append(UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t"))); + (void) output.append(U_CONSTANT_TO_PARAM("\n\t\n")); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("vcode")) == 0) // validation code + { + U_ASSERT(vcode.empty()) // NB: must be before other code and uniq... + + n = token.size() - U_CONSTANT_SIZE("vcode") - 2; + + token = UStringExt::trim(directive + U_CONSTANT_SIZE("vcode"), n); + + (void) vcode.append(U_CONSTANT_TO_PARAM("\n\t")); + (void) vcode.append(UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t"))); + (void) vcode.append(U_CONSTANT_TO_PARAM("\n\t\n")); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("pcode")) == 0) // parallelization code (long running task) + { + n = token.size() - U_CONSTANT_SIZE("pcode") - 2; + + token = UStringExt::trim(directive + U_CONSTANT_SIZE("pcode"), n); + + (void) output.append(U_CONSTANT_TO_PARAM("\n\t")); + (void) output.append(UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t"))); + (void) output.append(U_CONSTANT_TO_PARAM("\n\t\n")); + + (void) vcode.append(U_CONSTANT_TO_PARAM("\tif (UServer_Base::startParallelization()) { U_http_info.nResponseCode = HTTP_CONTINUE; return; }\n\t\n")); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("lcode")) == 0) // load balance code + { + n = token.size() - U_CONSTANT_SIZE("lcode") - 2; + + token = UStringExt::trim(directive + U_CONSTANT_SIZE("lcode"), n); + + (void) output.append(U_CONSTANT_TO_PARAM("\n\t")); + (void) output.append(UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t"))); + (void) output.append(U_CONSTANT_TO_PARAM("\n\t\n")); + + (void) vcode.append(U_CONSTANT_TO_PARAM("\tif (UServer_Base::startParallelization()) { U_http_info.nResponseCode = HTTP_CONTINUE; return; }\n\t\n")); +# ifdef USE_LOAD_BALANCE + (void) vcode.append(U_CONSTANT_TO_PARAM("\tif (UHTTP::manageRequestOnRemoteServer()) return;\n\t\n")); +# endif + } else if (strncmp(directive, U_CONSTANT_TO_PARAM("number")) == 0) { n = token.size() - U_CONSTANT_SIZE("number") - 2; @@ -433,42 +508,6 @@ class Application : public UApplication { (void) output.append(buffer); } - else - { - n = 0; - - if (strncmp(directive, U_CONSTANT_TO_PARAM("pcode")) == 0) - { - bparallelization = true; - - n = token.size() - U_CONSTANT_SIZE("pcode") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("pcode"), n); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("code")) == 0) - { - n = token.size() - U_CONSTANT_SIZE("code") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("code"), n); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("xcode")) == 0) - { - bvar = true; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("xcode"), token.size() - U_CONSTANT_SIZE("xcode") - 2); - - (void) xoutput.append(U_CONSTANT_TO_PARAM("\n\t")); - (void) xoutput.append(UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t"))); - (void) xoutput.append(U_CONSTANT_TO_PARAM("\n\t\n")); - } - - if (n) - { - (void) output.append(U_CONSTANT_TO_PARAM("\n\t")); - (void) output.append(UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t"))); - (void) output.append(U_CONSTANT_TO_PARAM("\n\t\n")); - } - } // no trailing \n... @@ -514,7 +553,7 @@ class Application : public UApplication { { // NB: we use insert because the possibility of UHTTP::callService() (see chat.usp)... - if (U_STRING_FIND(http_header, 0, "Content-Type") != U_NOT_FOUND) (void) xoutput.append(U_CONSTANT_TO_PARAM("\n\t\tU_http_content_type_len = 1;\n\t")); + if (U_STRING_FIND(http_header, 0, "Content-Type") != U_NOT_FOUND) (void) output2.append(U_CONSTANT_TO_PARAM("\n\t\tU_http_content_type_len = 1;\n\t")); UString header = UStringExt::dos2unix(http_header, true); @@ -532,9 +571,9 @@ class Application : public UApplication { UString tmp(encoded.size() + 200U); - tmp.snprintf(U_CONSTANT_TO_PARAM("\n\t\tU_INTERNAL_ASSERT_EQUALS(UClientImage_Base::wbuffer->findEndHeader(),false)" - "\n\t\tU_http_info.endHeader = %u;" - "\n\t\t(void) UClientImage_Base::wbuffer->insert(0, \n\tU_CONSTANT_TO_PARAM(%v));\n"), n, encoded.rep); + tmp.snprintf(U_CONSTANT_TO_PARAM("\n\tU_INTERNAL_ASSERT_EQUALS(UClientImage_Base::wbuffer->findEndHeader(),false)" + "\n\tU_http_info.endHeader = %u;" + "\n\t(void) UClientImage_Base::wbuffer->insert(0, U_CONSTANT_TO_PARAM(%v));\n\t\n"), n, encoded.rep); (void) x.append(tmp); } @@ -547,8 +586,7 @@ class Application : public UApplication { char ptr4[100] = { '\0' }; char ptr5[100] = { '\0' }; const char* ptr6 = ""; - const char* ptr7 = ""; - const char* ptr8 = (bcomment ? "\n\tUClientImage_Base::setRequestNoCache();\n\t\n" : ""); + const char* ptr7 = (bcomment ? "\n\tUClientImage_Base::setRequestNoCache();\n\t\n" : ""); if (binit) (void) u__snprintf(ptr1, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_INIT) { usp_init_%.*s(); return; }\n\t"), size, ptr); if (bsighup) (void) u__snprintf(ptr4, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_SIGHUP) { usp_sighup_%.*s(); return; }\n\t"), size, ptr); @@ -572,9 +610,7 @@ class Application : public UApplication { : "\n\t\tif (param >= U_DPAGE_FORK) return;\n"); } - if (bparallelization) ptr7 = "\t\n\t\tif (UServer_Base::startParallelization(UServer_Base::num_client_for_parallelization)) return;\n\t\n"; - - UString result(1024U + sizeof(USP_TEMPLATE) + declaration.size() + http_header.size() + output.size() + output1.size() + xoutput.size()); + UString result(1024U + sizeof(USP_TEMPLATE) + declaration.size() + http_header.size() + output.size() + output1.size() + output2.size()); result.snprintf(U_CONSTANT_TO_PARAM(USP_TEMPLATE), size, ptr, @@ -585,20 +621,20 @@ class Application : public UApplication { size, ptr, size, ptr, bvar ? "\n\tuint32_t usp_sz = 0;" - "\n\tchar usp_buffer[10 * 4096];\n" : "", + "\n\tchar usp_buffer[10 * 4096];\n" + : "", ptr1, ptr2, ptr3, ptr4, ptr5, ptr6, - ptr7, + vcode.rep, http_header.rep, - bform ? "\t\n\t\tif (UHTTP::isGETorPOST()) (void) UHTTP::processForm();\n" : "", output.rep, output1.rep, - xoutput.rep, - ptr8); + output2.rep, + ptr7); (void) UFile::writeTo(bufname, UStringExt::removeEmptyLine(result)); } diff --git a/src/ulib/net/server/server.cpp b/src/ulib/net/server/server.cpp index dd9246680..da84b9a78 100644 --- a/src/ulib/net/server/server.cpp +++ b/src/ulib/net/server/server.cpp @@ -152,6 +152,9 @@ UVector* UServer_Base::vlog; #ifdef U_WELCOME_SUPPORT UString* UServer_Base::msg_welcome; #endif +#if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) +unsigned char UServer_Base::loadavg_threshold = 45; // => 4.5 +#endif #ifdef U_ACL_SUPPORT UString* UServer_Base::allow_IP; UVector* UServer_Base::vallow_IP; @@ -892,6 +895,45 @@ class UTimeThread : public UThread { { U_TRACE_NO_PARAM(0, "UTimeThread::run()") +# if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) + UString ifname; + uusockaddr addr; + UUDPSocket udp_sock(UClientImage_Base::bIPv6); + + if (UServer_Base::bipc == false) + { + (void) memset(&addr, 0, sizeof(addr)); + + addr.psaIP4Addr.sin_family = PF_INET; + addr.psaIP4Addr.sin_port = htons(UServer_Base::port); + addr.psaIP4Addr.sin_addr.s_addr = htonl(INADDR_ANY); + + ifname = UServer_Base::getNetworkDevice(0); + + if (ifname.empty() || + UIPAddress::setBroadcastAddress(addr, ifname) == false) + { + U_WARNING("Can't get broadcast address on interface %V", ifname.rep); + } + else + { + udp_sock._socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + + udp_sock.setNonBlocking(); // setting socket to nonblocking + + if (udp_sock.setSockOpt(SOL_SOCKET, SO_REUSEADDR, (const int[]){ 1 }) == false) U_ERROR_SYSCALL("Can't enable SO_REUSEADDR on udp socket"); + if (udp_sock.setSockOpt(SOL_SOCKET, SO_BROADCAST, (const int[]){ 1 }) == false) U_ERROR_SYSCALL("Can't enable SO_BROADCAST on udp socket"); + + if (U_SYSCALL(bind, "%d,%p,%d", udp_sock.getFd(), (sockaddr*)&(addr.psaGeneric), sizeof(addr))) U_ERROR_SYSCALL("Can't bind on udp socket"); + + udp_sock.setLocal(); + + U_SRV_LOG("Load balance activated (by udp socket): loadavg_threshold = %u brodacast address = (%v:%v)", + UServer_Base::loadavg_threshold, ifname.rep, UIPAddress::toString(addr.psaIP4Addr.sin_addr.s_addr).rep); + } + } +# endif + struct timespec ts; u_timeval.tv_sec = u_now->tv_sec; @@ -940,6 +982,53 @@ class UTimeThread : public UThread { (void) U_SYSCALL(pthread_rwlock_unlock, "%p", ULog::prwlock); # endif } + +# if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) + if (ifname && + UServer_Base::bipc == false) + { + U_SRV_MY_LOAD = u_get_loadavg(); + + U_INTERNAL_DUMP("U_SRV_MY_LOAD = %u", U_SRV_MY_LOAD) + + int iBytesTransferred = U_SYSCALL(sendto, "%d,%p,%u,%u,%p,%d", udp_sock.getFd(), &U_SRV_MY_LOAD, sizeof(char), MSG_DONTROUTE, (sockaddr*)&(addr.psaGeneric), sizeof(addr)); + + if (iBytesTransferred == sizeof(char)) + { + UIPAddress cIPSource; + unsigned int iPortSource; + unsigned char datagram[65535]; + + uint8_t min_loadavg_remote = 255; + uint32_t min_loadavg_remote_ip = 0; + + while ((iBytesTransferred = udp_sock.recvFrom(datagram, sizeof(datagram), 0, cIPSource, iPortSource)) > 0) + { + U_DUMP("Received datagram from (%S,%u): (%u,%.*S)", cIPSource.getAddressString(), iPortSource, iBytesTransferred, iBytesTransferred, datagram) + + if (cIPSource == UServer_Base::socket->cLocalAddress) continue; + + if (iBytesTransferred == 1) + { + U_INTERNAL_ASSERT_EQUALS(UServer_Base::port, iPortSource) + + if (datagram[0] < min_loadavg_remote) + { + min_loadavg_remote = datagram[0]; + + u_put_unalignedp32(&min_loadavg_remote_ip, cIPSource.get_addr()); + } + } + } + + U_SRV_MIN_LOAD_REMOTE = min_loadavg_remote; + + u_put_unalignedp32(&U_SRV_MIN_LOAD_REMOTE_IP, min_loadavg_remote_ip); + + U_DUMP("U_SRV_MIN_LOAD_REMOTE = %u U_SRV_MIN_LOAD_REMOTE_IP = %s", U_SRV_MIN_LOAD_REMOTE, UIPAddress::getAddressString(U_SRV_MIN_LOAD_REMOTE_IP)) + } + } +# endif } } } @@ -1062,6 +1151,8 @@ UServer_Base::UServer_Base(UFileConfig* pcfg) U_WARNING("System date not updated: %#5D", u_now->tv_sec); } + U_DEBUG("sizeof(shared_data) = %u", sizeof(shared_data)); + /** * TMPDIR is the canonical Unix environment variable which points to user scratch space. Most Unix utilities will honor the setting of this * variable and use its value to denote the scratch area for temporary files instead of the common default of /tmp. Other forms sometimes @@ -1676,10 +1767,7 @@ void UServer_Base::loadConfigParam() // DOCUMENT_ROOT: The directory out of which we will serve your documents - if (setDocumentRoot(cfg->at(U_CONSTANT_TO_PARAM("DOCUMENT_ROOT"))) == false) - { - U_ERROR("Setting DOCUMENT ROOT %V failed", document_root->rep); - } + if (setDocumentRoot(cfg->at(U_CONSTANT_TO_PARAM("DOCUMENT_ROOT"))) == false) U_ERROR("Setting DOCUMENT ROOT %V failed", document_root->rep); #ifndef U_LOG_DISABLE x = cfg->at(U_CONSTANT_TO_PARAM("LOG_FILE")); @@ -2229,22 +2317,28 @@ void UServer_Base::init() if ( IP_address->empty()) *IP_address = ip; else if (*IP_address != ip) { - U_SRV_LOG("WARNING: SERVER IP ADDRESS from configuration : %V differ from system interface: %V", IP_address->rep, ip.rep); + U_SRV_LOG("WARNING: SERVER IP ADDRESS from configuration (%V) differ from system interface (%V)", IP_address->rep, ip.rep); } } - struct in_addr ia; - - if (inet_aton(IP_address->c_str(), &ia) == 0) + if (IP_address->empty()) { - U_WARNING("IP_ADDRESS conversion fail, we try using localhost"); + (void) IP_address->assign(U_CONSTANT_TO_PARAM("127.0.0.1")); + + socket->cLocalAddress.setLocalHost(UClientImage_Base::bIPv6); - (void) inet_aton("localhost", &ia); + U_WARNING("IP_ADDRESS from system interface fail, we try using localhost"); } + else + { + struct in_addr ia; - socket->setAddress(&ia); + if (inet_aton(IP_address->c_str(), &ia) == 0) U_ERROR("IP_ADDRESS conversion fail: %V", IP_address->rep); - public_address = (socket->cLocalAddress.isPrivate() == false); + socket->setAddress(&ia); + + public_address = (socket->cLocalAddress.isPrivate() == false); + } U_SRV_LOG("SERVER IP ADDRESS registered as: %v (%s)", IP_address->rep, (public_address ? "public" : "private")); @@ -2352,8 +2446,8 @@ void UServer_Base::init() U_INTERNAL_ASSERT_DIFFERS(ptr_shared_data, MAP_FAILED) #if defined(U_LINUX) && defined(ENABLE_THREAD) -# if defined(U_LOG_DISABLE) && !defined(USE_LIBZ) - bool bpthread_time = true; +# if (defined(U_LOG_DISABLE) && !defined(USE_LIBZ)) || (defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_)) + bool bpthread_time = true; # else bool bpthread_time = (preforked_num_kids >= 4); // intuitive heuristic... # endif @@ -2730,6 +2824,7 @@ RETSIGTYPE UServer_Base::handlerForSigTERM(int signo) flag_loop = false; + U_SRV_FLAG_SIGTERM = UNotifier::flag_sigterm = true; U_INTERNAL_ASSERT_POINTER(proc) @@ -3736,6 +3831,8 @@ void UServer_Base::run() if (status >= U_FAILED_SOME) { + to_sleep.nanosleep(); + UProcess::kill(0, SIGKILL); // SIGKILL is sent to every process in the process group of the calling process... (void) proc->waitAll(2); @@ -3752,6 +3849,8 @@ void UServer_Base::run() if (proc->parent() || preforked_num_kids <= 0) { + to_sleep.nanosleep(); + closeLog(); } @@ -3791,11 +3890,11 @@ pid_t UServer_Base::startNewChild() # ifdef U_LOG_DISABLE (void) UProcess::removeZombies(); # else - uint32_t n = UProcess::removeZombies(); - - U_SRV_CNT_PARALLELIZATION++; + uint32_t n = UProcess::removeZombies(), + u_srv_cnt_parallelization = U_SRV_CNT_PARALLELIZATION+1; + U_SRV_CNT_PARALLELIZATION = u_srv_cnt_parallelization; - U_SRV_LOG("Started new child (pid %d) for parallelization (%d) - removed %u zombies", pid, U_SRV_CNT_PARALLELIZATION, n); + U_SRV_LOG("Started new child (pid %d) for parallelization (%d) - removed %u zombies", pid, u_srv_cnt_parallelization, n); # endif U_RETURN(pid); // parent @@ -3810,17 +3909,14 @@ __noreturn void UServer_Base::endNewChild() { U_TRACE_NO_PARAM(0, "UServer_Base::endNewChild()") -#ifdef DEBUG - UInterrupt::setHandlerForSignal(SIGHUP, (sighandler_t)SIG_IGN); - UInterrupt::setHandlerForSignal(SIGTERM, (sighandler_t)SIG_IGN); -#endif - #ifndef U_LOG_DISABLE - if (LIKELY(U_SRV_CNT_PARALLELIZATION)) U_SRV_CNT_PARALLELIZATION--; + uint32_t u_srv_cnt_parallelization = U_SRV_CNT_PARALLELIZATION; + + if (LIKELY(u_srv_cnt_parallelization)) U_SRV_CNT_PARALLELIZATION = --u_srv_cnt_parallelization; - U_INTERNAL_DUMP("cnt_parallelization = %d", U_SRV_CNT_PARALLELIZATION) + U_INTERNAL_DUMP("cnt_parallelization = %u U_SRV_FLAG_SIGTERM = %b", u_srv_cnt_parallelization, U_SRV_FLAG_SIGTERM) - U_SRV_LOG("child for parallelization ended (%d)", U_SRV_CNT_PARALLELIZATION); + if (U_SRV_FLAG_SIGTERM == false) U_SRV_LOG("child for parallelization ended (%u)", u_srv_cnt_parallelization); #endif U_EXIT(0); diff --git a/src/ulib/net/socket.cpp b/src/ulib/net/socket.cpp index 59d0b74b4..72d6fc197 100644 --- a/src/ulib/net/socket.cpp +++ b/src/ulib/net/socket.cpp @@ -108,8 +108,8 @@ void USocket::_socket(int iSocketType, int domain, int protocol) if (domain == 0) { - domain = ((U_socket_Type(this) & SK_UNIX) != 0 ? AF_UNIX : - U_socket_IPv6(this) ? AF_INET6 : AF_INET); + domain = ((U_socket_Type(this) & SK_UNIX) != 0 ? AF_UNIX : + U_socket_IPv6(this) ? AF_INET6 : AF_INET); } else if (domain == AF_UNIX) U_socket_Type(this) |= SK_UNIX; // AF_UNIX == 1 @@ -207,8 +207,6 @@ void USocket::setLocal() U_CHECK_MEMORY - U_INTERNAL_ASSERT(isOpen()) - SocketAddress tmp; socklen_t slDummy = tmp.sizeOf(); @@ -721,7 +719,7 @@ int USocket::sendTo(void* pPayload, uint32_t iPayloadLength, uint32_t uiFlags, U cDestination.setIPAddress(cDestinationIP); cDestination.setPortNumber(iDestinationPortNumber); - loop: +loop: iBytesWrite = U_SYSCALL(sendto, "%d,%p,%u,%u,%p,%d", getFd(), CAST(pPayload), iPayloadLength, uiFlags, (sockaddr*)cDestination, cDestination.sizeOf()); if (iBytesWrite > 0) diff --git a/src/ulib/net/socket_address.cpp b/src/ulib/net/socket_address.cpp index c111a5ce7..e6bfb1230 100644 --- a/src/ulib/net/socket_address.cpp +++ b/src/ulib/net/socket_address.cpp @@ -102,10 +102,14 @@ class U_NO_EXPORT SocketAddress { # ifdef ENABLE_IPV6 if (addr.psaGeneric.sa_family == AF_INET6) + { U_MEMCPY(&(addr.psaIP6Addr.sin6_addr), cAddr.get_in_addr(), cAddr.getInAddrLength()); - else + + return; + } # endif - U_MEMCPY(&(addr.psaIP4Addr.sin_addr), cAddr.get_in_addr(), cAddr.getInAddrLength()); + + U_MEMCPY(&(addr.psaIP4Addr.sin_addr), cAddr.get_in_addr(), cAddr.getInAddrLength()); } // Sets the port number part of the sockaddr structure. Based on the value @@ -115,10 +119,15 @@ class U_NO_EXPORT SocketAddress { void setPortNumber(int iPortNumber) { # ifdef ENABLE_IPV6 - if (addr.psaGeneric.sa_family == AF_INET6) addr.psaIP6Addr.sin6_port = htons(iPortNumber); - else + if (addr.psaGeneric.sa_family == AF_INET6) + { + addr.psaIP6Addr.sin6_port = htons(iPortNumber); + + return; + } # endif - addr.psaIP4Addr.sin_port = htons(iPortNumber); + + addr.psaIP4Addr.sin_port = htons(iPortNumber); } // Returns the Address stored in the sockaddr structure. Based on the family @@ -128,10 +137,15 @@ class U_NO_EXPORT SocketAddress { void getIPAddress(UIPAddress& cAddr) { # ifdef ENABLE_IPV6 - if (addr.psaGeneric.sa_family == AF_INET6) cAddr.setAddress(&(addr.psaIP6Addr.sin6_addr), true); - else + if (addr.psaGeneric.sa_family == AF_INET6) + { + cAddr.setAddress(&(addr.psaIP6Addr.sin6_addr), true); + + return; + } # endif - cAddr.setAddress(&(addr.psaIP4Addr.sin_addr), false); + + cAddr.setAddress(&(addr.psaIP4Addr.sin_addr), false); } // Returns the port number stored in the sockaddr structure. Based on the @@ -142,9 +156,9 @@ class U_NO_EXPORT SocketAddress { { # ifdef ENABLE_IPV6 if (addr.psaGeneric.sa_family == AF_INET6) return ntohs(addr.psaIP6Addr.sin6_port); - else # endif - return ntohs(addr.psaIP4Addr.sin_port); + + return ntohs(addr.psaIP4Addr.sin_port); } // Returns the size of the structure pointed to by the (sockaddr*) cast. @@ -156,9 +170,9 @@ class U_NO_EXPORT SocketAddress { { # ifdef ENABLE_IPV6 if (addr.psaGeneric.sa_family == AF_INET6) return sizeof(sockaddr_in6); - else # endif - return sizeof(sockaddr_in); + + return sizeof(sockaddr_in); } operator sockaddr*() { return &(addr.psaGeneric); } @@ -185,12 +199,16 @@ class U_NO_EXPORT SocketAddress { # ifdef ENABLE_IPV6 if (addr.psaGeneric.sa_family == AF_INET6) + { U_MEMCPY(&(addr.psaIP6Addr.sin6_addr), &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, sizeof(in6_addr)); - else + + return; + } # endif - U_MEMCPY(&(addr.psaIP4Addr.sin_addr), - &((struct sockaddr_in*)result->ai_addr)->sin_addr, sizeof(in_addr)); + + U_MEMCPY(&(addr.psaIP4Addr.sin_addr), + &((struct sockaddr_in*)result->ai_addr)->sin_addr, sizeof(in_addr)); } #endif diff --git a/src/ulib/utility/bit_array.cpp b/src/ulib/utility/bit_array.cpp new file mode 100644 index 000000000..49e7fbf48 --- /dev/null +++ b/src/ulib/utility/bit_array.cpp @@ -0,0 +1,56 @@ +// ============================================================================ +// +// = LIBRARY +// ULib - c++ library +// +// = FILENAME +// bit_array.cpp +// +// = AUTHOR +// Stefano Casazza +// +// ============================================================================ + +#include + +void UBitArray::reserve(uint32_t nbits) +{ + U_TRACE(0, "UBitArray::reserve(%u)", nbits) + + U_INTERNAL_ASSERT_MAJOR(_capacity, 0) + + uint32_t nuint = (nbits / 32); + + U_INTERNAL_DUMP("nuint = %u _capacity = %u", nuint, _capacity) + + U_INTERNAL_ASSERT_MAJOR(nuint, _capacity) + + uint32_t* old_vec = vec; + + vec = (uint32_t*) UMemoryPool::_malloc(&nuint, sizeof(uint32_t)); + + U_MEMCPY(vec, old_vec, getNumBytes()); + + UMemoryPool::_free(old_vec, _capacity, sizeof(uint32_t)); + + (void) U_SYSCALL(memset, "%p,%d,%u", vec+_capacity, 0x00, (nuint-_capacity)*4); + + _capacity = nuint; +} + +#if defined(U_STDCPP_ENABLE) && defined(DEBUG) +const char* UBitArray::dump(bool reset) const +{ + *UObjectIO::os << "vec " << (void*)vec << '\n' + << "_capacity " << _capacity; + + if (reset) + { + UObjectIO::output(); + + return UObjectIO::buffer_output; + } + + return 0; +} +#endif diff --git a/src/ulib/utility/http2.cpp b/src/ulib/utility/http2.cpp index bfa68c2a6..1ad5df700 100644 --- a/src/ulib/utility/http2.cpp +++ b/src/ulib/utility/http2.cpp @@ -12,6 +12,7 @@ // ============================================================================ #include +#include #include // huff_sym_table, huff_decode_table int UHTTP2::nerror; @@ -160,132 +161,132 @@ void UHTTP2::ctor() UString::str_allocate(STR_ALLOCATE_HTTP2); - hpack_static_table[ 0].name = UString::str_authority; + hpack_static_table[ 0].name = UString::str_authority->rep; hash_static_table[ 0] = UString::str_authority->hashIgnoreCase(); - hpack_static_table[ 1].name = UString::str_method; + hpack_static_table[ 1].name = UString::str_method->rep; hash_static_table[ 1] = UString::str_method->hashIgnoreCase(); - hpack_static_table[ 1].value = UString::str_method_get; - hpack_static_table[ 2].name = UString::str_method; - hpack_static_table[ 2].value = UString::str_method_post; - hpack_static_table[ 3].name = UString::str_path; + hpack_static_table[ 1].value = UString::str_method_get->rep; + hpack_static_table[ 2].name = UString::str_method->rep; + hpack_static_table[ 2].value = UString::str_method_post->rep; + hpack_static_table[ 3].name = UString::str_path->rep; hash_static_table[ 3] = UString::str_path->hashIgnoreCase(); - hpack_static_table[ 3].value = UString::str_path_root; - hpack_static_table[ 4].name = UString::str_path; - hpack_static_table[ 4].value = UString::str_path_index; - hpack_static_table[ 5].name = UString::str_scheme; + hpack_static_table[ 3].value = UString::str_path_root->rep; + hpack_static_table[ 4].name = UString::str_path->rep; + hpack_static_table[ 4].value = UString::str_path_index->rep; + hpack_static_table[ 5].name = UString::str_scheme->rep; hash_static_table[ 5] = UString::str_scheme->hashIgnoreCase(); - hpack_static_table[ 5].value = UString::str_http; - hpack_static_table[ 6].name = UString::str_scheme; - hpack_static_table[ 6].value = UString::str_scheme_https; - hpack_static_table[ 7].name = UString::str_status; + hpack_static_table[ 5].value = UString::str_http->rep; + hpack_static_table[ 6].name = UString::str_scheme->rep; + hpack_static_table[ 6].value = UString::str_scheme_https->rep; + hpack_static_table[ 7].name = UString::str_status->rep; hash_static_table[ 7] = UString::str_status->hashIgnoreCase(); - hpack_static_table[ 7].value = UString::str_status_200; - hpack_static_table[ 8].name = UString::str_status; - hpack_static_table[ 8].value = UString::str_status_204; - hpack_static_table[ 9].name = UString::str_status; - hpack_static_table[ 9].value = UString::str_status_206; - hpack_static_table[10].name = UString::str_status; - hpack_static_table[10].value = UString::str_status_304; - hpack_static_table[11].name = UString::str_status; - hpack_static_table[11].value = UString::str_status_400; - hpack_static_table[12].name = UString::str_status; - hpack_static_table[12].value = UString::str_status_404; - hpack_static_table[13].name = UString::str_status; - hpack_static_table[13].value = UString::str_status_500; - hpack_static_table[14].name = UString::str_accept_charset; + hpack_static_table[ 7].value = UString::str_status_200->rep; + hpack_static_table[ 8].name = UString::str_status->rep; + hpack_static_table[ 8].value = UString::str_status_204->rep; + hpack_static_table[ 9].name = UString::str_status->rep; + hpack_static_table[ 9].value = UString::str_status_206->rep; + hpack_static_table[10].name = UString::str_status->rep; + hpack_static_table[10].value = UString::str_status_304->rep; + hpack_static_table[11].name = UString::str_status->rep; + hpack_static_table[11].value = UString::str_status_400->rep; + hpack_static_table[12].name = UString::str_status->rep; + hpack_static_table[12].value = UString::str_status_404->rep; + hpack_static_table[13].name = UString::str_status->rep; + hpack_static_table[13].value = UString::str_status_500->rep; + hpack_static_table[14].name = UString::str_accept_charset->rep; hash_static_table[14] = UString::str_accept_charset->hashIgnoreCase(); - hpack_static_table[15].name = UString::str_accept_encoding; + hpack_static_table[15].name = UString::str_accept_encoding->rep; hash_static_table[15] = UString::str_accept_encoding->hashIgnoreCase(); - hpack_static_table[15].value = UString::str_accept_encoding_value; - hpack_static_table[16].name = UString::str_accept_language; + hpack_static_table[15].value = UString::str_accept_encoding_value->rep; + hpack_static_table[16].name = UString::str_accept_language->rep; hash_static_table[16] = UString::str_accept_language->hashIgnoreCase(); - hpack_static_table[17].name = UString::str_accept_ranges; + hpack_static_table[17].name = UString::str_accept_ranges->rep; hash_static_table[17] = UString::str_accept_ranges->hashIgnoreCase(); - hpack_static_table[18].name = UString::str_accept; + hpack_static_table[18].name = UString::str_accept->rep; hash_static_table[18] = UString::str_accept->hashIgnoreCase(); - hpack_static_table[19].name = UString::str_access_control_allow_origin; + hpack_static_table[19].name = UString::str_access_control_allow_origin->rep; hash_static_table[19] = UString::str_access_control_allow_origin->hashIgnoreCase(); - hpack_static_table[20].name = UString::str_age; + hpack_static_table[20].name = UString::str_age->rep; hash_static_table[20] = UString::str_age->hashIgnoreCase(); - hpack_static_table[21].name = UString::str_allow; + hpack_static_table[21].name = UString::str_allow->rep; hash_static_table[21] = UString::str_allow->hashIgnoreCase(); - hpack_static_table[22].name = UString::str_authorization; + hpack_static_table[22].name = UString::str_authorization->rep; hash_static_table[22] = UString::str_authorization->hashIgnoreCase(); - hpack_static_table[23].name = UString::str_cache_control; + hpack_static_table[23].name = UString::str_cache_control->rep; hash_static_table[23] = UString::str_cache_control->hashIgnoreCase(); - hpack_static_table[24].name = UString::str_content_disposition; + hpack_static_table[24].name = UString::str_content_disposition->rep; hash_static_table[24] = UString::str_content_disposition->hashIgnoreCase(); - hpack_static_table[25].name = UString::str_content_encoding; + hpack_static_table[25].name = UString::str_content_encoding->rep; hash_static_table[25] = UString::str_content_encoding->hashIgnoreCase(); - hpack_static_table[26].name = UString::str_content_language; + hpack_static_table[26].name = UString::str_content_language->rep; hash_static_table[26] = UString::str_content_language->hashIgnoreCase(); - hpack_static_table[27].name = UString::str_content_length; + hpack_static_table[27].name = UString::str_content_length->rep; hash_static_table[27] = UString::str_content_length->hashIgnoreCase(); - hpack_static_table[28].name = UString::str_content_location; + hpack_static_table[28].name = UString::str_content_location->rep; hash_static_table[28] = UString::str_content_location->hashIgnoreCase(); - hpack_static_table[29].name = UString::str_content_range; + hpack_static_table[29].name = UString::str_content_range->rep; hash_static_table[29] = UString::str_content_range->hashIgnoreCase(); - hpack_static_table[30].name = UString::str_content_type; + hpack_static_table[30].name = UString::str_content_type->rep; hash_static_table[30] = UString::str_content_type->hashIgnoreCase(); - hpack_static_table[31].name = UString::str_cookie; + hpack_static_table[31].name = UString::str_cookie->rep; hash_static_table[31] = UString::str_cookie->hashIgnoreCase(); - hpack_static_table[32].name = UString::str_date; + hpack_static_table[32].name = UString::str_date->rep; hash_static_table[32] = UString::str_date->hashIgnoreCase(); - hpack_static_table[33].name = UString::str_etag; + hpack_static_table[33].name = UString::str_etag->rep; hash_static_table[33] = UString::str_etag->hashIgnoreCase(); - hpack_static_table[34].name = UString::str_expect; + hpack_static_table[34].name = UString::str_expect->rep; hash_static_table[34] = UString::str_expect->hashIgnoreCase(); - hpack_static_table[35].name = UString::str_expires; + hpack_static_table[35].name = UString::str_expires->rep; hash_static_table[35] = UString::str_expires->hashIgnoreCase(); - hpack_static_table[36].name = UString::str_from; + hpack_static_table[36].name = UString::str_from->rep; hash_static_table[36] = UString::str_from->hashIgnoreCase(); - hpack_static_table[37].name = UString::str_host; + hpack_static_table[37].name = UString::str_host->rep; hash_static_table[37] = UString::str_host->hashIgnoreCase(); - hpack_static_table[38].name = UString::str_if_match; + hpack_static_table[38].name = UString::str_if_match->rep; hash_static_table[38] = UString::str_if_match->hashIgnoreCase(); - hpack_static_table[39].name = UString::str_if_modified_since; + hpack_static_table[39].name = UString::str_if_modified_since->rep; hash_static_table[39] = UString::str_if_modified_since->hashIgnoreCase(); - hpack_static_table[40].name = UString::str_if_none_match; + hpack_static_table[40].name = UString::str_if_none_match->rep; hash_static_table[40] = UString::str_if_none_match->hashIgnoreCase(); - hpack_static_table[41].name = UString::str_if_range; + hpack_static_table[41].name = UString::str_if_range->rep; hash_static_table[41] = UString::str_if_range->hashIgnoreCase(); - hpack_static_table[42].name = UString::str_if_unmodified_since; + hpack_static_table[42].name = UString::str_if_unmodified_since->rep; hash_static_table[42] = UString::str_if_unmodified_since->hashIgnoreCase(); - hpack_static_table[43].name = UString::str_last_modified; + hpack_static_table[43].name = UString::str_last_modified->rep; hash_static_table[43] = UString::str_last_modified->hashIgnoreCase(); - hpack_static_table[44].name = UString::str_link; + hpack_static_table[44].name = UString::str_link->rep; hash_static_table[44] = UString::str_link->hashIgnoreCase(); - hpack_static_table[45].name = UString::str_location; + hpack_static_table[45].name = UString::str_location->rep; hash_static_table[45] = UString::str_location->hashIgnoreCase(); - hpack_static_table[46].name = UString::str_max_forwards; + hpack_static_table[46].name = UString::str_max_forwards->rep; hash_static_table[46] = UString::str_max_forwards->hashIgnoreCase(); - hpack_static_table[47].name = UString::str_proxy_authenticate; + hpack_static_table[47].name = UString::str_proxy_authenticate->rep; hash_static_table[47] = UString::str_proxy_authenticate->hashIgnoreCase(); - hpack_static_table[48].name = UString::str_proxy_authorization; + hpack_static_table[48].name = UString::str_proxy_authorization->rep; hash_static_table[48] = UString::str_proxy_authorization->hashIgnoreCase(); - hpack_static_table[49].name = UString::str_range; + hpack_static_table[49].name = UString::str_range->rep; hash_static_table[49] = UString::str_range->hashIgnoreCase(); - hpack_static_table[50].name = UString::str_referer; + hpack_static_table[50].name = UString::str_referer->rep; hash_static_table[50] = UString::str_referer->hashIgnoreCase(); - hpack_static_table[51].name = UString::str_refresh; + hpack_static_table[51].name = UString::str_refresh->rep; hash_static_table[51] = UString::str_refresh->hashIgnoreCase(); - hpack_static_table[52].name = UString::str_retry_after; + hpack_static_table[52].name = UString::str_retry_after->rep; hash_static_table[52] = UString::str_retry_after->hashIgnoreCase(); - hpack_static_table[53].name = UString::str_server; + hpack_static_table[53].name = UString::str_server->rep; hash_static_table[53] = UString::str_server->hashIgnoreCase(); - hpack_static_table[54].name = UString::str_set_cookie; + hpack_static_table[54].name = UString::str_set_cookie->rep; hash_static_table[54] = UString::str_set_cookie->hashIgnoreCase(); - hpack_static_table[55].name = UString::str_strict_transport_security; + hpack_static_table[55].name = UString::str_strict_transport_security->rep; hash_static_table[55] = UString::str_strict_transport_security->hashIgnoreCase(); - hpack_static_table[56].name = UString::str_transfer_encoding; + hpack_static_table[56].name = UString::str_transfer_encoding->rep; hash_static_table[56] = UString::str_transfer_encoding->hashIgnoreCase(); - hpack_static_table[57].name = UString::str_user_agent; + hpack_static_table[57].name = UString::str_user_agent->rep; hash_static_table[57] = UString::str_user_agent->hashIgnoreCase(); - hpack_static_table[58].name = UString::str_vary; + hpack_static_table[58].name = UString::str_vary->rep; hash_static_table[58] = UString::str_vary->hashIgnoreCase(); - hpack_static_table[59].name = UString::str_via; + hpack_static_table[59].name = UString::str_via->rep; hash_static_table[59] = UString::str_via->hashIgnoreCase(); - hpack_static_table[60].name = UString::str_www_authenticate; + hpack_static_table[60].name = UString::str_www_authenticate->rep; hash_static_table[60] = UString::str_www_authenticate->hashIgnoreCase(); #ifdef DEBUG @@ -462,6 +463,8 @@ unsigned char* UHTTP2::hpackDecodeString(unsigned char* src, unsigned char* src_ if (len <= 0) { + hpack_errno = -2; + err: value.clear(); U_RETURN_POINTER(src, unsigned char); @@ -470,7 +473,7 @@ err: value.clear(); #ifdef DEBUG if (src == src_end) { - hpack_errno = -2; // // The decoding buffer ends before the decoded HPACK block + hpack_errno = -2; // The decoding buffer ends before the decoded HPACK block goto err; } @@ -657,6 +660,48 @@ unsigned char* UHTTP2::hpackEncodeString(unsigned char* dst, const char* src, ui U_RETURN_POINTER(dst, unsigned char); } +void UHTTP2::evictHpackDynTblEntry(HpackDynamicTable* dyntbl, HpackHeaderTableEntry* entry, uint32_t index) +{ + U_TRACE(0, "UHTTP2::evictHpackDynTblEntry(%p,%p,%u)", dyntbl, entry, index) + + U_INTERNAL_DUMP("dyntbl->entry_start_index = %u dyntbl->entry_capacity = %u dyntbl->num_entries = %u", dyntbl->entry_start_index, dyntbl->entry_capacity, dyntbl->num_entries) + + U_ASSERT_EQUALS(entry, getHpackDynTblEntry(dyntbl, index)) + + evictHpackDynTblEntry(dyntbl, entry); + + if (index == 0) + { + dyntbl->entry_start_index = (dyntbl->entry_start_index+1+dyntbl->entry_capacity) % dyntbl->entry_capacity; + } + else if (index < dyntbl->num_entries) + { + HpackHeaderTableEntry* dst_entry = entry; + HpackHeaderTableEntry* src_entry = entry+1; + + entry = dyntbl->entries + dyntbl->entry_start_index; + + uint32_t src_index = dyntbl->entry_start_index+index+1; + +loop: U_INTERNAL_ASSERT_POINTER(src_entry->name) + U_INTERNAL_ASSERT_POINTER(src_entry->value) + + U_INTERNAL_DUMP("src_index = %u src_entry->name = %V src_entry->value = %V", src_index, src_entry->name, src_entry->value) + + *dst_entry = *src_entry; + + if (++index == dyntbl->num_entries) return; + + if (src_entry == entry) dst_entry = entry; + else ++dst_entry; + + if (++src_index != dyntbl->entry_capacity) ++src_entry; + else src_entry = entry; + + goto loop; + } +} + void UHTTP2::addHpackDynTblEntry(HpackDynamicTable* dyntbl, const UString& name, const UString& value) { U_TRACE(1, "UHTTP2::addHpackDynTblEntry(%p,%V,%V)", dyntbl, name.rep, value.rep) @@ -670,10 +715,10 @@ void UHTTP2::addHpackDynTblEntry(HpackDynamicTable* dyntbl, const UString& name, // adjust the size - while (dyntbl->num_entries != 0 && + while (dyntbl->num_entries > 0 && (dyntbl->hpack_size + size_add) > dyntbl->hpack_capacity) { - evictHpackDynTblEntry(dyntbl); + evictHpackDynTblFirstEntry(dyntbl); } if (dyntbl->num_entries == 0) @@ -695,7 +740,7 @@ void UHTTP2::addHpackDynTblEntry(HpackDynamicTable* dyntbl, const UString& name, HpackHeaderTableEntry* new_entries = (HpackHeaderTableEntry*) UMemoryPool::_malloc(&new_capacity, sizeof(HpackHeaderTableEntry)); - if (dyntbl->num_entries != 0) + if (dyntbl->num_entries > 0) { uint32_t src_index = dyntbl->entry_start_index, dst_index = 0; @@ -723,10 +768,15 @@ void UHTTP2::addHpackDynTblEntry(HpackDynamicTable* dyntbl, const UString& name, dyntbl->entry_start_index = (dyntbl->entry_start_index - 1 + dyntbl->entry_capacity) % dyntbl->entry_capacity; - UHTTP2::HpackHeaderTableEntry* entry = dyntbl->entries + dyntbl->entry_start_index; + HpackHeaderTableEntry* entry = dyntbl->entries + dyntbl->entry_start_index; + + U_INTERNAL_ASSERT_EQUALS(entry->name, 0) + U_INTERNAL_ASSERT_EQUALS(entry->value, 0) - U_NEW(UString, entry->name, UString(name)); - U_NEW(UString, entry->value, UString(value)); + // NB: we increases the reference string... + + (entry->name = name.rep)->hold(); + (entry->value = value.rep)->hold(); U_INTERNAL_DUMP("num_entries = %u entry_capacity = %u entry_start_index = %u hpack_size = %u hpack_capacity = %u hpack_max_capacity = %u", dyntbl->num_entries, dyntbl->entry_capacity, dyntbl->entry_start_index, dyntbl->hpack_size, dyntbl->hpack_capacity, dyntbl->hpack_max_capacity) @@ -972,58 +1022,48 @@ void UHTTP2::decodeHeaders(UHashMap* table, HpackDynamicTable* dyntbl, if (isHpackError()) return; # endif - if (name) + if (isHeaderName(name) == false) { - if (isHeaderName(name) == false) - { - hpack_errno = -7; // A invalid header name or value character was coded + hpack_errno = -7; // A invalid header name or value character was coded # ifdef DEBUG - if (btest) return; + if (btest) return; # endif - nerror = PROTOCOL_ERROR; - - return; - } - - if (name.equal(U_CONSTANT_TO_PARAM("connection"))) - { - nerror = PROTOCOL_ERROR; + nerror = PROTOCOL_ERROR; - return; - } + return; + } - ptr = hpackDecodeString(ptr, endptr, value); + if (name.equal(U_CONSTANT_TO_PARAM("connection"))) + { + nerror = PROTOCOL_ERROR; -# ifdef DEBUG - if (isHpackError()) return; -# endif + return; + } - if (name.first_char() != ':') - { - bregular = true; + ptr = hpackDecodeString(ptr, endptr, value); - if ( name.equal(U_CONSTANT_TO_PARAM("te")) && - value.equal(U_CONSTANT_TO_PARAM("trailers")) == false) - { - nerror = PROTOCOL_ERROR; +# ifdef DEBUG + if (isHpackError()) return; +# endif - return; - } - } + if (name.first_char() != ':') + { + bregular = true; - if (value) + if ( name.equal(U_CONSTANT_TO_PARAM("te")) && + value.equal(U_CONSTANT_TO_PARAM("trailers")) == false) { - table->hash = name.hashIgnoreCase(); + nerror = PROTOCOL_ERROR; - goto insert; + return; } } - nerror = COMPRESSION_ERROR; + table->hash = name.hashIgnoreCase(); - return; + goto insert; } check2: @@ -1041,29 +1081,31 @@ void UHTTP2::decodeHeaders(UHashMap* table, HpackDynamicTable* dyntbl, entry = getHpackDynTblEntry(dyntbl, index); - table->hash = (name = *(entry->name)).hashIgnoreCase(); + name._assign(entry->name); + + table->hash = entry->name->hashIgnoreCase(); if (binsert_dynamic_table == false) { - value = *(entry->value); + value._assign(entry->value); goto insert_table; } if ((table->lookup(name.rep), table->node)) { - /** - * A new entry can reference the name of an entry in the dynamic table that will be evicted when adding this new entry into the dynamic table. - * Implementations are cautioned to avoid deleting the referenced name if the referenced entry is evicted from the dynamic table prior to inserting the new entry - */ - ptr = hpackDecodeString(ptr, endptr, value); # ifdef DEBUG if (isHpackError()) return; # endif - evictHpackDynTblEntry(dyntbl, entry); + /** + * A new entry can reference the name of an entry in the dynamic table that will be evicted when adding this new entry into the dynamic table. + * Implementations are cautioned to avoid deleting the referenced name if the referenced entry is evicted from the dynamic table prior to inserting the new entry + */ + + evictHpackDynTblEntry(dyntbl, entry, index); goto insertd; } @@ -1101,7 +1143,7 @@ void UHTTP2::decodeHeaders(UHashMap* table, HpackDynamicTable* dyntbl, U_INTERNAL_DUMP("entry->value = %p", entry->value) - if (entry->value) value = *(entry->value); + if (entry->value) value._assign(entry->value); else { nerror = PROTOCOL_ERROR; @@ -1118,7 +1160,7 @@ void UHTTP2::decodeHeaders(UHashMap* table, HpackDynamicTable* dyntbl, # endif } - name = *(entry->name); + name._assign(entry->name); table->hash = hash_static_table[index]; @@ -1140,6 +1182,8 @@ void UHTTP2::decodeHeaders(UHashMap* table, HpackDynamicTable* dyntbl, table->hash = hash_static_table[0]; // authority +host: U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) + if (bvalue_is_indexed) { nerror = PROTOCOL_ERROR; @@ -1147,9 +1191,6 @@ void UHTTP2::decodeHeaders(UHashMap* table, HpackDynamicTable* dyntbl, return; } -host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) - U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) - ptr = hpackDecodeString(ptr, endptr, value); # ifdef DEBUG @@ -1189,9 +1230,9 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) U_http_method_type = (index == 2 ? HTTP_GET : (U_http_method_num = 2, HTTP_POST)); # ifdef DEBUG - if (btest) value = *(hpack_static_table[index-1].value); + if (btest) value._assign(hpack_static_table[index-1].value); - U_INTERNAL_DUMP("name = %V value = %V", UString::str_method->rep, hpack_static_table[index-1].value->rep) + U_INTERNAL_DUMP("name = %V value = %V", UString::str_method->rep, hpack_static_table[index-1].value) # endif } else @@ -1317,13 +1358,19 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_6: // http case_7: // https - U_INTERNAL_ASSERT(bvalue_is_indexed) U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) + if (bvalue_is_indexed == false) + { + nerror = PROTOCOL_ERROR; + + return; + } + bvalue_is_indexed = false; # ifdef DEBUG - U_INTERNAL_DUMP("name = %V value = %V", hpack_static_table[index-1].name->rep, hpack_static_table[index-1].value->rep) + U_INTERNAL_DUMP("name = %V value = %V", hpack_static_table[index-1].name, hpack_static_table[index-1].value) U_INTERNAL_DUMP("bregular = %b pseudo_header_mask = 0x%x %B", bregular, pseudo_header_mask, pseudo_header_mask) @@ -1349,7 +1396,7 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) index_ptr = ptr; - cout.write(buffer, u__snprintf(buffer, sizeof(buffer), U_CONSTANT_TO_PARAM("\n%v: %v"), hpack_static_table[index-1].name->rep, hpack_static_table[index-1].value->rep)); + cout.write(buffer, u__snprintf(buffer, sizeof(buffer), U_CONSTANT_TO_PARAM("\n%v: %v"), hpack_static_table[index-1].name, hpack_static_table[index-1].value)); } # endif @@ -1373,7 +1420,7 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) { bvalue_is_indexed = false; - value = *(hpack_static_table[index-1].value); + value._assign(hpack_static_table[index-1].value); } else { @@ -1423,9 +1470,15 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_17: // accept-language - U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) + if (bvalue_is_indexed) + { + nerror = PROTOCOL_ERROR; + + return; + } + name = *UString::str_accept_language; ptr = hpackDecodeString(ptr, endptr, value); @@ -1445,9 +1498,15 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_19: // accept - U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) + if (bvalue_is_indexed) + { + nerror = PROTOCOL_ERROR; + + return; + } + name = *UString::str_accept; ptr = hpackDecodeString(ptr, endptr, value); @@ -1467,7 +1526,12 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_28: // content_length - U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) + if (bvalue_is_indexed) + { + nerror = PROTOCOL_ERROR; + + return; + } name = *UString::str_content_length; @@ -1490,7 +1554,12 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_31: // content_type - U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) + if (bvalue_is_indexed) + { + nerror = PROTOCOL_ERROR; + + return; + } name = *UString::str_content_type; @@ -1514,9 +1583,15 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_32: // cookie - U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) + if (bvalue_is_indexed) + { + nerror = PROTOCOL_ERROR; + + return; + } + name = *UString::str_cookie; ptr = hpackDecodeString(ptr, endptr, value); @@ -1538,16 +1613,22 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_35: // expect - U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) + if (bvalue_is_indexed) + { + nerror = PROTOCOL_ERROR; + + return; + } + ptr = hpackDecodeString(ptr, endptr, value); # ifdef DEBUG if (isHpackError()) return; # endif - U_INTERNAL_DUMP("name = %V value = %V", hpack_static_table[35-1].name->rep, value.rep) + U_INTERNAL_DUMP("name = %V value = %V", hpack_static_table[35-1].name, value.rep) // NB: check for 'Expect: 100-continue' (as curl does)... @@ -1566,9 +1647,15 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_40: // if-modified-since - U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) + if (bvalue_is_indexed) + { + nerror = PROTOCOL_ERROR; + + return; + } + name = *UString::str_if_modified_since; ptr = hpackDecodeString(ptr, endptr, value); @@ -1587,9 +1674,15 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_50: // range - U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) + if (bvalue_is_indexed) + { + nerror = PROTOCOL_ERROR; + + return; + } + name = *UString::str_range; ptr = hpackDecodeString(ptr, endptr, value); @@ -1609,9 +1702,15 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_51: // referer - U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) + if (bvalue_is_indexed) + { + nerror = PROTOCOL_ERROR; + + return; + } + name = *UString::str_referer; ptr = hpackDecodeString(ptr, endptr, value); @@ -1639,9 +1738,15 @@ host: U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) case_58: // user-agent - U_INTERNAL_ASSERT_EQUALS(bvalue_is_indexed, false) U_INTERNAL_ASSERT_EQUALS(bdecodeHeadersDebug, false) + if (bvalue_is_indexed) + { + nerror = PROTOCOL_ERROR; + + return; + } + name = *UString::str_user_agent; ptr = hpackDecodeString(ptr, endptr, value); @@ -1716,18 +1821,18 @@ void UHTTP2::decodeHeaders() if (table->empty() == false) { - U_DUMP_CONTAINER(*table); + U_DUMP_CONTAINER(*table) table->callWithDeleteForAllEntry(eraseHeaders); - U_DUMP_CONTAINER(*table); + U_DUMP_CONTAINER(*table) } decodeHeaders(table, &(pConnection->idyntbl), (unsigned char*)pStream->headers.data(), (unsigned char*)pStream->headers.pend()); if (nerror == NO_ERROR) { - U_DUMP_CONTAINER(*table); + U_DUMP_CONTAINER(*table) U_INTERNAL_DUMP("URI(%u) = %.*S", U_http_info.uri_len, U_HTTP_URI_TO_TRACE) @@ -2150,7 +2255,7 @@ void UHTTP2::readFrame() if (bsetting_send) { - if (USocketExt::write(UServer_Base::csocket, U_CONSTANT_TO_PARAM(HTTP2_SETTINGS_ACK), 0) == 0) + if (USocketExt::write(UServer_Base::csocket, U_CONSTANT_TO_PARAM(HTTP2_SETTINGS_ACK), 0) != U_CONSTANT_SIZE(HTTP2_SETTINGS_ACK)) { nerror = CONNECT_ERROR; @@ -2161,7 +2266,7 @@ void UHTTP2::readFrame() { bsetting_send = true; - if (USocketExt::write(UServer_Base::csocket, U_CONSTANT_TO_PARAM(HTTP2_SETTINGS_BIN HTTP2_SETTINGS_ACK), 0) == 0) + if (USocketExt::write(UServer_Base::csocket, U_CONSTANT_TO_PARAM(HTTP2_SETTINGS_BIN HTTP2_SETTINGS_ACK), 0) != U_CONSTANT_SIZE(HTTP2_SETTINGS_BIN HTTP2_SETTINGS_ACK)) { nerror = CONNECT_ERROR; @@ -2499,7 +2604,7 @@ void UHTTP2::handlerResponse() uint32_t sz1 = UHTTP::set_cookie->size(), sz2 = UHTTP::ext->size(); - U_INTERNAL_DUMP("ext(%u) = %#V", sz2, UHTTP::ext->rep) + U_INTERNAL_DUMP("Set-Cookie(%u) = %V UHTTP::ext(%u) = %#V", sz1, UHTTP::set_cookie->rep, sz2, UHTTP::ext->rep) UClientImage_Base::wbuffer->setBuffer(800U + sz1 + sz2); @@ -2620,7 +2725,7 @@ void UHTTP2::handlerResponse() ULog::updateDate3(ptr_date); # endif - U_ASSERT(entry->name->equal(*UString::str_date)) + U_ASSERT(UString::str_date->equal(entry->name)) /** * dst = hpackEncodeInt(dst, 1+HTTP2_HEADER_TABLE_OFFSET, (1<<7)-1, 0x80); @@ -2809,7 +2914,6 @@ void UHTTP2::writeResponse() { U_TRACE_NO_PARAM(0, "UHTTP2::writeResponse()") - U_INTERNAL_ASSERT_MAJOR((int)pStream->id, 0) U_INTERNAL_ASSERT_DIFFERS(U_ClientImage_parallelization, U_PARALLELIZATION_PARENT) char buffer1[HTTP2_FRAME_HEADER_SIZE]; @@ -2930,9 +3034,58 @@ void UHTTP2::writeResponse() } } -void UHTTP2::handlerDelete(UClientImage_Base* pclient) +#if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) +void UHTTP2::wrapRequest() +{ + U_TRACE_NO_PARAM(0, "UHTTP2::wrapRequest()") + + UClientImage_Base::request->setBuffer(U_http_info.uri_len + + U_http_info.query_len + + U_http_host_len + + U_http_accept_len + + U_http_info.cookie_len + + U_http_info.referer_len + + U_http_info.user_agent_len + + U_http_accept_language_len + 500); + + + UClientImage_Base::request->snprintf(U_CONSTANT_TO_PARAM("%.*s %.*s HTTP/1.1\r\n"), U_HTTP_METHOD_NUM_TO_TRACE(U_http_method_num), U_HTTP_URI_QUERY_TO_TRACE); + + if (U_http_host_len) UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Host: %.*s\r\n"), U_HTTP_HOST_TO_TRACE); + if (U_http_accept_len) UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Accept: %.*s\r\n"), U_HTTP_ACCEPT_TO_TRACE); + if (U_http_info.cookie_len) UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Cookie: %.*s\r\n"), U_HTTP_COOKIE_TO_TRACE); + if (U_http_info.referer_len) UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Referer: %.*s\r\n"), U_HTTP_REFERER_TO_TRACE); + if (U_http_info.user_agent_len) UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("User-Agent: %.*s\r\n"), U_HTTP_USER_AGENT_TO_TRACE); + if (U_http_accept_language_len) UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Accept-Language: %.*s\r\n"), U_HTTP_ACCEPT_LANGUAGE_TO_TRACE); + + if (U_http_is_accept_gzip) + { + pConnection->itable.hash = hash_static_table[15]; // accept_encoding + + pConnection->itable.lookup(hpack_static_table[15].name); + + U_INTERNAL_ASSERT_POINTER(pConnection->itable.node) + + UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Accept-Encoding: %v\r\n"), pConnection->itable.elem()); + } + + uint32_t sz = UClientImage_Base::body->size(); + + if (sz) + { + if (U_http_content_type_len) UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Content-Type: %.*s\r\n"), U_HTTP_CTYPE_TO_TRACE); + UClientImage_Base::request->snprintf_add(U_CONSTANT_TO_PARAM("Content-Length: %u\r\n"), sz); + } + + pConnection->itable.callForAllEntry(copyHeaders); + + (void) UClientImage_Base::request->append(U_CONSTANT_TO_PARAM(U_CRLF)); +} +#endif + +void UHTTP2::handlerDelete(UClientImage_Base* pclient, bool& bsocket_open) { - U_TRACE(0, "UHTTP2::handlerDelete(%p)", pclient) + U_TRACE(0, "UHTTP2::handlerDelete(%p,%b)", pclient, bsocket_open) uint32_t idx = (pclient - UServer_Base::vClientImage); @@ -2950,9 +3103,7 @@ void UHTTP2::handlerDelete(UClientImage_Base* pclient) U_ASSERT(pStream->body.empty()) U_ASSERT(pStream->headers.empty()) - U_INTERNAL_ASSERT_EQUALS(pStream->id, 0) U_INTERNAL_ASSERT_EQUALS(pStream->clength, 0) - U_INTERNAL_ASSERT_EQUALS(pStream->state, STREAM_STATE_IDLE) } #endif @@ -2963,11 +3114,14 @@ void UHTTP2::handlerDelete(UClientImage_Base* pclient) U_INTERNAL_DUMP("pclient->socket->iState = %u", pclient->socket->iState) - if (pclient->socket->isTimeout()) + if (bsocket_open && + pclient->socket->isTimeout()) { nerror = NO_ERROR; sendGoAway(); + + bsocket_open = false; } } @@ -2988,25 +3142,26 @@ bool UHTTP2::initRequest() pStream = pStreamEnd = pConnection->streams; - U_DUMP("pStream->state = (%u, %s)", pStream->state, getStreamStatusDescription()) - U_ASSERT(pStream->body.empty()) U_ASSERT(pStream->headers.empty()) - U_INTERNAL_ASSERT_EQUALS(pStream->id, 0) U_INTERNAL_ASSERT_EQUALS(pStream->clength, 0) - U_INTERNAL_ASSERT_EQUALS(pStream->state, STREAM_STATE_IDLE) if (pConnection->state != CONN_STATE_IDLE) { if (pConnection->state == CONN_STATE_OPEN) { + U_DUMP("pStream->state = (%u, %s)", pStream->state, getStreamStatusDescription()) + U_INTERNAL_ASSERT_EQUALS(U_ClientImage_http(UServer_Base::pClientImage), '2') U_RETURN(true); } pConnection->reset(); + + pStream->id = 0; + pStream->state = STREAM_STATE_IDLE; } pConnection->itable.clear(); // NB: we can't clear it before because UClientImage_Base::getRequestUri() depend on it... @@ -3025,8 +3180,8 @@ void UHTTP2::handlerRequest() U_INTERNAL_ASSERT_EQUALS(U_http_version, '2') + char* ptr; uint32_t sz; - const char* ptr; nerror = hpack_errno = @@ -3041,7 +3196,11 @@ void UHTTP2::handlerRequest() { bsetting_send = true; - if (USocketExt::write(UServer_Base::csocket, U_CONSTANT_TO_PARAM(HTTP2_CONNECTION_UPGRADE HTTP2_SETTINGS_BIN), 0) == 0) goto err; + if (USocketExt::write(UServer_Base::csocket, U_CONSTANT_TO_PARAM(HTTP2_CONNECTION_UPGRADE HTTP2_SETTINGS_BIN), 0) != + U_CONSTANT_SIZE(HTTP2_CONNECTION_UPGRADE HTTP2_SETTINGS_BIN)) + { + goto err; + } U_INTERNAL_DUMP("U_http_uri_offset = %u", U_http_uri_offset) @@ -3151,7 +3310,7 @@ void UHTTP2::handlerRequest() sz = pStream->headers.size(); - U_INTERNAL_DUMP("sz = %u U_http_info.uri_len = %u U_http2_settings_len = %u", sz, U_http_info.uri_len, U_http2_settings_len) + U_INTERNAL_DUMP("sz = %u U_http_info.uri_len = %u U_http2_settings_len = %u U_ClientImage_close = %b", sz, U_http_info.uri_len, U_http2_settings_len, U_ClientImage_close) if (sz == 0) { @@ -3171,7 +3330,11 @@ void UHTTP2::handlerRequest() U_INTERNAL_ASSERT_EQUALS(U_http_info.uri_len, 0) - if (bsetting_send) goto read_request; // NB: OPTION upgrade, we need a HEADERS frame... + if (bsetting_send && + U_ClientImage_close == false) + { + goto read_request; // NB: OPTION upgrade, we need a HEADERS frame... + } UClientImage_Base::setRequestProcessed(); @@ -3205,7 +3368,7 @@ loop: U_DUMP("pStream->id = %d pStream->state = (%u, %s) pStream->headers(%u) = if (pStream->state <= STREAM_STATE_OPEN) goto read_request; - if ((int)pStream->id > 0) + if (pStream->headers) { decodeHeaders(); // parse header block @@ -3252,7 +3415,7 @@ loop: U_DUMP("pStream->id = %d pStream->state = (%u, %s) pStream->headers(%u) = u_write_unalignedp32(ptr+5,pStream->id); - if (USocketExt::write(UServer_Base::csocket, buffer, sizeof(buffer), 0) == 0) goto err; + if (USocketExt::write(UServer_Base::csocket, buffer, sizeof(buffer), 0) != sizeof(buffer)) goto err; goto read_request; // wait for DATA frames } @@ -3280,20 +3443,21 @@ loop: U_DUMP("pStream->id = %d pStream->state = (%u, %s) pStream->headers(%u) = U_INTERNAL_DUMP("nerror = %u", nerror) if (nerror != NO_ERROR) goto err; - } - pStream->id = -pStream->id; + pStream->clength = 0; + + pStream->body.clear(); + pStream->headers.clear(); + } while (++pStream <= pStreamEnd) { - if ((int)pStream->id > 0) - { - sz = pStream->headers.size(); - - U_INTERNAL_DUMP("sz = %u", sz) + sz = pStream->headers.size(); - U_INTERNAL_ASSERT_MAJOR(sz, 0) + U_INTERNAL_DUMP("sz = %u", sz) + if (sz) + { startRequest(); goto loop; @@ -3307,12 +3471,10 @@ loop: U_DUMP("pStream->id = %d pStream->state = (%u, %s) pStream->headers(%u) = { U_DUMP("pStream->id = %d pStream->state = (%u, %s) pStream->headers = %V pStream->clength = %u pStream->body(%u) = %V", pStream->id, pStream->state, getStreamStatusDescription(), pStream->headers.rep, pStream->clength, pStream->body.size(), pStream->body.rep) - - U_INTERNAL_ASSERT_MINOR((int)pStream->id, 0) } # endif - goto end; + return; } err: @@ -3417,41 +3579,6 @@ __pure bool UHTTP2::isHeaderValue(const char* s, uint32_t n) U_RETURN(true); } -void UHTTP2::clearHpackDynTbl(HpackDynamicTable* dyntbl) -{ - U_TRACE(0, "UHTTP2::clearHpackDynTbl(%p)", dyntbl) - - if (dyntbl->num_entries) - { - U_INTERNAL_DUMP("num_entries = %u entry_capacity = %u entry_start_index = %u hpack_size = %u hpack_capacity = %u hpack_max_capacity = %u", - dyntbl->num_entries, dyntbl->entry_capacity, dyntbl->entry_start_index, dyntbl->hpack_size, dyntbl->hpack_capacity, dyntbl->hpack_max_capacity) - - uint32_t index = dyntbl->entry_start_index; - - do { - HpackHeaderTableEntry* entry = dyntbl->entries + index; - - delete entry->name; - delete entry->value; - - if (++index == dyntbl->entry_capacity) index = 0; - - dyntbl->num_entries--; - } - while (dyntbl->num_entries != 0); - - UMemoryPool::_free(dyntbl->entries, dyntbl->entry_capacity, sizeof(HpackHeaderTableEntry)); - - dyntbl->entry_capacity = - dyntbl->entry_start_index = - dyntbl->hpack_size = 0; - dyntbl->entries = 0; - - U_INTERNAL_DUMP("num_entries = %u entry_capacity = %u entry_start_index = %u hpack_size = %u hpack_capacity = %u hpack_max_capacity = %u", - dyntbl->num_entries, dyntbl->entry_capacity, dyntbl->entry_start_index, dyntbl->hpack_size, dyntbl->hpack_capacity, dyntbl->hpack_max_capacity) - } -} - void UHTTP2::sendWindowUpdate() { U_TRACE_NO_PARAM(0, "UHTTP2::sendWindowUpdate()") @@ -3476,7 +3603,7 @@ void UHTTP2::sendWindowUpdate() u_write_unalignedp32(ptr+HTTP2_FRAME_HEADER_SIZE+4+5,pStream->id); u_write_unalignedp32(ptr+HTTP2_FRAME_HEADER_SIZE+4+9,pConnection->inp_window); - if (USocketExt::write(UServer_Base::csocket, buffer, sizeof(buffer), 0) == 0) nerror = CONNECT_ERROR; + if (USocketExt::write(UServer_Base::csocket, buffer, sizeof(buffer), 0) != sizeof(buffer)) nerror = CONNECT_ERROR; } void UHTTP2::sendPing() @@ -3497,7 +3624,7 @@ void UHTTP2::sendPing() if (*(uint64_t*)frame.payload) U_MEMCPY(buffer+HTTP2_FRAME_HEADER_SIZE, frame.payload, 8); - if (USocketExt::write(UServer_Base::csocket, buffer, sizeof(buffer), 0) == 0) nerror = CONNECT_ERROR; + if (USocketExt::write(UServer_Base::csocket, buffer, sizeof(buffer), 0) != sizeof(buffer)) nerror = CONNECT_ERROR; } void UHTTP2::sendGoAway() @@ -3525,7 +3652,7 @@ void UHTTP2::sendGoAway() pConnection->state = CONN_STATE_IS_CLOSING; - if (USocketExt::write(UServer_Base::csocket, buffer, sizeof(buffer), 0)) UClientImage_Base::close(); + if (USocketExt::write(UServer_Base::csocket, buffer, sizeof(buffer), 0) == sizeof(buffer)) UClientImage_Base::close(); } void UHTTP2::sendResetStream() @@ -3553,11 +3680,54 @@ void UHTTP2::sendResetStream() pStream->state = STREAM_STATE_CLOSED; - if (USocketExt::write(UServer_Base::csocket, buffer, sizeof(buffer), 0) == 0) nerror = CONNECT_ERROR; + if (USocketExt::write(UServer_Base::csocket, buffer, sizeof(buffer), 0) != sizeof(buffer)) nerror = CONNECT_ERROR; +} + +void UHTTP2::clearHpackDynTbl(HpackDynamicTable* dyntbl) +{ + U_TRACE(0, "UHTTP2::clearHpackDynTbl(%p)", dyntbl) + + if (dyntbl->num_entries) + { + U_INTERNAL_DUMP("num_entries = %u entry_capacity = %u entry_start_index = %u hpack_size = %u hpack_capacity = %u hpack_max_capacity = %u", + dyntbl->num_entries, dyntbl->entry_capacity, dyntbl->entry_start_index, dyntbl->hpack_size, dyntbl->hpack_capacity, dyntbl->hpack_max_capacity) + + uint32_t index = dyntbl->entry_start_index; + + do { + HpackHeaderTableEntry* entry = dyntbl->entries + index; + + U_INTERNAL_ASSERT_POINTER(entry->name) + U_INTERNAL_ASSERT_POINTER(entry->value) + + // NB: we decreases the reference string... + + entry->name->release(); + entry->value->release(); + + entry->name = + entry->value = 0; + + if (++index == dyntbl->entry_capacity) index = 0; + + dyntbl->num_entries--; + } + while (dyntbl->num_entries != 0); + + UMemoryPool::_free(dyntbl->entries, dyntbl->entry_capacity, sizeof(HpackHeaderTableEntry)); + + dyntbl->entry_capacity = + dyntbl->entry_start_index = + dyntbl->hpack_size = 0; + dyntbl->entries = 0; + + U_INTERNAL_DUMP("num_entries = %u entry_capacity = %u entry_start_index = %u hpack_size = %u hpack_capacity = %u hpack_max_capacity = %u", + dyntbl->num_entries, dyntbl->entry_capacity, dyntbl->entry_start_index, dyntbl->hpack_size, dyntbl->hpack_capacity, dyntbl->hpack_max_capacity) + } } #ifdef DEBUG -void UHTTP2::printHpackDynamicTable(const HpackDynamicTable* dyntbl, ostream& os) +void UHTTP2::printHpackDynamicTable(HpackDynamicTable* dyntbl, ostream& os) { U_TRACE(0, "UHTTP2::printHpackDynamicTable(%p,%p)", dyntbl, &os) @@ -3574,10 +3744,13 @@ void UHTTP2::printHpackDynamicTable(const HpackDynamicTable* dyntbl, ostream& os for (uint32_t idx = 0; idx < dyntbl->num_entries; ++idx) { - entry = getHpackDynTblEntry(dyntbl, idx); + entry = dyntbl->entries + ((dyntbl->entry_start_index + idx) % dyntbl->entry_capacity); - name = *(entry->name); - value = *(entry->value); + if (entry->name) name._assign(entry->name); + else name.clear(); + + if (entry->value) value._assign(entry->value); + else value.clear(); len = 32 + name.size() + value.size(); @@ -3600,6 +3773,56 @@ void UHTTP2::printHpackDynamicTable(const HpackDynamicTable* dyntbl, ostream& os } } +void UHTTP2::testHpackDynTbl() +{ + U_TRACE_NO_PARAM(0, "UHTTP2::testHpackDynTbl()") + + HpackDynamicTable dyntbl; + + (void) memset(&dyntbl, 0, sizeof(HpackDynamicTable)); + + dyntbl.hpack_capacity = + dyntbl.hpack_max_capacity = 4096; + + addHpackDynTblEntry(&dyntbl, U_STRING_FROM_CONSTANT("key1"), U_STRING_FROM_CONSTANT("value1")); + addHpackDynTblEntry(&dyntbl, U_STRING_FROM_CONSTANT("key2"), U_STRING_FROM_CONSTANT("value2")); + addHpackDynTblEntry(&dyntbl, U_STRING_FROM_CONSTANT("key3"), U_STRING_FROM_CONSTANT("value3")); + addHpackDynTblEntry(&dyntbl, U_STRING_FROM_CONSTANT("key4"), U_STRING_FROM_CONSTANT("value4")); + addHpackDynTblEntry(&dyntbl, U_STRING_FROM_CONSTANT("key5"), U_STRING_FROM_CONSTANT("value5")); + addHpackDynTblEntry(&dyntbl, U_STRING_FROM_CONSTANT("key6"), U_STRING_FROM_CONSTANT("value6")); + addHpackDynTblEntry(&dyntbl, U_STRING_FROM_CONSTANT("key7"), U_STRING_FROM_CONSTANT("value7")); + addHpackDynTblEntry(&dyntbl, U_STRING_FROM_CONSTANT("key8"), U_STRING_FROM_CONSTANT("value8")); + + U_DUMP_OBJECT(dyntbl) + + evictHpackDynTblFirstEntry(&dyntbl); + evictHpackDynTblFirstEntry(&dyntbl); + + U_INTERNAL_DUMP("** AFTER evictHpackDynTblFirstEntry() **") + + U_DUMP_OBJECT(dyntbl) + + evictHpackDynTblLastEntry(&dyntbl); + evictHpackDynTblLastEntry(&dyntbl); + + U_INTERNAL_DUMP("** AFTER evictHpackDynTblLastEntry() **") + + U_DUMP_OBJECT(dyntbl) + + evictHpackDynTblEntry(&dyntbl, getHpackDynTblEntry(&dyntbl, 1), 1); + addHpackDynTblEntry(&dyntbl, U_STRING_FROM_CONSTANT("key5"), U_STRING_FROM_CONSTANT("replace5")); + + U_INTERNAL_DUMP("** AFTER evictHpackDynTblEntry(1) **") + + U_DUMP_OBJECT(dyntbl) + + clearHpackDynTbl(&dyntbl); + + U_INTERNAL_DUMP("** AFTER clearHpackDynTbl(1) **") + + U_DUMP_OBJECT(dyntbl) +} + const char* UHTTP2::getFrameTypeDescription(char type) { U_TRACE(0, "UHTTP2::getFrameTypeDescription(%d)", type) diff --git a/src/ulib/utility/uhttp.cpp b/src/ulib/utility/uhttp.cpp index 7ca7c4ace..c95e46787 100644 --- a/src/ulib/utility/uhttp.cpp +++ b/src/ulib/utility/uhttp.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,9 @@ #endif #ifndef _MSWINDOWS_ # include +# ifdef USE_LOAD_BALANCE +# include +# endif #endif #ifdef U_HTTP_INOTIFY_SUPPORT @@ -160,6 +164,9 @@ USSLSession* UHTTP::data_session_ssl; UVector* UHTTP::vallow_IP; URDBObjectHandler* UHTTP::db_session_ssl; #endif +#if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) +UHttpClient* UHTTP::client_http; +#endif #ifdef U_HTTP_STRICT_TRANSPORT_SECURITY UString* UHTTP::uri_strict_transport_security_mask; #endif @@ -1027,6 +1034,13 @@ void UHTTP::init() if (msg) { U_SRV_LOG("%s", msg); } #endif +#if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) + U_NEW(UHttpClient, client_http, UHttpClient((UFileConfig*)0)); + + client_http->getResponseHeader()->setIgnoreCase(false); + client_http->UClient_Base::setActive(UServer_Base::bssl); +#endif + /** * Set up static environment variables * ------------------------------------------------------------------------------------------------------------------------------------------- @@ -1444,6 +1458,9 @@ void UHTTP::dtor() # ifdef USE_LIBV8 if (v8_javascript) delete v8_javascript; # endif +# if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) + if (client_http) delete client_http; +# endif // CACHE DOCUMENT ROOT FILE SYSTEM @@ -4247,7 +4264,18 @@ set_uri: U_http_info.uri = alias->data(); usp_page->runDynamicPage(0); - if (U_ClientImage_parallelization != U_PARALLELIZATION_PARENT) setDynamicResponse(); + U_DUMP("U_http_info.nResponseCode = %u U_ClientImage_parallelization = %d UClientImage_Base::isNoHeaderForResponse() = %b", + U_http_info.nResponseCode, U_ClientImage_parallelization, UClientImage_Base::isNoHeaderForResponse()) + + if (U_http_info.nResponseCode == HTTP_OK) + { + U_INTERNAL_ASSERT_DIFFERS(U_ClientImage_parallelization, U_PARALLELIZATION_PARENT) + +# if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) + if (UClientImage_Base::isNoHeaderForResponse() == false) +# endif + setDynamicResponse(); + } U_RESET_MODULE_NAME; @@ -4434,6 +4462,65 @@ set_uri: U_http_info.uri = alias->data(); U_RETURN(U_PLUGIN_HANDLER_FINISHED); } +//#define TEST_ON_LOCALHOST + +#if defined(USE_LOAD_BALANCE) && !defined(_MSWINDOWS_) +bool UHTTP::manageRequestOnRemoteServer() +{ + U_TRACE_NO_PARAM(0, "UHTTP::manageRequestOnRemoteServer()") + + U_DUMP("UServer_Base::loadavg_threshold = %u U_SRV_MY_LOAD = %u U_SRV_MIN_LOAD_REMOTE = %u U_SRV_MIN_LOAD_REMOTE_IP = %s", + UServer_Base::loadavg_threshold, U_SRV_MY_LOAD, U_SRV_MIN_LOAD_REMOTE, UIPAddress::getAddressString(U_SRV_MIN_LOAD_REMOTE_IP)) + + U_INTERNAL_ASSERT_POINTER(client_http) + +#ifdef TEST_ON_LOCALHOST + if (u_get_unalignedp32(&U_SRV_MIN_LOAD_REMOTE_IP) == U_MULTICHAR_CONSTANT32(127,0,0,1)) U_RETURN(false); + u_put_unalignedp32(&U_SRV_MIN_LOAD_REMOTE_IP, U_MULTICHAR_CONSTANT32(127,0,0,1)); +#else + if (U_SRV_MY_LOAD >= UServer_Base::loadavg_threshold && + U_SRV_MIN_LOAD_REMOTE < UServer_Base::loadavg_threshold) +#endif + { + // before connect to remote server check if it has changed... + + if (client_http->setHostPort(UIPAddress::toString(U_SRV_MIN_LOAD_REMOTE_IP), UServer_Base::port) && + client_http->UClient_Base::isConnected()) + { + client_http->UClient_Base::close(); + } + + U_INTERNAL_DUMP("U_http_version = %C", U_http_version) + +# ifndef U_HTTP2_DISABLE + bool bhttp2; + if ((bhttp2 = (U_http_version == '2'))) UHTTP2::wrapRequest(); +# endif + + client_http->prepareRequest(*UClientImage_Base::request, *UClientImage_Base::body); + + // connect to remote server, send request and get response + + if (client_http->sendRequestEngine()) + { + UClientImage_Base::setNoHeaderForResponse(); + + *UClientImage_Base::wbuffer = client_http->getResponse(); + +# ifndef U_HTTP2_DISABLE + if (bhttp2) UHTTP2::wrapResponse(); +# endif + + client_http->reset(); // reset reference to request... + + U_RETURN(true); + } + } + + U_RETURN(false); +} +#endif + UString UHTTP::checkDirectoryForUpload(const char* ptr, uint32_t len) { U_TRACE(0, "UHTTP::checkDirectoryForUpload(%.*S,%u)", len, ptr, len) @@ -8987,6 +9074,20 @@ bool UHTTP::setEnvironmentForLanguageProcessing(int type, void* env, vPFpvpcpc f U_RETURN(true); } +#ifndef U_HTTP2_DISABLE +bool UHTTP::copyHeaders(UStringRep* key, void* elem) +{ + U_TRACE(0, "UHTTP::copyHeaders(%V,%p)", key, elem) + + U_INTERNAL_ASSERT_POINTER(prequestHeader) + U_INTERNAL_ASSERT_EQUALS(U_http_version, '2') + + if (UHTTP2::isHeaderToCopy(key)) prequestHeader->insert(key, (const UStringRep*)elem); + + U_RETURN(true); +} +#endif + bool UHTTP::getCGIEnvironment(UString& environment, int type) { U_TRACE(0, "UHTTP::getCGIEnvironment(%V,%d)", environment.rep, type) diff --git a/tests/examples/benchmark/docroot/uploads/web_server.test b/tests/examples/benchmark/docroot/uploads/web_server.test deleted file mode 100644 index 9c8d340bf..000000000 --- a/tests/examples/benchmark/docroot/uploads/web_server.test +++ /dev/null @@ -1,245 +0,0 @@ -#!/bin/sh - -. ../.function - -# set -x - -## web_server.test -- Test web_server feature - -start_msg web_server - -(cd benchmark; rm -f db; creat_link FrameworkBenchmarks/ULib/db db; sync) -(cd ..; rm -f db; creat_link examples/benchmark/db db; sync) - creat_link benchmark/db db - creat_link benchmark/libraries libraries - -DOC_ROOT=docroot - -rm -f db/session.ssl* /tmp/ssl_session.txt /tmp/byterange* /tmp/soap.res /tmp/*.memusage.* /tmp/*.hpack.* \ - $DOC_ROOT/webserver*.log* $DOC_ROOT/uploads/* /var/log/httpd/access_log \ - out/userver_tcp.out err/userver_tcp.err web_server.err \ - trace.*userver_*.[0-9]* object.*userver_*.[0-9]* stack.*userver_*.[0-9]* mempool.*userver_*.[0-9]* \ - $DOC_ROOT/trace.*userver_*.[0-9]* $DOC_ROOT/object.*userver_*.[0-9]* $DOC_ROOT/stack.*userver_*.[0-9]* $DOC_ROOT/mempool.*userver_*.[0-9]* - -#UTRACE="0 50M 0" -#UTRACE_SIGNAL="0 50M 0" -#UOBJDUMP="0 10M 100" -#USIMERR="error.sim" -export UTRACE UOBJDUMP USIMERR UTRACE_SIGNAL - -if [ "$TERM" = "msys" ]; then - export TMPDIR="c:/tmp" -fi - -DIR_CMD="../../examples/userver" - -compile_usp - -check_for_netcat - -mkdir -p /var/log/httpd 2>/dev/null - -# function : upload_test -upload_test() { - -rm -rf uploads -mkdir -p uploads -$CHOWN nobody: uploads docroot 2>/dev/null -chmod 777 uploads - -$CURL -s -F 'file=@vuoto.txt' -F "name=prova" http://$1/cgi-bin/uploader.sh >>out/web_server.out 2>>err/web_server.err -$CURL -s -F 'file=@inp/xml2txt/operazione.xml;type=text/xml' -F "name=prova" http://$1/cgi-bin/uploader.sh >>out/web_server.out 2>>err/web_server.err -$CURL -s -T web_server.test http://$1/upload/web_server.test >>out/web_server.out 2>>err/web_server.err - -if [ $? -ne 0 ]; then - kill_prg userver_tcp TERM - exit 1 -fi -} - -# function : kill_server -kill_server() { - -kill_prg userver_tcp TERM -$SLEEP -pkill -9 userver_tcp 2>/dev/null -pkill -9 lt-userver_tcp 2>/dev/null -} - -# function : start_test -start_test() { - -#chmod 666 /proc/sys/net/ipv4/tcp_fin_timeout /proc/sys/net/core/somaxconn /proc/sys/net/ipv4/tcp_max_syn_backlog - -$SLEEP - -#STRACE=$TRUSS -#MALLOC_CHECK_=3 -#VALGRIND="valgrind" -#MUDFLAP_OPTIONS="-ignore-reads -backtrace=8" - start_prg_background userver_tcp -c inp/webserver.cfg - -for i in 1 2 3 4 5; do - $NC -c localhost 8080 /dev/null - if [ $? -eq 0 ]; then - break - fi -done - -#LS=tst_90 -#LS=`ls inp/http/and` -#mkdir -p /tmp/web_server -#for i in $LS; do -# $NC -w 10 localhost 8080 /tmp/web_server/$i -#done - -#./sendbytes.pl -#ncat -4 test 80 < inp/http/request.8197 -#$NC -w 10 test 80 < inp/request.14215 >>out/web_server.out -#$NC -w 10 10.10.100.115 80 < inp/http/all4.inp >>out/web_server.out -#$CURL http://$1/browserconfig.xml >>out/web_server.out 2>>err/web_server.err -#send_req $NCAT test 80 inp/request.14215 web_server 2 -#exit 0 -#return - -LS=`ls inp/http/close` -for i in $LS; do - send_req $1 $2 8080 inp/http/close/$i web_server 2 -# if [ $? -ne 0 ]; then -# kill_server -# exit 1 -# fi -done - -for i in all.inp all0.inp all01.inp all1.inp all2.inp plaintext.inp post.inp; do - send_req $1 $2 8080 inp/http/$i web_server 4 -# if [ $? -ne 0 ]; then -# kill_server -# exit 1 -# fi -done - -upload_test $2:8080 - -kill_server -} - -# function : creat_config -creat_config() { - -if [ -z "$2" ]; then - N=$1 -else - N=$2 -fi - -cat <inp/webserver.cfg -userver { - PORT 8080 - RUN_AS_USER nobody -#MIN_SIZE_FOR_SENDFILE 2k - REQ_TIMEOUT 30 - LOG_FILE webserver$1.log - LOG_FILE_SZ 1M - LOG_MSG_SIZE -1 - DOCUMENT_ROOT $DOC_ROOT - PLUGIN "ssi http" - PLUGIN_DIR ../../../src/ulib/net/server/plugin/.libs - ORM_DRIVER_DIR ../../../src/ulib/orm/driver/.libs - PREFORK_CHILD $N -} -http { - ENABLE_INOTIFY yes - ALIAS @FILE:../alias.txt - LIMIT_REQUEST_BODY 700K - REQUEST_READ_TIMEOUT 30 - DIGEST_AUTHENTICATION no - APACHE_LIKE_LOG /var/log/httpd/access_log - BANDWIDTH_THROTTLING_MASK @FILE:../throttling.txt - CACHE_FILE_MASK inp/http/data/file1|*.flv|*.svgz - CACHE_AVOID_MASK www.sito1.com|ruby -} -EOF -} - -# --------------------------------------------------------- -# virtual host -# --------------------------------------------------------- -rm -rf $DOC_ROOT/www.sito1.com 2>/dev/null - -grep 'www.sito1.com' /etc/hosts >/dev/null 2>/dev/null - -if [ $? -ne 0 ]; then - echo '# virtual host userver' >> /etc/hosts 2>/dev/null - echo localhost www.sito1.com >> /etc/hosts 2>/dev/null - echo localhost www.sito2.com >> /etc/hosts 2>/dev/null -fi - -mkdir -p $DOC_ROOT/benchmark/docroot $DOC_ROOT/www.sito1.com/benchmark/docroot - -creat_link ../ok $DOC_ROOT/ok -creat_link ../tmp $DOC_ROOT/tmp -creat_link ../uploads $DOC_ROOT/uploads -creat_link ../../../benchmark/docroot/servlet $DOC_ROOT/benchmark/docroot/servlet -creat_link ../../inp $DOC_ROOT/www.sito1.com/inp -creat_link ../../tmp $DOC_ROOT/www.sito1.com/tmp -creat_link ../SSI $DOC_ROOT/www.sito1.com/SSI -creat_link ../cgi-bin $DOC_ROOT/www.sito1.com/cgi-bin -creat_link ../../uploads $DOC_ROOT/www.sito1.com/uploads -creat_link ../../../../benchmark/docroot/servlet $DOC_ROOT/www.sito1.com/benchmark/docroot/servlet - -touch vuoto.txt $DOC_ROOT/vuoto.txt $DOC_ROOT/www.sito1.com/vuoto.txt -cat << EOF >tmp/c -c -c -EOF - -#cp $DOC_ROOT/../.htpasswd $DOC_ROOT/../tmp.htpasswd - -export UMEMPOOL="136,0,60,100,250,-22,-17,-23,60" - -# webserver-1 - creat_config -1 - start_test $NCAT localhost -# webserver0 - creat_config 0 - start_test $NCAT localhost -# webserver1 - creat_config 1 - start_test $NCAT localhost -# webserver2 - creat_config 2 - start_test $NCAT localhost -# webserverN - creat_config N 2 - start_test $NCAT localhost -# webserverV - creat_config V 2 - start_test $NCAT www.sito1.com - -kill_server - -# ----------------------------------------------------------------------------------- -# for GDB -# ----------------------------------------------------------------------------------- -# sed "s/Host: 10.30.1.131/Host: www.sito1.com/" inp/http/all.inp | nc localhost 8080 -# ----------------------------------------------------------------------------------- - -diff inp/xml2txt/operazione.xml uploads/operazione.xml -RESULT=$? -if [ "$RESULT" = "0" ]; then - diff web_server.test uploads/web_server.test - RESULT=$? -fi - -mv err/userver_tcp.err err/web_server.err - -# ------------------------------------------------------------------------------------------------------------------------------------------------------- -# cut -d ' ' -f7 /var/log/httpd/access_log > /tmp/urls.txt -# siege -c -b -f urls.txt -# ------------------------------------------------------------------------------------------------------------------------------------------------------- -# curl -v -0 -k -H "Host:" -H "Accept:" -H "User-Agent: SSL Labs (https://www.ssllabs.com/about/assessment.html)" https://wifi-aaa.comune.fi.it -# ------------------------------------------------------------------------------------------------------------------------------------------------------- - -# Test against expected output -test_output_wc l web_server diff --git a/tests/examples/businesses.test b/tests/examples/businesses.test index 4954189d2..96d9c0894 100755 --- a/tests/examples/businesses.test +++ b/tests/examples/businesses.test @@ -53,6 +53,10 @@ start_prg_background userver_tcp -c inp/webserver.cfg send_req $NCAT localhost 8080 inp/http/businesses1.req businesses 2 send_req $NCAT localhost 8080 inp/http/businesses2.req businesses 2 send_req $NCAT localhost 8080 inp/http/businesses3.req businesses 2 + send_req $NCAT localhost 8080 inp/http/businesses4.req businesses 2 + +#JSON_REQ=`tail -1 inp/http/businesses1.req` +#curl -v --http2-prior-knowledge http://localhost:8080/servlet/businesses -d "$JSON_REQ" http://localhost/businesses >out/businesses.out kill_prg userver_tcp TERM diff --git a/tests/examples/inp/http/businesses4.req b/tests/examples/inp/http/businesses4.req new file mode 100644 index 000000000..f63e4dea2 --- /dev/null +++ b/tests/examples/inp/http/businesses4.req @@ -0,0 +1,7 @@ +POST /servlet/businesses HTTP/1.1 +Host: localhost:8080 +Connection: Keep-Alive +Content-Type: application/jsonrequest +Content-Length: 29 + +{"type1":"startup","authe":0} diff --git a/tests/examples/ok/businesses.ok b/tests/examples/ok/businesses.ok index 2654af8b6..d7d38eef6 100644 --- a/tests/examples/ok/businesses.ok +++ b/tests/examples/ok/businesses.ok @@ -1,21 +1,36 @@ HTTP/1.1 200 OK -Date: Sun, 29 Jan 2017 14:54:34 GMT +Date: Sun, 19 Feb 2017 16:40:41 GMT Server: ULib Connection: close Content-Length: 56 Content-Type: application/json {"name":"","rating":"","address":"","phone":"","url":""}HTTP/1.1 200 OK -Date: Sun, 29 Jan 2017 14:54:34 GMT +Date: Sun, 19 Feb 2017 16:40:41 GMT Server: ULib Connection: close Content-Length: 0 HTTP/1.1 200 OK -Date: Sun, 29 Jan 2017 14:54:34 GMT +Date: Sun, 19 Feb 2017 16:40:41 GMT Server: ULib Connection: close Content-Length: 87 Content-Type: application/json -{"type":"startup","token":"","fbPermissions":["public_profile","user_friends","email"]} \ No newline at end of file +{"type":"startup","token":"","fbPermissions":["public_profile","user_friends","email"]}HTTP/1.1 400 Bad Request +Date: Sun, 19 Feb 2017 16:40:41 GMT +Server: ULib +Connection: close +Content-Type: text/html; charset=UTF-8 +Content-Length: 263 + + + +400 Bad Request + +

Bad Request

+

Your browser sent a request that this server could not understand

+
+
ULib Server
+ diff --git a/tests/examples/tsa_https.test b/tests/examples/tsa_https.test index e14b07fc4..9a0f9cf80 100755 --- a/tests/examples/tsa_https.test +++ b/tests/examples/tsa_https.test @@ -90,6 +90,7 @@ DIR_CMD="../../examples/userver" # set -x pkill userver_tcp 2>/dev/null +pkill userver_ssl 2>/dev/null #STRACE=$TRUSS start_prg_background userver_ssl -c inp/webserver.cfg diff --git a/tests/examples/tsa_rpc.test b/tests/examples/tsa_rpc.test index 7623f58c9..561763324 100755 --- a/tests/examples/tsa_rpc.test +++ b/tests/examples/tsa_rpc.test @@ -6,7 +6,7 @@ start_msg tsa_rpc -#UTRACE="0 50M 0" +#UTRACE="0 20M 0" #UTRACE_SIGNAL="0 10M -1" #UOBJDUMP="0 1M 100" #USIMERR="error.sim" @@ -42,6 +42,7 @@ userver { CA_PATH ../../ulib/CA/CApath CA_FILE ../../ulib/CA/cacert.pem VERIFY_MODE 1 +#PREFORK_CHILD 0 } rpc { #include "soap_or_rpc_tsa.cfg" diff --git a/tests/examples/web_server.sh b/tests/examples/web_server.sh index a468256fc..5a4d5f857 100755 --- a/tests/examples/web_server.sh +++ b/tests/examples/web_server.sh @@ -11,8 +11,8 @@ rm -f tmp/usp_compile.sh.err /tmp/*.hpack.* \ trace.*userver_*.[0-9]* object.*userver_*.[0-9]* stack.*userver_*.[0-9]* mempool.*userver_*.[0-9]* \ $DOC_ROOT/trace.*userver_*.[0-9]* $DOC_ROOT/object.*userver_*.[0-9]* $DOC_ROOT/stack.*userver_*.[0-9]* $DOC_ROOT/mempool.*userver_*.[0-9]* - UTRACE="0 20M 0" -#UTRACE_SIGNAL="0 50M -1" + UTRACE="0 20M -1" + UTRACE_SIGNAL="0 20M -1" #UOBJDUMP="0 10M 100" #USIMERR="error.sim" export UTRACE UOBJDUMP USIMERR UTRACE_SIGNAL diff --git a/tests/examples/web_server_multiclient.test b/tests/examples/web_server_multiclient.test index f1f9ecf7b..f484752f2 100755 --- a/tests/examples/web_server_multiclient.test +++ b/tests/examples/web_server_multiclient.test @@ -16,7 +16,7 @@ rm -f $DOC_ROOT/web_server_multiclient.log* \ trace.*userver_*.[0-9]* object.*userver_*.[0-9]* stack.*userver_*.[0-9]* mempool.*userver_*.[0-9]* \ $DOC_ROOT/trace.*userver_*.[0-9]* $DOC_ROOT/object.*userver_*.[0-9]* $DOC_ROOT/stack.*userver_*.[0-9]* $DOC_ROOT/mempool.*userver_*.[0-9]* -#UTRACE="0 100M 0" +#UTRACE="0 10M 0" #UTRACE_SIGNAL="0 100M -1" #UOBJDUMP="0 10M 100" #USIMERR="error.sim" diff --git a/tests/ulib/Makefile.am b/tests/ulib/Makefile.am index 69d510d64..fea590a30 100644 --- a/tests/ulib/Makefile.am +++ b/tests/ulib/Makefile.am @@ -13,7 +13,7 @@ DEFAULT_INCLUDES = -I. -I$(top_builddir)/include LDADD = @ULIBS@ $(top_builddir)/src/ulib/lib@ULIB@.la @ULIB_LIBS@ PRG = test_timeval test_timer test_notifier test_string \ - test_file test_cdb test_rdb test_file_config test_log \ + test_file test_cdb test_rdb test_file_config test_log test_bit_array \ test_vector test_options test_application test_tree test_compress test_cache test_date \ test_services test_base64 test_header test_entity \ test_ipaddress test_socket test_ftp test_http test_rdb_client \ @@ -29,6 +29,14 @@ TST = timeval.test timer.test notifier.test string.test \ tokenizer.test query_parser.test multipart.test rdb_client_server.test command.test json.test server.test server_rpc.test ## pop3.test imap.test smtp.test dialog.test redis.test elasticsearch.test twilio.test +if SSH + PRG += test_ssh_client +##TST += ssh_client.test +endif +if LDAP + PRG += test_ldap +##TST += ldap.test +endif if MONGODB PRG += test_mongodb ##TST += mongodb.test @@ -46,6 +54,7 @@ test_timer_SOURCES = test_timer.cpp test_notifier_SOURCES = test_notifier.cpp test_string_SOURCES = test_string.cpp test_file_SOURCES = test_file.cpp +test_bit_array_SOURCES = test_bit_array.cpp test_cdb_SOURCES = test_cdb.cpp test_rdb_SOURCES = test_rdb.cpp test_file_config_SOURCES = test_file_config.cpp @@ -232,7 +241,7 @@ TESTS = $(TST) ../reset.color ## arping.test event.test curl.test ftp.test imap.test ldap.test pop3.test sigslot.test smtp.test ssh_client.test test: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) - ../make_test.sh application.test base64.test cache.test cdb.test certificate.test command.test compress.test crl.test date.test des3.test dialog.test digest.test entity.test expat.test file.test file_config.test header.test http.test https.test interrupt.test json.test log.test memory_pool.test multipart.test notifier.test options.test pcre.test pkcs10.test pkcs7.test plugin.test process.test query_parser.test rdb.test rdb_client_server.test server.test server_rpc.test services.test soap_client.test soap_server.test ssl_client_server.test string.test timer.test timestamp.test timeval.test tokenizer.test tree.test unixsocket.test url.test vector.test zip.test ../reset.color + ../make_test.sh application.test base64.test bit_array.test cache.test cdb.test certificate.test command.test compress.test crl.test date.test des3.test dialog.test digest.test entity.test expat.test file.test file_config.test header.test http.test https.test interrupt.test json.test log.test memory_pool.test multipart.test notifier.test options.test pcre.test pkcs10.test pkcs7.test plugin.test process.test query_parser.test rdb.test rdb_client_server.test server.test server_rpc.test services.test soap_client.test soap_server.test ssl_client_server.test string.test timer.test timestamp.test timeval.test tokenizer.test tree.test unixsocket.test url.test vector.test zip.test ../reset.color clean-local: -rm -rf out err core .libs *.bb* *.da *.gc* *.log test_log.log* tmp/* \ diff --git a/tests/ulib/Makefile.in b/tests/ulib/Makefile.in index 3e5778aa6..3f9d6e314 100644 --- a/tests/ulib/Makefile.in +++ b/tests/ulib/Makefile.in @@ -89,43 +89,45 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -@MONGODB_TRUE@am__append_1 = test_mongodb -@PTHREAD_TRUE@am__append_2 = test_thread -@PTHREAD_TRUE@am__append_3 = thread.test -@ZIP_TRUE@am__append_4 = test_zip -@ZIP_TRUE@am__append_5 = zip.test -@LIBTDB_TRUE@am__append_6 = test_tdb -@LIBTDB_TRUE@am__append_7 = tdb.test -@PCRE_TRUE@am__append_8 = test_pcre -@PCRE_TRUE@am__append_9 = pcre.test -@SSL_TRUE@am__append_10 = test_des3 test_digest test_certificate test_crl test_pkcs10 test_ssl_client test_ssl_server test_https test_pkcs7 test_url -@SSL_TRUE@am__append_11 = des3.test digest.test certificate.test crl.test pkcs10.test ssl_client_server.test https.test pkcs7.test url.test -@SSL_TRUE@@SSL_TS_TRUE@am__append_12 = test_timestamp -@SSL_TRUE@@SSL_TS_TRUE@am__append_13 = timestamp.test -@SSH_TRUE@am__append_14 = test_ssh_client -@SSH_TRUE@am__append_15 = ssh_client.test -@LDAP_TRUE@am__append_16 = test_ldap -@LDAP_TRUE@am__append_17 = ldap.test -@CURL_TRUE@am__append_18 = test_curl -@CURL_TRUE@am__append_19 = curl.test -@MAGIC_TRUE@am__append_20 = test_magic -@MAGIC_TRUE@am__append_21 = magic.test -@EXPAT_TRUE@am__append_22 = test_expat test_soap_server test_soap_client -@EXPAT_TRUE@am__append_23 = expat.test soap_server.test soap_client.test -@MEMORY_POOL_TRUE@am__append_24 = test_memory_pool -@MEMORY_POOL_TRUE@am__append_25 = memory_pool.test -@DBI_TRUE@am__append_26 = test_dbi -@DBI_TRUE@am__append_27 = dbi.test -@HAVE_SQLITE3_TRUE@am__append_28 = test_orm -@HAVE_SQLITE3_TRUE@am__append_29 = orm.test -@LIBEVENT_TRUE@am__append_30 = test_event -@LIBEVENT_TRUE@am__append_31 = event.test -@LINUX_TRUE@am__append_32 = test_process test_interrupt test_unixsocket_client test_unixsocket_server test_arping -@LINUX_TRUE@am__append_33 = process.test interrupt.test unixsocket.test -@LINUX_TRUE@@SANITIZE_TRUE@am__append_34 = -lubsan -@LINUX_TRUE@@SANITIZE_TRUE@am__append_35 = -lubsan -@PLUGIN_TRUE@@STDCPP_TRUE@am__append_36 = test_plugin -@PLUGIN_TRUE@@STDCPP_TRUE@am__append_37 = plugin.test +@SSH_TRUE@am__append_1 = test_ssh_client +@LDAP_TRUE@am__append_2 = test_ldap +@MONGODB_TRUE@am__append_3 = test_mongodb +@PTHREAD_TRUE@am__append_4 = test_thread +@PTHREAD_TRUE@am__append_5 = thread.test +@ZIP_TRUE@am__append_6 = test_zip +@ZIP_TRUE@am__append_7 = zip.test +@LIBTDB_TRUE@am__append_8 = test_tdb +@LIBTDB_TRUE@am__append_9 = tdb.test +@PCRE_TRUE@am__append_10 = test_pcre +@PCRE_TRUE@am__append_11 = pcre.test +@SSL_TRUE@am__append_12 = test_des3 test_digest test_certificate test_crl test_pkcs10 test_ssl_client test_ssl_server test_https test_pkcs7 test_url +@SSL_TRUE@am__append_13 = des3.test digest.test certificate.test crl.test pkcs10.test ssl_client_server.test https.test pkcs7.test url.test +@SSL_TRUE@@SSL_TS_TRUE@am__append_14 = test_timestamp +@SSL_TRUE@@SSL_TS_TRUE@am__append_15 = timestamp.test +@SSH_TRUE@am__append_16 = test_ssh_client +@SSH_TRUE@am__append_17 = ssh_client.test +@LDAP_TRUE@am__append_18 = test_ldap +@LDAP_TRUE@am__append_19 = ldap.test +@CURL_TRUE@am__append_20 = test_curl +@CURL_TRUE@am__append_21 = curl.test +@MAGIC_TRUE@am__append_22 = test_magic +@MAGIC_TRUE@am__append_23 = magic.test +@EXPAT_TRUE@am__append_24 = test_expat test_soap_server test_soap_client +@EXPAT_TRUE@am__append_25 = expat.test soap_server.test soap_client.test +@MEMORY_POOL_TRUE@am__append_26 = test_memory_pool +@MEMORY_POOL_TRUE@am__append_27 = memory_pool.test +@DBI_TRUE@am__append_28 = test_dbi +@DBI_TRUE@am__append_29 = dbi.test +@HAVE_SQLITE3_TRUE@am__append_30 = test_orm +@HAVE_SQLITE3_TRUE@am__append_31 = orm.test +@LIBEVENT_TRUE@am__append_32 = test_event +@LIBEVENT_TRUE@am__append_33 = event.test +@LINUX_TRUE@am__append_34 = test_process test_interrupt test_unixsocket_client test_unixsocket_server test_arping +@LINUX_TRUE@am__append_35 = process.test interrupt.test unixsocket.test +@LINUX_TRUE@@SANITIZE_TRUE@am__append_36 = -lubsan +@LINUX_TRUE@@SANITIZE_TRUE@am__append_37 = -lubsan +@PLUGIN_TRUE@@STDCPP_TRUE@am__append_38 = test_plugin +@PLUGIN_TRUE@@STDCPP_TRUE@am__append_39 = plugin.test check_PROGRAMS = $(am__EXEEXT_19) subdir = tests/ulib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -177,19 +179,19 @@ product2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(product2_la_LDFLAGS) $(LDFLAGS) -o $@ @PLUGIN_TRUE@@STDCPP_TRUE@am_product2_la_rpath = -@MONGODB_TRUE@am__EXEEXT_1 = test_mongodb$(EXEEXT) -@PTHREAD_TRUE@am__EXEEXT_2 = test_thread$(EXEEXT) -@ZIP_TRUE@am__EXEEXT_3 = test_zip$(EXEEXT) -@LIBTDB_TRUE@am__EXEEXT_4 = test_tdb$(EXEEXT) -@PCRE_TRUE@am__EXEEXT_5 = test_pcre$(EXEEXT) -@SSL_TRUE@am__EXEEXT_6 = test_des3$(EXEEXT) test_digest$(EXEEXT) \ +@SSH_TRUE@am__EXEEXT_1 = test_ssh_client$(EXEEXT) +@LDAP_TRUE@am__EXEEXT_2 = test_ldap$(EXEEXT) +@MONGODB_TRUE@am__EXEEXT_3 = test_mongodb$(EXEEXT) +@PTHREAD_TRUE@am__EXEEXT_4 = test_thread$(EXEEXT) +@ZIP_TRUE@am__EXEEXT_5 = test_zip$(EXEEXT) +@LIBTDB_TRUE@am__EXEEXT_6 = test_tdb$(EXEEXT) +@PCRE_TRUE@am__EXEEXT_7 = test_pcre$(EXEEXT) +@SSL_TRUE@am__EXEEXT_8 = test_des3$(EXEEXT) test_digest$(EXEEXT) \ @SSL_TRUE@ test_certificate$(EXEEXT) test_crl$(EXEEXT) \ @SSL_TRUE@ test_pkcs10$(EXEEXT) test_ssl_client$(EXEEXT) \ @SSL_TRUE@ test_ssl_server$(EXEEXT) test_https$(EXEEXT) \ @SSL_TRUE@ test_pkcs7$(EXEEXT) test_url$(EXEEXT) -@SSL_TRUE@@SSL_TS_TRUE@am__EXEEXT_7 = test_timestamp$(EXEEXT) -@SSH_TRUE@am__EXEEXT_8 = test_ssh_client$(EXEEXT) -@LDAP_TRUE@am__EXEEXT_9 = test_ldap$(EXEEXT) +@SSL_TRUE@@SSL_TS_TRUE@am__EXEEXT_9 = test_timestamp$(EXEEXT) @CURL_TRUE@am__EXEEXT_10 = test_curl$(EXEEXT) @MAGIC_TRUE@am__EXEEXT_11 = test_magic$(EXEEXT) @EXPAT_TRUE@am__EXEEXT_12 = test_expat$(EXEEXT) \ @@ -208,10 +210,10 @@ product2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ am__EXEEXT_19 = test_timeval$(EXEEXT) test_timer$(EXEEXT) \ test_notifier$(EXEEXT) test_string$(EXEEXT) test_file$(EXEEXT) \ test_cdb$(EXEEXT) test_rdb$(EXEEXT) test_file_config$(EXEEXT) \ - test_log$(EXEEXT) test_vector$(EXEEXT) test_options$(EXEEXT) \ - test_application$(EXEEXT) test_tree$(EXEEXT) \ - test_compress$(EXEEXT) test_cache$(EXEEXT) test_date$(EXEEXT) \ - test_services$(EXEEXT) test_base64$(EXEEXT) \ + test_log$(EXEEXT) test_bit_array$(EXEEXT) test_vector$(EXEEXT) \ + test_options$(EXEEXT) test_application$(EXEEXT) \ + test_tree$(EXEEXT) test_compress$(EXEEXT) test_cache$(EXEEXT) \ + test_date$(EXEEXT) test_services$(EXEEXT) test_base64$(EXEEXT) \ test_header$(EXEEXT) test_entity$(EXEEXT) \ test_ipaddress$(EXEEXT) test_socket$(EXEEXT) test_ftp$(EXEEXT) \ test_http$(EXEEXT) test_rdb_client$(EXEEXT) \ @@ -223,10 +225,11 @@ am__EXEEXT_19 = test_timeval$(EXEEXT) test_timer$(EXEEXT) \ test_pop3$(EXEEXT) test_imap$(EXEEXT) $(am__EXEEXT_1) \ $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) \ $(am__EXEEXT_5) $(am__EXEEXT_6) $(am__EXEEXT_7) \ - $(am__EXEEXT_8) $(am__EXEEXT_9) $(am__EXEEXT_10) \ - $(am__EXEEXT_11) $(am__EXEEXT_12) $(am__EXEEXT_13) \ - $(am__EXEEXT_14) $(am__EXEEXT_15) $(am__EXEEXT_16) \ - $(am__EXEEXT_17) $(am__EXEEXT_18) + $(am__EXEEXT_8) $(am__EXEEXT_9) $(am__EXEEXT_1) \ + $(am__EXEEXT_2) $(am__EXEEXT_10) $(am__EXEEXT_11) \ + $(am__EXEEXT_12) $(am__EXEEXT_13) $(am__EXEEXT_14) \ + $(am__EXEEXT_15) $(am__EXEEXT_16) $(am__EXEEXT_17) \ + $(am__EXEEXT_18) am_test_application_OBJECTS = test_application.$(OBJEXT) test_application_OBJECTS = $(am_test_application_OBJECTS) test_application_LDADD = $(LDADD) @@ -240,6 +243,10 @@ am_test_base64_OBJECTS = test_base64.$(OBJEXT) test_base64_OBJECTS = $(am_test_base64_OBJECTS) test_base64_LDADD = $(LDADD) test_base64_DEPENDENCIES = $(top_builddir)/src/ulib/lib@ULIB@.la +am_test_bit_array_OBJECTS = test_bit_array.$(OBJEXT) +test_bit_array_OBJECTS = $(am_test_bit_array_OBJECTS) +test_bit_array_LDADD = $(LDADD) +test_bit_array_DEPENDENCIES = $(top_builddir)/src/ulib/lib@ULIB@.la am_test_cache_OBJECTS = test_cache.$(OBJEXT) test_cache_OBJECTS = $(am_test_cache_OBJECTS) test_cache_LDADD = $(LDADD) @@ -588,58 +595,58 @@ am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(product1_la_SOURCES) $(product2_la_SOURCES) \ $(test_application_SOURCES) $(test_arping_SOURCES) \ - $(test_base64_SOURCES) $(test_cache_SOURCES) \ - $(test_cdb_SOURCES) $(test_certificate_SOURCES) \ - $(test_command_SOURCES) $(test_compress_SOURCES) \ - $(test_crl_SOURCES) $(test_curl_SOURCES) $(test_date_SOURCES) \ - $(test_dbi_SOURCES) $(test_des3_SOURCES) \ - $(test_dialog_SOURCES) $(test_digest_SOURCES) \ - $(test_elasticsearch_SOURCES) $(test_entity_SOURCES) \ - $(test_event_SOURCES) $(test_expat_SOURCES) \ - $(test_file_SOURCES) $(test_file_config_SOURCES) \ - $(test_ftp_SOURCES) $(test_header_SOURCES) \ - $(test_http_SOURCES) $(test_https_SOURCES) \ - $(test_imap_SOURCES) $(test_interrupt_SOURCES) \ - $(test_ipaddress_SOURCES) $(test_json_SOURCES) \ - $(test_ldap_SOURCES) $(test_log_SOURCES) $(test_magic_SOURCES) \ - $(test_memory_pool_SOURCES) $(test_mongodb_SOURCES) \ - $(test_multipart_SOURCES) $(test_notifier_SOURCES) \ - $(test_options_SOURCES) $(test_orm_SOURCES) \ - $(test_pcre_SOURCES) $(test_pkcs10_SOURCES) \ - $(test_pkcs7_SOURCES) $(test_plugin_SOURCES) \ - $(test_pop3_SOURCES) $(test_process_SOURCES) \ - $(test_query_parser_SOURCES) $(test_rdb_SOURCES) \ - $(test_rdb_client_SOURCES) $(test_rdb_server_SOURCES) \ - $(test_redis_SOURCES) $(test_server_SOURCES) \ - $(test_services_SOURCES) $(test_smtp_SOURCES) \ - $(test_soap_client_SOURCES) $(test_soap_server_SOURCES) \ - $(test_socket_SOURCES) $(test_ssh_client_SOURCES) \ - $(test_ssl_client_SOURCES) $(test_ssl_server_SOURCES) \ - $(test_string_SOURCES) $(test_tdb_SOURCES) \ - $(test_thread_SOURCES) $(test_timer_SOURCES) \ - $(test_timestamp_SOURCES) $(test_timeval_SOURCES) \ - $(test_tokenizer_SOURCES) $(test_tree_SOURCES) \ - $(test_unixsocket_client_SOURCES) \ + $(test_base64_SOURCES) $(test_bit_array_SOURCES) \ + $(test_cache_SOURCES) $(test_cdb_SOURCES) \ + $(test_certificate_SOURCES) $(test_command_SOURCES) \ + $(test_compress_SOURCES) $(test_crl_SOURCES) \ + $(test_curl_SOURCES) $(test_date_SOURCES) $(test_dbi_SOURCES) \ + $(test_des3_SOURCES) $(test_dialog_SOURCES) \ + $(test_digest_SOURCES) $(test_elasticsearch_SOURCES) \ + $(test_entity_SOURCES) $(test_event_SOURCES) \ + $(test_expat_SOURCES) $(test_file_SOURCES) \ + $(test_file_config_SOURCES) $(test_ftp_SOURCES) \ + $(test_header_SOURCES) $(test_http_SOURCES) \ + $(test_https_SOURCES) $(test_imap_SOURCES) \ + $(test_interrupt_SOURCES) $(test_ipaddress_SOURCES) \ + $(test_json_SOURCES) $(test_ldap_SOURCES) $(test_log_SOURCES) \ + $(test_magic_SOURCES) $(test_memory_pool_SOURCES) \ + $(test_mongodb_SOURCES) $(test_multipart_SOURCES) \ + $(test_notifier_SOURCES) $(test_options_SOURCES) \ + $(test_orm_SOURCES) $(test_pcre_SOURCES) \ + $(test_pkcs10_SOURCES) $(test_pkcs7_SOURCES) \ + $(test_plugin_SOURCES) $(test_pop3_SOURCES) \ + $(test_process_SOURCES) $(test_query_parser_SOURCES) \ + $(test_rdb_SOURCES) $(test_rdb_client_SOURCES) \ + $(test_rdb_server_SOURCES) $(test_redis_SOURCES) \ + $(test_server_SOURCES) $(test_services_SOURCES) \ + $(test_smtp_SOURCES) $(test_soap_client_SOURCES) \ + $(test_soap_server_SOURCES) $(test_socket_SOURCES) \ + $(test_ssh_client_SOURCES) $(test_ssl_client_SOURCES) \ + $(test_ssl_server_SOURCES) $(test_string_SOURCES) \ + $(test_tdb_SOURCES) $(test_thread_SOURCES) \ + $(test_timer_SOURCES) $(test_timestamp_SOURCES) \ + $(test_timeval_SOURCES) $(test_tokenizer_SOURCES) \ + $(test_tree_SOURCES) $(test_unixsocket_client_SOURCES) \ $(test_unixsocket_server_SOURCES) $(test_url_SOURCES) \ $(test_vector_SOURCES) $(test_zip_SOURCES) DIST_SOURCES = $(am__product1_la_SOURCES_DIST) \ $(am__product2_la_SOURCES_DIST) $(test_application_SOURCES) \ $(am__test_arping_SOURCES_DIST) $(test_base64_SOURCES) \ - $(test_cache_SOURCES) $(test_cdb_SOURCES) \ - $(am__test_certificate_SOURCES_DIST) $(test_command_SOURCES) \ - $(test_compress_SOURCES) $(am__test_crl_SOURCES_DIST) \ - $(am__test_curl_SOURCES_DIST) $(test_date_SOURCES) \ - $(am__test_dbi_SOURCES_DIST) $(am__test_des3_SOURCES_DIST) \ - $(test_dialog_SOURCES) $(am__test_digest_SOURCES_DIST) \ - $(test_elasticsearch_SOURCES) $(test_entity_SOURCES) \ - $(am__test_event_SOURCES_DIST) $(am__test_expat_SOURCES_DIST) \ - $(test_file_SOURCES) $(test_file_config_SOURCES) \ - $(test_ftp_SOURCES) $(test_header_SOURCES) \ - $(test_http_SOURCES) $(am__test_https_SOURCES_DIST) \ - $(test_imap_SOURCES) $(am__test_interrupt_SOURCES_DIST) \ - $(test_ipaddress_SOURCES) $(test_json_SOURCES) \ - $(am__test_ldap_SOURCES_DIST) $(test_log_SOURCES) \ - $(am__test_magic_SOURCES_DIST) \ + $(test_bit_array_SOURCES) $(test_cache_SOURCES) \ + $(test_cdb_SOURCES) $(am__test_certificate_SOURCES_DIST) \ + $(test_command_SOURCES) $(test_compress_SOURCES) \ + $(am__test_crl_SOURCES_DIST) $(am__test_curl_SOURCES_DIST) \ + $(test_date_SOURCES) $(am__test_dbi_SOURCES_DIST) \ + $(am__test_des3_SOURCES_DIST) $(test_dialog_SOURCES) \ + $(am__test_digest_SOURCES_DIST) $(test_elasticsearch_SOURCES) \ + $(test_entity_SOURCES) $(am__test_event_SOURCES_DIST) \ + $(am__test_expat_SOURCES_DIST) $(test_file_SOURCES) \ + $(test_file_config_SOURCES) $(test_ftp_SOURCES) \ + $(test_header_SOURCES) $(test_http_SOURCES) \ + $(am__test_https_SOURCES_DIST) $(test_imap_SOURCES) \ + $(am__test_interrupt_SOURCES_DIST) $(test_ipaddress_SOURCES) \ + $(test_json_SOURCES) $(am__test_ldap_SOURCES_DIST) \ + $(test_log_SOURCES) $(am__test_magic_SOURCES_DIST) \ $(am__test_memory_pool_SOURCES_DIST) $(test_mongodb_SOURCES) \ $(test_multipart_SOURCES) $(test_notifier_SOURCES) \ $(test_options_SOURCES) $(am__test_orm_SOURCES_DIST) \ @@ -1090,20 +1097,20 @@ MAINTAINERCLEANFILES = Makefile.in DEFAULT_INCLUDES = -I. -I$(top_builddir)/include LDADD = @ULIBS@ $(top_builddir)/src/ulib/lib@ULIB@.la @ULIB_LIBS@ PRG = test_timeval test_timer test_notifier test_string test_file \ - test_cdb test_rdb test_file_config test_log test_vector \ - test_options test_application test_tree test_compress \ - test_cache test_date test_services test_base64 test_header \ - test_entity test_ipaddress test_socket test_ftp test_http \ - test_rdb_client test_tokenizer test_query_parser \ + test_cdb test_rdb test_file_config test_log test_bit_array \ + test_vector test_options test_application test_tree \ + test_compress test_cache test_date test_services test_base64 \ + test_header test_entity test_ipaddress test_socket test_ftp \ + test_http test_rdb_client test_tokenizer test_query_parser \ test_multipart test_command test_dialog test_rdb_server \ test_json test_server test_redis test_elasticsearch test_smtp \ test_pop3 test_imap $(am__append_1) $(am__append_2) \ - $(am__append_4) $(am__append_6) $(am__append_8) \ - $(am__append_10) $(am__append_12) $(am__append_14) \ - $(am__append_16) $(am__append_18) $(am__append_20) \ - $(am__append_22) $(am__append_24) $(am__append_26) \ - $(am__append_28) $(am__append_30) $(am__append_32) \ - $(am__append_36) + $(am__append_3) $(am__append_4) $(am__append_6) \ + $(am__append_8) $(am__append_10) $(am__append_12) \ + $(am__append_14) $(am__append_16) $(am__append_18) \ + $(am__append_20) $(am__append_22) $(am__append_24) \ + $(am__append_26) $(am__append_28) $(am__append_30) \ + $(am__append_32) $(am__append_34) $(am__append_38) TST = timeval.test timer.test notifier.test string.test file.test \ cdb.test rdb.test file_config.test log.test vector.test \ options.test application.test tree.test compress.test \ @@ -1111,12 +1118,12 @@ TST = timeval.test timer.test notifier.test string.test file.test \ entity.test ipaddress.test socket.test ftp.test http.test \ tokenizer.test query_parser.test multipart.test \ rdb_client_server.test command.test json.test server.test \ - server_rpc.test $(am__append_3) $(am__append_5) \ - $(am__append_7) $(am__append_9) $(am__append_11) \ - $(am__append_13) $(am__append_15) $(am__append_17) \ - $(am__append_19) $(am__append_21) $(am__append_23) \ - $(am__append_25) $(am__append_27) $(am__append_29) \ - $(am__append_31) $(am__append_33) $(am__append_37) + server_rpc.test $(am__append_5) $(am__append_7) \ + $(am__append_9) $(am__append_11) $(am__append_13) \ + $(am__append_15) $(am__append_17) $(am__append_19) \ + $(am__append_21) $(am__append_23) $(am__append_25) \ + $(am__append_27) $(am__append_29) $(am__append_31) \ + $(am__append_33) $(am__append_35) $(am__append_39) test_smtp_SOURCES = test_smtp.cpp test_pop3_SOURCES = test_pop3.cpp test_imap_SOURCES = test_imap.cpp @@ -1129,6 +1136,7 @@ test_timer_SOURCES = test_timer.cpp test_notifier_SOURCES = test_notifier.cpp test_string_SOURCES = test_string.cpp test_file_SOURCES = test_file.cpp +test_bit_array_SOURCES = test_bit_array.cpp test_cdb_SOURCES = test_cdb.cpp test_rdb_SOURCES = test_rdb.cpp test_file_config_SOURCES = test_file_config.cpp @@ -1187,8 +1195,8 @@ test_elasticsearch_SOURCES = test_elasticsearch.cpp @LINUX_TRUE@test_interrupt_SOURCES = test_interrupt.cpp @LINUX_TRUE@test_unixsocket_client_SOURCES = test_unixsocket_client.cpp @LINUX_TRUE@test_unixsocket_server_SOURCES = test_unixsocket_server.cpp -@LINUX_TRUE@test_process_LDADD = $(LDADD) $(am__append_34) -@LINUX_TRUE@test_interrupt_LDADD = $(LDADD) $(am__append_35) +@LINUX_TRUE@test_process_LDADD = $(LDADD) $(am__append_36) +@LINUX_TRUE@test_interrupt_LDADD = $(LDADD) $(am__append_37) @PLUGIN_TRUE@@STDCPP_TRUE@test_plugin_SOURCES = test_plugin.cpp @PLUGIN_TRUE@@STDCPP_TRUE@product1_la_SOURCES = plugin/product1.cpp @PLUGIN_TRUE@@STDCPP_TRUE@product1_la_LIBADD = $(LDADD) @@ -1280,6 +1288,10 @@ test_base64$(EXEEXT): $(test_base64_OBJECTS) $(test_base64_DEPENDENCIES) $(EXTRA @rm -f test_base64$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_base64_OBJECTS) $(test_base64_LDADD) $(LIBS) +test_bit_array$(EXEEXT): $(test_bit_array_OBJECTS) $(test_bit_array_DEPENDENCIES) $(EXTRA_test_bit_array_DEPENDENCIES) + @rm -f test_bit_array$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(test_bit_array_OBJECTS) $(test_bit_array_LDADD) $(LIBS) + test_cache$(EXEEXT): $(test_cache_OBJECTS) $(test_cache_DEPENDENCIES) $(EXTRA_test_cache_DEPENDENCIES) @rm -f test_cache$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_cache_OBJECTS) $(test_cache_LDADD) $(LIBS) @@ -1563,6 +1575,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_application.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_arping.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_base64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_bit_array.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_cdb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_certificate.Po@am__quote@ @@ -2045,7 +2058,7 @@ uninstall-am: test: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) - ../make_test.sh application.test base64.test cache.test cdb.test certificate.test command.test compress.test crl.test date.test des3.test dialog.test digest.test entity.test expat.test file.test file_config.test header.test http.test https.test interrupt.test json.test log.test memory_pool.test multipart.test notifier.test options.test pcre.test pkcs10.test pkcs7.test plugin.test process.test query_parser.test rdb.test rdb_client_server.test server.test server_rpc.test services.test soap_client.test soap_server.test ssl_client_server.test string.test timer.test timestamp.test timeval.test tokenizer.test tree.test unixsocket.test url.test vector.test zip.test ../reset.color + ../make_test.sh application.test base64.test bit_array.test cache.test cdb.test certificate.test command.test compress.test crl.test date.test des3.test dialog.test digest.test entity.test expat.test file.test file_config.test header.test http.test https.test interrupt.test json.test log.test memory_pool.test multipart.test notifier.test options.test pcre.test pkcs10.test pkcs7.test plugin.test process.test query_parser.test rdb.test rdb_client_server.test server.test server_rpc.test services.test soap_client.test soap_server.test ssl_client_server.test string.test timer.test timestamp.test timeval.test tokenizer.test tree.test unixsocket.test url.test vector.test zip.test ../reset.color clean-local: -rm -rf out err core .libs *.bb* *.da *.gc* *.log test_log.log* tmp/* \ diff --git a/tests/ulib/bit_array.test b/tests/ulib/bit_array.test new file mode 100755 index 000000000..82f9b36ca --- /dev/null +++ b/tests/ulib/bit_array.test @@ -0,0 +1,18 @@ +#!/bin/sh + +. ../.function + +## bit_array -- Test bit_array feature + +start_msg bit_array + +#UTRACE="0 5M 0" +#UOBJDUMP="0 100k 10" +#USIMERR="error.sim" + export UTRACE UOBJDUMP USIMERR + +start_prg bit_array + +# Test against expected output + +test_output_wc w bit_array diff --git a/tests/ulib/http2/hencode.cpp b/tests/ulib/http2/hencode.cpp index 2cf563546..65e9de47b 100644 --- a/tests/ulib/http2/hencode.cpp +++ b/tests/ulib/http2/hencode.cpp @@ -273,7 +273,9 @@ idx_err: UHTTP2::hpack_errno = -4; // The decoded or specified index is out o entry = UHTTP2::getHpackDynTblEntry(dyntbl, index); - name = *(entry->name); + if (entry == 0) return; + + name._assign(entry->name); UHTTP2::evictHpackDynTblEntry(dyntbl, entry); @@ -305,7 +307,7 @@ idx_err: UHTTP2::hpack_errno = -4; // The decoded or specified index is out o entry = UHTTP2::hpack_static_table + idx-1; - name = *(entry->name); + name._assign(entry->name); U_INTERNAL_DUMP("name = %V value = %V", name.rep, value.rep) diff --git a/tests/ulib/ok/bit_array.ok b/tests/ulib/ok/bit_array.ok new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ulib/rdb_client_server.test b/tests/ulib/rdb_client_server.test index dd09db68d..5e4860023 100755 --- a/tests/ulib/rdb_client_server.test +++ b/tests/ulib/rdb_client_server.test @@ -28,6 +28,7 @@ fi #STRACE=$TRUSS start_cmd_background "./test_rdb_server$SUFFIX inp/rdb_server.cf $ARG1 >out/rdb_client.out 2>>err/rdb_server.err" +$SLEEP start_prg rdb_client localhost if [ "$TERM" = "msys" ] || \ diff --git a/tests/ulib/server.test b/tests/ulib/server.test index 35841af86..9cab6c0ed 100755 --- a/tests/ulib/server.test +++ b/tests/ulib/server.test @@ -6,7 +6,7 @@ start_msg server -#UTRACE="0 50M 0" +#UTRACE="0 20M 0" #UTRACE_SIGNAL="0 10M 0" #UOBJDUMP="0 50M 1000" #USIMERR="error.sim" @@ -30,6 +30,7 @@ $SLEEP #$TRUSS socat -u open:inp/http/form_enctype.http tcp4-connect:127.0.0.1:8080 >out/server.out 2>/tmp/trace.out check_for_netcat +$SLEEP send_req $NCAT localhost 8080 inp/http/form_enctype.http server 3 $SLEEP diff --git a/tests/ulib/server_rpc.test b/tests/ulib/server_rpc.test index 2be2c9dbc..148f39111 100755 --- a/tests/ulib/server_rpc.test +++ b/tests/ulib/server_rpc.test @@ -21,6 +21,7 @@ start_prg_background server ../../src/ulib/net/server/plugin/.libs rpc server_rp $SLEEP check_for_netcat +$SLEEP send_req $NCAT localhost 8080 inp/rpc_request server_rpc 3 $SLEEP diff --git a/tests/ulib/test_bit_array.cpp b/tests/ulib/test_bit_array.cpp new file mode 100644 index 000000000..0a44a9ec4 --- /dev/null +++ b/tests/ulib/test_bit_array.cpp @@ -0,0 +1,63 @@ +// test_bit_array.cpp + +#include + +#ifndef U_HTTP2_DISABLE +# include +#endif + +int U_EXPORT main(int argc, char** argv) +{ + U_ULIB_INIT(argv); + + U_TRACE(5, "::main(%d,%p)", argc, argv) + + UBitArray addrmask; + uint32_t i, nbits = addrmask.getNumBits(); + + U_ASSERT_EQUALS( addrmask.count(), 0 ) + + for (i = 0; i < nbits; ++i) + { + U_ASSERT_EQUALS( addrmask[i], false ) + } + + addrmask.setAll(); + + U_ASSERT_EQUALS( addrmask.count(), nbits ) + + for (i = 0; i < nbits; ++i) + { + U_ASSERT( addrmask[i] ) + } + + addrmask.clearAll(); + + U_ASSERT_EQUALS( addrmask.count(), 0 ) + + for (i = 0; i < nbits; ++i) + { + U_ASSERT_EQUALS( addrmask[i], false ) + } + + addrmask.setAll(); + addrmask.set(1024); + + ++nbits; + + U_ASSERT_EQUALS( addrmask.count(), nbits ) + + for (i = 0; i < nbits; ++i) + { + U_ASSERT( addrmask[i] ) + } + + for (nbits = addrmask.getNumBits(); i < nbits; ++i) + { + U_ASSERT_EQUALS( addrmask[i], false ) + } + +#if defined(DEBUG) && !defined(U_HTTP2_DISABLE) + UHTTP2::testHpackDynTbl(); +#endif +} diff --git a/tests/ulib/test_cdb.cpp b/tests/ulib/test_cdb.cpp index 591f36491..e4807e7d1 100644 --- a/tests/ulib/test_cdb.cpp +++ b/tests/ulib/test_cdb.cpp @@ -10,7 +10,7 @@ static int print(UStringRep* key, UStringRep* data) } int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_elasticsearch.cpp b/tests/ulib/test_elasticsearch.cpp index a0de0a087..9e734dda1 100644 --- a/tests/ulib/test_elasticsearch.cpp +++ b/tests/ulib/test_elasticsearch.cpp @@ -4,7 +4,7 @@ // Basic use elasticsearch wrapper -int U_EXPORT main(int argc, char* argv[]) +int U_EXPORT main(int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_entity.cpp b/tests/ulib/test_entity.cpp index 621d0adcb..84acbb568 100644 --- a/tests/ulib/test_entity.cpp +++ b/tests/ulib/test_entity.cpp @@ -112,7 +112,7 @@ static void parse(const UString& dati, const UString& file) printf("%.*s parsed as %s \n", U_STRING_TO_TRACE(file), type); } -int U_EXPORT main(int argc, char* argv[]) +int U_EXPORT main(int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_file_config.cpp b/tests/ulib/test_file_config.cpp index 37141a319..32711b5c6 100644 --- a/tests/ulib/test_file_config.cpp +++ b/tests/ulib/test_file_config.cpp @@ -110,7 +110,7 @@ static bool cancella(UStringRep* key, void* value) U_RETURN(false); } -int U_EXPORT main (int argc, char* argv[]) +int U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_header.cpp b/tests/ulib/test_header.cpp index cc88e0930..501133317 100644 --- a/tests/ulib/test_header.cpp +++ b/tests/ulib/test_header.cpp @@ -32,7 +32,7 @@ "\r\n" int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_http.cpp b/tests/ulib/test_http.cpp index 9251e3a5d..2afc26313 100644 --- a/tests/ulib/test_http.cpp +++ b/tests/ulib/test_http.cpp @@ -6,7 +6,7 @@ // #define JOHN -int U_EXPORT main(int argc, char* argv[]) +int U_EXPORT main(int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_https.cpp b/tests/ulib/test_https.cpp index 403c84191..fb804c17b 100644 --- a/tests/ulib/test_https.cpp +++ b/tests/ulib/test_https.cpp @@ -3,7 +3,7 @@ #include #include -int U_EXPORT main(int argc, char* argv[]) +int U_EXPORT main(int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_json.cpp b/tests/ulib/test_json.cpp index 835d2ea68..d138670a6 100644 --- a/tests/ulib/test_json.cpp +++ b/tests/ulib/test_json.cpp @@ -474,7 +474,7 @@ static void testMultiple() } int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_log.cpp b/tests/ulib/test_log.cpp index f7537229f..eacb3c9b6 100644 --- a/tests/ulib/test_log.cpp +++ b/tests/ulib/test_log.cpp @@ -3,7 +3,7 @@ #include int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_pkcs7.cpp b/tests/ulib/test_pkcs7.cpp index 836f3c76b..015f86f70 100644 --- a/tests/ulib/test_pkcs7.cpp +++ b/tests/ulib/test_pkcs7.cpp @@ -236,7 +236,7 @@ static void check(const UString& dati) "# that require network functionality will fail.\n" \ "127.0.0.1 localhost.localdomain localhost" -int U_EXPORT main(int argc, char* argv[]) +int U_EXPORT main(int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_rdb.cpp b/tests/ulib/test_rdb.cpp index 7c19f2a03..710ac4437 100644 --- a/tests/ulib/test_rdb.cpp +++ b/tests/ulib/test_rdb.cpp @@ -55,7 +55,7 @@ static void transaction(URDB& rdb) } int -U_EXPORT main(int argc, char* argv[]) +U_EXPORT main(int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_rdb_client.cpp b/tests/ulib/test_rdb_client.cpp index 6d99358f8..805605c6d 100644 --- a/tests/ulib/test_rdb_client.cpp +++ b/tests/ulib/test_rdb_client.cpp @@ -53,7 +53,7 @@ static void transaction(URDBClient& rdb) } int -U_EXPORT main(int argc, char* argv[]) +U_EXPORT main(int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_rdb_server.cpp b/tests/ulib/test_rdb_server.cpp index 4d8fdb104..eeaa4d80a 100644 --- a/tests/ulib/test_rdb_server.cpp +++ b/tests/ulib/test_rdb_server.cpp @@ -4,7 +4,7 @@ #include #include -int U_EXPORT main(int argc, char* argv[]) +int U_EXPORT main(int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_redis.cpp b/tests/ulib/test_redis.cpp index 58241b913..bb72f4a2e 100644 --- a/tests/ulib/test_redis.cpp +++ b/tests/ulib/test_redis.cpp @@ -3,7 +3,7 @@ #include #include -int main(int argc, char *argv[]) +int main(int argc, char *argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_server.cpp b/tests/ulib/test_server.cpp index 2c8c928b5..e623f4a5d 100644 --- a/tests/ulib/test_server.cpp +++ b/tests/ulib/test_server.cpp @@ -7,7 +7,7 @@ U_MACROSERVER(UServerExample, UClientImage, UTCPSocket); int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_soap_client.cpp b/tests/ulib/test_soap_client.cpp index 8283e9ba1..ee52be266 100644 --- a/tests/ulib/test_soap_client.cpp +++ b/tests/ulib/test_soap_client.cpp @@ -130,7 +130,7 @@ template class UTestSOAPClient : public USOAPClient { }; int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_soap_server.cpp b/tests/ulib/test_soap_server.cpp index 2c071db87..e1510e665 100644 --- a/tests/ulib/test_soap_server.cpp +++ b/tests/ulib/test_soap_server.cpp @@ -174,7 +174,7 @@ class USOAPExample : public USOAPObject { // USOAPObject acts as a container for }; int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_ssl_client.cpp b/tests/ulib/test_ssl_client.cpp index 1e8eec309..6588ea440 100644 --- a/tests/ulib/test_ssl_client.cpp +++ b/tests/ulib/test_ssl_client.cpp @@ -5,7 +5,7 @@ static const char* getArg(const char* param) { return (param && *param ? param : 0); } int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_ssl_server.cpp b/tests/ulib/test_ssl_server.cpp index b6c30af00..0bb2f9f00 100644 --- a/tests/ulib/test_ssl_server.cpp +++ b/tests/ulib/test_ssl_server.cpp @@ -69,7 +69,7 @@ U_MACROSERVER(USSLServer, USSLClientImage, USSLSocket); static const char* getArg(const char* param) { return (param && *param ? param : 0); } int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_tokenizer.cpp b/tests/ulib/test_tokenizer.cpp index 37c5375d7..609f14bb9 100644 --- a/tests/ulib/test_tokenizer.cpp +++ b/tests/ulib/test_tokenizer.cpp @@ -5,7 +5,7 @@ #include int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_unixsocket_client.cpp b/tests/ulib/test_unixsocket_client.cpp index e77015db7..2dfc32c07 100644 --- a/tests/ulib/test_unixsocket_client.cpp +++ b/tests/ulib/test_unixsocket_client.cpp @@ -3,7 +3,7 @@ #include int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv); diff --git a/tests/ulib/test_unixsocket_server.cpp b/tests/ulib/test_unixsocket_server.cpp index 283bef167..e153f66f2 100644 --- a/tests/ulib/test_unixsocket_server.cpp +++ b/tests/ulib/test_unixsocket_server.cpp @@ -47,7 +47,7 @@ class UUnixClientImage : public UClientImage { U_MACROSERVER(UUnixServer, UUnixClientImage, UUnixSocket); int -U_EXPORT main (int argc, char* argv[]) +U_EXPORT main (int argc, char* argv[], char* env[]) { U_ULIB_INIT(argv);